/[drupal]/contributions/modules/recent_changes/recent_changes.module
ViewVC logotype

Diff of /contributions/modules/recent_changes/recent_changes.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.1.2.4, Wed Apr 4 23:58:09 2007 UTC revision 1.1.2.5, Wed Feb 20 23:45:22 2008 UTC
# Line 1  Line 1 
1  <?php  <?php
2  // $Id: recent_changes.module,v 1.5 2007/04/04 23:54:17 roetzi Exp $  // $Id: recent_changes.module,v 1.1.2.3 2007/03/07 03:20:50 roetzi Exp $
3    
4  /**  /**
5   * @file   * @file
# Line 12  Line 12 
12  function recent_changes_help($section) {  function recent_changes_help($section) {
13    switch ($section) {    switch ($section) {
14      case 'admin/help#recent_changes':      case 'admin/help#recent_changes':
15        $output = '<p>'.t('The recent changes module offers a page which shows all recent changes on nodes. The page can be viewed by anyone with the <em>view revisions</em> permission. If you have the <em>diff</em> module installed, a link to the diff-view will be offered in the table.').'</p>';        $output = '<p>'.t('The recent changes module offers a page which shows all recent changes on nodes. The page can be viewed by anyone with the <em>access content</em> permission, but no content is shown for node types the user has no permissions for. If you have the <em>diff</em> module installed, a link to the diff-view will be offered in the table. A feed of all recent changes, or per content type is also available. Headers of inaccessible content can be shown in feeds, depending on the settings in the recent changes administrative page.').'</p>';
16        return $output;        return $output;
17        break;        break;
18     }     }
# Line 28  function recent_changes_menu($may_cache) Line 28  function recent_changes_menu($may_cache)
28        'title' => t('Recent changes'),        'title' => t('Recent changes'),
29        'path' => 'recent_changes',        'path' => 'recent_changes',
30        'callback' => 'recent_changes_view',        'callback' => 'recent_changes_view',
31        'access' => user_access('view revisions'),        'access' => user_access('access content'),
32        'type' => MENU_NORMAL_ITEM        'type' => MENU_NORMAL_ITEM
33      );      );
34        $items[] = array(
35          'path' => 'admin/settings/recent_changes',
36          'title' => t('Recent changes'),
37          'description' => t('Adjust the settings of the recent changes page and feed.'),
38          'callback' => 'drupal_get_form',
39          'callback arguments' => array('recent_changes_admin_settings'),
40          'access' => user_access('administer site configuration')
41        );
42    }    }
43    return $items;    return $items;
44  }  }
45    
46    
47  /**  /**
48   * Menu callback which displays a list of recent changes.   * Settings form
49     */
50    function recent_changes_admin_settings() {
51      $form = array();
52    
53      $form['general_settings'] = array(
54            '#type' => 'fieldset',
55            '#title' => t('Recent changes general settings'),
56            '#collapsible' => TRUE,
57            '#collapsed' => FALSE,
58            '#weight' => -3
59          );
60    
61      $form['general_settings']['recent_changes_allowed_node_types'] = array(
62            '#type' => 'select',
63            '#title' => t('Allowed content types'),
64            '#default_value' => variable_get('recent_changes_allowed_node_types', array()),
65            '#options' => node_get_types('names'),
66            '#multiple' => TRUE,
67            '#description' => t('Select the content types that will be shown on the recent changes page and in recent changes feeds. Select none to list all content types. Note that nodes or comments that are inaccessible to a user will not be listed on his or her recent changes page, but headers of inaccessible nodes and comments might show up in recent changes feeds, depending on the settings below.'),
68          );
69    
70      $form['general_settings']['recent_changes_show_comments']= array(
71            '#type' => 'checkbox',
72            '#title' => t('Show comments'),
73            '#return_value' => 2,
74            '#default_value' => variable_get('recent_changes_show_comments', TRUE),
75            '#description' => t('Add a comments option to the content type filter on the recent changes page. To enable the selection of comments for a certain content type in the content type filter, you should enable multiple filter selection below.'),
76          );
77    
78      $form['page_settings'] = array(
79            '#type' => 'fieldset',
80            '#title' => t('Recent changes page settings'),
81            '#collapsible' => TRUE,
82            '#collapsed' => FALSE,
83            '#weight' => -2
84          );
85    
86      $form['page_settings']['recent_changes_entries_per_page']= array(
87            '#type' => 'textfield',
88            '#title' => t('Entries per page'),
89            '#size' => 5,
90            '#maxlength' => 4,
91            '#default_value' => variable_get('recent_changes_entries_per_page', 50),
92            '#description' => t('The number of entries per page'),
93          );
94    
95      $form['page_settings']['recent_changes_show_filter']= array(
96            '#type' => 'checkbox',
97            '#title' => t('Show content type filter'),
98            '#return_value' => 1,
99            '#default_value' => variable_get('recent_changes_show_filter', TRUE),
100            '#description' => t('Enable to show the content type filter on top of the recent changes page'),
101          );
102    
103      $form['page_settings']['recent_changes_type_select_size'] = array(
104            '#type' => 'select',
105            '#title' => t('Number of visible content types in content type filter'),
106            '#default_value' => variable_get('recent_changes_type_select_size', 5),
107            '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
108            '#description' => t('The number of rows that will be displayed in the content type filter. Hint: select 1 in case multiple selection is disabled!'),
109          );
110    
111      $form['page_settings']['recent_changes_allow_multiple_filter']= array(
112            '#type' => 'checkbox',
113            '#title' => t('Allow multiple content type selection'),
114            '#return_value' => 1,
115            '#default_value' => variable_get('recent_changes_allow_multiple_filter', TRUE),
116            '#description' => t('Allow multiple selection in the content type filter.'),
117          );
118    
119      $form['feed_settings'] = array(
120            '#type' => 'fieldset',
121            '#title' => t('Recent changes feed settings'),
122            '#collapsible' => TRUE,
123            '#collapsed' => FALSE,
124            '#weight' => -1,
125            '#description' => t('A feed is available for the recent items page. Links to feeds per content type are also available when a single content type is selected in the content type filter.'),
126          );
127    
128      $form['feed_settings']['recent_changes_list_inacces_revisions_in_feeds']= array(
129            '#type' => 'checkbox',
130            '#title' => t('List inaccessible revisions'),
131            '#return_value' => 1,
132            '#default_value' => variable_get('recent_changes_list_inacces_revisions_in_feeds', TRUE),
133            '#description' => t('Usually no login takes place when the recent changes feed is accessed, which means that older revisions might not be accessible. Enable this option to list revisions in feeds even if the \'view revisions\' permission is disabled for anonymous users. Note that titles of inaccessible content can be replaced by \'access denied\' messages by disabling the checkbox below.'),
134          );
135    
136      $form['feed_settings']['recent_changes_list_inacces_nodes_in_feeds']= array(
137            '#type' => 'checkbox',
138            '#title' => t('List inaccessible nodes'),
139            '#return_value' => 1,
140            '#default_value' => variable_get('recent_changes_list_inacces_nodes_in_feeds', TRUE),
141            '#description' => t('Usually no login takes place when the recent changes feed is accessed, which means certain content types might be inaccessible. Enable this option to list inaccessible nodes in feeds. Note that titles of inaccessible content can be replaced by \'access denied\' messages by disabling the checkbox below.'),
142          );
143    
144      $form['feed_settings']['recent_changes_show_access_denied_titles']= array(
145            '#type' => 'checkbox',
146            '#title' => t('Show titles of inaccessible content'),
147            '#return_value' => 1,
148            '#default_value' => variable_get('recent_changes_show_access_denied_titles', TRUE),
149            '#description' => t('Usually no login takes place when the recent changes feed is accessed, which means certain nodes, comments or revisions migth be inaccessible. Enable this option to show the titles of inaccessible nodes. Note that the content of inaccessible nodes will never be displayed in feeds.'),
150          );
151    
152      $form['feed_settings']['recent_changes_show_diff']= array(
153            '#type' => 'checkbox',
154            '#title' => t('Show diffs in feeds'),
155            '#return_value' => 1,
156            '#default_value' => variable_get('recent_changes_show_diffs', TRUE),
157            '#description' => t('When the diff module is installed and the length of XML items (see below) is set to \'Full text\', the difference between a revision of a node and its predecessor can be shown. Check this box to enable this feature.'),
158          );
159    
160      $form['feed_settings']['recent_changes_feed_default_items'] = array(
161            '#type' => 'select',
162            '#title' => t('Number of items per feed'),
163            '#default_value' => variable_get('recent_changes_feed_default_items', 10),
164            '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
165            '#description' => t('The default number of items to include in the recent changes feed.'),
166          );
167    
168      $form['feed_settings']['recent_changes_feed_item_type']= array(
169            '#type' => 'select',
170            '#title' => t('Display of XML feed items'),
171            '#default_value' => variable_get('recent_changes_feed_item_type', 'teaser'),
172            '#options' => array('title' => 'Titles only', 'teaser' => 'Titles plus teaser', 'fulltext' => 'Full text'),
173            '#multiple' => FALSE,
174            '#description' => t('The length of XML items in the recent changes feed.'),
175          );
176    
177      return system_settings_form($form);
178    }
179    
180    
181    /**
182     * Menu callback.
183   */   */
184  function recent_changes_view() {  function recent_changes_view() {
185    // Print feed if requested or display normal page otherwise    // Print feed if requested or display normal page otherwise
186    if (arg(1) == 'feed') {    if (arg(1) === 'feed') {
187      return recent_changes_feed(arg(2));       return recent_changes_feed(arg(2));
188    }    }
189    else {    else {
190      return recent_changes_page();      return recent_changes_page();
191    }    }
192  }  }
193    
194    
195  /**  /**
196   * Page display of recent changes.   * Page display of recent changes.
197   */   */
198  function recent_changes_page() {  function recent_changes_page() {
199    $output = '';    $node_types = ($_REQUEST['op'] === t('Filter')) ? _recent_changes_parse_node_types($_REQUEST['recent_changes_filter_node_types']) : _recent_changes_parse_node_types();
200    
201    // Add stylesheet for page.    // Unset the page in pager query if the filter button was pressed.
202    drupal_add_css(drupal_get_path('module', 'recent_changes').'/recent_changes.css');    if ($_POST['op'] === t('Filter')) {
203        unset($_GET['page']);
   // Show filter if enabled  
   if (recent_changes_show_filter()) {  
     $output .= drupal_get_form('recent_changes_filter_form');  
204    }    }
205    
206      // Initialize
207      $output = '';
208      $day = -1;
209      $rows = array();
210    
211    if ($_REQUEST['op'] == t('Filter')) {    // Add rss feed and stylesheet to page.
212      // Use submitted values if filter form was used.    drupal_add_css(drupal_get_path('module', 'recent_changes').'/recent_changes.css');
     $show_comments = check_plain($_REQUEST['recent_changes_show_comments']);  
     $node_type = check_plain($_REQUEST['recent_changes_show_node_type']);  
   }  
   else {  
     // Default values  
     $show_comments = recent_changes_show_comments();  
     $node_type = '';  
   }  
213    
214    // Add feed    // Add feed
215    if ($node_type) {    if (count($node_types) == 1) {
216      // Filter by node type is active      // Single node type was selected in filter
217      drupal_add_feed(url('recent_changes/feed/' . $node_type, null, null, true), t('recent changes of !site filtered by node type !node_type', array('!site' => variable_get('site_name', 'drupal'), '!node_type' => $node_type)));      drupal_add_feed(url('recent_changes/feed/' . $node_types[0], NULL, NULL, TRUE), t('Recent changes of !site filtered by content type !node_type', array('!site' => variable_get('site_name', 'drupal'), '!node_type' => $node_type_name = _recent_changes_node_type_name($node_types[0]))));
218    }    }
219    else {    else {
220      // No filtering      drupal_add_feed(url('recent_changes/feed', NULL, NULL, TRUE), t('Recent changes of !site', array('!site' => variable_get('site_name', 'drupal'))));
     drupal_add_feed(url('recent_changes/feed', null, null, true), t('recent changes of !site', array('!site' => variable_get('site_name', 'drupal'))));  
221    }    }
222    
223      // Show filter if enabled
224      $output .= (variable_get('recent_changes_show_filter', TRUE)) ? drupal_get_form('recent_changes_filter_form') : '';
225    
226    // Header for recent changes table.    // Header for recent changes table.
227    $header = array(    $header = array('', '', t('Type'), t('Title'), t('User'), t('Log'));
     '', // operations  
     '', // time  
     t('Type'),  
     t('Title'),  
     t('User'),  
     t('Log'),  
   );  
   $rows = array();  
228    
229    // Build SQL query depending on node type filter and comments filter.    // SQL results provided by pager implementation
230      list($sql, $count_sql) = _recent_changes_query($node_types, user_access('view revisions'));
231    // Query to get all revisions of the selected node types    $sql_results = pager_query($sql, variable_get('recent_changes_entries_per_page', 50), 0, $count_sql);
232    $revisions_query = recent_changes_revisions_query($node_type);  
233    if (module_exists('comment') && $show_comments) {    // put database results in $results
234      // Query to get all comments of the selected node types    $results = array();
235      $comments_query = recent_changes_comments_query($node_type);    while ($db_item = db_fetch_object($sql_results)) {
236      // Final query as a combination of node revisions and comments      $results[] = $db_item;
237      $sql = "($revisions_query) UNION ALL ($comments_query) ORDER BY timestamp DESC";    }
238      if ($node_type) {  
239        // Number of total nodes and comments if a specific node type is selected    // parse results into items
240        $count_sql = "SELECT (SELECT COUNT(*) FROM {node_revisions} r JOIN {node} n ON r.nid = n.nid WHERE n.type = '" . check_plain($node_type) . "') + (SELECT COUNT(*) FROM {comments} c LEFT JOIN {node} n ON c.nid = n.nid WHERE n.type = '" . check_plain($node_type) . "')";    $items = _recent_changes_parse_results($results);
241      }  
242      else {    foreach ($items as $item) {
       // Number of total nodes and comments if all node types are shown  
       $count_sql = "SELECT (SELECT COUNT(*) FROM {node_revisions}) + (SELECT COUNT(*) FROM {comments})";  
     }  
     // Check MySQL version  
     $version = db_version();  
     if ($GLOBALS['db_type'] == 'mysql' && version_compare($version, '4.1.0') < 0) {  
       // MySQL before 4.1.0 cannot execute the subqueries. Just ignore comments for total count.  
       if ($node_type) {  
         // Number of total node revisions if a specific node type is selected  
         $count_sql = "SELECT COUNT(*) FROM {node_revisions} r JOIN {node} n ON r.nid = n.nid WHERE n.type = '" . check_plain($node_type) . "'";  
       }  
       else {  
         // Number of total node revisions if all node types are shown  
         $count_sql = "SELECT COUNT(*) FROM {node_revisions}";  
       }  
     }  
   }  
   else {  
     // Query to select all node revisions  
     $sql = "$revisions_query ORDER BY timestamp DESC";  
     if ($node_type) {  
       // Number of total node revisions if a specific node type is selected  
       $count_sql = "SELECT COUNT(*) FROM {node_revisions} r JOIN {node} n ON r.nid = n.nid WHERE n.type = '" . check_plain($node_type) . "'";  
     }  
     else {  
       // Number of total node revisions if all node types are shown  
       $count_sql = "SELECT COUNT(*) FROM {node_revisions}";  
     }  
   }  
   
   // SQL result provided by pager implementation  
   $result = pager_query($sql, recent_changes_count_per_page(), 0, $count_sql);  
   
   $day = -1;  
   $has_revisions = array();  
   // List all results  
   while ($change = db_fetch_object($result)) {  
243      // Check if day of week changed and if yes output the new day.      // Check if day of week changed and if yes output the new day.
244      $current_day = format_date($change->timestamp, 'custom', 'z');      $current_day = format_date($item->timestamp, 'custom', 'z');
245      if ($day != $current_day) {      if ($day != $current_day) {
246        $day = $current_day;        $day = $current_day;
247        $rows[] = array(        $rows[] = array(
248          array(          array(
249            'data' => format_date($change->timestamp, 'custom', 'D, j F Y'),            'data' => format_date($item->timestamp, 'custom', 'D, j F Y'),
250            'colspan' => '6',            'colspan' => '6',
251            'class' => 'date'            'class' => 'date'
252          )          )
253        );        );
254      }      }
     // Comments have a non-zero 'cid', node revisions a non-zero 'vid'. Both have a 'nid'  
     $is_comment = ($change->cid != 0);  
     if ($is_comment) {  
       // Format the row if the change is a comment  
       $rows[] = array(  
         // Link to comment  
         l('(comment)', "node/$change->nid", null, null, "comment-$change->cid"),  
         // Time of submit  
         format_date($change->timestamp, 'custom', 'H:i'),  
         // Node type of comment's node  
         $change->type,  
         // Title of comment's node  
         l($change->title, "node/$change->nid"),  
         // User which submitted comment  
         theme('username', $change),  
         // Title of comment  
         filter_xss($change->log),  
       );  
     } else {  
       // Format the row if the change is a node revision  
   
       // Check if that node has any revisions at all and cache the result.  
       if (!isset($has_revisions[$change->nid])) {  
         $has_revisions[$change->nid] = db_result(db_query('SELECT COUNT(*) FROM {node_revisions} WHERE nid=%d', $change->nid)) > 1;  
       }  
255    
256        // Get the version and title of the previous revision      // Add the items
257        $old_node = db_fetch_object(db_query('SELECT vid, title FROM {node_revisions} WHERE nid=%d AND vid<%d ORDER BY vid DESC LIMIT 1', $change->nid, $change->vid));      $rows[] = array(
258          $item->op_link,
259        $operations = '';        format_date($item->timestamp, 'custom', 'H:i'),
260        // Add a link to the diff between the current version and the one before that.        $item->node_type_name,
261        if (module_exists('diff')) {        '<span class="change-flag">' . $item->flag . '</span> ' . call_user_func_array('l', array_merge(array($item->item_title), $item->link_array)) . (($item->item_title_add) ? '<br>'. $item->item_title_add : ''),
262          if ($old_node->vid) {        $item->user_link,
263            $operations .= l('(diff)', "node/$change->nid/revisions/view/$old_node->vid/$change->vid").'&nbsp;';        $item->log_text,
264          }      );
         else {  
           $operations = '(diff)&nbsp;';  
         }  
       }  
       // Add a link to the revisions history of the node.  
       if ($has_revisions[$change->nid]) {  
         $operations .= l('(hist)', "node/$change->nid/revisions");  
       }  
       else {  
         $operations .= '(hist)';  
       }  
   
       $special = '';  
       if ($old_node->vid == 0) {  
         // The node is new.  
         $special = '<span class="change-flag">new</span> ';  
       }  
       elseif ($old_node->title != $change->title) {  
         // The node title changed.  
         $special = '<span class="change-flag">moved</span> ';  
       }  
       $rows[] = array(  
         // Link to diff and history  
         $operations,  
         // Submit time  
         format_date($change->timestamp, 'custom', 'H:i'),  
         // Node type  
         $change->type,  
         // Title of node  
         $special . l($change->title, "node/$change->nid"),  
         // User which submitted node  
         theme('username', $change),  
         // Log message of revision  
         filter_xss($change->log),  
       );  
     }  
265    }    }
266    
267    // Print table and pager    // Print table and pager
268    $output .= theme('table', $header, $rows, array('class' => 'recent-changes'));    $output .= theme('table', $header, $rows, array('class' => 'recent-changes'));
269    $output .= theme('pager', NULL, recent_changes_count_per_page, 0);    $output .= theme('pager', NULL, variable_get('recent_changes_entries_per_page', 50), 0);
270      return($output);
   return $output;  
271  }  }
272    
 /**  
  * Form for input filter.  
  */  
 function recent_changes_filter_form() {  
   $form = array();  
   $form['#attributes'] = array('class' => 'inline');  
   // Enable/Disable comments in recent changes view  
   if (module_exists('comment')) {  
     $form['recent_changes_show_comments'] = array(  
       '#type' => 'checkbox',  
       '#title' => t('Show comments'),  
       '#default_value' => isset($_REQUEST['form_id']) ? isset($_REQUEST['recent_changes_show_comments']) : recent_changes_show_comments(),  
     );  
   }  
   // Filter node type of recent changes view  
   $node_types = array('' => 'all node types');  
   $node_types = array_merge($node_types, node_get_types('names'));  
   $form['recent_changes_show_node_type'] = array(  
     '#type' => 'select',  
     '#default_value' => isset($_REQUEST['recent_changes_show_node_type']) ? $_REQUEST['recent_changes_show_node_type'] : '',  
     '#options' => $node_types,  
   );  
   $form['submit'] = array(  
     '#type' => 'button',  
     '#value' => t('Filter')  
   );  
   return $form;  
 }  
273    
274  /**  /**
275   * RSS feed of recent changes.   * RSS feed of recent changes.
276   */   */
277  function recent_changes_feed($node_type = NULL) {  function recent_changes_feed($node_types = NULL) {
278    global $base_url;    global $base_url;
279    
280    // Query to get all revisions of the selected node types    $list_inaccess_content = variable_get('recent_changes_list_inacces_nodes_in_feeds', TRUE);
281    $revisions_query = recent_changes_revisions_query($node_type);    $node_types = ($list_inaccess_content) ? _recent_changes_array_node_types($node_types) : _recent_changes_parse_node_types($node_types);
282    if (module_exists('comment')) {    $show_access_denied_titles = variable_get('recent_changes_show_access_denied_titles', TRUE);
283      // Query to get all comments of the selected node types    $item_type = variable_get('recent_changes_feed_item_type', 'teaser');
284      $comments_query = recent_changes_comments_query($node_type);    $teaser = ($item_type == 'teaser');
285      // Final query as a combination of node revisions and comments    $load_revisions = user_access('view revisions') || variable_get('recent_changes_list_inacces_revisions_in_feeds', TRUE);
286      $sql = "($revisions_query) UNION ALL ($comments_query) ORDER BY timestamp DESC LIMIT %d";  
287      // perform sql query
288      list($sql, $count_sql) = _recent_changes_query($node_types, $load_revisions);
289      $sql_results = db_query($sql . " LIMIT %d", variable_get('recent_changes_feed_default_items', 10));
290    
291      // put database results in $results
292      $results = array();
293      while ($db_item = db_fetch_object($sql_results)) {
294        $results[] = $db_item;
295    }    }
   else {  
     $sql = "$revisions_query ORDER BY timestamp DESC LIMIT %d";  
   }  
   $result = db_query($sql, variable_get('feed_default_items', 10));  
296    
297    // Type of RSS feed: 'title', 'teaser', 'full'    // parse results into items
298    $item_length = variable_get('feed_item_length', 'teaser');    $items = _recent_changes_parse_results($results);
299    // Is node teaser displayed (only used if $item_length not 'title')  
300    $teaser = ($item_length == 'teaser') ? true : false;    // initialize
   // RSS namespace used  
301    $namespaces = array('xmlns:dc="http://purl.org/dc/elements/1.1/"');    $namespaces = array('xmlns:dc="http://purl.org/dc/elements/1.1/"');
302    // RSS text    $feed_output = '';
303    $items = '';  
304    while ($item = db_fetch_object($result)) {    foreach ($items as $item) {
     // Comments have a non-zero 'cid', node revisions a non-zero 'vid'. Both have a 'nid'  
305      $is_comment = ($item->cid != 0);      $is_comment = ($item->cid != 0);
306      if ($is_comment) {  
307        // Format comment for RSS: Comment title as item title, comment body as text      $text = '';
308        $comment = db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $item->cid));      $url = call_user_func_array('url', array_merge($item->url_array, array(TRUE)));
309        $title = '(' . $item->flag . ') ' . $item->node_type_name . ': ' . $item->item_title;
310        // RSS Title: title of comment with comment mark      $extra = array();
311        $title = t('Comment') . ': ' . $comment->subject;  
312        // RSS Link: Direct link to comment      // load node to check node access, and check access if the loaded node is an older revision
313        $link = url("node/$comment->nid", null, "comment-$comment->cid", 1);      $node = node_load($item->nid, $item->vid);
314        // Node title comment belongs to (used in feed body)      $node_access = node_access('view', $node) && ($item->is_current_revision || user_access('view revisions'));
315        $node_title = l($item->title,"node/$item->nid", null, null, null, 1);  
316        // User which submitted comment (used in feed body)      $prev_revision = ($item->prev_revision) ? node_load($item->nid, $item->prev_revision->vid) : NULL;
317        $username = ($comment->uid ? l($comment->name, "user/$comment->uid", null, null, null, 1) : $comment->name);      $prev_revision_access = ($prev_revision) ? (node_access('view', $prev_revision) && user_access('view revisions')) : FALSE;
318        // RSS body: has meta info about comment  
319        $item_text = '<p><em>' . t('Comment on !node_title from !user', array('!node_title' => $node_title, '!user' => $username)) . '</em></p><hr/>';      $load_diff = module_exists('diff') && variable_get('recent_changes_show_diff', TRUE) && !$is_comment && $prev_revision_access && ($item_type == 'fulltext');
320        if ($item_length != 'title') {      $load_node_text = $node_access && ($item_type != 'title') && !$load_diff;
321          // If not just titles are in RSS feeds, put the comment in RSS body  
322          $item_text .= check_markup($comment->comment, $comment->format);      // load node or comment body text
323        }      if ($load_node_text) {
324        // No extras here (like attachments or taxonomy)        if ($is_comment) {
325        $extra = array();          $body_text = $item->comment_text;
326      }          $teaser_text = node_teaser($body_text, $node->format);
327      else {          $node->body = check_markup($body_text, $node->format, FALSE);
328        // Format comment for RSS          $node->teaser = check_markup($teaser_text, $node->format, FALSE);
329        $node = node_load($item->nid, $item->vid);          $node->readmore = ($teaser && (strlen($teaser_text) < strlen($body_text)));
       // Select the older revision if available. Set flag accordingly  
       $old_entry = db_fetch_object(db_query('SELECT vid, timestamp FROM {node_revisions} WHERE nid = %d AND vid < %d ORDER BY vid DESC LIMIT 1', $item->nid, $item->vid));  
       if ($old_entry->vid) {  
         $old_node = node_load($node->nid, $old_entry->vid);  
         if ($old_node->title != $node->title) {  
           $flag = t('Moved');  
         }  
         else {  
           $flag = t('Edited');  
         }  
330        }        }
331        else {        else {
332            $flag = t('New');          $node = (node_hook($node, 'view')) ? node_invoke($node, 'view', $teaser, FALSE) : node_prepare($node, $teaser);
333            node_invoke_nodeapi($node, 'view', $teaser, FALSE);
334            $extra = node_invoke_nodeapi($node, 'rss item');
335        }        }
336        }
337    
338        // RSS title      // load diff
339        $title = $flag . ' ' . $node->type . ': ' . $node->title;      if($load_diff) {
340        // RSS link: link to node        $node->body = _recent_changes_get_diff($node, $prev_revision);
341        $link = url("node/$node->nid", null, null, 1);      }
   
       // RSS body  
       $item_text = '';  
       if ($old_entry->vid && module_exists('diff')) {  
         // If diff module exists, put a diff in the RSS feed  
         $item_text  = '<table style="width:100%">';  
         $item_text .= '<thead><tr><th></th><th>Revision of '. format_date($old_entry->timestamp) .'</th><th></th><th>Revision of '. format_date($item->timestamp) .'</th></tr></thead>';  
         $item_text .= _diff_table_body($old_node, $node);  
         $item_text .= '</table>';  
         // Replace css classes from diff with actual style elements since we cannot reference  
         // a css file from the rss feed.  
         $patterns = array(  
           '/class=["\']diff-section-title["\']/',  
           '/class=["\']diff-deletedline["\']/',  
           '/class=["\']diff-addedline["\']/',  
           '/class=["\']diff-context["\']/',  
           '/class=["\']diffchange["\']/',  
         );  
         $replacements = array(  
           'style="background-color: #f0f0ff;"',  
           'style="background-color: #ffa;width: 50%"',  
           'style="background-color: #afa;width: 50%"',  
           'style="background-color: #fafafa"',  
           'style="color: #f00;font-weight:bold"',  
         );  
         $item_text = preg_replace($patterns, $replacements, $item_text);  
         $item_text .= "<hr/>\n";  
       }  
342    
343        if ($item_length != 'title') {      // check access for content and title
344          // Load node to display in feed      if (!$node_access) {
345          if (node_hook($node, 'view')) {        $node->body = t('You are not authorized to access this item.');
346            $node = node_invoke($node, 'view', $teaser, false);        $node->teaser = t('You are not authorized to access this item.');
347          }        $title = ($show_access_denied_titles) ? $title : t('Access denied');
348          else {      }
           $node = node_prepare($node, $teaser);  
         }  
         // If only teaser is shown, add 'read more' link to feed  
         if ($teaser) {  
           $item_text .= $node->teaser;  
           if ($node->readmore) {  
             $item_text .= '<p>'. l(t('read more'), 'node/'. $node->nid, null, null, null, true) .'</p>';  
           }  
         }  
         else {  
           $item_text .= $node->body;  
         }  
       }  
349    
350        // RSS extras: load extras from node modules      // add additional info at the first line of the body text
351        $extra = node_invoke_nodeapi($node, 'rss item');      if (($item->item_title_add) && ($node_access || $show_access_denied_titles)) {
352          $text = '<p><em>' . (($is_comment) ? t('Comment') . ' ' . $item->item_title_add : ucfirst($item->item_title_add)) . '</em></p><hr/>';
353      }      }
354      // Put in normal extra information  
355        // set the body text
356        switch ($item_type) {
357          case 'fulltext':
358            $text .= $node->body;
359            break;
360          case 'teaser':
361            $text .= $node->teaser;
362            if ($node->readmore) {
363              $text .= '<p>'. l(t('read more'), 'node/'. $node->nid, NULL, NULL, ($is_comment) ? "comment-$item->cid" : NULL, TRUE) .'</p>';
364            }
365            break;
366          case 'title':
367            $text .= '';
368            break;
369        }
370    
371        // put in normal extra information
372      $extra = array_merge($extra,      $extra = array_merge($extra,
373        array(        array(
374          array('key' => 'pubDate', 'value' =>  date('r', $item->timestamp)),          array('key' => 'pubDate', 'value' =>  date('r', $item->timestamp)),
375          array('key' => 'dc:creator', 'value' => $item->name),          array('key' => 'dc:creator', 'value' => $item->user_name),
376          array('key' => 'guid', 'value' => $item->nid .' at '. $base_url . ($is_comment ? ' comment '.$item->cid : ' revision '.$item->vid), 'attributes' => array('isPermaLink' => 'false'))          array('key' => 'guid', 'value' => $item->nid .' at '. $base_url . (($is_comment) ? ' comment '.$item->cid : ' revision '.$item->vid), 'attributes' => array('isPermaLink' => 'false')),
377        )        )
378      );      );
379    
380        $feed_output .= format_rss_item($title, $url, $text, $extra);
381    
382        // Add namespaces
383      foreach ($extra as $element) {      foreach ($extra as $element) {
384        if ($element['namespace']) {        if ($element['namespace']) {
385          $namespaces = array_merge($namespaces, $element['namespace']);          $namespaces = array_merge($namespaces, $element['namespace']);
386        }        }
387      }      }
     // Add rss feed item to output  
     $items .= format_rss_item($title, $link, $item_text, $extra);  
388    }    }
389    
390    // RSS channel information    // RSS channel information
391      $single_node_type = count($node_types) == 1;
392      $filter_text = ($single_node_type) ? ' filtered by '. _recent_changes_node_type_name($node_types[0]) : '';
393    $channel = array(    $channel = array(
394      'version'     => '2.0',      'version'     => '2.0',
395      'link'        => $base_url,      'link'        => $base_url,
396        'title'       => variable_get('site_name', 'drupal') .' - ' . t('Recent changes') . $filter_text,
397      'description' => t('Recent changes of nodes and comments on %site', array('%site' => variable_get('site_name', 'drupal'))),      'description' => t('Recent changes of nodes and comments on %site', array('%site' => variable_get('site_name', 'drupal'))),
398      'language'    => $GLOBALS['locale'],      'language'    => $GLOBALS['locale'],
399    );    );
400    if ($node_type) {  
     $channel['title'] = variable_get('site_name', 'drupal') .' - ' . t('Recent changes filtered by !node_type', array('!node_type' => $node_type));  
   }  
   else {  
     $channel['title'] = variable_get('site_name', 'drupal') .' - ' . t('Recent changes');  
   }  
401    // Construct actual RSS feed text    // Construct actual RSS feed text
402    $output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";    $output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
403    $output .= "<rss version=\"". $channel["version"] . "\" xml:base=\"". $base_url ."\" ". implode(' ', $namespaces) .">\n";    $output .= "<rss version=\"". $channel["version"] . "\" xml:base=\"". $base_url ."\" ". implode(' ', $namespaces) .">\n";
404    $output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language']);    $output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $feed_output, $channel['language']);
405    $output .= "</rss>\n";    $output .= "</rss>\n";
406    
407    // Set MIME type in HTML header    // Set MIME type in HTML header
408    drupal_set_header('Content-Type: application/rss+xml; charset=utf-8');    drupal_set_header('Content-Type: application/rss+xml; charset=utf-8');
409    
410    // Print feed text    // Print feed text
411    print $output;    print $output;
412  }  }
413    
 /*  
  * Settings  
  */  
414    
415  /**  /**
416   * Number of entries per page.   * Parsing of recent changes results
417   */   */
418  function recent_changes_count_per_page($value = NULL) {  function _recent_changes_parse_results($results) {
419    if (is_null($value)) {    // initialize
420      return variable_get('recent_changes_entries_per_page', 50);    $has_revisions = array();
421      $nids = array();
422      $items = array();
423      $access_revisions = user_access('view revisions');
424      $exists_diff = module_exists('diff');
425    
426      // put node nids in the the nids array (needed for querying previous revisions on this page)
427      foreach ($results as $result) {
428        $nids[$result->nid] = TRUE;
429      }
430    
431      // get previous revisions
432      $all_node_nid = implode(", ", array_keys($nids, TRUE));
433      $where_nid = ($all_node_nid) ? "WHERE n.nid IN ($all_node_nid)" : "WHERE FALSE";
434      $revisions_result = db_query("SELECT n.nid, n.vid AS curr_vid, p.vid, p.title FROM {node_revisions} n LEFT JOIN {node_revisions} p ON ((n.nid = p.nid) AND (n.vid > p.vid)) $where_nid ORDER BY p.vid DESC");
435    
436      while ($revision = db_fetch_object($revisions_result)) {
437        $curr_vid = $revision->curr_vid;
438        if(is_null($revision->vid)) {
439          break;
440        }
441        $has_revisions[$revision->nid] = TRUE;
442        $prev_revisions[$curr_vid] = (!isset($prev_revisions[$curr_vid])) ? $revision : $prev_revisions[$curr_vid];
443    }    }
444    variable_set('recent_changes_entries_per_page', $value);  
445      // parse results
446      foreach ($results as $result) {
447        $is_comment = ($result->cid != 0);
448        $prev_revision = $prev_revisions[$result->vid];
449    
450        // the owner is the user specified in the {node} table (also called "author" in drupal terminology)
451        $owner_user->uid = $result->uid;
452        $owner_user->name = $result->name;
453    
454        // the active user is the user that performed the update, or posted the revision or comment
455        $active_user->uid = $result->auid;
456        $active_user->name = $result->aname;
457    
458        $is_current_revision = $result->vid == $result->cvid;
459        $show_revisions = $access_revisions && $has_revisions[$result->nid];
460        $show_diff_link = $prev_revision->vid && $exists_diff && $access_revisions;
461        $moved = !$is_comment && $prev_revision->vid && ($prev_revision->title !== $result->title);
462    
463        $flags = array(
464          'comment' => $is_comment,
465          'updated' => !$is_comment && !$prev_revision->vid && ($result->timestamp != $result->created),
466          'new' => !$is_comment && !$prev_revision->vid && ($result->timestamp == $result->created),
467          'revised' => !$is_comment && $prev_revision->vid && ($prev_revision->title === $result->title),
468          'moved' => $moved,
469        );
470    
471        $comment_link = l('(comment)', "node/$result->nid", NULL, NULL, "comment-$result->cid");
472        $operations = ($show_diff_link) ? l('(diff)', "node/$result->nid/revisions/view/$prev_revision->vid/$result->vid") : '(diff)';
473        $operations .= '&nbsp;'. (($show_revisions) ? l('(hist)', "node/$result->nid/revisions") : '(hist)');
474    
475        $result_title = ($is_comment) ? $result->subject : $result->title;
476        $result_link = array("node/$result->nid" . (($is_comment || $is_current_revision) ? '' : "/revisions/$result->vid/view"), NULL, NULL, ($is_comment) ? "comment-$result->cid" : NULL);
477        $result_url =  array("node/$result->nid" . (($is_comment || $is_current_revision) ? '' : "/revisions/$result->vid/view"), NULL, ($is_comment) ? "comment-$result->cid" : NULL);
478    
479        $owner_intro_text = ($moved && $access_revisions) ? ', ' . t('from') . ' ' : t('author') . ': ';
480        $result_title_add = ($moved && $access_revisions) ? t('source: ') . l($prev_revision->title, "node/$result->nid/revisions/$prev_revision->vid/view") : '';
481        $result_title_add .= (!$is_comment && ($result->uid != $result->auid)) ? $owner_intro_text . theme('username', $owner_user) : '';
482        $result_title_add .= ($is_comment) ? t('on') . ' ' . l($result->title, "node/$result->nid") . ' ' . t('from') . ' ' . theme('username', $owner_user) : '';
483    
484        $items[] = (object) array(
485          'is_current_revision' => $is_current_revision,
486          'cid' => $result->cid,
487          'nid' => $result->nid,
488          'vid' => $result->vid,
489          'prev_revision' => $prev_revision,
490          'op_link' => ($is_comment) ? $comment_link : $operations,
491          'timestamp' => $result->timestamp,
492          'node_type_name' => _recent_changes_node_type_name($result->type),
493          'flag' => t(array_search(TRUE, $flags)),
494          'item_title' => $result_title,
495          'link_array' => $result_link,
496          'url_array' => $result_url,
497          'item_title_add' => $result_title_add,
498          'user_link' => theme('username', $active_user),
499          'user_name' => $active_user->name,
500          'log_text' => filter_xss($result->log),
501          'comment_text' => $result->comment,
502        );
503      }
504    
505      return($items);
506    }
507    
508    
509    /**
510     * Build SQL query depending on node type filter and comments filter.
511     * Inaccessible node types should already have been filtered out by this stage.
512     * If the load_revisions is false, only the recent changes from the {node} table are used, otherwise older revisions might also show up if they were recently changed.
513    */
514    function _recent_changes_query($node_types, $load_revisions) {
515      // show comments
516      $comment_index = array_search('comment', $node_types);
517      $show_comments = (!is_bool($comment_index) && !is_null($comment_index));
518    
519      // if only comments is selected, show comments for all allowed node types
520      $comments_only = (count($node_types) == 1 && $node_types[0] === 'comment');
521      $node_types = $comments_only ? _recent_changes_parse_node_types() : $node_types;
522    
523      // construct node type query (note that leading and trailing single quotes (') need to be added later)
524      $where_type = implode("', '", $node_types);
525    
526      // construct where queries depending on whether the revision, node, or comment should be displayed
527      $node_where = ($where_type && !$comments_only && !$load_revisions) ? "WHERE n.type IN ('$where_type')" : "WHERE FALSE";
528      $revision_where = ($where_type && !$comments_only && $load_revisions) ? "WHERE n.type IN ('$where_type')" : "WHERE FALSE";
529      $comment_where = ($where_type && $show_comments) ? "WHERE n.type IN ('$where_type')" : "WHERE FALSE";
530    
531      // queries to get the selected nodes, comments and revisions for the selected node types
532      $nodes_query     = "SELECT n.nid, n.vid, n.vid AS cvid, n.uid, u.name, r.title, '' AS log, n.created,              r.timestamp, n.type, 0 AS cid, '' AS subject, '' AS comment, r.uid AS auid, a.name AS aname FROM {node} n LEFT JOIN {node_revisions} r ON n.vid = r.vid LEFT JOIN {users} u ON n.uid = u.uid LEFT JOIN {users} a ON r.uid = a.uid $node_where AND n.status >= 1";
533      $revisions_query = "SELECT r.nid, r.vid, n.vid AS cvid, n.uid, u.name, r.title, r.log,     n.created,              r.timestamp, n.type, 0 AS cid, '' AS subject, '' AS comment, r.uid AS auid, a.name AS aname FROM {node_revisions} r LEFT JOIN {node} n ON r.nid = n.nid LEFT JOIN {users} u ON n.uid = u.uid LEFT JOIN {users} a ON r.uid = a.uid $revision_where AND n.status >= 1";
534      $comments_query  = "SELECT c.nid, n.vid, n.vid AS cvid, n.uid, u.name, n.title, '' AS log, c.timestamp AS created, c.timestamp, n.type, c.cid,    c.subject,     c.comment,     c.uid AS auid, c.name AS aname FROM {comments} c LEFT JOIN {node} n ON c.nid = n.nid LEFT JOIN {users} u ON n.uid = u.uid $comment_where AND n.status >= 1";
535    
536      // counter queries
537      $node_count = "SELECT COUNT(*) FROM {node} n $node_where AND n.status >= 1";
538      $revision_count = "SELECT COUNT(*) FROM {node_revisions} r JOIN {node} n ON r.nid = n.nid $revision_where AND n.status >= 1";
539      $comment_count = "SELECT COUNT(*) FROM {comments} c LEFT JOIN {node} n ON c.nid = n.nid $comment_where AND n.status >= 1";
540    
541      // unify queries
542      $sql = "($nodes_query) UNION ALL ($revisions_query) UNION ALL ($comments_query) ORDER BY timestamp DESC";
543      $sql_count = "SELECT ($node_count) + ($revision_count) + ($comment_count)";
544    
545      return(array($sql, $sql_count));
546  }  }
547    
548    
549  /**  /**
550   * Is the filter form shown on the recent changes page?   * Form for input filter.
551   */   */
552  function recent_changes_show_filter($value = NULL) {  function recent_changes_filter_form() {
553    if (is_null($value)) {    $node_types = _recent_changes_parse_node_types();
554      return variable_get('recent_changes_show_filter', true);    $allow_multiple = variable_get('recent_changes_allow_multiple_filter', TRUE);
555      $default_value = ($_REQUEST['op'] === t('Filter')) ? $_REQUEST['recent_changes_filter_node_types'] : '';
556    
557      // get associative array with content types and human-friendly content names
558      $node_names = array();
559      foreach ($node_types AS $type) {
560        $node_names[$type] = _recent_changes_node_type_name($type);
561      }
562    
563      // content types have no weights, so we can safely sort them here
564      asort($node_names);
565    
566      // add "All content types" if only single selection is allowed
567      $node_names = ($allow_multiple) ? $node_names : array_merge(array(FALSE => t('All content types')), $node_names);
568    
569      $form = array();
570      $form['#attributes'] = array('class' => 'inline');
571    
572      $form['recent_changes_filter_node_types'] = array(
573        '#type' => 'select',
574        '#title' => t('Filter content type'),
575        '#default_value' => $default_value,
576        '#options' => $node_names,
577        '#multiple' => $allow_multiple,
578        '#size' => min(count($node_names), variable_get('recent_changes_type_select_size', 5)),
579      );
580    
581      $form['submit'] = array(
582        '#type' => 'button',
583        '#value' => t('Filter')
584      );
585    
586      return $form;
587    }
588    
589    
590    /*
591    * Interface with the diff module. Returns a table with the differences between $node and $prev_revision
592    */
593    function _recent_changes_get_diff($node, $prev_revision) {
594      $item_text  = '<table style="width:100%">';
595      $item_text .= '<thead><tr><th></th><th>Revision of '. format_date($prev_revision->revision_timestamp) .'</th><th></th><th>Revision of '. format_date($node->revision_timestamp) .'</th></tr></thead>';
596      $item_text .= _diff_table_body($prev_revision, $node);
597      $item_text .= '</table>';
598    
599      // Replace css classes from diff with actual style elements since we cannot reference a css file from the rss feed.
600      $patterns = array(
601        '/class=["\']diff-section-title["\']/',
602        '/class=["\']diff-deletedline["\']/',
603        '/class=["\']diff-addedline["\']/',
604        '/class=["\']diff-context["\']/',
605        '/class=["\']diffchange["\']/',
606      );
607    
608      $replacements = array(
609        'style="background-color: #f0f0ff;"',
610        'style="background-color: #ffa;width: 50%"',
611        'style="background-color: #afa;width: 50%"',
612        'style="background-color: #fafafa"',
613        'style="color: #f00;font-weight:bold"',
614      );
615    
616      $item_text = preg_replace($patterns, $replacements, $item_text);
617      $item_text .= "<hr/>\n";
618    
619      return($item_text);
620    }
621    
622    
623    /*
624    * Removes the node types to which the user has no access
625    */
626    function _recent_changes_access_check($node_types) {
627    
628      // Check for each node type (and comments) whether current user has 'view' access to it
629      foreach ($node_types as $key=>$type) {
630        $access = FALSE;
631        if ($type == 'comment') {
632          $access = module_exists('comment') && user_access('access comments');
633        }
634        else {
635          $module = node_get_types('module', $type);
636          if ($module == 'node') {
637            $access = user_access('access content');
638          }
639          else {
640            // this would be the right way to implement access checks, but unfortunately most modules don't implement it
641            $access = module_invoke($module, 'access', 'view', NULL);
642    
643            // If $access is empty, we try it another way:
644            // First we request all possible permissions, then we check the first one with the word 'access' in it with the user_access command. If there is no permission with the word access in it, user_access('access content') is used. This works most of the time.
645            if (is_null($access)) {
646              $perms = module_invoke($module, 'perm');
647              $pattern = "/(?m)^access.*$/";
648              preg_match($pattern, ((empty($perms)) ? '' : implode("\n", $perms)), $matches);
649              $selected_perm = (empty($matches)) ? 'access content' : $matches[0];
650              $access = user_access($selected_perm);
651            }
652          }
653        }
654    
655        // If the user has no access, remove the content type from the list
656        if (!$access) {
657          unset($node_types[$key]);
658        }
659    }    }
660    variable_set('recent_changes_show_filter', $value);  
661      return($node_types);
662  }  }
663    
664    
665  /**  /**
666   * Are comments shown by default?   * Return allowed node types, including a 'comments' option
667   */   */
668  function recent_changes_show_comments($value = NULL) {  function _recent_changes_get_allowed_node_types() {
669    if (is_null($value)) {    $allowed_node_types = variable_get('recent_changes_allowed_node_types', array());
670      return variable_get('recent_changes_show_comments', true);    $allowed_node_types = ($allowed_node_types) ? $allowed_node_types : array_keys(node_get_types('names'));
671    }  
672    variable_set('recent_changes_show_comments', $value);    // add comments option
673      $allowed_node_types = (variable_get('recent_changes_show_comments', TRUE)) ? array_merge(array('comment'), $allowed_node_types) : $allowed_node_types;
674    
675      return $allowed_node_types;
676  }  }
677    
678    
679  /**  /**
680   * SQL query for all node revisions.   * Parse (and cache) node types, and perform access check
681   */   */
682  function recent_changes_revisions_query($node_type = NULL) {  function _recent_changes_parse_node_types($node_types = NULL) {
683    $result = 'SELECT n.type, r.nid, r.vid, 0 AS cid, r.title, r.timestamp, r.log, r.uid, u.name FROM {node_revisions} r LEFT JOIN {node} n ON r.nid = n.nid LEFT JOIN {users} u ON r.uid = u.uid';    // do some caching in case node_types is NULL
684    // Change for query if access right restrictions apply    static $all_parsed_node_types;
685    list($join, $where, $distinct) = _db_rewrite_sql($result, 'r', 'nid');  
686    if ($node_type) {    $parse_all_node_types = is_null($node_types);
687      // Filter on node type  
688      $where .= " AND n.type = '" . check_plain($node_type) . "'";    // return cached version if available
689    }    if ($parse_all_node_types && isset($all_parsed_node_types)) {
690    if ($join) {      return $all_parsed_node_types;
     $result .= ' ' . $join;  
691    }    }
692    if ($where) {  
693      $result .= ' WHERE ' . $where;    // put content types in an array, and use allowed_content_types if node_types was empty
694      $node_types = _recent_changes_array_node_types($node_types);
695    
696      // perform access check
697      $node_types = _recent_changes_access_check($node_types);
698    
699      // cache all parsed node types if all node types were requested
700      if ($parse_all_node_types) {
701        $all_parsed_node_types = $node_types;
702    }    }
703    return $result;  
704      return($node_types);
705  }  }
706    
707    
708  /**  /**
709   * SQL query for all comments.   * Given an array or of node types or a single node type, this function returns the node types that are also in allowed node types
710     * If the input argument $node_types is NULL, all allowed node types are returned
711     * Note that no access checking is performed here!
712   */   */
713  function recent_changes_comments_query($node_type = NULL) {  function _recent_changes_array_node_types($node_types = NULL) {
714    $result = 'SELECT n.type, c.nid, 0 AS vid, c.cid, n.title, c.timestamp, c.subject AS log, c.uid, c.name FROM {comments} c LEFT JOIN {node} n ON c.nid = n.nid';    $allowed_node_types = _recent_changes_get_allowed_node_types();
715    list($join, $where, $distinct) = _db_rewrite_sql($result, 'c', 'nid');  
716    if ($node_type) {    // in case $node_types is empty ('All content types' was selected), set it to all allowed node types
717      $where .= " AND n.type = '" . check_plain($node_type) . "'";    $node_types = ($node_types) ? $node_types : $allowed_node_types;
718    }  
719    if ($join) {    // in case $node_types is a single node type (single selection), put it in an array
720      $result .= ' ' . $join;    $node_types = (is_array($node_types)) ? $node_types : array($node_types);
721    }  
722    if ($where) {    // check whether the $node_types are actually in $allowed_node types, and make sure the key starts at index 0 (with array_values)
723      $result .= ' WHERE ' . $where;    $node_types = array_values(array_intersect($node_types, $allowed_node_types));
724    }  
725    return $result;    return($node_types);
726  }  }
727    
728    /**
729     * Returns the node type name, given the node type, and handles 'comment' as a special case because 'comment' is not an actual node type
730     */
731    function _recent_changes_node_type_name($type) {
732      $node_type_name = ($type === 'comment') ? t('Comment') : node_get_types('name', $type);
733      return $node_type_name;
734    }
735    
736    // query that returns which nodes have more than one revision
737    //$revisions_result = db_query("SELECT nid, COUNT(vid) AS num FROM {node_revisions} GROUP BY nid HAVING (COUNT(nid) > 1)");
738    //while ($has_revision_nid = db_fetch_object($revisions_result)) {
739    //  $has_revisions[$has_revision_nid->nid] = TRUE;
740    //}
741    
742    ?>

Legend:
Removed from v.1.1.2.4  
changed lines
  Added in v.1.1.2.5

  ViewVC Help
Powered by ViewVC 1.1.2