array( '#label' => t('Write a message to the log'), '#arguments' => array( 'subject' => array('#entity' => array('node', 'user'), '#label' => t('Entity whose log to write to')), ), '#module' => 'Per-Entity Logging', ), 'workflow_ng_log_action_clean' => array( '#label' => t('Clean up by removing old log messages'), '#arguments' => array(), '#module' => 'Per-Entity Logging', ), ); } /** * Action: Writes a message to the per-user or per-entity log. */ function workflow_ng_log_action_message($subject, $settings, &$arguments, &$log) { if (isset($subject->nid)) { $subject_id = $subject->nid; $query = 'workflow_ng_log_node} (nid'; } else { $subject_id = $subject->uid; $query = 'workflow_ng_log_user} (uid'; } $query = 'INSERT INTO {'. $query .", type, category, message, time) VALUES (%d, '%s', '%s', '%s', %d)"; extract(workflow_ng_token_replace_all(array('type', 'category', 'message'), $settings, $arguments, $log)); db_query($query, $subject_id, substr($type, 0, 255), substr($category, 0, 255), $message, time()); } /** * Action "Write a message to the user / node log" configuration form */ function workflow_ng_log_action_message_form($settings = array(), $argument_info) { $form = array(); $form['type'] = array( '#type' => 'textfield', '#title' => t('Message type'), '#default_value' => $settings['type'], '#description' => t('Enter the message type.'), '#required' => FALSE, // No maximum length specified, even though the database field has a limited // length (255), as the tokens may expand or contract. ); $form['category'] = array( '#type' => 'textfield', '#title' => t('Message category'), '#default_value' => $settings['category'], '#description' => t('Enter the message category.'), '#required' => FALSE, // No maximum length specified, even though the database field has a limited // length (255), as the tokens may expand or contract. ); $form['message'] = array( '#type' => 'textarea', '#title' => t('Message'), '#default_value' => $settings['message'], '#description' => t('Enter the message to log. Be sure to only use replacement patterns that contain no raw user input.'), '#required' => TRUE, ); workflow_ng_token_replacement_help($form, $argument_info); return $form; } /** * Action "Write a message to the user / node log" configuration form submission handler */ function workflow_ng_log_action_message_submit($form_id, $form_values) { return workflow_ng_token_get_settings(array('type', 'category', 'message'), $form_values); } /** * Action "Clean up log messages" */ function workflow_ng_log_action_clean($settings) { $sql = "DELETE FROM {workflow_ng_log_". $settings['entity'] ."} WHERE time < %d"; $args = array(time() - $settings['time']); if ($settings['category']) { $sql .= ' AND category = \'%s\''; $args[] = $settings['category']; } if ($settings['type']) { $sql .= ' AND type = \'%s\''; $args[] = $settings['type']; } db_query($sql, $args); } function workflow_ng_log_action_clean_form($settings) { $settings += array('entity' => ''); $form['entity'] = array( '#type' => 'radios', '#title' => t('Entity, for which to clean up the log'), '#options' => array( 'user' => t('User'), 'node' => t('Content'), ), '#default_value' => $settings['entity'], '#required' => TRUE, ); $form['time'] = array( '#type' => 'select', '#title' => t('Remove messages older than'), '#default_value' => $settings['time'], '#options' => drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval'), ); $form['type'] = array( '#type' => 'textfield', '#title' => t('Message type'), '#default_value' => $settings['type'], '#description' => t('Enter the type of messages to remove. Leave it empty to remove messages regardless of their type.'), ); $form['category'] = array( '#type' => 'textfield', '#title' => t('Message category'), '#default_value' => $settings['category'], '#description' => t('Enter the category of messages to remove. Leave it empty to remove messages regardless of their category.'), ); return $form; } function workflow_ng_log_action_clean_submit($form_id, $form_values) { return array_intersect_key($form_values, drupal_map_assoc(array('type', 'category', 'entity', 'time'))); } /** * Implementation of hook_perm() */ function workflow_ng_log_perm() { return array('delete all user entries', 'delete own user entries', 'delete all node entries'); } /** * Implementation of hook_menu() */ function workflow_ng_log_menu($may_cache) { if ($may_cache) { $items = array(); // path for deleting entry $items[] = array( 'path' => 'workflow_ng/log/delete', 'title' => t('Delete entry'), 'access' => user_access('access content'), 'type' => MENU_CALLBACK, 'callback' => 'drupal_get_form', 'callback arguments' => array('workflow_ng_log_delete_entry'), ); return $items; } } /** * Implementation of hook_nodeapi() */ function workflow_ng_log_nodeapi($node, $op) { if ($op == 'delete') { db_query("DELETE FROM {workflow_ng_log_node} WHERE nid = %d", $node->nid); } } /** * Implementation of hook_user() */ function workflow_ng_log_user($op, $edit, $account, $category = NULL) { if ($op == 'delete') { db_query("DELETE FROM {workflow_ng_log_user} WHERE uid = %d", $account->uid); } } /** * Helper function for workflow_ng_log_views_tables; adds definitions common to * user log messages and node log messages to a views table definition. * @param $table A views table definition to extend * @param $entity_upper Name of the capitalised entity (Node or User) * @param $entity_lower Name of the entity (node or user) */ function _workflow_ng_log_tables_common(&$table, $entity_upper, $entity_lower) { $group = t('Per-@entity Log: ', array('@entity' => $entity_upper)); $table['fields'] = array( 'type' => array( 'name' => $group . t('Message type'), 'sortable' => TRUE, 'help' => t('Displays the type given to the log message.'), ), 'category' => array( 'name' => $group . t('Message category'), 'sortable' => TRUE, 'help' => t('Displays the category given to the log message.'), ), 'message' => array( 'name' => $group . t('Message'), 'sortable' => TRUE, 'help' => t('Displays the actual log message.'), 'handler' => 'workflow_ng_log_handler_message_unfiltered', ), 'time' => array( 'name' => $group . t('Message time'), 'sortable' => TRUE, 'help' => t('Displays the time at which the message was logged.') .' '. t('The option field may be used to specify the custom date format as it\'s required by the date() function or if "as time ago" has been chosen to customize the granularity of the time interval.'), 'handler' => views_handler_field_dates(), 'option' => 'string', ), 'delete' => array( 'name' => $group . t('Delete entry'), 'handler' => array( 'workflow_ng_log_handler_delete' => t('Delete entry') ), 'notafield' => TRUE, 'query_handler' => 'workflow_ng_log_handler_delete_query', 'help' => t('Display a link to delete an entry.'), ), ); $table['sorts'] = array( 'time' => array( 'name' => $group . t('Message time'), 'help' => t("Sort by the time at which log messages were created."), 'handler' => 'views_handler_sort_date', 'option' => views_handler_sort_date_options(), ), ); $table['filters'] = array( 'type' => array( 'name' => $group . t('Message type'), 'help' => t('Filter per-@entity log messages based on their type.', array('@entity' => $entity_lower)), 'operator' => 'views_handler_operator_like', 'handler' => 'views_handler_filter_like', ), 'category' => array( 'name' => $group . t('Message category'), 'help' => t('Filter per-@entity log messages based on their category.', array('@entity' => $entity_lower)), 'operator' => 'views_handler_operator_like', 'handler' => 'views_handler_filter_like', ), 'time' => array( 'name' => $group . t('Message time'), 'help' => t('Filter per-@entity log messages based on the logging time.', array('@entity' => $entity_lower)) .' '. views_t_strings('filter date'), 'operator' => 'views_handler_operator_gtlt', 'value' => views_handler_filter_date_value_form(), 'handler' => 'views_handler_filter_timestamp', 'option' => 'string', ), ); } /** * field handler to display message as is */ function workflow_ng_log_handler_message_unfiltered($fieldinfo, $fielddata, $value, $data) { return $value; } /** * query handler for delete link */ function workflow_ng_log_handler_delete_query($fielddata, $fieldinfo, &$query) { $query->ensure_table($fielddata['tablename']); $query->add_field('mid', $fielddata['tablename']); } /** * displays a link to delete an entry */ function workflow_ng_log_handler_delete($fieldinfo, $fielddata, $value, $data) { if (strpos(strtolower($fielddata['tablename']), 'user')) { $type = 'user'; } else if (strpos(strtolower($fielddata['tablename']), 'node')) { $type = 'node'; } $link_text = t('Delete entry'); return l($link_text, "workflow_ng/log/delete/". $data->mid ."/". $type, NULL, drupal_get_destination()); } /** * Shows confirm form to delete an entry */ function workflow_ng_log_delete_entry($id, $type) { global $user; $table = 'workflow_ng_log_'. $type; if ($type == 'user') { $sql = "SELECT uid, message FROM {$table} WHERE mid = %d"; } else if ($type == 'node') { $sql = "SELECT nid, message FROM {$table} WHERE mid = %d"; } $result = db_fetch_array(db_query($sql, array($id))); // check permissions for deleting if (($type == 'user' && !(user_access('delete all user entries') || (($user->uid == $result['uid']) && user_access('delete own user entries')))) || ($type == 'node' && !(user_access('delete all node entries')))) { drupal_access_denied(); } $form = array(); $form['mid'] = array( '#type' => 'value', '#value' => $id, ); $form['type'] = array( '#type' => 'value', '#value' => $type, ); return confirm_form($form, t('Delete entry'), $_GET['destination'], t("Are you sure you want to delete the entry !message?", array('!message' => ''. $result['message'] .'')), t('Delete'), t('Cancel'), 'workflow_ng_log_delete_entry_confirm'); } /** * submit function to delete an entry */ function workflow_ng_log_delete_entry_submit($form_id, $form_values) { $table = 'workflow_ng_log_'. $form_values['type']; $sql = "DELETE FROM {$table} WHERE mid = %d"; db_query($sql, array($form_values['mid'])); drupal_set_message(t("Entry deleted")); return ''; } /** * Implementation of hook_views_tables(): * Presents fields and filters for log messages. */ function workflow_ng_log_views_tables() { $tables['workflow_ng_log_node'] = array( 'name' => 'workflow_ng_log_node', 'provider' => 'internal', // won't show up in external list. 'join' => array( 'type' => 'inner', 'left' => array( 'table' => 'node', 'field' => 'nid', ), 'right' => array( 'field' => 'nid', ), ), ); _workflow_ng_log_tables_common($tables['workflow_ng_log_node'], 'Node', 'node'); if (module_exists('usernode')) { $tables['workflow_ng_log_user'] = array( 'name' => 'workflow_ng_log_user', 'provider' => 'internal', // won't show up in external list. 'join' => array( 'type' => 'inner', 'left' => array( 'table' => 'usernode', 'field' => 'uid', ), 'right' => array( 'field' => 'uid', ), ), ); _workflow_ng_log_tables_common($tables['workflow_ng_log_user'], 'User', 'user'); } return $tables; } /** * Implementation of hook_views_default_views(): * Generate a default views: a list of all user log messages and a list of all node log messages */ function workflow_ng_log_views_default_views() { $view = new stdClass(); $view->name = 'userlog_msgs'; $view->description = 'All messages to per-user logs'; $view->access = array ( ); $view->view_args_php = ''; $view->page = TRUE; $view->page_title = 'User log messages'; $view->page_header = ''; $view->page_header_format = '1'; $view->page_footer = ''; $view->page_footer_format = '1'; $view->page_empty = ''; $view->page_empty_format = '1'; $view->page_type = 'table'; $view->url = 'admin/workflow-ng/user-log'; $view->use_pager = TRUE; $view->nodes_per_page = '10'; $view->menu = TRUE; $view->menu_title = 'User log messages'; $view->menu_tab = FALSE; $view->menu_tab_weight = '0'; $view->menu_tab_default = FALSE; $view->menu_tab_default_parent = NULL; $view->menu_tab_default_parent_type = 'tab'; $view->menu_parent_tab_weight = '0'; $view->menu_parent_title = ''; $view->sort = array ( ); $view->argument = array ( ); $view->field = array ( array ( 'tablename' => 'usernode_users', 'field' => 'name', 'label' => 'User', 'handler' => 'usernode_views_handler_field_username_link', 'sortable' => '1', ), array ( 'tablename' => 'workflow_ng_log_user', 'field' => 'type', 'label' => 'Message type', 'sortable' => '1', ), array ( 'tablename' => 'workflow_ng_log_user', 'field' => 'category', 'label' => 'Message category', 'sortable' => '1', ), array ( 'tablename' => 'workflow_ng_log_user', 'field' => 'message', 'label' => 'Message', 'sortable' => '1', ), array ( 'tablename' => 'workflow_ng_log_user', 'field' => 'time', 'label' => 'Time', 'handler' => 'views_handler_field_date_small', 'sortable' => '1', 'defaultsort' => 'DESC', ), array ( 'tablename' => 'workflow_ng_log_user', 'field' => 'delete', 'label' => '', 'handler' => 'workflow_ng_log_handler_delete', ), ); $view->filter = array ( array ( 'tablename' => 'workflow_ng_log_user', 'field' => 'type', 'operator' => '=', 'options' => '', 'value' => '', ), array ( 'tablename' => 'workflow_ng_log_user', 'field' => 'category', 'operator' => '=', 'options' => '', 'value' => '', ), ); $view->exposed_filter = array ( array ( 'tablename' => 'workflow_ng_log_user', 'field' => 'type', 'label' => 'Message type', 'optional' => '1', 'is_default' => '0', 'operator' => '0', 'single' => '0', ), array ( 'tablename' => 'workflow_ng_log_user', 'field' => 'category', 'label' => 'Message category', 'optional' => '1', 'is_default' => '0', 'operator' => '0', 'single' => '0', ), ); $view->requires = array(usernode_users, workflow_ng_log_user); $views[$view->name] = $view; $view = new stdClass(); $view->name = 'contentlog_msgs'; $view->description = 'All messages to per-content logs'; $view->access = array ( ); $view->view_args_php = ''; $view->page = TRUE; $view->page_title = 'Content log messages'; $view->page_header = ''; $view->page_header_format = '1'; $view->page_footer = ''; $view->page_footer_format = '1'; $view->page_empty = ''; $view->page_empty_format = '1'; $view->page_type = 'table'; $view->url = 'admin/workflow-ng/node-log'; $view->use_pager = TRUE; $view->nodes_per_page = '10'; $view->menu = TRUE; $view->menu_title = 'Content log messages'; $view->menu_tab = FALSE; $view->menu_tab_weight = '0'; $view->menu_tab_default = FALSE; $view->menu_tab_default_parent = NULL; $view->menu_tab_default_parent_type = 'tab'; $view->menu_parent_tab_weight = '0'; $view->menu_parent_title = ''; $view->sort = array ( ); $view->argument = array ( ); $view->field = array ( array ( 'tablename' => 'node', 'field' => 'title', 'label' => 'Content', 'handler' => 'views_handler_field_nodelink', 'sortable' => '1', 'options' => 'link', ), array ( 'tablename' => 'workflow_ng_log_node', 'field' => 'type', 'label' => 'Message type', 'sortable' => '1', ), array ( 'tablename' => 'workflow_ng_log_node', 'field' => 'category', 'label' => 'Message category', 'sortable' => '1', ), array ( 'tablename' => 'workflow_ng_log_node', 'field' => 'message', 'label' => 'Message', 'sortable' => '1', ), array ( 'tablename' => 'workflow_ng_log_node', 'field' => 'time', 'label' => 'Time', 'handler' => 'views_handler_field_date_small', 'sortable' => '1', 'defaultsort' => 'DESC', ), array ( 'tablename' => 'workflow_ng_log_node', 'field' => 'delete', 'label' => '', 'handler' => 'workflow_ng_log_handler_delete', ), ); $view->filter = array ( array ( 'tablename' => 'workflow_ng_log_node', 'field' => 'type', 'operator' => '=', 'options' => '', 'value' => '', ), array ( 'tablename' => 'workflow_ng_log_node', 'field' => 'category', 'operator' => '=', 'options' => '', 'value' => '', ), ); $view->exposed_filter = array ( array ( 'tablename' => 'workflow_ng_log_node', 'field' => 'type', 'label' => 'Message type', 'optional' => '1', 'is_default' => '0', 'operator' => '0', 'single' => '0', ), array ( 'tablename' => 'workflow_ng_log_node', 'field' => 'category', 'label' => 'Message category', 'optional' => '1', 'is_default' => '0', 'operator' => '0', 'single' => '0', ), ); $view->requires = array(node, workflow_ng_log_node); $views[$view->name] = $view; return $views; }