/[drupal]/drupal/modules/node.module
ViewVC logotype

Diff of /drupal/modules/node.module

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

revision 1.641, Thu Apr 27 22:20:51 2006 UTC revision 1.641.2.31, Thu Jan 4 20:50:02 2007 UTC
# Line 1  Line 1 
1  <?php  <?php
2  // $Id: node.module,v 1.640 2006/04/23 05:22:05 drumm Exp $  // $Id: node.module,v 1.641.2.30 2007/01/04 19:50:28 killes Exp $
3    
4  /**  /**
5   * @file   * @file
# Line 43  function node_help($section) { Line 43  function node_help($section) {
43        return t('<p>Enter a simple pattern to search for a post. This can include the wildcard character *.<br />For example, a search for "br*" might return "bread bakers", "our daily bread" and "brenda".</p>');        return t('<p>Enter a simple pattern to search for a post. This can include the wildcard character *.<br />For example, a search for "br*" might return "bread bakers", "our daily bread" and "brenda".</p>');
44    }    }
45    
46    if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'revisions') {    if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'revisions' && !arg(3)) {
47      return t('The revisions let you track differences between multiple versions of a post.');      return t('The revisions let you track differences between multiple versions of a post.');
48    }    }
49    
# Line 160  function node_teaser($body, $format = NU Line 160  function node_teaser($body, $format = NU
160      return $body;      return $body;
161    }    }
162    
163      // If a valid delimiter has been specified, use it to chop off the teaser.
164      if ($delimiter !== FALSE) {
165        return substr($body, 0, $delimiter);
166      }
167    
168    // We check for the presence of the PHP evaluator filter in the current    // We check for the presence of the PHP evaluator filter in the current
169    // format. If the body contains PHP code, we do not split it up to prevent    // format. If the body contains PHP code, we do not split it up to prevent
170    // parse errors.    // parse errors.
# Line 170  function node_teaser($body, $format = NU Line 175  function node_teaser($body, $format = NU
175      }      }
176    }    }
177    
   // If a valid delimiter has been specified, use it to chop of the teaser.  
   if ($delimiter !== FALSE) {  
     return substr($body, 0, $delimiter);  
   }  
   
178    // If we have a short body, the entire body is the teaser.    // If we have a short body, the entire body is the teaser.
179    if (strlen($body) < $size) {    if (strlen($body) < $size) {
180      return $body;      return $body;
181    }    }
182    
183    // In some cases, no delimiter has been specified (e.g. when posting using    // The teaser may not be longer than maximum length specified. Initial slice.
184    // the Blogger API). In this case, we try to split at paragraph boundaries.    $teaser = truncate_utf8($body, $size);
185    // When even the first paragraph is too long, we try to split at the end of    $position = 0;
186    // the next sentence.    // Cache the reverse of the teaser.
187    $breakpoints = array('</p>' => 4, '<br />' => 0, '<br>' => 0, "\n" => 0, '. ' => 1, '! ' => 1, '? ' => 1, '。' => 3, '؟ ' => 1);    $reversed = strrev($teaser);
188    foreach ($breakpoints as $point => $charnum) {  
189      if ($length = strpos($body, $point, $size)) {    // In some cases, no delimiter has been specified. In this case, we try to
190        return substr($body, 0, $length + $charnum);    // split at paragraph boundaries.
191      $breakpoints = array('</p>' => 0, '<br />' => 6, '<br>' => 4, "\n" => 1);
192      // We use strpos on the reversed needle and haystack for speed.
193      foreach ($breakpoints as $point => $offset) {
194        $length = strpos($reversed, strrev($point));
195        if ($length !== FALSE) {
196          $position = - $length - $offset;
197          return ($position == 0) ? $teaser : substr($teaser, 0, $position);
198      }      }
199    }    }
200    
201    // If all else fails, we simply truncate the string.    // When even the first paragraph is too long, we try to split at the end of
202    return truncate_utf8($body, $size);    // the last full sentence.
203      $breakpoints = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);
204      $min_length = strlen($reversed);
205      foreach ($breakpoints as $point => $offset) {
206        $length = strpos($reversed, strrev($point));
207        if ($length !== FALSE) {
208          $min_length = min($length, $min_length);
209          $position = 0 - $length - $offset;
210        }
211      }
212      return ($position == 0) ? $teaser : substr($teaser, 0, $position);
213  }  }
214    
215  function _node_names($op = '', $node = NULL) {  function _node_names($op = '', $node = NULL) {
# Line 256  function node_get_name($node) { Line 273  function node_get_name($node) {
273  /**  /**
274   * Return the list of available node types.   * Return the list of available node types.
275   *   *
  * @param $node  
  *   Either a node object, a node array, or a string containing the node type.  
276   * @return   * @return
277   *   An array consisting ('#type' => name) pairs.   *   An array consisting ('#type' => name) pairs.
278   */   */
# Line 345  function node_load($param = array(), $re Line 360  function node_load($param = array(), $re
360      $nodes = array();      $nodes = array();
361    }    }
362    
363      $cachable = ($revision == NULL);
364    $arguments = array();    $arguments = array();
365    if (is_numeric($param)) {    if (is_numeric($param)) {
     $cachable = $revision == NULL;  
366      if ($cachable && isset($nodes[$param])) {      if ($cachable && isset($nodes[$param])) {
367        return $nodes[$param];        return is_object($nodes[$param]) ? drupal_clone($nodes[$param]) : $nodes[$param];
368      }      }
369      $cond = 'n.nid = %d';      $cond = 'n.nid = %d';
370      $arguments[] = $param;      $arguments[] = $param;
# Line 364  function node_load($param = array(), $re Line 379  function node_load($param = array(), $re
379    }    }
380    
381    // Retrieve the node.    // Retrieve the node.
382      // No db_rewrite_sql is applied so as to get complete indexing for search.
383    if ($revision) {    if ($revision) {
384      array_unshift($arguments, $revision);      array_unshift($arguments, $revision);
385      $node = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, r.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.moderate, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.nid = n.nid AND r.vid = %d WHERE '. $cond), $arguments));      $node = db_fetch_object(db_query('SELECT n.nid, r.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.moderate, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.nid = n.nid AND r.vid = %d WHERE '. $cond, $arguments));
386    }    }
387    else {    else {
388      $node = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.moderate, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE '. $cond), $arguments));      $node = db_fetch_object(db_query('SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.moderate, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE '. $cond, $arguments));
389    }    }
390    
391    if ($node->nid) {    if ($node->nid) {
# Line 386  function node_load($param = array(), $re Line 402  function node_load($param = array(), $re
402          $node->$key = $value;          $node->$key = $value;
403        }        }
404      }      }
405    }      if ($cachable) {
406          $nodes[$node->nid] = is_object($node) ? drupal_clone($node) : $node;
407    if ($cachable) {      }
     $nodes[$param] = $node;  
408    }    }
409    
410    return $node;    return $node;
# Line 660  function node_search($op = 'search', $ke Line 675  function node_search($op = 'search', $ke
675        $ranking = array();        $ranking = array();
676        $arguments2 = array();        $arguments2 = array();
677        $join2 = '';        $join2 = '';
678          $total = 0;
679        // Used to avoid joining on node_comment_statistics twice        // Used to avoid joining on node_comment_statistics twice
680        $stats_join = false;        $stats_join = false;
681        if ($weight = (int)variable_get('node_rank_relevance', 5)) {        if ($weight = (int)variable_get('node_rank_relevance', 5)) {
682          // Average relevance values hover around 0.15          // Average relevance values hover around 0.15
683          $ranking[] = '%d * i.relevance';          $ranking[] = '%d * i.relevance';
684          $arguments2[] = $weight;          $arguments2[] = $weight;
685            $total += $weight;
686        }        }
687        if ($weight = (int)variable_get('node_rank_recent', 5)) {        if ($weight = (int)variable_get('node_rank_recent', 5)) {
688          // Exponential decay with half-life of 6 months, starting at last indexed node          // Exponential decay with half-life of 6 months, starting at last indexed node
# Line 674  function node_search($op = 'search', $ke Line 691  function node_search($op = 'search', $ke
691          $arguments2[] = (int)variable_get('node_cron_last', 0);          $arguments2[] = (int)variable_get('node_cron_last', 0);
692          $join2 .= ' INNER JOIN {node} n ON n.nid = i.sid LEFT JOIN {node_comment_statistics} c ON c.nid = i.sid';          $join2 .= ' INNER JOIN {node} n ON n.nid = i.sid LEFT JOIN {node_comment_statistics} c ON c.nid = i.sid';
693          $stats_join = true;          $stats_join = true;
694            $total += $weight;
695        }        }
696        if (module_exist('comment') && $weight = (int)variable_get('node_rank_comments', 5)) {        if (module_exist('comment') && $weight = (int)variable_get('node_rank_comments', 5)) {
697          // Inverse law that maps the highest reply count on the site to 1 and 0 to 0.          // Inverse law that maps the highest reply count on the site to 1 and 0 to 0.
# Line 684  function node_search($op = 'search', $ke Line 702  function node_search($op = 'search', $ke
702          if (!$stats_join) {          if (!$stats_join) {
703            $join2 .= ' LEFT JOIN {node_comment_statistics} c ON c.nid = i.sid';            $join2 .= ' LEFT JOIN {node_comment_statistics} c ON c.nid = i.sid';
704          }          }
705            $total += $weight;
706        }        }
707        if (module_exist('statistics') && variable_get('statistics_count_content_views', 0) &&        if (module_exist('statistics') && variable_get('statistics_count_content_views', 0) &&
708            $weight = (int)variable_get('node_rank_views', 5)) {            $weight = (int)variable_get('node_rank_views', 5)) {
# Line 693  function node_search($op = 'search', $ke Line 712  function node_search($op = 'search', $ke
712          $arguments2[] = $weight;          $arguments2[] = $weight;
713          $arguments2[] = $scale;          $arguments2[] = $scale;
714          $join2 .= ' LEFT JOIN {node_counter} nc ON nc.nid = i.sid';          $join2 .= ' LEFT JOIN {node_counter} nc ON nc.nid = i.sid';
715            $total += $weight;
716        }        }
717        $select2 = (count($ranking) ? implode(' + ', $ranking) : 'i.relevance') . ' AS score';        $select2 = (count($ranking) ? implode(' + ', $ranking) : 'i.relevance') . ' AS score';
718    
# Line 727  function node_search($op = 'search', $ke Line 747  function node_search($op = 'search', $ke
747                             'date' => $node->changed,                             'date' => $node->changed,
748                             'node' => $node,                             'node' => $node,
749                             'extra' => $extra,                             'extra' => $extra,
750                               'score' => $item->score / $total,
751                             'snippet' => search_excerpt($keys, $node->body));                             'snippet' => search_excerpt($keys, $node->body));
752        }        }
753        return $results;        return $results;
# Line 805  function node_link($type, $node = 0, $ma Line 826  function node_link($type, $node = 0, $ma
826    $links = array();    $links = array();
827    
828    if ($type == 'node') {    if ($type == 'node') {
     if (array_key_exists('links', $node)) {  
       $links = $node->links;  
     }  
   
829      if ($main == 1 && $node->teaser && $node->readmore) {      if ($main == 1 && $node->teaser && $node->readmore) {
830        $links[] = l(t('read more'), "node/$node->nid", array('title' => t('Read the rest of this posting.'), 'class' => 'read-more'));        $links[] = l(t('read more'), "node/$node->nid", array('title' => t('Read the rest of this posting.'), 'class' => 'read-more'));
831      }      }
# Line 847  function node_menu($may_cache) { Line 864  function node_menu($may_cache) {
864      $items[] = array('path' => 'node', 'title' => t('content'),      $items[] = array('path' => 'node', 'title' => t('content'),
865        'callback' => 'node_page',        'callback' => 'node_page',
866        'access' => user_access('access content'),        'access' => user_access('access content'),
867        'type' => MENU_SUGGESTED_ITEM);        'type' => MENU_MODIFIABLE_BY_ADMIN);
868      $items[] = array('path' => 'node/add', 'title' => t('create content'),      $items[] = array('path' => 'node/add', 'title' => t('create content'),
869        'callback' => 'node_page',        'callback' => 'node_page',
870        'access' => user_access('access content'),        'access' => user_access('access content'),
# Line 884  function node_menu($may_cache) { Line 901  function node_menu($may_cache) {
901            'access' => $revisions_access,            'access' => $revisions_access,
902            'weight' => 2,            'weight' => 2,
903            'type' => MENU_LOCAL_TASK);            'type' => MENU_LOCAL_TASK);
904            $items[] = array('path' => 'node/'. arg(1) .'/revisions/' . arg(3) . '/delete',
905              'title' => t('revisions'),
906              'callback' => 'node_revisions',
907              'access' => $revisions_access,
908              'weight' => 2,
909              'type' => MENU_CALLBACK);
910            $items[] = array('path' => 'node/'. arg(1) .'/revisions/' . arg(3) . '/revert',
911              'title' => t('revisions'),
912              'callback' => 'node_revisions',
913              'access' => $revisions_access,
914              'weight' => 2,
915              'type' => MENU_CALLBACK);
916        }        }
917      }      }
918      else if (arg(0) == 'admin' && arg(1) == 'settings' && arg(2) == 'content-types' && is_string(arg(3))) {      else if (arg(0) == 'admin' && arg(1) == 'settings' && arg(2) == 'content-types' && is_string(arg(3))) {
# Line 907  function node_last_changed($nid) { Line 936  function node_last_changed($nid) {
936  function node_operations() {  function node_operations() {
937    $operations = array(    $operations = array(
938      'approve' =>   array(t('Approve the selected posts'), 'UPDATE {node} SET status = 1, moderate = 0 WHERE nid = %d'),      'approve' =>   array(t('Approve the selected posts'), 'UPDATE {node} SET status = 1, moderate = 0 WHERE nid = %d'),
939      'promote' =>   array(t('Promote the selected posts'), 'UPDATE {node} SET status = 1, promote = 1 WHERE nid = %d'),      'promote' =>   array(t('Promote the selected posts'), 'UPDATE {node} SET status = 1, promote = 1, moderate = 0 WHERE nid = %d'),
940      'sticky' =>    array(t('Make the selected posts sticky'), 'UPDATE {node} SET status = 1, sticky = 1 WHERE nid = %d'),      'sticky' =>    array(t('Make the selected posts sticky'), 'UPDATE {node} SET status = 1, sticky = 1 WHERE nid = %d'),
941      'demote' =>    array(t('Demote the selected posts'), 'UPDATE {node} SET promote = 0 WHERE nid = %d'),      'demote' =>    array(t('Demote the selected posts'), 'UPDATE {node} SET promote = 0 WHERE nid = %d'),
942      'unpublish' => array(t('Unpublish the selected posts'), 'UPDATE {node} SET status = 0 WHERE nid = %d'),      'unpublish' => array(t('Unpublish the selected posts'), 'UPDATE {node} SET status = 0 WHERE nid = %d'),
# Line 1094  function node_admin_nodes_submit($form_i Line 1123  function node_admin_nodes_submit($form_i
1123          db_query($operation, $nid);          db_query($operation, $nid);
1124        }        }
1125      }      }
1126        cache_clear_all();
1127      drupal_set_message(t('The update has been performed.'));      drupal_set_message(t('The update has been performed.'));
1128    }    }
1129  }  }
# Line 1307  function node_revision_revert($nid, $rev Line 1337  function node_revision_revert($nid, $rev
1337    $node = node_load($nid, $revision);    $node = node_load($nid, $revision);
1338    if ((user_access('revert revisions') || user_access('administer nodes')) && node_access('update', $node)) {    if ((user_access('revert revisions') || user_access('administer nodes')) && node_access('update', $node)) {
1339      if ($node->vid) {      if ($node->vid) {
1340        $node->revision = 1;        $form = array();
1341        $node->log = t('Copy of the revision from %date.', array('%date' => theme('placeholder', format_date($node->revision_timestamp))));        $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
1342        $node->taxonomy = array_keys($node->taxonomy);        $form['vid'] = array('#type' => 'value', '#value' => $node->vid);
1343          return confirm_form('node_revision_revert_confirm', $form,
1344        node_save($node);                       t('Are you sure you want to revert %title to the revision from %revision-date?', array('%title' => theme('placeholder', $node->title), '%revision-date' => theme('placeholder', format_date($node->revision_timestamp)))),
1345                         "node/$nid/revisions", ' ', t('Revert'), t('Cancel'));
       drupal_set_message(t('%title has been reverted back to the revision from %revision-date', array('%revision-date' => theme('placeholder', format_date($node->revision_timestamp)), '%title' => theme('placeholder', check_plain($node->title)))));  
       watchdog('content', t('%type: reverted %title revision %revision.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title), '%revision' => theme('placeholder', $revision))));  
1346      }      }
1347      else {      else {
1348        drupal_set_message(t('You tried to revert to an invalid revision.'), 'error');        drupal_set_message(t('You tried to revert to an invalid revision.'), 'error');
# Line 1324  function node_revision_revert($nid, $rev Line 1352  function node_revision_revert($nid, $rev
1352    drupal_access_denied();    drupal_access_denied();
1353  }  }
1354    
1355    function node_revision_revert_confirm_submit($form_id, $form_values) {
1356      $nid = $form_values['nid'];
1357      $revision = $form_values['vid'];
1358      $node = node_load($nid, $revision);
1359      $node->revision = 1;
1360      $node->log = t('Copy of the revision from %date.', array('%date' => theme('placeholder', format_date($node->revision_timestamp))));
1361      if (module_exist('taxonomy')) {
1362        $node->taxonomy = array_keys($node->taxonomy);
1363      }
1364    
1365      node_save($node);
1366      drupal_set_message(t('%title has been reverted back to the revision from %revision-date', array('%revision-date' => theme('placeholder', format_date($node->revision_timestamp)), '%title' => theme('placeholder', check_plain($node->title)))));
1367      watchdog('content', t('%type: reverted %title revision %revision.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title), '%revision' => theme('placeholder', $revision))));
1368      return 'node/'. $nid .'/revisions';
1369    }
1370    
1371  /**  /**
1372   * Delete the revision with specified revision number. A "delete revision" nodeapi event is invoked when a   * Delete the revision with specified revision number. A "delete revision" nodeapi event is invoked when a
1373   * revision is deleted.   * revision is deleted.
# Line 1335  function node_revision_delete($nid, $rev Line 1379  function node_revision_delete($nid, $rev
1379        // Don't delete the current revision        // Don't delete the current revision
1380        if ($revision != $node->vid) {        if ($revision != $node->vid) {
1381          $node = node_load($nid, $revision);          $node = node_load($nid, $revision);
1382            $form = array();
1383          db_query("DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $nid, $revision);          $form['nid'] = array('#type' => 'value', '#value' => $nid);
1384          node_invoke_nodeapi($node, 'delete revision');          $form['vid'] = array('#type' => 'value', '#value' => $revision);
1385          drupal_set_message(t('Deleted %title revision %revision.', array('%title' => theme('placeholder', $node->title), '%revision' => theme('placeholder', $revision))));          return confirm_form('node_revision_delete_confirm', $form,
1386          watchdog('content', t('%type: deleted %title revision %revision.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title), '%revision' => theme('placeholder', $revision))));                       t('Are you sure you want to delete %title revision %revision?', array('%title' => theme('placeholder', $node->title), '%revision' => theme('placeholder', $revision))),
1387                         "node/$nid/revisions", '', t('Delete'), t('Cancel'));
1388        }        }
   
1389        else {        else {
1390          drupal_set_message(t('Deletion failed. You tried to delete the current revision.'));          drupal_set_message(t('Deletion failed. You tried to delete the current revision.'));
1391        }        }
# Line 1353  function node_revision_delete($nid, $rev Line 1397  function node_revision_delete($nid, $rev
1397        }        }
1398      }      }
1399    }    }
   
1400    drupal_access_denied();    drupal_access_denied();
1401  }  }
1402    
1403    function node_revision_delete_confirm_submit($form_id, $form_values) {
1404      $node = node_load($form_values['nid'], $form_values['vid']);
1405      db_query("DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $node->nid, $node->vid);
1406      node_invoke_nodeapi($node, 'delete revision');
1407      drupal_set_message(t('Deleted %title revision %revision.', array('%title' => theme('placeholder', $node->title), '%revision' => theme('placeholder', $node->vid))));
1408      watchdog('content', t('%type: deleted %title revision %revision.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title), '%revision' => theme('placeholder', $node->revision))));
1409    
1410      if (db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', $node->nid)) > 1) {
1411        return "node/$node->nid/revisions";
1412      }
1413      return "node/$node->nid";
1414    }
1415    
1416  /**  /**
1417   * Return a list of all the existing revision numbers.   * Return a list of all the existing revision numbers.
1418   */   */
# Line 1404  function node_feed($nodes = 0, $channel Line 1460  function node_feed($nodes = 0, $channel
1460    global $base_url, $locale;    global $base_url, $locale;
1461    
1462    if (!$nodes) {    if (!$nodes) {
1463      $nodes = db_query_range(db_rewrite_sql('SELECT n.nid FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.created DESC'), 0, variable_get('feed_default_items', 10));      $nodes = db_query_range(db_rewrite_sql('SELECT n.nid, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.created DESC'), 0, variable_get('feed_default_items', 10));
1464    }    }
1465    
1466    $item_length = variable_get('feed_item_length', 'teaser');    $item_length = variable_get('feed_item_length', 'teaser');
# Line 1430  function node_feed($nodes = 0, $channel Line 1486  function node_feed($nodes = 0, $channel
1486        node_invoke_nodeapi($item, 'view', $teaser, FALSE);        node_invoke_nodeapi($item, 'view', $teaser, FALSE);
1487      }      }
1488    
1489        // Allow modules to add additional item fields
1490        $extra = node_invoke_nodeapi($item, 'rss item');
1491        $extra = array_merge($extra, array(array('key' => 'pubDate', 'value' =>  date('r', $item->created)), array('key' => 'dc:creator', 'value' => $item->name), array('key' => 'guid', 'value' => $item->nid . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false'))));
1492        foreach ($extra as $element) {
1493          if ($element['namespace']) {
1494            $namespaces = array_merge($namespaces, $element['namespace']);
1495          }
1496        }
1497    
1498      // Prepare the item description      // Prepare the item description
1499      switch ($item_length) {      switch ($item_length) {
1500        case 'fulltext':        case 'fulltext':
# Line 1446  function node_feed($nodes = 0, $channel Line 1511  function node_feed($nodes = 0, $channel
1511          break;          break;
1512      }      }
1513    
     // Allow modules to add additional item fields  
     $extra = node_invoke_nodeapi($item, 'rss item');  
     $extra = array_merge($extra, array(array('key' => 'pubDate', 'value' =>  date('r', $item->created)), array('key' => 'dc:creator', 'value' => $item->name), array('key' => 'guid', 'value' => $item->nid . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false'))));  
     foreach ($extra as $element) {  
       if ($element['namespace']) {  
         $namespaces = array_merge($namespaces, $element['namespace']);  
       }  
     }  
1514      $items .= format_rss_item($item->title, $link, $item_text, $extra);      $items .= format_rss_item($item->title, $link, $item_text, $extra);
1515    }    }
1516    
# Line 1471  function node_feed($nodes = 0, $channel Line 1528  function node_feed($nodes = 0, $channel
1528    $output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language']);    $output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language']);
1529    $output .= "</rss>\n";    $output .= "</rss>\n";
1530    
1531    drupal_set_header('Content-Type: text/xml; charset=utf-8');    drupal_set_header('Content-Type: application/rss+xml; charset=utf-8');
1532    print $output;    print $output;
1533  }  }
1534    
# Line 1533  function node_validate($node, $form = ar Line 1590  function node_validate($node, $form = ar
1590    }    }
1591    
1592    if (isset($node->nid) && (node_last_changed($node->nid) > $node->changed)) {    if (isset($node->nid) && (node_last_changed($node->nid) > $node->changed)) {
1593      form_set_error('changed', t('This content has been modified by another user; changes cannot be saved.'));      form_set_error('changed', t('This content has been modified by another user, changes cannot be saved.'));
1594    }    }
1595    
1596    if (user_access('administer nodes')) {    if (user_access('administer nodes')) {
# Line 1597  function node_form_array($node) { Line 1654  function node_form_array($node) {
1654     * Basic node information.     * Basic node information.
1655     * These elements are just values so they are not even sent to the client.     * These elements are just values so they are not even sent to the client.
1656     */     */
1657    foreach (array('nid', 'vid', 'uid', 'created', 'changed', 'type') as $key) {    foreach (array('nid', 'vid', 'uid', 'created', 'type') as $key) {
1658      $form[$key] = array('#type' => 'value', '#value' => $node->$key);      $form[$key] = array('#type' => 'value', '#value' => $node->$key);
1659    }    }
1660    
1661      // Changed must be sent to the client, for later overwrite error checking.
1662      $form['changed'] = array('#type' => 'hidden', '#default_value' => $node->changed);
1663    
1664    // Get the node-specific bits.    // Get the node-specific bits.
1665    $form = array_merge_recursive($form, node_invoke($node, 'form'));    $form = array_merge_recursive($form, node_invoke($node, 'form'));
1666    if (!isset($form['title']['#weight'])) {    if (!isset($form['title']['#weight'])) {
# Line 1659  function node_form_array($node) { Line 1719  function node_form_array($node) {
1719    return $form;    return $form;
1720  }  }
1721    
1722  function node_form_add_preview($form, $edit) {  function node_form_add_preview($form) {
1723      global $form_values;
1724    
1725    $op = isset($_POST['op']) ? $_POST['op'] : '';    $op = isset($_POST['op']) ? $_POST['op'] : '';
1726    if ($op == t('Preview')) {    if ($op == t('Preview')) {
1727      drupal_validate_form($form['form_id']['#value'], $form);      drupal_validate_form($form['form_id']['#value'], $form);
1728      if (!form_get_errors()) {      if (!form_get_errors()) {
1729        $form['node_preview'] = array('#value' => node_preview((object)$edit), '#weight' => -100);        // Because the node preview may display a form, we must render it
1730          // outside the node submission form tags using the #prefix property
1731          // (i.e. to prevent illegally nested forms).
1732          // If the node form already has a #prefix, we must preserve it.
1733          // In this case, we put the preview before the #prefix so we keep
1734          // the #prefix as "close" to the rest of the form as possible,
1735          // for example, to keep a <div> only around the form, not the
1736          // preview. We pass the global $form_values here to preserve
1737          // changes made during form validation.
1738          $preview = node_preview((object)$form_values);
1739          $form['#prefix'] = isset($form['#prefix']) ? $preview . $form['#prefix'] : $preview;
1740      }      }
1741    }    }
1742    if (variable_get('node_preview', 0) && (form_get_errors() || $op != t('Preview'))) {    if (variable_get('node_preview', 0) && (form_get_errors() || $op != t('Preview'))) {
# Line 1674  function node_form_add_preview($form, $e Line 1746  function node_form_add_preview($form, $e
1746  }  }
1747    
1748  function theme_node_form($form) {  function theme_node_form($form) {
1749    $output = '<div class="node-form">';    $output = "\n<div class=\"node-form\">\n";
   if (isset($form['node_preview'])) {  
     $output .= form_render($form['node_preview']);  
   }  
1750    
1751    $output .= '  <div class="standard">';    // Admin form fields and submit buttons must be rendered first, because
1752      // they need to go to the bottom of the form, and so should not be part of
1753      // the catch-all call to form_render().
1754      $admin = '';
1755      if (isset($form['author'])) {
1756        $admin .= "    <div class=\"authored\">\n";
1757        $admin .= form_render($form['author']);
1758        $admin .= "    </div>\n";
1759      }
1760      if (isset($form['options'])) {
1761        $admin .= "    <div class=\"options\">\n";
1762        $admin .= form_render($form['options']);
1763        $admin .= "    </div>\n";
1764      }
1765      $buttons = form_render($form['preview']);
1766      $buttons .= form_render($form['submit']);
1767      $buttons .= isset($form['delete']) ? form_render($form['delete']) : '';
1768    
1769      // Everything else gets rendered here, and is displayed before the admin form
1770      // field and the submit buttons.
1771      $output .= "  <div class=\"standard\">\n";
1772    $output .= form_render($form);    $output .= form_render($form);
1773    $output .= '  </div>';    $output .= "  </div>\n";
1774    $output .= '  <div class="admin">';  
1775    $output .= '    <div class="authored">';    if (!empty($admin)) {
1776    $output .= form_render($form['author']);      $output .= "  <div class=\"admin\">\n";
1777    $output .= '    </div>';      $output .= $admin;
1778    $output .= '    <div class="options">';      $output .= "  </div>\n";
1779    $output .= form_render($form['options']);    }
1780    $output .= '    </div>';    $output .= $buttons;
1781    $output .= '  </div>';    $output .= "</div>\n";
1782    $output .= '</div>';  
1783    return $output;    return $output;
1784  }  }
1785    
# Line 1711  function node_add($type) { Line 1800  function node_add($type) {
1800    else {    else {
1801      // If no (valid) node type has been provided, display a node type overview.      // If no (valid) node type has been provided, display a node type overview.
1802      foreach (node_get_types() as $type => $name) {      foreach (node_get_types() as $type => $name) {
1803        if (module_invoke(node_get_base($type), 'access', 'create', $type)) {        if (node_access('create', $type)) {
1804          $out = '<dt>'. l($name, "node/add/$type", array('title' => t('Add a new %s.', array('%s' => $name)))) .'</dt>';          $out = '<dt>'. l($name, "node/add/$type", array('title' => t('Add a new %s.', array('%s' => $name)))) .'</dt>';
1805          $out .= '<dd>'. implode("\n", module_invoke_all('help', 'node/add#'. $type)) .'</dd>';          $out .= '<dd>'. implode("\n", module_invoke_all('help', 'node/add#'. $type)) .'</dd>';
1806          $item[$name] = $out;          $item[$name] = $out;
# Line 1719  function node_add($type) { Line 1808  function node_add($type) {
1808      }      }
1809    
1810      if (isset($item)) {      if (isset($item)) {
1811        uasort($item, 'strnatcasecmp');        uksort($item, 'strnatcasecmp');
1812        $output = t('Choose the appropriate item from the list:') .'<dl>'. implode('', $item) .'</dl>';        $output = t('Choose the appropriate item from the list:') .'<dl>'. implode('', $item) .'</dl>';
1813      }      }
1814      else {      else {
# Line 1741  function node_preview($node) { Line 1830  function node_preview($node) {
1830        // user ID 0 denotes the anonymous user.        // user ID 0 denotes the anonymous user.
1831        if ($user = user_load(array('name' => $node->name))) {        if ($user = user_load(array('name' => $node->name))) {
1832          $node->uid = $user->uid;          $node->uid = $user->uid;
1833            $node->picture = $user->picture;
1834        }        }
1835        else {        else {
1836          $node->uid = 0; // anonymous user          $node->uid = 0; // anonymous user
# Line 1749  function node_preview($node) { Line 1839  function node_preview($node) {
1839      else if ($node->uid) {      else if ($node->uid) {
1840        $user = user_load(array('uid' => $node->uid));        $user = user_load(array('uid' => $node->uid));
1841        $node->name = $user->name;        $node->name = $user->name;
1842          $node->picture = $user->picture;
1843      }      }
1844    
1845      // Set the timestamps when needed:      // Set the timestamps when needed:
# Line 1810  function node_form_submit($form_id, $edi Line 1901  function node_form_submit($form_id, $edi
1901    if ($node->nid) {    if ($node->nid) {
1902      // Check whether the current user has the proper access rights to      // Check whether the current user has the proper access rights to
1903      // perform this operation:      // perform this operation:
1904      if (node_access('update', $node)) {      $original_node = node_load($node->nid); //check access rights using the unmodified node
1905        if (node_access('update', $original_node)) {
1906        node_save($node);        node_save($node);
1907        watchdog('content', t('%type: updated %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $node->nid));        watchdog('content', t('%type: updated %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title))), WATCHDOG_NOTICE, l(t('view'), 'node/'. $node->nid));
1908        drupal_set_message(t('The %post was updated.', array ('%post' => node_get_name($node))));        drupal_set_message(t('The %post was updated.', array ('%post' => node_get_name($node))));
# Line 1922  function node_revisions() { Line 2014  function node_revisions() {
2014          }          }
2015          break;          break;
2016        case 'revert':        case 'revert':
2017          node_revision_revert(arg(1), arg(3));          return node_revision_revert(arg(1), arg(3));
2018          break;          break;
2019        case 'delete':        case 'delete':
2020          node_revision_delete(arg(1), arg(3));          return node_revision_delete(arg(1), arg(3));
2021          break;          break;
2022      }      }
2023    }    }
# Line 1951  function node_page_default() { Line 2043  function node_page_default() {
2043      $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));      $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
2044    }    }
2045    else {    else {
2046      $output = t("      $output = t('
2047        <p>Welcome to your new <a href=\"%drupal\">Drupal</a>-powered website. This message will guide you through your first steps with Drupal, and will disappear once you have posted your first piece of content.</p>        <h1 class="title">Welcome to your new Drupal website!</h1>
2048        <p>The first thing you will need to do is <a href=\"%register\">create the first account</a>. This account will have full administration rights and will allow you to configure your website. Once logged in, you can visit the <a href=\"%admin\">administration section</a> and <a href=\"%config\">set up your site's configuration</a>.</p>        <p>Please follow these steps to set up and start using your website:</p>
2049        <p>Drupal comes with various modules, each of which contains a specific piece of functionality. You should visit the <a href=\"%modules\">module list</a> and enable those modules which suit your website's needs.</p>        <ol>
2050        <p><a href=\"%themes\">Themes</a> handle the presentation of your website. You can use one of the existing themes, modify them or create your own from scratch.</p>          <li>
2051        <p>We suggest you look around the administration section and explore the various options Drupal offers you. For more information, you can refer to the <a href=\"%handbook\">Drupal handbooks online</a>.</p>", array('%drupal' => 'http://drupal.org/', '%register' => url('user/register'), '%admin' => url('admin'), '%config' => url('admin/settings'), '%modules' => url('admin/modules'), '%themes' => url('admin/themes'), '%handbook' => 'http://drupal.org/handbooks'));            <strong>Create your administrator account</strong>
2052              To begin, <a href="%register">create the first account</a>. This account will have full administration rights and will allow you to configure your website.
2053            </li>
2054            <li>
2055              <strong>Configure your website</strong>
2056              Once logged in, visit the <a href="%admin">administration section</a>, where you can <a href="%config">customize and configure</a> all aspects of your website.
2057            </li>
2058            <li>
2059              <strong>Enable additional functionality</strong>
2060              Next, visit the <a href="%modules">module list</a> and enable features which suit your specific needs. You can find additional modules in the <a href="%download_modules">Drupal modules download section</a>.
2061            </li>
2062            <li>
2063              <strong>Customize your website design</strong>
2064              To change the "look and feel" of your website, visit the <a href="%themes">themes section</a>. You may choose from one of the included themes or download additional themes from the <a href="%download_themes">Drupal themes download section</a>.
2065            </li>
2066            <li>
2067              <strong>Start posting content</strong>
2068              Finally, you can <a href="%content">create content</a> for your website. This message will disappear once you have published your first post.
2069            </li>
2070          </ol>
2071          <p>For more information, please refer to the <a href="%help">Help section</a>, or the <a href="%handbook">online Drupal handbooks</a>. You may also post at the <a href="%forum">Drupal forum</a>, or view the wide range of <a href="%support">other support options</a> available.</p>',
2072          array('%drupal' => 'http://drupal.org/', '%register' => url('user/register'), '%admin' => url('admin'), '%config' => url('admin/settings'), '%modules' => url('admin/modules'), '%download_modules' => 'http://drupal.org/project/modules', '%themes' => url('admin/themes'), '%download_themes' => 'http://drupal.org/project/themes', '%content' => url('node/add'), '%help' => url('admin/help'), '%handbook' => 'http://drupal.org/handbooks', '%forum' => 'http://drupal.org/forum', '%support' => 'http://drupal.org/support')
2073        );
2074        $output = '<div id="first-time">'. $output .'</div>';
2075    }    }
2076    
2077    return $output;    return $output;
# Line 2049  function node_update_index() { Line 2164  function node_update_index() {
2164    variable_set('node_cron_comments_scale', 1.0 / max(1, db_result(db_query('SELECT MAX(comment_count) FROM {node_comment_statistics}'))));    variable_set('node_cron_comments_scale', 1.0 / max(1, db_result(db_query('SELECT MAX(comment_count) FROM {node_comment_statistics}'))));
2165    variable_set('node_cron_views_scale', 1.0 / max(1, db_result(db_query('SELECT MAX(totalcount) FROM {node_counter}'))));    variable_set('node_cron_views_scale', 1.0 / max(1, db_result(db_query('SELECT MAX(totalcount) FROM {node_counter}'))));
2166    
2167    $result = db_query_range('SELECT GREATEST(c.last_comment_timestamp, n.changed) as last_change, n.nid FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND ((GREATEST(n.changed, c.last_comment_timestamp) = %d AND n.nid > %d) OR (n.changed > %d OR c.last_comment_timestamp > %d)) ORDER BY GREATEST(n.changed, c.last_comment_timestamp) ASC, n.nid ASC', $last, $last_nid, $last, $last, $last, 0, $limit);    $result = db_query_range('SELECT GREATEST(IF(c.last_comment_timestamp IS NULL, 0, c.last_comment_timestamp), n.changed) as last_change, n.nid FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND ((GREATEST(n.changed, c.last_comment_timestamp) = %d AND n.nid > %d) OR (n.changed > %d OR c.last_comment_timestamp > %d)) ORDER BY GREATEST(n.changed, c.last_comment_timestamp) ASC, n.nid ASC', $last, $last_nid, $last, $last, $last, 0, $limit);
2168    
2169    while ($node = db_fetch_object($result)) {    while ($node = db_fetch_object($result)) {
2170      $last_change = $node->last_change;      $last_change = $node->last_change;

Legend:
Removed from v.1.641  
changed lines
  Added in v.1.641.2.31

  ViewVC Help
Powered by ViewVC 1.1.2