Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.562
diff -u -u -p -r1.562 system.module
--- modules/system/system.module	16 Dec 2007 21:01:45 -0000	1.562
+++ modules/system/system.module	18 Dec 2007 16:42:31 -0000
@@ -1229,6 +1229,17 @@ function system_action_info() {
         'taxonomy' => array('insert', 'update', 'delete'),
       ),
     ),
+    'system_watchdog_action' => array(
+      'type' => 'system',
+      'description' => t('Write a message to the log'),
+      'configurable' => TRUE,
+      'hooks' => array(
+        'nodeapi' => array('view', 'insert', 'update', 'delete'),
+        'comment' => array('view', 'insert', 'update', 'delete'),
+        'user' => array('view', 'insert', 'update', 'delete', 'login'),
+        'taxonomy' => array('insert', 'update', 'delete'),
+      ),
+    ),
     'system_send_email_action' => array(
       'description' => t('Send e-mail'),
       'type' => 'system',
@@ -1770,6 +1781,104 @@ function system_message_action(&$object,
   drupal_set_message($context['message']);
 }
 
+function system_watchdog_action_form($context) {
+  $form['type'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Type'),
+    '#description' => t('The type of message to write, used for filtering log entries when viewing logs. Examples are content, page not found, user.')
+  );
+
+  $form['severity'] = array(
+    '#type' => 'select',
+    '#title' => t('Severity'),
+    '#description' => t('Choose the appropriate severity level for this message.'),
+    '#default_value' => isset($context['severity']) ? $context['severity'] : 6,
+    '#options' => array(
+      WATCHDOG_EMERG => t('Emergency: system is unusable'),
+      WATCHDOG_ALERT => t('Alert: action must be taken immediately'),
+      WATCHDOG_CRITICAL => t('Critical: critical conditions'),
+      WATCHDOG_WARNING => t('Warning: warning conditions'),
+      WATCHDOG_NOTICE => t('Notice: normal but significant conditions'),
+      WATCHDOG_INFO => t('Information: informational messages'),
+      WATCHDOG_DEBUG => t('Debug: debug-level messages'),
+    ),
+  );
+  $form['message'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Message'),
+    '#default_value' => isset($context['message']) ? $context['message'] : '',
+    '#required' => TRUE,
+    '#rows' => '8',
+    '#description' => t('The message to be recorded in the log. You may include the following variables: %site_name, %username, %node_url, %node_type, %title, %teaser, %body. Not all variables will be available in all contexts.'),
+  );
+  return $form;
+}
+
+function system_watchdog_action_submit($form, $form_state) {
+  return array(
+    'type' => $form_state['values']['type'],
+    'severity' => $form_state['values']['severity'],
+    'message' => $form_state['values']['message'],
+  );
+}
+
+/**
+ * A configurable Drupal action. Writes a message to watchdog.
+ */
+function system_watchdog_action(&$object, $context = array()) {
+  global $user;
+  $variables = array(
+    '%site_name' => variable_get('site_name', 'Drupal'),
+    '%username' => $user->name ? $user->name : variable_get('anonymous', t('Anonymous')),
+  );
+
+  // This action can be called in any context, but if placeholders
+  // are used a node object must be present to be the source
+  // of substituted text.
+  switch ($context['hook']) {
+    case 'nodeapi':
+      // Because this is not an action of type 'node' the node
+      // will not be passed as $object, but it will still be available
+      // in $context.
+      $node = $context['node'];
+      break;
+    // The comment hook also provides the node, in context.
+    case 'comment':
+      $comment = $context['comment'];
+      $node = node_load($comment->nid);
+      break;
+    case 'taxonomy':
+      $vocabulary = taxonomy_vocabulary_load($object->vid);
+      $variables = array_merge($variables, array(
+        '%term_name' => $object->name,
+        '%term_description' => $object->description,
+        '%term_id' => $object->tid,
+        '%vocabulary_name' => $vocabulary->name,
+        '%vocabulary_description' => $vocabulary->description,
+        '%vocabulary_id' => $vocabulary->vid,
+        )
+      );
+      break;
+    default:
+      // We are being called directly.
+      $node = $object;
+  }
+
+  if (isset($node) && is_object($node)) {
+    $variables = array_merge($variables, array(
+      '%uid' => $node->uid,
+      '%node_url' => url('node/'. $node->nid, array('absolute' => TRUE)),
+      '%node_type' => check_plain(node_get_types('name', $node)),
+      '%title' => filter_xss($node->title),
+      '%teaser' => filter_xss($node->teaser),
+      '%body' => filter_xss($node->body),
+      )
+    );
+  }
+  $context['message'] = strtr($context['message'], $variables);
+  watchdog($context['type'], $context['message'], array(), $context['severity']);
+}
+
 /**
  * Implementation of a configurable Drupal action. Redirect user to a URL.
  */
