Index: install.php =================================================================== RCS file: /cvs/drupal/drupal/install.php,v retrieving revision 1.169 diff -u -p -r1.169 install.php --- install.php 21 May 2009 21:12:22 -0000 1.169 +++ install.php 22 May 2009 23:43:01 -0000 @@ -40,6 +40,7 @@ function install_main() { global $profile, $install_locale, $conf; require_once DRUPAL_ROOT . '/modules/system/system.install'; + require_once DRUPAL_ROOT . '/modules/system/system.registry.inc'; require_once DRUPAL_ROOT . '/includes/file.inc'; // Ensure correct page headers are sent (e.g. caching) Index: includes/theme.maintenance.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.maintenance.inc,v retrieving revision 1.28 diff -u -p -r1.28 theme.maintenance.inc --- includes/theme.maintenance.inc 21 May 2009 21:12:22 -0000 1.28 +++ includes/theme.maintenance.inc 22 May 2009 23:43:01 -0000 @@ -29,6 +29,7 @@ function _drupal_maintenance_theme() { require_once DRUPAL_ROOT . '/includes/file.inc'; require_once DRUPAL_ROOT . '/includes/module.inc'; require_once DRUPAL_ROOT . '/includes/database/database.inc'; + require_once DRUPAL_ROOT . '/modules/system/system.registry.inc'; unicode_check(); // Install and update pages are treated differently to prevent theming overrides. Index: modules/aggregator/aggregator.block.inc =================================================================== RCS file: modules/aggregator/aggregator.block.inc diff -N modules/aggregator/aggregator.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/aggregator/aggregator.block.inc 22 May 2009 23:44:20 -0000 @@ -0,0 +1,54 @@ +cid]['info'] = t('!title category latest items', array('!title' => $category->title)); + } + $result = db_query('SELECT fid, title FROM {aggregator_feed} WHERE block <> 0 ORDER BY fid'); + foreach ($result as $feed) { + $block['feed-' . $feed->fid]['info'] = t('!title feed latest items', array('!title' => $feed->title)); + } + return $block; +} + +/** + * Implementation of hook_block_configure(). + */ +function aggregator_block_configure($delta = '') { + list($type, $id) = explode('-', $delta); + if ($type == 'category') { + $value = db_query('SELECT block FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $id))->fetchField(); + $form['block'] = array( + '#type' => 'select', + '#title' => t('Number of news items in block'), + '#default_value' => $value, + '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)) + ); + return $form; + } +} + +/** + * Implementation of hook_block_save(). + */ +function aggregator_block_save($delta = '', $edit = array()) { + list($type, $id) = explode('-', $delta); + if ($type == 'category') { + db_update('aggregator_category') + ->fields(array('block' => $edit['block'])) + ->condition('cid', $id) + ->execute(); + } +} + Index: modules/aggregator/aggregator.cron.inc =================================================================== RCS file: modules/aggregator/aggregator.cron.inc diff -N modules/aggregator/aggregator.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/aggregator/aggregator.cron.inc 22 May 2009 23:44:20 -0000 @@ -0,0 +1,20 @@ + 0', array(':time' => REQUEST_TIME)); + foreach ($result as $feed) { + aggregator_refresh($feed); + } +} + Index: modules/aggregator/aggregator.help.inc =================================================================== RCS file: modules/aggregator/aggregator.help.inc diff -N modules/aggregator/aggregator.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/aggregator/aggregator.help.inc 22 May 2009 23:44:20 -0000 @@ -0,0 +1,31 @@ +' . t('The aggregator is a powerful on-site syndicator and news reader that gathers fresh content from RSS-, RDF-, and Atom-based feeds made available across the web. Thousands of sites (particularly news sites and blogs) publish their latest headlines and posts in feeds, using a number of standardized XML-based formats. Formats supported by the aggregator include RSS, RDF, and Atom.', array('@rss' => 'http://cyber.law.harvard.edu/rss/', '@rdf' => 'http://www.w3.org/RDF/', '@atom' => 'http://www.atomenabled.org')) . '
'; + $output .= '' . t('Feeds contain feed items, or individual posts published by the site providing the feed. Feeds may be grouped in categories, generally by topic. Users view feed items in the main aggregator display or by their source. Administrators can add, edit and delete feeds and choose how often to check each feed for newly updated items. The most recent items in either a feed or category can be displayed as a block through the blocks administration page. A machine-readable OPML file of all feeds is available. A correctly configured cron maintenance task is required to update feeds automatically.', array('@aggregator' => url('aggregator'), '@aggregator-sources' => url('aggregator/sources'), '@feededit' => url('admin/content/aggregator'), '@admin-block' => url('admin/build/block'), '@aggregator-opml' => url('aggregator/opml'), '@cron' => url('admin/reports/status'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Aggregator module.', array('@aggregator' => 'http://drupal.org/handbook/modules/aggregator/')) . '
'; + return $output; + case 'admin/content/aggregator': + $output = '' . t('Thousands of sites (particularly news sites and blogs) publish their latest headlines and posts in feeds, using a number of standardized XML-based formats. Formats supported by the aggregator include RSS, RDF, and Atom.', array('@rss' => 'http://cyber.law.harvard.edu/rss/', '@rdf' => 'http://www.w3.org/RDF/', '@atom' => 'http://www.atomenabled.org')) . '
'; + $output .= '' . t('Current feeds are listed below, and new feeds may be added. For each feed or feed category, the latest items block may be enabled at the blocks administration page.', array('@addfeed' => url('admin/content/aggregator/add/feed'), '@block' => url('admin/build/block'))) . '
'; + return $output; + case 'admin/content/aggregator/add/feed': + return '' . t('Add a feed in RSS, RDF or Atom format. A feed may only have one entry.') . '
'; + case 'admin/content/aggregator/add/category': + return '' . t('Categories allow feed items from different feeds to be grouped together. For example, several sport-related feeds may belong to a category named Sports. Feed items may be grouped automatically (by selecting a category when creating or editing a feed) or manually (via the Categorize page available from feed item listings). Each category provides its own feed page and block.') . '
'; + case 'admin/content/aggregator/add/opml': + return '' . t('OPML is an XML format used to exchange multiple feeds between aggregators. A single OPML document may contain a collection of many feeds. Drupal can parse such a file and import all feeds at once, saving you the effort of adding them manually. You may either upload a local file from your computer or enter a URL where Drupal can download it.') . '
'; + } +} + Index: modules/aggregator/aggregator.info =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.info,v retrieving revision 1.11 diff -u -p -r1.11 aggregator.info --- modules/aggregator/aggregator.info 15 Mar 2009 18:59:05 -0000 1.11 +++ modules/aggregator/aggregator.info 22 May 2009 23:44:20 -0000 @@ -11,3 +11,8 @@ files[] = aggregator.fetcher.inc files[] = aggregator.parser.inc files[] = aggregator.processor.inc files[] = aggregator.install +files[] = aggregator.registry.inc +files[] = aggregator.user.inc +files[] = aggregator.block.inc +files[] = aggregator.cron.inc +files[] = aggregator.help.inc Index: modules/aggregator/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v retrieving revision 1.410 diff -u -p -r1.410 aggregator.module --- modules/aggregator/aggregator.module 21 May 2009 23:07:14 -0000 1.410 +++ modules/aggregator/aggregator.module 22 May 2009 23:44:20 -0000 @@ -7,237 +7,6 @@ */ /** - * Implementation of hook_help(). - */ -function aggregator_help($path, $arg) { - switch ($path) { - case 'admin/help#aggregator': - $output = '' . t('The aggregator is a powerful on-site syndicator and news reader that gathers fresh content from RSS-, RDF-, and Atom-based feeds made available across the web. Thousands of sites (particularly news sites and blogs) publish their latest headlines and posts in feeds, using a number of standardized XML-based formats. Formats supported by the aggregator include RSS, RDF, and Atom.', array('@rss' => 'http://cyber.law.harvard.edu/rss/', '@rdf' => 'http://www.w3.org/RDF/', '@atom' => 'http://www.atomenabled.org')) . '
'; - $output .= '' . t('Feeds contain feed items, or individual posts published by the site providing the feed. Feeds may be grouped in categories, generally by topic. Users view feed items in the main aggregator display or by their source. Administrators can add, edit and delete feeds and choose how often to check each feed for newly updated items. The most recent items in either a feed or category can be displayed as a block through the blocks administration page. A machine-readable OPML file of all feeds is available. A correctly configured cron maintenance task is required to update feeds automatically.', array('@aggregator' => url('aggregator'), '@aggregator-sources' => url('aggregator/sources'), '@feededit' => url('admin/content/aggregator'), '@admin-block' => url('admin/build/block'), '@aggregator-opml' => url('aggregator/opml'), '@cron' => url('admin/reports/status'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Aggregator module.', array('@aggregator' => 'http://drupal.org/handbook/modules/aggregator/')) . '
'; - return $output; - case 'admin/content/aggregator': - $output = '' . t('Thousands of sites (particularly news sites and blogs) publish their latest headlines and posts in feeds, using a number of standardized XML-based formats. Formats supported by the aggregator include RSS, RDF, and Atom.', array('@rss' => 'http://cyber.law.harvard.edu/rss/', '@rdf' => 'http://www.w3.org/RDF/', '@atom' => 'http://www.atomenabled.org')) . '
'; - $output .= '' . t('Current feeds are listed below, and new feeds may be added. For each feed or feed category, the latest items block may be enabled at the blocks administration page.', array('@addfeed' => url('admin/content/aggregator/add/feed'), '@block' => url('admin/build/block'))) . '
'; - return $output; - case 'admin/content/aggregator/add/feed': - return '' . t('Add a feed in RSS, RDF or Atom format. A feed may only have one entry.') . '
'; - case 'admin/content/aggregator/add/category': - return '' . t('Categories allow feed items from different feeds to be grouped together. For example, several sport-related feeds may belong to a category named Sports. Feed items may be grouped automatically (by selecting a category when creating or editing a feed) or manually (via the Categorize page available from feed item listings). Each category provides its own feed page and block.') . '
'; - case 'admin/content/aggregator/add/opml': - return '' . t('OPML is an XML format used to exchange multiple feeds between aggregators. A single OPML document may contain a collection of many feeds. Drupal can parse such a file and import all feeds at once, saving you the effort of adding them manually. You may either upload a local file from your computer or enter a URL where Drupal can download it.') . '
'; - } -} - -/** - * Implementation of hook_theme(). - */ -function aggregator_theme() { - return array( - 'aggregator_wrapper' => array( - 'arguments' => array('content' => NULL), - 'file' => 'aggregator.pages.inc', - 'template' => 'aggregator-wrapper', - ), - 'aggregator_categorize_items' => array( - 'arguments' => array('form' => NULL), - 'file' => 'aggregator.pages.inc', - ), - 'aggregator_feed_source' => array( - 'arguments' => array('feed' => NULL), - 'file' => 'aggregator.pages.inc', - 'template' => 'aggregator-feed-source', - ), - 'aggregator_block_item' => array( - 'arguments' => array('item' => NULL, 'feed' => 0), - ), - 'aggregator_summary_items' => array( - 'arguments' => array('summary_items' => NULL, 'source' => NULL), - 'file' => 'aggregator.pages.inc', - 'template' => 'aggregator-summary-items', - ), - 'aggregator_summary_item' => array( - 'arguments' => array('item' => NULL), - 'file' => 'aggregator.pages.inc', - 'template' => 'aggregator-summary-item', - ), - 'aggregator_item' => array( - 'arguments' => array('item' => NULL), - 'file' => 'aggregator.pages.inc', - 'template' => 'aggregator-item', - ), - 'aggregator_page_opml' => array( - 'arguments' => array('feeds' => NULL), - 'file' => 'aggregator.pages.inc', - ), - 'aggregator_page_rss' => array( - 'arguments' => array('feeds' => NULL, 'category' => NULL), - 'file' => 'aggregator.pages.inc', - ), - ); -} - -/** - * Implementation of hook_menu(). - */ -function aggregator_menu() { - $items['admin/content/aggregator'] = array( - 'title' => 'Feed aggregator', - 'description' => "Configure which content your site aggregates from other sites, how often it polls them, and how they're categorized.", - 'page callback' => 'aggregator_admin_overview', - 'access arguments' => array('administer news feeds'), - ); - $items['admin/content/aggregator/add/feed'] = array( - 'title' => 'Add feed', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_feed'), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - 'parent' => 'admin/content/aggregator', - ); - $items['admin/content/aggregator/add/category'] = array( - 'title' => 'Add category', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_category'), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - 'parent' => 'admin/content/aggregator', - ); - $items['admin/content/aggregator/add/opml'] = array( - 'title' => 'Import OPML', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_opml'), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - 'parent' => 'admin/content/aggregator', - ); - $items['admin/content/aggregator/remove/%aggregator_feed'] = array( - 'title' => 'Remove items', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_admin_remove_feed', 4), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_CALLBACK, - ); - $items['admin/content/aggregator/update/%aggregator_feed'] = array( - 'title' => 'Update items', - 'page callback' => 'aggregator_admin_refresh_feed', - 'page arguments' => array(4), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_CALLBACK, - ); - $items['admin/content/aggregator/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['admin/settings/aggregator'] = array( - 'title' => 'Aggregator', - 'description' => 'Configure the behavior of the feed aggregator, including when to discard feed items and how to present feed items and categories.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_admin_form'), - 'access arguments' => array('administer news feeds'), - ); - $items['aggregator'] = array( - 'title' => 'Feed aggregator', - 'page callback' => 'aggregator_page_last', - 'access arguments' => array('access news feeds'), - 'weight' => 5, - ); - $items['aggregator/sources'] = array( - 'title' => 'Sources', - 'page callback' => 'aggregator_page_sources', - 'access arguments' => array('access news feeds'), - ); - $items['aggregator/categories'] = array( - 'title' => 'Categories', - 'page callback' => 'aggregator_page_categories', - 'access callback' => '_aggregator_has_categories', - ); - $items['aggregator/rss'] = array( - 'title' => 'RSS feed', - 'page callback' => 'aggregator_page_rss', - 'access arguments' => array('access news feeds'), - 'type' => MENU_CALLBACK, - ); - $items['aggregator/opml'] = array( - 'title' => 'OPML feed', - 'page callback' => 'aggregator_page_opml', - 'access arguments' => array('access news feeds'), - 'type' => MENU_CALLBACK, - ); - $items['aggregator/categories/%aggregator_category'] = array( - 'title callback' => '_aggregator_category_title', - 'title arguments' => array(2), - 'page callback' => 'aggregator_page_category', - 'page arguments' => array(2), - 'access callback' => 'user_access', - 'access arguments' => array('access news feeds'), - ); - $items['aggregator/categories/%aggregator_category/view'] = array( - 'title' => 'View', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['aggregator/categories/%aggregator_category/categorize'] = array( - 'title' => 'Categorize', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_page_category', 2), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - ); - $items['aggregator/categories/%aggregator_category/configure'] = array( - 'title' => 'Configure', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_category', 2), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 1, - ); - $items['aggregator/sources/%aggregator_feed'] = array( - 'page callback' => 'aggregator_page_source', - 'page arguments' => array(2), - 'access arguments' => array('access news feeds'), - 'type' => MENU_CALLBACK, - ); - $items['aggregator/sources/%aggregator_feed/view'] = array( - 'title' => 'View', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['aggregator/sources/%aggregator_feed/categorize'] = array( - 'title' => 'Categorize', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_page_source', 2), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - ); - $items['aggregator/sources/%aggregator_feed/configure'] = array( - 'title' => 'Configure', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_feed', 2), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 1, - ); - $items['admin/content/aggregator/edit/feed/%aggregator_feed'] = array( - 'title' => 'Edit feed', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_feed', 5), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_CALLBACK, - ); - $items['admin/content/aggregator/edit/category/%aggregator_category'] = array( - 'title' => 'Edit category', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('aggregator_form_category', 5), - 'access arguments' => array('administer news feeds'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** * Menu callback. * * @return @@ -265,80 +34,6 @@ function _aggregator_has_categories() { } /** - * Implementation of hook_perm(). - */ -function aggregator_perm() { - return array( - 'administer news feeds' => array( - 'title' => t('Administer news feeds'), - 'description' => t('Add, edit or delete news feeds that are aggregated to your site.'), - ), - 'access news feeds' => array( - 'title' => t('Access news feeds'), - 'description' => t('View aggregated news feed items.'), - ), - ); -} - -/** - * Implementation of hook_cron(). - * - * Checks news feeds for updates once their refresh interval has elapsed. - */ -function aggregator_cron() { - $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh > 0', array(':time' => REQUEST_TIME)); - foreach ($result as $feed) { - aggregator_refresh($feed); - } -} - -/** - * Implementation of hook_block_list(). - */ -function aggregator_block_list() { - $block = array(); - $result = db_query('SELECT cid, title FROM {aggregator_category} ORDER BY title'); - foreach ($result as $category) { - $block['category-' . $category->cid]['info'] = t('!title category latest items', array('!title' => $category->title)); - } - $result = db_query('SELECT fid, title FROM {aggregator_feed} WHERE block <> 0 ORDER BY fid'); - foreach ($result as $feed) { - $block['feed-' . $feed->fid]['info'] = t('!title feed latest items', array('!title' => $feed->title)); - } - return $block; -} - -/** - * Implementation of hook_block_configure(). - */ -function aggregator_block_configure($delta = '') { - list($type, $id) = explode('-', $delta); - if ($type == 'category') { - $value = db_query('SELECT block FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $id))->fetchField(); - $form['block'] = array( - '#type' => 'select', - '#title' => t('Number of news items in block'), - '#default_value' => $value, - '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)) - ); - return $form; - } -} - -/** - * Implementation of hook_block_save(). - */ -function aggregator_block_save($delta = '', $edit = array()) { - list($type, $id) = explode('-', $delta); - if ($type == 'category') { - db_update('aggregator_category') - ->fields(array('block' => $edit['block'])) - ->condition('cid', $id) - ->execute(); - } -} - -/** * Implementation of hook_block_view(). * * Generates blocks for the latest news items in each category and feed. Index: modules/aggregator/aggregator.registry.inc =================================================================== RCS file: modules/aggregator/aggregator.registry.inc diff -N modules/aggregator/aggregator.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/aggregator/aggregator.registry.inc 22 May 2009 23:44:20 -0000 @@ -0,0 +1,216 @@ + 'Feed aggregator', + 'description' => "Configure which content your site aggregates from other sites, how often it polls them, and how they're categorized.", + 'page callback' => 'aggregator_admin_overview', + 'access arguments' => array('administer news feeds'), + ); + $items['admin/content/aggregator/add/feed'] = array( + 'title' => 'Add feed', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_form_feed'), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_LOCAL_TASK, + 'parent' => 'admin/content/aggregator', + ); + $items['admin/content/aggregator/add/category'] = array( + 'title' => 'Add category', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_form_category'), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_LOCAL_TASK, + 'parent' => 'admin/content/aggregator', + ); + $items['admin/content/aggregator/add/opml'] = array( + 'title' => 'Import OPML', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_form_opml'), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_LOCAL_TASK, + 'parent' => 'admin/content/aggregator', + ); + $items['admin/content/aggregator/remove/%aggregator_feed'] = array( + 'title' => 'Remove items', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_admin_remove_feed', 4), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_CALLBACK, + ); + $items['admin/content/aggregator/update/%aggregator_feed'] = array( + 'title' => 'Update items', + 'page callback' => 'aggregator_admin_refresh_feed', + 'page arguments' => array(4), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_CALLBACK, + ); + $items['admin/content/aggregator/list'] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + $items['admin/settings/aggregator'] = array( + 'title' => 'Aggregator', + 'description' => 'Configure the behavior of the feed aggregator, including when to discard feed items and how to present feed items and categories.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_admin_form'), + 'access arguments' => array('administer news feeds'), + ); + $items['aggregator'] = array( + 'title' => 'Feed aggregator', + 'page callback' => 'aggregator_page_last', + 'access arguments' => array('access news feeds'), + 'weight' => 5, + ); + $items['aggregator/sources'] = array( + 'title' => 'Sources', + 'page callback' => 'aggregator_page_sources', + 'access arguments' => array('access news feeds'), + ); + $items['aggregator/categories'] = array( + 'title' => 'Categories', + 'page callback' => 'aggregator_page_categories', + 'access callback' => '_aggregator_has_categories', + ); + $items['aggregator/rss'] = array( + 'title' => 'RSS feed', + 'page callback' => 'aggregator_page_rss', + 'access arguments' => array('access news feeds'), + 'type' => MENU_CALLBACK, + ); + $items['aggregator/opml'] = array( + 'title' => 'OPML feed', + 'page callback' => 'aggregator_page_opml', + 'access arguments' => array('access news feeds'), + 'type' => MENU_CALLBACK, + ); + $items['aggregator/categories/%aggregator_category'] = array( + 'title callback' => '_aggregator_category_title', + 'title arguments' => array(2), + 'page callback' => 'aggregator_page_category', + 'page arguments' => array(2), + 'access callback' => 'user_access', + 'access arguments' => array('access news feeds'), + ); + $items['aggregator/categories/%aggregator_category/view'] = array( + 'title' => 'View', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + $items['aggregator/categories/%aggregator_category/categorize'] = array( + 'title' => 'Categorize', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_page_category', 2), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_LOCAL_TASK, + ); + $items['aggregator/categories/%aggregator_category/configure'] = array( + 'title' => 'Configure', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_form_category', 2), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 1, + ); + $items['aggregator/sources/%aggregator_feed'] = array( + 'page callback' => 'aggregator_page_source', + 'page arguments' => array(2), + 'access arguments' => array('access news feeds'), + 'type' => MENU_CALLBACK, + ); + $items['aggregator/sources/%aggregator_feed/view'] = array( + 'title' => 'View', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + $items['aggregator/sources/%aggregator_feed/categorize'] = array( + 'title' => 'Categorize', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_page_source', 2), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_LOCAL_TASK, + ); + $items['aggregator/sources/%aggregator_feed/configure'] = array( + 'title' => 'Configure', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_form_feed', 2), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 1, + ); + $items['admin/content/aggregator/edit/feed/%aggregator_feed'] = array( + 'title' => 'Edit feed', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_form_feed', 5), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_CALLBACK, + ); + $items['admin/content/aggregator/edit/category/%aggregator_category'] = array( + 'title' => 'Edit category', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('aggregator_form_category', 5), + 'access arguments' => array('administer news feeds'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function aggregator_theme() { + return array( + 'aggregator_wrapper' => array( + 'arguments' => array('content' => NULL), + 'file' => 'aggregator.pages.inc', + 'template' => 'aggregator-wrapper', + ), + 'aggregator_categorize_items' => array( + 'arguments' => array('form' => NULL), + 'file' => 'aggregator.pages.inc', + ), + 'aggregator_feed_source' => array( + 'arguments' => array('feed' => NULL), + 'file' => 'aggregator.pages.inc', + 'template' => 'aggregator-feed-source', + ), + 'aggregator_block_item' => array( + 'arguments' => array('item' => NULL, 'feed' => 0), + ), + 'aggregator_summary_items' => array( + 'arguments' => array('summary_items' => NULL, 'source' => NULL), + 'file' => 'aggregator.pages.inc', + 'template' => 'aggregator-summary-items', + ), + 'aggregator_summary_item' => array( + 'arguments' => array('item' => NULL), + 'file' => 'aggregator.pages.inc', + 'template' => 'aggregator-summary-item', + ), + 'aggregator_item' => array( + 'arguments' => array('item' => NULL), + 'file' => 'aggregator.pages.inc', + 'template' => 'aggregator-item', + ), + 'aggregator_page_opml' => array( + 'arguments' => array('feeds' => NULL), + 'file' => 'aggregator.pages.inc', + ), + 'aggregator_page_rss' => array( + 'arguments' => array('feeds' => NULL, 'category' => NULL), + 'file' => 'aggregator.pages.inc', + ), + ); +} + Index: modules/aggregator/aggregator.user.inc =================================================================== RCS file: modules/aggregator/aggregator.user.inc diff -N modules/aggregator/aggregator.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/aggregator/aggregator.user.inc 22 May 2009 23:44:20 -0000 @@ -0,0 +1,24 @@ + array( + 'title' => t('Administer news feeds'), + 'description' => t('Add, edit or delete news feeds that are aggregated to your site.'), + ), + 'access news feeds' => array( + 'title' => t('Access news feeds'), + 'description' => t('View aggregated news feed items.'), + ), + ); +} + Index: modules/aggregator/tests/aggregator_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/tests/aggregator_test.info,v retrieving revision 1.1 diff -u -p -r1.1 aggregator_test.info --- modules/aggregator/tests/aggregator_test.info 2 Apr 2009 20:50:37 -0000 1.1 +++ modules/aggregator/tests/aggregator_test.info 22 May 2009 23:44:19 -0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = aggregator_test.module hidden = TRUE +files[] = aggregator_test.registry.inc Index: modules/aggregator/tests/aggregator_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/tests/aggregator_test.module,v retrieving revision 1.2 diff -u -p -r1.2 aggregator_test.module --- modules/aggregator/tests/aggregator_test.module 22 Apr 2009 09:45:02 -0000 1.2 +++ modules/aggregator/tests/aggregator_test.module 22 May 2009 23:44:19 -0000 @@ -2,20 +2,6 @@ // $Id: aggregator_test.module,v 1.2 2009/04/22 09:45:02 dries Exp $ /** - * Implementation of hook_menu(). - */ -function aggregator_test_menu() { - $items['aggregator/test-feed'] = array( - 'title' => 'Test feed static last modified date', - 'description' => "A cached test feed with a static last modified date.", - 'page callback' => 'aggregator_test_feed', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** * Page callback. Generates a test feed and simulates last-modified and etags. * * @param $use_last_modified Index: modules/aggregator/tests/aggregator_test.registry.inc =================================================================== RCS file: modules/aggregator/tests/aggregator_test.registry.inc diff -N modules/aggregator/tests/aggregator_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/aggregator/tests/aggregator_test.registry.inc 22 May 2009 23:44:19 -0000 @@ -0,0 +1,22 @@ + 'Test feed static last modified date', + 'description' => "A cached test feed with a static last modified date.", + 'page callback' => 'aggregator_test_feed', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + Index: modules/block/block.block.inc =================================================================== RCS file: modules/block/block.block.inc diff -N modules/block/block.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/block/block.block.inc 22 May 2009 23:44:21 -0000 @@ -0,0 +1,89 @@ +bid]['info'] = $block->info; + // Not worth caching. + $blocks[$block->bid]['cache'] = BLOCK_NO_CACHE; + } + return $blocks; +} + +/** + * Implementation of hook_block_configure(). + */ +function block_block_configure($delta = 0, $edit = array()) { + $box = array('format' => FILTER_FORMAT_DEFAULT); + if ($delta) { + $box = block_box_get($delta); + } + if (filter_access($box['format'])) { + return block_box_form($box); + } +} + +/** + * Implementation of hook_block_save(). + */ +function block_block_save($delta = 0, $edit = array()) { + block_box_save($edit, $delta); +} + +function block_box_get($bid) { + return db_fetch_array(db_query("SELECT * FROM {box} WHERE bid = %d", $bid)); +} + +/** + * Define the custom block form. + */ +function block_box_form($edit = array()) { + $edit += array( + 'info' => '', + 'body' => '', + ); + $form['info'] = array( + '#type' => 'textfield', + '#title' => t('Block description'), + '#default_value' => $edit['info'], + '#maxlength' => 64, + '#description' => t('A brief description of your block. Used on the block overview page.', array('@overview' => url('admin/build/block'))), + '#required' => TRUE, + '#weight' => -19, + ); + $form['body_field']['#weight'] = -17; + $form['body_field']['body'] = array( + '#type' => 'textarea', + '#title' => t('Block body'), + '#default_value' => $edit['body'], + '#text_format' => isset($edit['format']) ? $edit['format'] : FILTER_FORMAT_DEFAULT, + '#rows' => 15, + '#description' => t('The content of the block as shown to the user.'), + '#required' => TRUE, + '#weight' => -17, + ); + + return $form; +} + +function block_box_save($edit, $delta) { + if (!filter_access($edit['body_format'])) { + $edit['body_format'] = FILTER_FORMAT_DEFAULT; + } + + db_query("UPDATE {box} SET body = '%s', info = '%s', format = %d WHERE bid = %d", $edit['body'], $edit['info'], $edit['body_format'], $delta); + + return TRUE; +} + Index: modules/block/block.form.inc =================================================================== RCS file: modules/block/block.form.inc diff -N modules/block/block.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/block/block.form.inc 22 May 2009 23:44:21 -0000 @@ -0,0 +1,76 @@ + 'fieldset', + '#title' => t('Block cache'), + '#description' => t('Enabling the block cache can offer a performance increase for all users by preventing blocks from being reconstructed on each page load. If the page cache is also enabled, performance increases from enabling the block cache will mainly benefit authenticated users.'), + '#weight' => 0, + ); + + $form['block_cache']['block_cache'] = array( + '#type' => 'radios', + '#title' => t('Block cache'), + '#default_value' => variable_get('block_cache', CACHE_DISABLED), + '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Enabled (recommended)')), + '#disabled' => count(module_implements('node_grants')), + '#description' => t('Note that block caching is inactive when modules defining content access restrictions are enabled.'), + ); + + // Check if the "Who's online" block is enabled. + $online_block_enabled = db_select('block') + ->condition('module', 'user') + ->condition('delta', 'online') + ->condition('status', 1) + ->countQuery() + ->execute() + ->fetchField(); + + // If the "Who's online" block is enabled, append some descriptive text to + // the end of the form description. + if ($online_block_enabled) { + $form['page_cache']['cache']['#description'] .= '' . t('When caching is enabled, anonymous user sessions are only saved to the database when needed, so the "Who\'s online" block does not display the number of anonymous users.') . '
'; + } + +} + +/** + * Implementation of hook_form_FORM_ID_alter(). + */ +function block_form_system_themes_form_alter(&$form, &$form_state) { + $form['#submit'][] = 'block_system_themes_form_submit'; +} + +/** + * Initialize blocks for enabled themes. + */ +function block_system_themes_form_submit(&$form, &$form_state) { + if ($form_state['values']['op'] == t('Save configuration')) { + if (is_array($form_state['values']['status'])) { + foreach ($form_state['values']['status'] as $key => $choice) { + if ($choice || $form_state['values']['theme_default'] == $key) { + block_initialize_theme_blocks($key); + } + } + } + if ($form_state['values']['admin_theme'] && $form_state['values']['admin_theme'] != variable_get('admin_theme', 0)) { + // If we're changing themes, make sure the theme has its blocks initialized. + $has_blocks = (bool) db_query_range('SELECT 1 FROM {block} WHERE theme = :theme', array(':theme' => $form_state['values']['admin_theme']), 0, 1)->fetchField(); + if (!$has_blocks) { + block_initialize_theme_blocks($form_state['values']['admin_theme']); + } + } + } +} + Index: modules/block/block.help.inc =================================================================== RCS file: modules/block/block.help.inc diff -N modules/block/block.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/block/block.help.inc 22 May 2009 23:44:19 -0000 @@ -0,0 +1,35 @@ +' . t('Blocks are boxes of content rendered into an area, or region, of a web page. The default theme Garland, for example, implements the regions "left sidebar", "right sidebar", "content", "header", and "footer", and a block may appear in any one of these areas. The blocks administration page provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions.', array('@blocks' => url('admin/build/block'))) . ''; + $output .= '' . t('Although blocks are usually generated automatically by modules (like the User login block, for example), administrators can also define custom blocks. Custom blocks have a title, description, and body. The body of the block can be as long as necessary, and can contain content supported by any available text format.', array('@text-format' => url('admin/settings/filter'))) . '
'; + $output .= '' . t('When working with blocks, remember that:') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Block module.', array('@block' => 'http://drupal.org/handbook/modules/block/')) . '
'; + return $output; + case 'admin/build/block': + $output = '' . t('This page provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions. To change the region or order of a block, grab a drag-and-drop handle under the Block column and drag the block to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the Save blocks button at the bottom of the page.') . '
'; + $output .= '' . t('Click the configure link next to each block to configure its specific title and visibility settings. Use the add block page to create a custom block.', array('@add-block' => url('admin/build/block/add'))) . '
'; + return $output; + case 'admin/build/block/add': + return '' . t('Use this page to create a new custom block. New blocks are disabled by default, and must be moved to a region on the blocks administration page to be visible.', array('@blocks' => url('admin/build/block'))) . '
'; + } +} + Index: modules/block/block.info =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.info,v retrieving revision 1.12 diff -u -p -r1.12 block.info --- modules/block/block.info 3 Feb 2009 12:30:14 -0000 1.12 +++ modules/block/block.info 22 May 2009 23:44:19 -0000 @@ -8,3 +8,8 @@ core = 7.x files[] = block.module files[] = block.admin.inc files[] = block.install +files[] = block.registry.inc +files[] = block.user.inc +files[] = block.block.inc +files[] = block.form.inc +files[] = block.help.inc Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.334 diff -u -p -r1.334 block.module --- modules/block/block.module 21 May 2009 23:07:14 -0000 1.334 +++ modules/block/block.module 22 May 2009 23:44:21 -0000 @@ -61,118 +61,6 @@ define('BLOCK_CACHE_PER_PAGE', 0x0004); define('BLOCK_CACHE_GLOBAL', 0x0008); /** - * Implementation of hook_help(). - */ -function block_help($path, $arg) { - switch ($path) { - case 'admin/help#block': - $output = '' . t('Blocks are boxes of content rendered into an area, or region, of a web page. The default theme Garland, for example, implements the regions "left sidebar", "right sidebar", "content", "header", and "footer", and a block may appear in any one of these areas. The blocks administration page provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions.', array('@blocks' => url('admin/build/block'))) . '
'; - $output .= '' . t('Although blocks are usually generated automatically by modules (like the User login block, for example), administrators can also define custom blocks. Custom blocks have a title, description, and body. The body of the block can be as long as necessary, and can contain content supported by any available text format.', array('@text-format' => url('admin/settings/filter'))) . '
'; - $output .= '' . t('When working with blocks, remember that:') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Block module.', array('@block' => 'http://drupal.org/handbook/modules/block/')) . '
'; - return $output; - case 'admin/build/block': - $output = '' . t('This page provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions. To change the region or order of a block, grab a drag-and-drop handle under the Block column and drag the block to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the Save blocks button at the bottom of the page.') . '
'; - $output .= '' . t('Click the configure link next to each block to configure its specific title and visibility settings. Use the add block page to create a custom block.', array('@add-block' => url('admin/build/block/add'))) . '
'; - return $output; - case 'admin/build/block/add': - return '' . t('Use this page to create a new custom block. New blocks are disabled by default, and must be moved to a region on the blocks administration page to be visible.', array('@blocks' => url('admin/build/block'))) . '
'; - } -} - -/** - * Implementation of hook_theme(). - */ -function block_theme() { - return array( - 'block' => array( - 'arguments' => array('block' => NULL), - 'template' => 'block', - ), - 'block_admin_display_form' => array( - 'template' => 'block-admin-display-form', - 'file' => 'block.admin.inc', - 'arguments' => array('form' => NULL), - ), - ); -} - -/** - * Implementation of hook_perm(). - */ -function block_perm() { - return array( - 'administer blocks' => array( - 'title' => t('Administer blocks'), - 'description' => t('Select which blocks are displayed, and arrange them on the page.'), - ), - ); -} - -/** - * Implementation of hook_menu(). - */ -function block_menu() { - $items['admin/build/block'] = array( - 'title' => 'Blocks', - 'description' => 'Configure what block content appears in your site\'s sidebars and other regions.', - 'page callback' => 'block_admin_display', - 'access arguments' => array('administer blocks'), - ); - $items['admin/build/block/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['admin/build/block/list/js'] = array( - 'title' => 'JavaScript List Form', - 'page callback' => 'block_admin_display_js', - 'access arguments' => array('administer blocks'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/block/configure'] = array( - 'title' => 'Configure block', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('block_admin_configure'), - 'access arguments' => array('administer blocks'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/block/delete'] = array( - 'title' => 'Delete block', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('block_box_delete'), - 'access arguments' => array('administer blocks'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/block/add'] = array( - 'title' => 'Add block', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('block_add_block_form'), - 'access arguments' => array('administer blocks'), - 'type' => MENU_LOCAL_TASK, - ); - $default = variable_get('theme_default', 'garland'); - foreach (list_themes() as $key => $theme) { - $items['admin/build/block/list/' . $key] = array( - 'title' => check_plain($theme->info['name']), - 'page arguments' => array($key), - 'type' => $key == $default ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, - 'weight' => $key == $default ? -10 : 0, - 'access callback' => '_block_themes_access', - 'access arguments' => array($theme), - ); - } - return $items; -} - -/** * Menu item access callback - only admin or enabled themes can be accessed. */ function _block_themes_access($theme) { @@ -180,41 +68,6 @@ function _block_themes_access($theme) { } /** - * Implementation of hook_block_list(). - */ -function block_block_list() { - $blocks = array(); - - $result = db_query('SELECT bid, info FROM {box} ORDER BY info'); - while ($block = db_fetch_object($result)) { - $blocks[$block->bid]['info'] = $block->info; - // Not worth caching. - $blocks[$block->bid]['cache'] = BLOCK_NO_CACHE; - } - return $blocks; -} - -/** - * Implementation of hook_block_configure(). - */ -function block_block_configure($delta = 0, $edit = array()) { - $box = array('format' => FILTER_FORMAT_DEFAULT); - if ($delta) { - $box = block_box_get($delta); - } - if (filter_access($box['format'])) { - return block_box_form($box); - } -} - -/** - * Implementation of hook_block_save(). - */ -function block_block_save($delta = 0, $edit = array()) { - block_box_save($edit, $delta); -} - -/** * Implementation of hook_block_view(). * * Generates the administrator-defined blocks for display. @@ -357,152 +210,6 @@ function _block_rehash() { return $blocks; } -function block_box_get($bid) { - return db_fetch_array(db_query("SELECT * FROM {box} WHERE bid = %d", $bid)); -} - -/** - * Define the custom block form. - */ -function block_box_form($edit = array()) { - $edit += array( - 'info' => '', - 'body' => '', - ); - $form['info'] = array( - '#type' => 'textfield', - '#title' => t('Block description'), - '#default_value' => $edit['info'], - '#maxlength' => 64, - '#description' => t('A brief description of your block. Used on the block overview page.', array('@overview' => url('admin/build/block'))), - '#required' => TRUE, - '#weight' => -19, - ); - $form['body_field']['#weight'] = -17; - $form['body_field']['body'] = array( - '#type' => 'textarea', - '#title' => t('Block body'), - '#default_value' => $edit['body'], - '#text_format' => isset($edit['format']) ? $edit['format'] : FILTER_FORMAT_DEFAULT, - '#rows' => 15, - '#description' => t('The content of the block as shown to the user.'), - '#required' => TRUE, - '#weight' => -17, - ); - - return $form; -} - -function block_box_save($edit, $delta) { - if (!filter_access($edit['body_format'])) { - $edit['body_format'] = FILTER_FORMAT_DEFAULT; - } - - db_query("UPDATE {box} SET body = '%s', info = '%s', format = %d WHERE bid = %d", $edit['body'], $edit['info'], $edit['body_format'], $delta); - - return TRUE; -} - -/** - * Implementation of hook_user_form(). - */ -function block_user_form(&$edit, &$account, $category = NULL) { - if ($category == 'account') { - $rids = array_keys($account->roles); - $result = db_query("SELECT DISTINCT b.* FROM {block} b LEFT JOIN {block_role} r ON b.module = r.module AND b.delta = r.delta WHERE b.status = 1 AND b.custom <> 0 AND (r.rid IN (:rids) OR r.rid IS NULL) ORDER BY b.weight, b.module", array(':rids' => $rids)); - $form['block'] = array('#type' => 'fieldset', '#title' => t('Block configuration'), '#weight' => 3, '#collapsible' => TRUE, '#tree' => TRUE); - while ($block = db_fetch_object($result)) { - $data = module_invoke($block->module, 'block_list'); - if ($data[$block->delta]['info']) { - $return = TRUE; - $form['block'][$block->module][$block->delta] = array('#type' => 'checkbox', '#title' => check_plain($data[$block->delta]['info']), '#default_value' => isset($account->block[$block->module][$block->delta]) ? $account->block[$block->module][$block->delta] : ($block->custom == 1)); - } - } - - if (!empty($return)) { - return $form; - } - } -} - -/** - * Implementation of hook_user_validate(). - */ -function block_user_validate(&$edit, &$account, $category = NULL) { - if (empty($edit['block'])) { - $edit['block'] = array(); - } - return $edit; -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function block_form_system_performance_settings_alter(&$form, &$form_state) { - - // Add the block cache fieldset on the performance settings page. - $form['block_cache'] = array( - '#type' => 'fieldset', - '#title' => t('Block cache'), - '#description' => t('Enabling the block cache can offer a performance increase for all users by preventing blocks from being reconstructed on each page load. If the page cache is also enabled, performance increases from enabling the block cache will mainly benefit authenticated users.'), - '#weight' => 0, - ); - - $form['block_cache']['block_cache'] = array( - '#type' => 'radios', - '#title' => t('Block cache'), - '#default_value' => variable_get('block_cache', CACHE_DISABLED), - '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Enabled (recommended)')), - '#disabled' => count(module_implements('node_grants')), - '#description' => t('Note that block caching is inactive when modules defining content access restrictions are enabled.'), - ); - - // Check if the "Who's online" block is enabled. - $online_block_enabled = db_select('block') - ->condition('module', 'user') - ->condition('delta', 'online') - ->condition('status', 1) - ->countQuery() - ->execute() - ->fetchField(); - - // If the "Who's online" block is enabled, append some descriptive text to - // the end of the form description. - if ($online_block_enabled) { - $form['page_cache']['cache']['#description'] .= '' . t('When caching is enabled, anonymous user sessions are only saved to the database when needed, so the "Who\'s online" block does not display the number of anonymous users.') . '
'; - } - -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function block_form_system_themes_form_alter(&$form, &$form_state) { - $form['#submit'][] = 'block_system_themes_form_submit'; -} - -/** - * Initialize blocks for enabled themes. - */ -function block_system_themes_form_submit(&$form, &$form_state) { - if ($form_state['values']['op'] == t('Save configuration')) { - if (is_array($form_state['values']['status'])) { - foreach ($form_state['values']['status'] as $key => $choice) { - if ($choice || $form_state['values']['theme_default'] == $key) { - block_initialize_theme_blocks($key); - } - } - } - if ($form_state['values']['admin_theme'] && $form_state['values']['admin_theme'] != variable_get('admin_theme', 0)) { - // If we're changing themes, make sure the theme has its blocks initialized. - $has_blocks = (bool) db_query_range('SELECT 1 FROM {block} WHERE theme = :theme', array(':theme' => $form_state['values']['admin_theme']), 0, 1)->fetchField(); - if (!$has_blocks) { - block_initialize_theme_blocks($form_state['values']['admin_theme']); - } - } - } -} - /** * Assign an initial, default set of blocks for a theme. * @@ -727,13 +434,6 @@ function _block_get_cache_id($block) { } /** - * Implementation of hook_flush_caches(). - */ -function block_flush_caches() { - return array('cache_block'); -} - -/** * Process variables for block.tpl.php * * Prepare the values passed to the theme_block function to be passed Index: modules/block/block.registry.inc =================================================================== RCS file: modules/block/block.registry.inc diff -N modules/block/block.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/block/block.registry.inc 22 May 2009 23:44:18 -0000 @@ -0,0 +1,88 @@ + 'Blocks', + 'description' => 'Configure what block content appears in your site\'s sidebars and other regions.', + 'page callback' => 'block_admin_display', + 'access arguments' => array('administer blocks'), + ); + $items['admin/build/block/list'] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + $items['admin/build/block/list/js'] = array( + 'title' => 'JavaScript List Form', + 'page callback' => 'block_admin_display_js', + 'access arguments' => array('administer blocks'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/block/configure'] = array( + 'title' => 'Configure block', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('block_admin_configure'), + 'access arguments' => array('administer blocks'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/block/delete'] = array( + 'title' => 'Delete block', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('block_box_delete'), + 'access arguments' => array('administer blocks'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/block/add'] = array( + 'title' => 'Add block', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('block_add_block_form'), + 'access arguments' => array('administer blocks'), + 'type' => MENU_LOCAL_TASK, + ); + $default = variable_get('theme_default', 'garland'); + foreach (list_themes() as $key => $theme) { + $items['admin/build/block/list/' . $key] = array( + 'title' => check_plain($theme->info['name']), + 'page arguments' => array($key), + 'type' => $key == $default ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK, + 'weight' => $key == $default ? -10 : 0, + 'access callback' => '_block_themes_access', + 'access arguments' => array($theme), + ); + } + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function block_theme() { + return array( + 'block' => array( + 'arguments' => array('block' => NULL), + 'template' => 'block', + ), + 'block_admin_display_form' => array( + 'template' => 'block-admin-display-form', + 'file' => 'block.admin.inc', + 'arguments' => array('form' => NULL), + ), + ); +} + +/** + * Implementation of hook_flush_caches(). + */ +function block_flush_caches() { + return array('cache_block'); +} + Index: modules/block/block.user.inc =================================================================== RCS file: modules/block/block.user.inc diff -N modules/block/block.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/block/block.user.inc 22 May 2009 23:44:18 -0000 @@ -0,0 +1,52 @@ + array( + 'title' => t('Administer blocks'), + 'description' => t('Select which blocks are displayed, and arrange them on the page.'), + ), + ); +} + +/** + * Implementation of hook_user_form(). + */ +function block_user_form(&$edit, &$account, $category = NULL) { + if ($category == 'account') { + $rids = array_keys($account->roles); + $result = db_query("SELECT DISTINCT b.* FROM {block} b LEFT JOIN {block_role} r ON b.module = r.module AND b.delta = r.delta WHERE b.status = 1 AND b.custom <> 0 AND (r.rid IN (:rids) OR r.rid IS NULL) ORDER BY b.weight, b.module", array(':rids' => $rids)); + $form['block'] = array('#type' => 'fieldset', '#title' => t('Block configuration'), '#weight' => 3, '#collapsible' => TRUE, '#tree' => TRUE); + while ($block = db_fetch_object($result)) { + $data = module_invoke($block->module, 'block_list'); + if ($data[$block->delta]['info']) { + $return = TRUE; + $form['block'][$block->module][$block->delta] = array('#type' => 'checkbox', '#title' => check_plain($data[$block->delta]['info']), '#default_value' => isset($account->block[$block->module][$block->delta]) ? $account->block[$block->module][$block->delta] : ($block->custom == 1)); + } + } + + if (!empty($return)) { + return $form; + } + } +} + +/** + * Implementation of hook_user_validate(). + */ +function block_user_validate(&$edit, &$account, $category = NULL) { + if (empty($edit['block'])) { + $edit['block'] = array(); + } + return $edit; +} + Index: modules/blog/blog.block.inc =================================================================== RCS file: modules/blog/blog.block.inc diff -N modules/blog/blog.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/blog/blog.block.inc 22 May 2009 23:44:17 -0000 @@ -0,0 +1,16 @@ +' . t('The blog module allows registered users to maintain an online journal, or blog. Blogs are made up of individual blog entries, and the blog entries are most often displayed in descending order by creation time.') . ''; + $output .= '' . t('There is an (optional) Blogs menu item added to the Navigation menu, which displays all blogs available on your site, and a My blog item displaying the current user\'s blog entries. The Blog entry menu item under Create content allows new blog entries to be created.') . '
'; + $output .= '' . t('Each blog entry is displayed with an automatic link to other blogs created by the same user. By default, blog entries have comments enabled and are automatically promoted to the site front page. The blog module also creates a Recent blog posts block that may be enabled at the blocks administration page.', array('@blocks' => url('admin/build/block'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Blog module.', array('@blog' => 'http://drupal.org/handbook/modules/blog/')) . '
'; + return $output; + } +} + Index: modules/blog/blog.info =================================================================== RCS file: /cvs/drupal/drupal/modules/blog/blog.info,v retrieving revision 1.10 diff -u -p -r1.10 blog.info --- modules/blog/blog.info 11 Oct 2008 02:32:36 -0000 1.10 +++ modules/blog/blog.info 22 May 2009 23:44:21 -0000 @@ -7,3 +7,8 @@ version = VERSION core = 7.x files[] = blog.module files[] = blog.pages.inc +files[] = blog.registry.inc +files[] = blog.user.inc +files[] = blog.block.inc +files[] = blog.help.inc +files[] = blog.node.inc Index: modules/blog/blog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v retrieving revision 1.319 diff -u -p -r1.319 blog.module --- modules/blog/blog.module 3 May 2009 10:11:33 -0000 1.319 +++ modules/blog/blog.module 22 May 2009 23:44:21 -0000 @@ -7,26 +7,6 @@ */ /** - * Implementation of hook_node_info(). - */ -function blog_node_info() { - return array( - 'blog' => array( - 'name' => t('Blog entry'), - 'base' => 'blog', - 'description' => t('A blog entry is a single post to an online journal, or blog.'), - ) - ); -} - -/** - * Implementation of hook_perm(). - */ -function blog_perm() { - return node_list_permissions('blog'); -} - -/** * Implementation of hook_access(). */ function blog_access($op, $node, $account) { @@ -56,44 +36,6 @@ function blog_user_view(&$edit, &$user, } /** - * Implementation of hook_help(). - */ -function blog_help($path, $arg) { - switch ($path) { - case 'admin/help#blog': - $output = '' . t('The blog module allows registered users to maintain an online journal, or blog. Blogs are made up of individual blog entries, and the blog entries are most often displayed in descending order by creation time.') . '
'; - $output .= '' . t('There is an (optional) Blogs menu item added to the Navigation menu, which displays all blogs available on your site, and a My blog item displaying the current user\'s blog entries. The Blog entry menu item under Create content allows new blog entries to be created.') . '
'; - $output .= '' . t('Each blog entry is displayed with an automatic link to other blogs created by the same user. By default, blog entries have comments enabled and are automatically promoted to the site front page. The blog module also creates a Recent blog posts block that may be enabled at the blocks administration page.', array('@blocks' => url('admin/build/block'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Blog module.', array('@blog' => 'http://drupal.org/handbook/modules/blog/')) . '
'; - return $output; - } -} - -/** - * Implementation of hook_form(). - */ -function blog_form($node, $form_state) { - global $nid; - $type = node_get_types('type', $node); - - $form['title'] = array('#type' => 'textfield', '#title' => check_plain($type->title_label), '#required' => TRUE, '#default_value' => !empty($node->title) ? $node->title : NULL, '#weight' => -5); - $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count); - return $form; -} - -/** - * Implementation of hook_view(). - */ -function blog_view($node, $teaser) { - if ((bool)menu_get_object()) { - // Breadcrumb navigation. - drupal_set_breadcrumb(array(l(t('Home'), NULL), l(t('Blogs'), 'blog'), l(t("!name's blog", array('!name' => $node->name)), 'blog/' . $node->uid))); - } - - return node_prepare($node, $teaser); -} - -/** * Implementation of hook_node_view. */ function blog_node_view($node, $teaser = FALSE) { @@ -113,41 +55,6 @@ function blog_node_view($node, $teaser = } /** - * Implementation of hook_menu(). - */ -function blog_menu() { - $items['blog'] = array( - 'title' => 'Blogs', - 'page callback' => 'blog_page_last', - 'access arguments' => array('access content'), - 'type' => MENU_SUGGESTED_ITEM, - ); - $items['blog/%user_uid_optional'] = array( - 'title' => 'My blog', - 'page callback' => 'blog_page_user', - 'page arguments' => array(1), - 'access callback' => 'blog_page_user_access', - 'access arguments' => array(1), - ); - $items['blog/%user/feed'] = array( - 'title' => 'Blogs', - 'page callback' => 'blog_feed_user', - 'page arguments' => array(1), - 'access callback' => 'blog_page_user_access', - 'access arguments' => array(1), - 'type' => MENU_CALLBACK, - ); - $items['blog/feed'] = array( - 'title' => 'Blogs', - 'page callback' => 'blog_feed_last', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** * Access callback for user blog pages. */ function blog_page_user_access($account) { @@ -173,14 +80,6 @@ function _blog_post_exists($account) { } /** - * Implementation of hook_block_list(). - */ -function blog_block_list() { - $block['recent']['info'] = t('Recent blog posts'); - return $block; -} - -/** * Implementation of hook_block_view(). * * Displays the most recent 10 blog titles. Index: modules/blog/blog.node.inc =================================================================== RCS file: modules/blog/blog.node.inc diff -N modules/blog/blog.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/blog/blog.node.inc 22 May 2009 23:44:21 -0000 @@ -0,0 +1,32 @@ + 'textfield', '#title' => check_plain($type->title_label), '#required' => TRUE, '#default_value' => !empty($node->title) ? $node->title : NULL, '#weight' => -5); + $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count); + return $form; +} + +/** + * Implementation of hook_view(). + */ +function blog_view($node, $teaser) { + if ((bool)menu_get_object()) { + // Breadcrumb navigation. + drupal_set_breadcrumb(array(l(t('Home'), NULL), l(t('Blogs'), 'blog'), l(t("!name's blog", array('!name' => $node->name)), 'blog/' . $node->uid))); + } + + return node_prepare($node, $teaser); +} + Index: modules/blog/blog.registry.inc =================================================================== RCS file: modules/blog/blog.registry.inc diff -N modules/blog/blog.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/blog/blog.registry.inc 22 May 2009 23:44:17 -0000 @@ -0,0 +1,56 @@ + 'Blogs', + 'page callback' => 'blog_page_last', + 'access arguments' => array('access content'), + 'type' => MENU_SUGGESTED_ITEM, + ); + $items['blog/%user_uid_optional'] = array( + 'title' => 'My blog', + 'page callback' => 'blog_page_user', + 'page arguments' => array(1), + 'access callback' => 'blog_page_user_access', + 'access arguments' => array(1), + ); + $items['blog/%user/feed'] = array( + 'title' => 'Blogs', + 'page callback' => 'blog_feed_user', + 'page arguments' => array(1), + 'access callback' => 'blog_page_user_access', + 'access arguments' => array(1), + 'type' => MENU_CALLBACK, + ); + $items['blog/feed'] = array( + 'title' => 'Blogs', + 'page callback' => 'blog_feed_last', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implementation of hook_node_info(). + */ +function blog_node_info() { + return array( + 'blog' => array( + 'name' => t('Blog entry'), + 'base' => 'blog', + 'description' => t('A blog entry is a single post to an online journal, or blog.'), + ) + ); +} + Index: modules/blog/blog.user.inc =================================================================== RCS file: modules/blog/blog.user.inc diff -N modules/blog/blog.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/blog/blog.user.inc 22 May 2009 23:44:17 -0000 @@ -0,0 +1,15 @@ + 1) : array(); + $form['blogapi_node_types'] = array( + '#type' => 'checkboxes', + '#title' => t('Enable for external blogging clients'), + '#required' => TRUE, + '#default_value' => variable_get('blogapi_node_types', $defaults), + '#options' => $node_types, + '#description' => t('Select the content types available to external blogging clients via Blog API. If supported, each enabled content type will be displayed as a separate "blog" by the external client.') + ); + + $blogapi_extensions_default = variable_get('blogapi_extensions_default', 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'); + $blogapi_uploadsize_default = variable_get('blogapi_uploadsize_default', 1); + $blogapi_usersize_default = variable_get('blogapi_usersize_default', 1); + + $form['settings_general'] = array( + '#type' => 'fieldset', + '#title' => t('File settings'), + '#collapsible' => TRUE, + ); + + $form['settings_general']['blogapi_extensions_default'] = array( + '#type' => 'textfield', + '#title' => t('Default permitted file extensions'), + '#default_value' => $blogapi_extensions_default, + '#maxlength' => 255, + '#description' => t('Default extensions that users can upload. Separate extensions with a space and do not include the leading dot.'), + ); + + $form['settings_general']['blogapi_uploadsize_default'] = array( + '#type' => 'textfield', + '#title' => t('Default maximum file size per upload'), + '#default_value' => $blogapi_uploadsize_default, + '#size' => 5, + '#maxlength' => 5, + '#description' => t('The default maximum file size a user can upload.'), + '#field_suffix' => t('MB') + ); + + $form['settings_general']['blogapi_usersize_default'] = array( + '#type' => 'textfield', + '#title' => t('Default total file size per user'), + '#default_value' => $blogapi_usersize_default, + '#size' => 5, + '#maxlength' => 5, + '#description' => t('The default maximum size of all files a user can have on the site.'), + '#field_suffix' => t('MB') + ); + + $form['settings_general']['upload_max_size'] = array('#value' => ''. t('Your PHP settings limit the maximum file size per upload to %size.', array('%size' => format_size(file_upload_max_size()))).'
'); + + $roles = user_roles(FALSE, 'administer content with blog api'); + $form['roles'] = array('#type' => 'value', '#value' => $roles); + + foreach ($roles as $rid => $role) { + $form['settings_role_' . $rid] = array( + '#type' => 'fieldset', + '#title' => t('Settings for @role', array('@role' => $role)), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['settings_role_' . $rid]['blogapi_extensions_' . $rid] = array( + '#type' => 'textfield', + '#title' => t('Permitted file extensions'), + '#default_value' => variable_get('blogapi_extensions_' . $rid, $blogapi_extensions_default), + '#maxlength' => 255, + '#description' => t('Extensions that users in this role can upload. Separate extensions with a space and do not include the leading dot.'), + ); + $form['settings_role_' . $rid]['blogapi_uploadsize_' . $rid] = array( + '#type' => 'textfield', + '#title' => t('Maximum file size per upload'), + '#default_value' => variable_get('blogapi_uploadsize_' . $rid, $blogapi_uploadsize_default), + '#size' => 5, + '#maxlength' => 5, + '#description' => t('The maximum size of a file a user can upload (in megabytes).'), + ); + $form['settings_role_' . $rid]['blogapi_usersize_' . $rid] = array( + '#type' => 'textfield', + '#title' => t('Total file size per user'), + '#default_value' => variable_get('blogapi_usersize_' . $rid, $blogapi_usersize_default), + '#size' => 5, + '#maxlength' => 5, + '#description' => t('The maximum size of all files a user can have on the site (in megabytes).'), + ); + } + + return system_settings_form($form, FALSE); +} + Index: modules/blogapi/blogapi.help.inc =================================================================== RCS file: modules/blogapi/blogapi.help.inc diff -N modules/blogapi/blogapi.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/blogapi/blogapi.help.inc 22 May 2009 23:44:17 -0000 @@ -0,0 +1,22 @@ +' . t("The Blog API module allows your site's users to access and post to their blogs from external blogging clients. External blogging clients are available for a wide range of desktop operating systems, and generally provide a feature-rich graphical environment for creating and editing posts.") . ''; + $output .= '' . t('Ecto, a blogging client available for both Mac OS X and Microsoft Windows, can be used with Blog API. Blog API also supports Blogger API, MetaWeblog API, and most of the Movable Type API. Blogging clients and other services (e.g. Flickr\'s "post to blog") that support these APIs may also be compatible.', array('@ecto-link' => url('http://infinite-sushi.com/software/ecto/'), '@blogger-api' => url('http://www.blogger.com/developers/api/1_docs/'), '@metaweblog-api' => url('http://www.xmlrpc.com/metaWeblogApi'), '@movabletype-api' => url('http://www.movabletype.org/docs/mtmanual_programmatic.html'), '@flickr' => url('http://www.flickr.com'))) . '
'; + $output .= '' . t('Select the content types available to external clients on the Blog API settings page. If supported and available, each content type will be displayed as a separate "blog" by the external client.', array('@blogapi-settings' => url('admin/settings/blogapi'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Blog API module.', array('@blogapi' => url('http://drupal.org/handbook/modules/blogapi/'))) . '
'; + return $output; + } +} + Index: modules/blogapi/blogapi.info =================================================================== RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.info,v retrieving revision 1.9 diff -u -p -r1.9 blogapi.info --- modules/blogapi/blogapi.info 11 Oct 2008 02:32:37 -0000 1.9 +++ modules/blogapi/blogapi.info 22 May 2009 23:44:22 -0000 @@ -7,3 +7,8 @@ version = VERSION core = 7.x files[] = blogapi.module files[] = blogapi.install +files[] = blogapi.registry.inc +files[] = blogapi.user.inc +files[] = blogapi.xmlrpc.inc +files[] = blogapi.help.inc +files[] = blogapi.admin.inc Index: modules/blogapi/blogapi.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.module,v retrieving revision 1.150 diff -u -p -r1.150 blogapi.module --- modules/blogapi/blogapi.module 9 May 2009 18:28:11 -0000 1.150 +++ modules/blogapi/blogapi.module 22 May 2009 23:44:22 -0000 @@ -7,321 +7,6 @@ */ /** - * Implementation of hook_help(). - */ -function blogapi_help($path, $arg) { - switch ($path) { - case 'admin/help#blogapi': - $output = '' . t("The Blog API module allows your site's users to access and post to their blogs from external blogging clients. External blogging clients are available for a wide range of desktop operating systems, and generally provide a feature-rich graphical environment for creating and editing posts.") . '
'; - $output .= '' . t('Ecto, a blogging client available for both Mac OS X and Microsoft Windows, can be used with Blog API. Blog API also supports Blogger API, MetaWeblog API, and most of the Movable Type API. Blogging clients and other services (e.g. Flickr\'s "post to blog") that support these APIs may also be compatible.', array('@ecto-link' => url('http://infinite-sushi.com/software/ecto/'), '@blogger-api' => url('http://www.blogger.com/developers/api/1_docs/'), '@metaweblog-api' => url('http://www.xmlrpc.com/metaWeblogApi'), '@movabletype-api' => url('http://www.movabletype.org/docs/mtmanual_programmatic.html'), '@flickr' => url('http://www.flickr.com'))) . '
'; - $output .= '' . t('Select the content types available to external clients on the Blog API settings page. If supported and available, each content type will be displayed as a separate "blog" by the external client.', array('@blogapi-settings' => url('admin/settings/blogapi'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Blog API module.', array('@blogapi' => url('http://drupal.org/handbook/modules/blogapi/'))) . '
'; - return $output; - } -} - -/** - * Implementation of hook_perm(). - */ -function blogapi_perm() { - return array( - 'administer content with blog api' => array( - 'title' => t('Administer content with blog API'), - 'description' => t('Manage website content from external tools.'), - ), - ); -} - -/** - * Implementation of hook_xmlrpc(). - */ -function blogapi_xmlrpc() { - return array( - array( - 'blogger.getUsersBlogs', - 'blogapi_blogger_get_users_blogs', - array('array', 'string', 'string', 'string'), - t('Returns a list of blogs to which an author has posting privileges.')), - array( - 'blogger.getUserInfo', - 'blogapi_blogger_get_user_info', - array('struct', 'string', 'string', 'string'), - t('Returns information about an author in the system.')), - array( - 'blogger.newPost', - 'blogapi_blogger_new_post', - array('string', 'string', 'string', 'string', 'string', 'string', 'boolean'), - t('Creates a new post, and optionally publishes it.')), - array( - 'blogger.editPost', - 'blogapi_blogger_edit_post', - array('boolean', 'string', 'string', 'string', 'string', 'string', 'boolean'), - t('Updates the information about an existing post.')), - array( - 'blogger.getPost', - 'blogapi_blogger_get_post', - array('struct', 'string', 'string', 'string', 'string'), - t('Returns information about a specific post.')), - array( - 'blogger.deletePost', - 'blogapi_blogger_delete_post', - array('boolean', 'string', 'string', 'string', 'string', 'boolean'), - t('Deletes a post.')), - array( - 'blogger.getRecentPosts', - 'blogapi_blogger_get_recent_posts', - array('array', 'string', 'string', 'string', 'string', 'int'), - t('Returns a list of the most recent posts in the system.')), - array( - 'metaWeblog.newPost', - 'blogapi_metaweblog_new_post', - array('string', 'string', 'string', 'string', 'struct', 'boolean'), - t('Creates a new post, and optionally publishes it.')), - array( - 'metaWeblog.editPost', - 'blogapi_metaweblog_edit_post', - array('boolean', 'string', 'string', 'string', 'struct', 'boolean'), - t('Updates information about an existing post.')), - array( - 'metaWeblog.getPost', - 'blogapi_metaweblog_get_post', - array('struct', 'string', 'string', 'string'), - t('Returns information about a specific post.')), - array( - 'metaWeblog.newMediaObject', - 'blogapi_metaweblog_new_media_object', - array('string', 'string', 'string', 'string', 'struct'), - t('Uploads a file to your webserver.')), - array( - 'metaWeblog.getCategories', - 'blogapi_metaweblog_get_category_list', - array('struct', 'string', 'string', 'string'), - t('Returns a list of all categories to which the post is assigned.')), - array( - 'metaWeblog.getRecentPosts', - 'blogapi_metaweblog_get_recent_posts', - array('array', 'string', 'string', 'string', 'int'), - t('Returns a list of the most recent posts in the system.')), - array( - 'mt.getRecentPostTitles', - 'blogapi_mt_get_recent_post_titles', - array('array', 'string', 'string', 'string', 'int'), - t('Returns a bandwidth-friendly list of the most recent posts in the system.')), - array( - 'mt.getCategoryList', - 'blogapi_mt_get_category_list', - array('array', 'string', 'string', 'string'), - t('Returns a list of all categories defined in the blog.')), - array( - 'mt.getPostCategories', - 'blogapi_mt_get_post_categories', - array('array', 'string', 'string', 'string'), - t('Returns a list of all categories to which the post is assigned.')), - array( - 'mt.setPostCategories', - 'blogapi_mt_set_post_categories', - array('boolean', 'string', 'string', 'string', 'array'), - t('Sets the categories for a post.')), - array( - 'mt.supportedMethods', - 'xmlrpc_server_list_methods', - array('array'), - t('Retrieve information about the XML-RPC methods supported by the server.')), - array( - 'mt.supportedTextFilters', - 'blogapi_mt_supported_text_filters', - array('array'), - t('Retrieve information about the text formatting plugins supported by the server.')), - array( - 'mt.publishPost', - 'blogapi_mt_publish_post', - array('boolean', 'string', 'string', 'string'), - t('Publish (rebuild) all of the static files related to an entry from your blog. Equivalent to saving an entry in the system (but without the ping).'))); -} - -/** - * Blogging API callback. Finds the URL of a user's blog. - */ -function blogapi_blogger_get_users_blogs($appid, $username, $password) { - $user = blogapi_validate_user($username, $password); - if ($user->uid) { - $types = _blogapi_get_node_types(); - $structs = array(); - foreach ($types as $type) { - $structs[] = array('url' => url('user/' . $user->uid, array('absolute' => TRUE)), 'blogid' => $type, 'blogName' => $user->name . ": " . $type); - } - - return $structs; - } - else { - return blogapi_error($user); - } -} - -/** - * Blogging API callback. Returns profile information about a user. - */ -function blogapi_blogger_get_user_info($appkey, $username, $password) { - $user = blogapi_validate_user($username, $password); - - if ($user->uid) { - $name = explode(' ', $user->realname ? $user->realname : $user->name, 2); - return array( - 'userid' => $user->uid, - 'lastname' => $name[1], - 'firstname' => $name[0], - 'nickname' => $user->name, - 'email' => $user->mail, - 'url' => url('user/' . $user->uid, array('absolute' => TRUE))); - } - else { - return blogapi_error($user); - } -} - -/** - * Blogging API callback. Inserts a new blog post as a node. - */ -function blogapi_blogger_new_post($appkey, $blogid, $username, $password, $content, $publish) { - $user = blogapi_validate_user($username, $password); - if (!$user->uid) { - return blogapi_error($user); - } - - if (($error = _blogapi_validate_blogid($blogid)) !== TRUE) { - // Return an error if not configured type. - return $error; - } - - $edit = array(); - $edit['type'] = $blogid; - // Get the node type defaults. - $node_type_default = variable_get('node_options_' . $edit['type'], array('status', 'promote')); - $edit['uid'] = $user->uid; - $edit['name'] = $user->name; - $edit['promote'] = in_array('promote', $node_type_default); - $edit['comment'] = variable_get('comment_' . $edit['type'], 2); - $edit['revision'] = in_array('revision', $node_type_default); - $edit['format'] = FILTER_FORMAT_DEFAULT; - $edit['status'] = $publish; - - // Check for bloggerAPI vs. metaWeblogAPI. - if (is_array($content)) { - $edit['title'] = $content['title']; - $edit['body'] = $content['description']; - _blogapi_mt_extra($edit, $content); - } - else { - $edit['title'] = blogapi_blogger_title($content); - $edit['body'] = $content; - } - - if (!node_access('create', $edit['type'])) { - return blogapi_error(t('You do not have permission to create this type of post.')); - } - - if (user_access('administer nodes') && !isset($edit['date'])) { - $edit['date'] = format_date(REQUEST_TIME, 'custom', 'Y-m-d H:i:s O'); - } - - module_invoke_all('node_blogapi_new', $edit); - - $valid = blogapi_status_error_check($edit, $publish); - if ($valid !== TRUE) { - return $valid; - } - - node_validate($edit); - if ($errors = form_get_errors()) { - return blogapi_error(implode("\n", $errors)); - } - - $node = node_submit($edit); - node_save($node); - if ($node->nid) { - watchdog('content', '@type: added %title using blog API.', array('@type' => $node->type, '%title' => $node->title), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid")); - // blogger.newPost returns a string so we cast the nid to a string by putting it in double quotes. - return "$node->nid"; - } - - return blogapi_error(t('Error storing post.')); -} - -/** - * Blogging API callback. Modifies the specified blog node. - */ -function blogapi_blogger_edit_post($appkey, $postid, $username, $password, $content, $publish) { - $user = blogapi_validate_user($username, $password); - - if (!$user->uid) { - return blogapi_error($user); - } - - $node = node_load($postid); - if (!$node) { - return blogapi_error(t('n/a')); - } - // Let the teaser be re-generated. - unset($node->teaser); - - if (!node_access('update', $node)) { - return blogapi_error(t('You do not have permission to update this post.')); - } - // Save the original status for validation of permissions. - $original_status = $node->status; - $node->status = $publish; - - // check for bloggerAPI vs. metaWeblogAPI - if (is_array($content)) { - $node->title = $content['title']; - $node->body = $content['description']; - _blogapi_mt_extra($node, $content); - } - else { - $node->title = blogapi_blogger_title($content); - $node->body = $content; - } - - module_invoke_all('node_blogapi_edit', $node); - - $valid = blogapi_status_error_check($node, $original_status); - if ($valid !== TRUE) { - return $valid; - } - - node_validate($node); - if ($errors = form_get_errors()) { - return blogapi_error(implode("\n", $errors)); - } - - if (user_access('administer nodes') && !isset($edit['date'])) { - $node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O'); - } - $node = node_submit($node); - node_save($node); - if ($node->nid) { - watchdog('content', '@type: updated %title using Blog API.', array('@type' => $node->type, '%title' => $node->title), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid")); - return TRUE; - } - - return blogapi_error(t('Error storing post.')); -} - -/** - * Blogging API callback. Returns a specified blog node. - */ -function blogapi_blogger_get_post($appkey, $postid, $username, $password) { - $user = blogapi_validate_user($username, $password); - if (!$user->uid) { - return blogapi_error($user); - } - - $node = node_load($postid); - - return _blogapi_get_post($node, TRUE); -} - -/** * Check that the user has permission to save the node with the chosen status. * * @return @@ -349,322 +34,6 @@ function blogapi_status_error_check($nod /** - * Blogging API callback. Removes the specified blog node. - */ -function blogapi_blogger_delete_post($appkey, $postid, $username, $password, $publish) { - $user = blogapi_validate_user($username, $password); - if (!$user->uid) { - return blogapi_error($user); - } - - node_delete($postid); - return TRUE; -} - -/** - * Blogging API callback. Returns the latest few postings in a user's blog. $bodies TRUE - * - * returns a bandwidth-friendly list. - */ -function blogapi_blogger_get_recent_posts($appkey, $blogid, $username, $password, $number_of_posts, $bodies = TRUE) { - // Remove unused appkey (from bloggerAPI). - $user = blogapi_validate_user($username, $password); - if (!$user->uid) { - return blogapi_error($user); - } - - if (($error = _blogapi_validate_blogid($blogid)) !== TRUE) { - // Return an error if not configured type. - return $error; - } - - if ($bodies) { - $result = db_query_range("SELECT n.nid, n.title, r.body, r.format, n.comment, n.created, u.name FROM {node} n, {node_revision} r, {users} u WHERE n.uid = u.uid AND n.vid = r.vid AND n.type = :type AND n.uid = :uid ORDER BY n.created DESC", array( - ':type' => $blogid, - ':uid' => $user->uid - ), 0, $number_of_posts); - } - else { - $result = db_query_range("SELECT n.nid, n.title, n.created, u.name FROM {node} n, {users} u WHERE n.uid = u.uid AND n.type = :type AND n.uid = :uid ORDER BY n.created DESC", array( - ':type' => $blogid, - ':uid' => $user->uid - ), 0, $number_of_posts); - } - $blogs = array(); - foreach ($result as $blog) { - $blogs[] = _blogapi_get_post($blog, $bodies); - } - - return $blogs; -} - -function blogapi_metaweblog_new_post($blogid, $username, $password, $content, $publish) { - return blogapi_blogger_new_post('0123456789ABCDEF', $blogid, $username, $password, $content, $publish); -} - -function blogapi_metaweblog_edit_post($postid, $username, $password, $content, $publish) { - return blogapi_blogger_edit_post('0123456789ABCDEF', $postid, $username, $password, $content, $publish); -} - -function blogapi_metaweblog_get_post($postid, $username, $password) { - return blogapi_blogger_get_post('01234567890ABCDEF', $postid, $username, $password); -} - -/** - * Blogging API callback. Inserts a file into Drupal. - */ -function blogapi_metaweblog_new_media_object($blogid, $username, $password, $file) { - $user = blogapi_validate_user($username, $password); - if (!$user->uid) { - return blogapi_error($user); - } - - $usersize = 0; - $uploadsize = 0; - - $roles = array_intersect(user_roles(FALSE, 'administer content with blog api'), $user->roles); - - foreach ($roles as $rid => $name) { - $extensions .= ' ' . strtolower(variable_get("blogapi_extensions_$rid", variable_get('blogapi_extensions_default', 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'))); - $usersize = max($usersize, variable_get("blogapi_usersize_$rid", variable_get('blogapi_usersize_default', 1)) * 1024 * 1024); - $uploadsize = max($uploadsize, variable_get("blogapi_uploadsize_$rid", variable_get('blogapi_uploadsize_default', 1)) * 1024 * 1024); - } - - $filesize = strlen($file['bits']); - - if ($filesize > $uploadsize) { - return blogapi_error(t('It is not possible to upload the file, because it exceeded the maximum filesize of @maxsize.', array('@maxsize' => format_size($uploadsize)))); - } - - if (_blogapi_space_used($user->uid) + $filesize > $usersize) { - return blogapi_error(t('The file can not be attached to this post, because the disk quota of @quota has been reached.', array('@quota' => format_size($usersize)))); - } - - // Only allow files with whitelisted extensions and convert remaining dots to - // underscores to prevent attacks via non-terminal executable extensions with - // files such as exploit.php.jpg. - - $whitelist = array_unique(explode(' ', trim($extensions))); - - $name = basename($file['name']); - - if ($extension_position = strrpos($name, '.')) { - $filename = drupal_substr($name, 0, $extension_position); - $final_extension = drupal_substr($name, $extension_position + 1); - - if (!in_array(strtolower($final_extension), $whitelist)) { - return blogapi_error(t('It is not possible to upload the file, because it is only possible to upload files with the following extensions: @extensions', array('@extensions' => implode(' ', $whitelist)))); - } - - $filename = str_replace('.', '_', $filename); - $filename .= '.' . $final_extension; - } - - $data = $file['bits']; - - if (!$data) { - return blogapi_error(t('No file sent.')); - } - - if (!$file = file_unmanaged_save_data($data, $filename)) { - return blogapi_error(t('Error storing file.')); - } - - $row = new stdClass(); - $row->uid = $user->uid; - $row->filepath = $file; - $row->filesize = $filesize; - - drupal_write_record('blogapi_files', $row); - - // Return the successful result. - return array('url' => file_create_url($file), 'struct'); -} -/** - * Blogging API callback. Returns a list of the taxonomy terms that can be - * associated with a blog node. - */ -function blogapi_metaweblog_get_category_list($blogid, $username, $password) { - $user = blogapi_validate_user($username, $password); - if (!$user->uid) { - return blogapi_error($user); - } - - if (($error = _blogapi_validate_blogid($blogid)) !== TRUE) { - // Return an error if not configured type. - return $error; - } - - $vocabularies = module_invoke('taxonomy', 'get_vocabularies', $blogid, 'vid'); - $categories = array(); - if ($vocabularies) { - foreach ($vocabularies as $vocabulary) { - $terms = module_invoke('taxonomy', 'get_tree', $vocabulary->vid); - foreach ($terms as $term) { - $term_name = $term->name; - foreach (module_invoke('taxonomy', 'get_parents', $term->tid, 'tid') as $parent) { - $term_name = $parent->name . '/' . $term_name; - } - $categories[] = array('categoryName' => $term_name, 'categoryId' => $term->tid); - } - } - } - - return $categories; -} - -function blogapi_metaweblog_get_recent_posts($blogid, $username, $password, $number_of_posts) { - return blogapi_blogger_get_recent_posts('0123456789ABCDEF', $blogid, $username, $password, $number_of_posts, TRUE); -} - -function blogapi_mt_get_recent_post_titles($blogid, $username, $password, $number_of_posts) { - return blogapi_blogger_get_recent_posts('0123456789ABCDEF', $blogid, $username, $password, $number_of_posts, FALSE); -} - -function blogapi_mt_get_category_list($blogid, $username, $password) { - return blogapi_metaweblog_get_category_list($blogid, $username, $password); -} - -/** - * Blogging API callback. Returns a list of the taxonomy terms that are - * assigned to a particular node. - */ -function blogapi_mt_get_post_categories($postid, $username, $password) { - $user = blogapi_validate_user($username, $password); - if (!$user->uid) { - return blogapi_error($user); - } - - $node = node_load($postid); - $terms = module_invoke('taxonomy', 'node_get_terms', $node, 'tid'); - $categories = array(); - foreach ($terms as $term) { - $term_name = $term->name; - foreach (module_invoke('taxonomy', 'get_parents', $term->tid, 'tid') as $parent) { - $term_name = $parent->name . '/' . $term_name; - } - $categories[] = array('categoryName' => $term_name, 'categoryId' => $term->tid, 'isPrimary' => TRUE); - } - - return $categories; -} - -/** - * Blogging API callback. Assigns taxonomy terms to a particular node. - */ -function blogapi_mt_set_post_categories($postid, $username, $password, $categories) { - $user = blogapi_validate_user($username, $password); - if (!$user->uid) { - return blogapi_error($user); - } - - $node = node_load($postid); - $node->taxonomy = array(); - foreach ($categories as $category) { - $node->taxonomy[] = $category['categoryId']; - } - $validated = blogapi_mt_validate_terms($node); - if ($validated !== TRUE) { - return $validated; - } - node_save($node); - - return TRUE; -} - -/** - * Blogging API helper - find allowed taxonomy terms for a node type. - */ -function blogapi_mt_validate_terms($node) { - // We do a lot of heavy lifting here since taxonomy module doesn't have a - // stand-alone validation function. - if (module_exists('taxonomy')) { - $found_terms = array(); - if (!empty($node->taxonomy)) { - $term_list = array_unique($node->taxonomy); - $params = $term_list; - $params[] = $node->type; - $result = db_query(db_rewrite_sql("SELECT t.tid, t.vid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_vocabulary_node_type} n ON t.vid = n.vid WHERE t.tid IN (". db_placeholders($term_list) .") AND n.type = '%s'", 't', 'tid'), $params); - $found_terms = array(); - $found_count = 0; - while ($term = db_fetch_object($result)) { - $found_terms[$term->vid][$term->tid] = $term->tid; - $found_count++; - } - // If the counts don't match, some terms are invalid or not accessible to this user. - if (count($term_list) != $found_count) { - return blogapi_error(t('Invalid categories submitted.')); - } - } - // Look up all the vocabularies for this node type. - $result2 = db_query(db_rewrite_sql("SELECT v.vid, v.name, v.required, v.multiple FROM {taxonomy_vocabulary} v INNER JOIN {taxonomy_vocabulary_node_type} n ON v.vid = n.vid WHERE n.type = '%s'", 'v', 'vid'), $node->type); - // Check each vocabulary associated with this node type. - while ($vocabulary = db_fetch_object($result2)) { - // Required vocabularies must have at least one term. - if ($vocabulary->required && empty($found_terms[$vocabulary->vid])) { - return blogapi_error(t('A category from the @vocabulary_name vocabulary is required.', array('@vocabulary_name' => $vocabulary->name))); - } - // Vocabularies that don't allow multiple terms may have at most one. - if (!($vocabulary->multiple) && (isset($found_terms[$vocabulary->vid]) && count($found_terms[$vocabulary->vid]) > 1)) { - return blogapi_error(t('You may only choose one category from the @vocabulary_name vocabulary.'), array('@vocabulary_name' => $vocabulary->name)); - } - } - } - elseif (!empty($node->taxonomy)) { - return blogapi_error(t('Error saving categories. This feature is not available.')); - } - return TRUE; -} - -/** - * Blogging API callback. Sends a list of available text formats. - */ -function blogapi_mt_supported_text_filters() { - // NOTE: we're only using anonymous' formats because the MT spec - // does not allow for per-user formats. - $formats = filter_formats(); - - $filters = array(); - foreach ($formats as $format) { - $filter['key'] = $format->format; - $filter['label'] = $format->name; - $filters[] = $filter; - } - - return $filters; -} - -/** - * Blogging API callback. Publishes the given node. - */ -function blogapi_mt_publish_post($postid, $username, $password) { - $user = blogapi_validate_user($username, $password); - - if (!$user->uid) { - return blogapi_error($user); - } - $node = node_load($postid); - - if (!$node) { - return blogapi_error(t('Invalid post.')); - } - - // Nothing needs to be done if already published. - if ($node->status) { - return; - } - - if (!node_access('update', $node) || !user_access('administer nodes')) { - return blogapi_error(t('You do not have permission to update this post.')); - } - - $node->status = 1; - node_save($node); - - return TRUE; -} - -/** * Prepare an error message for returning to the XMLRPC caller. */ function blogapi_error($message) { @@ -701,136 +70,6 @@ function blogapi_validate_user($username } /** - * For the blogger API, extract the node title from the contents field. - */ -function blogapi_blogger_title(&$contents) { - if (preg_match('/'. t('Your PHP settings limit the maximum file size per upload to %size.', array('%size' => format_size(file_upload_max_size()))).'
'); - - $roles = user_roles(FALSE, 'administer content with blog api'); - $form['roles'] = array('#type' => 'value', '#value' => $roles); - - foreach ($roles as $rid => $role) { - $form['settings_role_' . $rid] = array( - '#type' => 'fieldset', - '#title' => t('Settings for @role', array('@role' => $role)), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - ); - $form['settings_role_' . $rid]['blogapi_extensions_' . $rid] = array( - '#type' => 'textfield', - '#title' => t('Permitted file extensions'), - '#default_value' => variable_get('blogapi_extensions_' . $rid, $blogapi_extensions_default), - '#maxlength' => 255, - '#description' => t('Extensions that users in this role can upload. Separate extensions with a space and do not include the leading dot.'), - ); - $form['settings_role_' . $rid]['blogapi_uploadsize_' . $rid] = array( - '#type' => 'textfield', - '#title' => t('Maximum file size per upload'), - '#default_value' => variable_get('blogapi_uploadsize_' . $rid, $blogapi_uploadsize_default), - '#size' => 5, - '#maxlength' => 5, - '#description' => t('The maximum size of a file a user can upload (in megabytes).'), - ); - $form['settings_role_' . $rid]['blogapi_usersize_' . $rid] = array( - '#type' => 'textfield', - '#title' => t('Total file size per user'), - '#default_value' => variable_get('blogapi_usersize_' . $rid, $blogapi_usersize_default), - '#size' => 5, - '#maxlength' => 5, - '#description' => t('The maximum size of all files a user can have on the site (in megabytes).'), - ); - } - - return system_settings_form($form, FALSE); -} - -/** - * Implementation of hook_menu(). - */ -function blogapi_menu() { - $items['blogapi/rsd'] = array( - 'title' => 'RSD', - 'page callback' => 'blogapi_rsd', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['admin/settings/blogapi'] = array( - 'title' => 'Blog API', - 'description' => 'Configure the content types available to external blogging clients.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('blogapi_admin_settings'), - 'access arguments' => array('administer site configuration'), - 'type' => MENU_NORMAL_ITEM, - ); - - return $items; -} - -/** * Implementation of hook_init(). */ function blogapi_init() { Index: modules/blogapi/blogapi.registry.inc =================================================================== RCS file: modules/blogapi/blogapi.registry.inc diff -N modules/blogapi/blogapi.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/blogapi/blogapi.registry.inc 22 May 2009 23:44:16 -0000 @@ -0,0 +1,30 @@ + 'RSD', + 'page callback' => 'blogapi_rsd', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['admin/settings/blogapi'] = array( + 'title' => 'Blog API', + 'description' => 'Configure the content types available to external blogging clients.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('blogapi_admin_settings'), + 'access arguments' => array('administer site configuration'), + 'type' => MENU_NORMAL_ITEM, + ); + + return $items; +} + Index: modules/blogapi/blogapi.user.inc =================================================================== RCS file: modules/blogapi/blogapi.user.inc diff -N modules/blogapi/blogapi.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/blogapi/blogapi.user.inc 22 May 2009 23:44:16 -0000 @@ -0,0 +1,20 @@ + array( + 'title' => t('Administer content with blog API'), + 'description' => t('Manage website content from external tools.'), + ), + ); +} + Index: modules/blogapi/blogapi.xmlrpc.inc =================================================================== RCS file: modules/blogapi/blogapi.xmlrpc.inc diff -N modules/blogapi/blogapi.xmlrpc.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/blogapi/blogapi.xmlrpc.inc 22 May 2009 23:44:17 -0000 @@ -0,0 +1,628 @@ +uid) { + $types = _blogapi_get_node_types(); + $structs = array(); + foreach ($types as $type) { + $structs[] = array('url' => url('user/' . $user->uid, array('absolute' => TRUE)), 'blogid' => $type, 'blogName' => $user->name . ": " . $type); + } + + return $structs; + } + else { + return blogapi_error($user); + } +} + +/** + * Blogging API callback. Returns profile information about a user. + */ +function blogapi_blogger_get_user_info($appkey, $username, $password) { + $user = blogapi_validate_user($username, $password); + + if ($user->uid) { + $name = explode(' ', $user->realname ? $user->realname : $user->name, 2); + return array( + 'userid' => $user->uid, + 'lastname' => $name[1], + 'firstname' => $name[0], + 'nickname' => $user->name, + 'email' => $user->mail, + 'url' => url('user/' . $user->uid, array('absolute' => TRUE))); + } + else { + return blogapi_error($user); + } +} + +/** + * Blogging API callback. Inserts a new blog post as a node. + */ +function blogapi_blogger_new_post($appkey, $blogid, $username, $password, $content, $publish) { + $user = blogapi_validate_user($username, $password); + if (!$user->uid) { + return blogapi_error($user); + } + + if (($error = _blogapi_validate_blogid($blogid)) !== TRUE) { + // Return an error if not configured type. + return $error; + } + + $edit = array(); + $edit['type'] = $blogid; + // Get the node type defaults. + $node_type_default = variable_get('node_options_' . $edit['type'], array('status', 'promote')); + $edit['uid'] = $user->uid; + $edit['name'] = $user->name; + $edit['promote'] = in_array('promote', $node_type_default); + $edit['comment'] = variable_get('comment_' . $edit['type'], 2); + $edit['revision'] = in_array('revision', $node_type_default); + $edit['format'] = FILTER_FORMAT_DEFAULT; + $edit['status'] = $publish; + + // Check for bloggerAPI vs. metaWeblogAPI. + if (is_array($content)) { + $edit['title'] = $content['title']; + $edit['body'] = $content['description']; + _blogapi_mt_extra($edit, $content); + } + else { + $edit['title'] = blogapi_blogger_title($content); + $edit['body'] = $content; + } + + if (!node_access('create', $edit['type'])) { + return blogapi_error(t('You do not have permission to create this type of post.')); + } + + if (user_access('administer nodes') && !isset($edit['date'])) { + $edit['date'] = format_date(REQUEST_TIME, 'custom', 'Y-m-d H:i:s O'); + } + + module_invoke_all('node_blogapi_new', $edit); + + $valid = blogapi_status_error_check($edit, $publish); + if ($valid !== TRUE) { + return $valid; + } + + node_validate($edit); + if ($errors = form_get_errors()) { + return blogapi_error(implode("\n", $errors)); + } + + $node = node_submit($edit); + node_save($node); + if ($node->nid) { + watchdog('content', '@type: added %title using blog API.', array('@type' => $node->type, '%title' => $node->title), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid")); + // blogger.newPost returns a string so we cast the nid to a string by putting it in double quotes. + return "$node->nid"; + } + + return blogapi_error(t('Error storing post.')); +} + +/** + * Blogging API callback. Modifies the specified blog node. + */ +function blogapi_blogger_edit_post($appkey, $postid, $username, $password, $content, $publish) { + $user = blogapi_validate_user($username, $password); + + if (!$user->uid) { + return blogapi_error($user); + } + + $node = node_load($postid); + if (!$node) { + return blogapi_error(t('n/a')); + } + // Let the teaser be re-generated. + unset($node->teaser); + + if (!node_access('update', $node)) { + return blogapi_error(t('You do not have permission to update this post.')); + } + // Save the original status for validation of permissions. + $original_status = $node->status; + $node->status = $publish; + + // check for bloggerAPI vs. metaWeblogAPI + if (is_array($content)) { + $node->title = $content['title']; + $node->body = $content['description']; + _blogapi_mt_extra($node, $content); + } + else { + $node->title = blogapi_blogger_title($content); + $node->body = $content; + } + + module_invoke_all('node_blogapi_edit', $node); + + $valid = blogapi_status_error_check($node, $original_status); + if ($valid !== TRUE) { + return $valid; + } + + node_validate($node); + if ($errors = form_get_errors()) { + return blogapi_error(implode("\n", $errors)); + } + + if (user_access('administer nodes') && !isset($edit['date'])) { + $node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O'); + } + $node = node_submit($node); + node_save($node); + if ($node->nid) { + watchdog('content', '@type: updated %title using Blog API.', array('@type' => $node->type, '%title' => $node->title), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid")); + return TRUE; + } + + return blogapi_error(t('Error storing post.')); +} + +/** + * Blogging API callback. Returns a specified blog node. + */ +function blogapi_blogger_get_post($appkey, $postid, $username, $password) { + $user = blogapi_validate_user($username, $password); + if (!$user->uid) { + return blogapi_error($user); + } + + $node = node_load($postid); + + return _blogapi_get_post($node, TRUE); +} + +/** + * Blogging API callback. Removes the specified blog node. + */ +function blogapi_blogger_delete_post($appkey, $postid, $username, $password, $publish) { + $user = blogapi_validate_user($username, $password); + if (!$user->uid) { + return blogapi_error($user); + } + + node_delete($postid); + return TRUE; +} + +/** + * Blogging API callback. Returns the latest few postings in a user's blog. $bodies TRUE + * + * returns a bandwidth-friendly list. + */ +function blogapi_blogger_get_recent_posts($appkey, $blogid, $username, $password, $number_of_posts, $bodies = TRUE) { + // Remove unused appkey (from bloggerAPI). + $user = blogapi_validate_user($username, $password); + if (!$user->uid) { + return blogapi_error($user); + } + + if (($error = _blogapi_validate_blogid($blogid)) !== TRUE) { + // Return an error if not configured type. + return $error; + } + + if ($bodies) { + $result = db_query_range("SELECT n.nid, n.title, r.body, r.format, n.comment, n.created, u.name FROM {node} n, {node_revision} r, {users} u WHERE n.uid = u.uid AND n.vid = r.vid AND n.type = :type AND n.uid = :uid ORDER BY n.created DESC", array( + ':type' => $blogid, + ':uid' => $user->uid + ), 0, $number_of_posts); + } + else { + $result = db_query_range("SELECT n.nid, n.title, n.created, u.name FROM {node} n, {users} u WHERE n.uid = u.uid AND n.type = :type AND n.uid = :uid ORDER BY n.created DESC", array( + ':type' => $blogid, + ':uid' => $user->uid + ), 0, $number_of_posts); + } + $blogs = array(); + foreach ($result as $blog) { + $blogs[] = _blogapi_get_post($blog, $bodies); + } + + return $blogs; +} + +function blogapi_metaweblog_new_post($blogid, $username, $password, $content, $publish) { + return blogapi_blogger_new_post('0123456789ABCDEF', $blogid, $username, $password, $content, $publish); +} + +function blogapi_metaweblog_edit_post($postid, $username, $password, $content, $publish) { + return blogapi_blogger_edit_post('0123456789ABCDEF', $postid, $username, $password, $content, $publish); +} + +function blogapi_metaweblog_get_post($postid, $username, $password) { + return blogapi_blogger_get_post('01234567890ABCDEF', $postid, $username, $password); +} + +/** + * Blogging API callback. Inserts a file into Drupal. + */ +function blogapi_metaweblog_new_media_object($blogid, $username, $password, $file) { + $user = blogapi_validate_user($username, $password); + if (!$user->uid) { + return blogapi_error($user); + } + + $usersize = 0; + $uploadsize = 0; + + $roles = array_intersect(user_roles(FALSE, 'administer content with blog api'), $user->roles); + + foreach ($roles as $rid => $name) { + $extensions .= ' ' . strtolower(variable_get("blogapi_extensions_$rid", variable_get('blogapi_extensions_default', 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'))); + $usersize = max($usersize, variable_get("blogapi_usersize_$rid", variable_get('blogapi_usersize_default', 1)) * 1024 * 1024); + $uploadsize = max($uploadsize, variable_get("blogapi_uploadsize_$rid", variable_get('blogapi_uploadsize_default', 1)) * 1024 * 1024); + } + + $filesize = strlen($file['bits']); + + if ($filesize > $uploadsize) { + return blogapi_error(t('It is not possible to upload the file, because it exceeded the maximum filesize of @maxsize.', array('@maxsize' => format_size($uploadsize)))); + } + + if (_blogapi_space_used($user->uid) + $filesize > $usersize) { + return blogapi_error(t('The file can not be attached to this post, because the disk quota of @quota has been reached.', array('@quota' => format_size($usersize)))); + } + + // Only allow files with whitelisted extensions and convert remaining dots to + // underscores to prevent attacks via non-terminal executable extensions with + // files such as exploit.php.jpg. + + $whitelist = array_unique(explode(' ', trim($extensions))); + + $name = basename($file['name']); + + if ($extension_position = strrpos($name, '.')) { + $filename = drupal_substr($name, 0, $extension_position); + $final_extension = drupal_substr($name, $extension_position + 1); + + if (!in_array(strtolower($final_extension), $whitelist)) { + return blogapi_error(t('It is not possible to upload the file, because it is only possible to upload files with the following extensions: @extensions', array('@extensions' => implode(' ', $whitelist)))); + } + + $filename = str_replace('.', '_', $filename); + $filename .= '.' . $final_extension; + } + + $data = $file['bits']; + + if (!$data) { + return blogapi_error(t('No file sent.')); + } + + if (!$file = file_unmanaged_save_data($data, $filename)) { + return blogapi_error(t('Error storing file.')); + } + + $row = new stdClass(); + $row->uid = $user->uid; + $row->filepath = $file; + $row->filesize = $filesize; + + drupal_write_record('blogapi_files', $row); + + // Return the successful result. + return array('url' => file_create_url($file), 'struct'); +} +/** + * Blogging API callback. Returns a list of the taxonomy terms that can be + * associated with a blog node. + */ +function blogapi_metaweblog_get_category_list($blogid, $username, $password) { + $user = blogapi_validate_user($username, $password); + if (!$user->uid) { + return blogapi_error($user); + } + + if (($error = _blogapi_validate_blogid($blogid)) !== TRUE) { + // Return an error if not configured type. + return $error; + } + + $vocabularies = module_invoke('taxonomy', 'get_vocabularies', $blogid, 'vid'); + $categories = array(); + if ($vocabularies) { + foreach ($vocabularies as $vocabulary) { + $terms = module_invoke('taxonomy', 'get_tree', $vocabulary->vid); + foreach ($terms as $term) { + $term_name = $term->name; + foreach (module_invoke('taxonomy', 'get_parents', $term->tid, 'tid') as $parent) { + $term_name = $parent->name . '/' . $term_name; + } + $categories[] = array('categoryName' => $term_name, 'categoryId' => $term->tid); + } + } + } + + return $categories; +} + +function blogapi_metaweblog_get_recent_posts($blogid, $username, $password, $number_of_posts) { + return blogapi_blogger_get_recent_posts('0123456789ABCDEF', $blogid, $username, $password, $number_of_posts, TRUE); +} + +function blogapi_mt_get_recent_post_titles($blogid, $username, $password, $number_of_posts) { + return blogapi_blogger_get_recent_posts('0123456789ABCDEF', $blogid, $username, $password, $number_of_posts, FALSE); +} + +function blogapi_mt_get_category_list($blogid, $username, $password) { + return blogapi_metaweblog_get_category_list($blogid, $username, $password); +} + +/** + * Blogging API callback. Returns a list of the taxonomy terms that are + * assigned to a particular node. + */ +function blogapi_mt_get_post_categories($postid, $username, $password) { + $user = blogapi_validate_user($username, $password); + if (!$user->uid) { + return blogapi_error($user); + } + + $node = node_load($postid); + $terms = module_invoke('taxonomy', 'node_get_terms', $node, 'tid'); + $categories = array(); + foreach ($terms as $term) { + $term_name = $term->name; + foreach (module_invoke('taxonomy', 'get_parents', $term->tid, 'tid') as $parent) { + $term_name = $parent->name . '/' . $term_name; + } + $categories[] = array('categoryName' => $term_name, 'categoryId' => $term->tid, 'isPrimary' => TRUE); + } + + return $categories; +} + +/** + * Blogging API callback. Assigns taxonomy terms to a particular node. + */ +function blogapi_mt_set_post_categories($postid, $username, $password, $categories) { + $user = blogapi_validate_user($username, $password); + if (!$user->uid) { + return blogapi_error($user); + } + + $node = node_load($postid); + $node->taxonomy = array(); + foreach ($categories as $category) { + $node->taxonomy[] = $category['categoryId']; + } + $validated = blogapi_mt_validate_terms($node); + if ($validated !== TRUE) { + return $validated; + } + node_save($node); + + return TRUE; +} + +/** + * Blogging API helper - find allowed taxonomy terms for a node type. + */ +function blogapi_mt_validate_terms($node) { + // We do a lot of heavy lifting here since taxonomy module doesn't have a + // stand-alone validation function. + if (module_exists('taxonomy')) { + $found_terms = array(); + if (!empty($node->taxonomy)) { + $term_list = array_unique($node->taxonomy); + $params = $term_list; + $params[] = $node->type; + $result = db_query(db_rewrite_sql("SELECT t.tid, t.vid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_vocabulary_node_type} n ON t.vid = n.vid WHERE t.tid IN (". db_placeholders($term_list) .") AND n.type = '%s'", 't', 'tid'), $params); + $found_terms = array(); + $found_count = 0; + while ($term = db_fetch_object($result)) { + $found_terms[$term->vid][$term->tid] = $term->tid; + $found_count++; + } + // If the counts don't match, some terms are invalid or not accessible to this user. + if (count($term_list) != $found_count) { + return blogapi_error(t('Invalid categories submitted.')); + } + } + // Look up all the vocabularies for this node type. + $result2 = db_query(db_rewrite_sql("SELECT v.vid, v.name, v.required, v.multiple FROM {taxonomy_vocabulary} v INNER JOIN {taxonomy_vocabulary_node_type} n ON v.vid = n.vid WHERE n.type = '%s'", 'v', 'vid'), $node->type); + // Check each vocabulary associated with this node type. + while ($vocabulary = db_fetch_object($result2)) { + // Required vocabularies must have at least one term. + if ($vocabulary->required && empty($found_terms[$vocabulary->vid])) { + return blogapi_error(t('A category from the @vocabulary_name vocabulary is required.', array('@vocabulary_name' => $vocabulary->name))); + } + // Vocabularies that don't allow multiple terms may have at most one. + if (!($vocabulary->multiple) && (isset($found_terms[$vocabulary->vid]) && count($found_terms[$vocabulary->vid]) > 1)) { + return blogapi_error(t('You may only choose one category from the @vocabulary_name vocabulary.'), array('@vocabulary_name' => $vocabulary->name)); + } + } + } + elseif (!empty($node->taxonomy)) { + return blogapi_error(t('Error saving categories. This feature is not available.')); + } + return TRUE; +} + +/** + * Blogging API callback. Sends a list of available text formats. + */ +function blogapi_mt_supported_text_filters() { + // NOTE: we're only using anonymous' formats because the MT spec + // does not allow for per-user formats. + $formats = filter_formats(); + + $filters = array(); + foreach ($formats as $format) { + $filter['key'] = $format->format; + $filter['label'] = $format->name; + $filters[] = $filter; + } + + return $filters; +} + +/** + * Blogging API callback. Publishes the given node. + */ +function blogapi_mt_publish_post($postid, $username, $password) { + $user = blogapi_validate_user($username, $password); + + if (!$user->uid) { + return blogapi_error($user); + } + $node = node_load($postid); + + if (!$node) { + return blogapi_error(t('Invalid post.')); + } + + // Nothing needs to be done if already published. + if ($node->status) { + return; + } + + if (!node_access('update', $node) || !user_access('administer nodes')) { + return blogapi_error(t('You do not have permission to update this post.')); + } + + $node->status = 1; + node_save($node); + + return TRUE; +} + +/** + * For the blogger API, extract the node title from the contents field. + */ +function blogapi_blogger_title(&$contents) { + if (preg_match('/' . t('%title is part of a book outline, and has associated child pages. If you proceed with deletion, the child pages will be relocated automatically.', array('%title' => $node->title)) . '
', + '#weight' => -10, + ); + } +} + Index: modules/book/book.help.inc =================================================================== RCS file: modules/book/book.help.inc diff -N modules/book/book.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/book/book.help.inc 22 May 2009 23:44:15 -0000 @@ -0,0 +1,31 @@ +' . t('The book module is suited for creating structured, multi-page hypertexts such as site resource guides, manuals, and Frequently Asked Questions (FAQs). It permits a document to have chapters, sections, subsections, etc. Authors with suitable permissions can add pages to a collaborative book, placing them into the existing document by adding them to a table of contents menu.') . ''; + $output .= '' . t('Pages in the book hierarchy have navigation elements at the bottom of the page for moving through the text. These links lead to the previous and next pages in the book, and to the level above the current page in the book\'s structure. More comprehensive navigation may be provided by enabling the book navigation block on the blocks administration page.', array('@admin-block' => url('admin/build/block'))) . '
'; + $output .= '' . t('Users can select the printer-friendly version link visible at the bottom of a book page to generate a printer-friendly display of the page and all of its subsections. ') . '
'; + $output .= '' . t("Users with the administer book outlines permission can add a post of any content type to a book, by selecting the appropriate book while editing the post or by using the interface available on the post's outline tab.") . '
'; + $output .= '' . t('Administrators can view a list of all books on the book administration page. The Outline page for each book allows section titles to be edited or rearranged.', array('@admin-node-book' => url('admin/content/book'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Book module.', array('@book' => 'http://drupal.org/handbook/modules/book/')) . '
'; + + return $output; + + case 'admin/content/book': + return '' . t('The book module offers a means to organize a collection of related posts, collectively known as a book. When viewed, these posts automatically display links to adjacent book pages, providing a simple navigation system for creating and reviewing structured content.') . '
'; + + case 'node/%/outline': + return '' . t('The outline feature allows you to include posts in the book hierarchy, as well as move them within the hierarchy or to reorder an entire book.', array('@book' => url('book'), '@book-admin' => url('admin/content/book'))) . '
'; + } +} + Index: modules/book/book.info =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.info,v retrieving revision 1.11 diff -u -p -r1.11 book.info --- modules/book/book.info 13 Oct 2008 19:59:41 -0000 1.11 +++ modules/book/book.info 22 May 2009 23:44:15 -0000 @@ -9,3 +9,9 @@ files[] = book.module files[] = book.admin.inc files[] = book.pages.inc files[] = book.install +files[] = book.registry.inc +files[] = book.user.inc +files[] = book.block.inc +files[] = book.node.inc +files[] = book.form.inc +files[] = book.help.inc Index: modules/book/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.module,v retrieving revision 1.493 diff -u -p -r1.493 book.module --- modules/book/book.module 9 May 2009 18:28:11 -0000 1.493 +++ modules/book/book.module 22 May 2009 23:44:15 -0000 @@ -7,60 +7,6 @@ */ /** - * Implementation of hook_theme(). - */ -function book_theme() { - return array( - 'book_navigation' => array( - 'arguments' => array('book_link' => NULL), - 'template' => 'book-navigation', - ), - 'book_export_html' => array( - 'arguments' => array('title' => NULL, 'contents' => NULL, 'depth' => NULL), - 'template' => 'book-export-html', - ), - 'book_admin_table' => array( - 'arguments' => array('form' => NULL), - ), - 'book_title_link' => array( - 'arguments' => array('link' => NULL), - ), - 'book_all_books_block' => array( - 'arguments' => array('book_menus' => array()), - 'template' => 'book-all-books-block', - ), - 'book_node_export_html' => array( - 'arguments' => array('node' => NULL, 'children' => NULL), - 'template' => 'book-node-export-html', - ), - ); -} - -/** - * Implementation of hook_perm(). - */ -function book_perm() { - return array( - 'administer book outlines' => array( - 'title' => t('Administer book outlines'), - 'description' => t('Manage books through the administration panel.'), - ), - 'create new books' => array( - 'title' => t('Create new books'), - 'description' => t('Add new top-level books.'), - ), - 'add content to books' => array( - 'title' => t('Add content to books'), - 'description' => t('Add new content and child pages to books.'), - ), - 'access printer-friendly version' => array( - 'title' => t('Access printer-friendly version'), - 'description' => t('View a book page and all of its sub-pages as a single document for ease of printing. Can be performance heavy.'), - ), - ); -} - -/** * Inject links into $node as needed. */ function book_node_view_link($node, $teaser) { @@ -96,74 +42,6 @@ function book_node_view_link($node, $tea } /** - * Implementation of hook_menu(). - */ -function book_menu() { - $items['admin/content/book'] = array( - 'title' => 'Books', - 'description' => "Manage your site's book outlines.", - 'page callback' => 'book_admin_overview', - 'access arguments' => array('administer book outlines'), - ); - $items['admin/content/book/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/content/book/settings'] = array( - 'title' => 'Settings', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('book_admin_settings'), - 'access arguments' => array('administer site configuration'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 8, - ); - $items['admin/content/book/%node'] = array( - 'title' => 'Re-order book pages and change titles', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('book_admin_edit', 3), - 'access callback' => '_book_outline_access', - 'access arguments' => array(3), - 'type' => MENU_CALLBACK, - ); - $items['book'] = array( - 'title' => 'Books', - 'page callback' => 'book_render', - 'access arguments' => array('access content'), - 'type' => MENU_SUGGESTED_ITEM, - ); - $items['book/export/%/%'] = array( - 'page callback' => 'book_export', - 'page arguments' => array(2, 3), - 'access arguments' => array('access printer-friendly version'), - 'type' => MENU_CALLBACK, - ); - $items['node/%node/outline'] = array( - 'title' => 'Outline', - 'page callback' => 'book_outline', - 'page arguments' => array(1), - 'access callback' => '_book_outline_access', - 'access arguments' => array(1), - 'type' => MENU_LOCAL_TASK, - 'weight' => 2, - ); - $items['node/%node/outline/remove'] = array( - 'title' => 'Remove from outline', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('book_remove_form', 1), - 'access callback' => '_book_outline_remove_access', - 'access arguments' => array(1), - 'type' => MENU_CALLBACK, - ); - $items['book/js/form'] = array( - 'page callback' => 'book_form_update', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** * Menu item access callback - determine if the outline tab is accessible. */ function _book_outline_access($node) { @@ -185,17 +63,6 @@ function book_init() { } /** - * Implementation of hook_block_list(). - */ -function book_block_list() { - $block = array(); - $block['navigation']['info'] = t('Book navigation'); - $block['navigation']['cache'] = BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_ROLE; - - return $block; -} - -/** * Implementation of hook_block_view(). * * Displays the book table of contents in a block when the current page is a @@ -249,34 +116,6 @@ function book_block_view($delta = '') { } /** - * Implementation of hook_block_configure(). - */ -function book_block_configure($delta = '') { - $block = array(); - $options = array( - 'all pages' => t('Show block on all pages'), - 'book pages' => t('Show block only on book pages'), - ); - $form['book_block_mode'] = array( - '#type' => 'radios', - '#title' => t('Book navigation block display'), - '#options' => $options, - '#default_value' => variable_get('book_block_mode', 'all pages'), - '#description' => t("If Show block on all pages is selected, the block will contain the automatically generated menus for all of the site's books. If Show block only on book pages is selected, the block will contain only the one menu corresponding to the current page's book. In this case, if the current page is not in a book, no block will be displayed. The Page specific visibility settings or other visibility settings can be used in addition to selectively display this block."), - ); - - return $form; -} - -/** - * Implementation of hook_block_save(). - */ -function book_block_save($delta = '', $edit = array()) { - $block = array(); - variable_set('book_block_mode', $edit['book_block_mode']); -} - -/** * Generate the HTML output for a link to a book title when used as a block title. * * @ingroup themeable @@ -735,109 +574,6 @@ function book_page_alter(&$page) { } /** - * Implementation of hook_node_presave(). - */ -function book_node_presave($node) { - // Always save a revision for non-administrators. - if (!empty($node->book['bid']) && !user_access('administer nodes')) { - $node->revision = 1; - // The database schema requires a log message for every revision. - if (!isset($node->log)) { - $node->log = ''; - } - } - // Make sure a new node gets a new menu link. - if (empty($node->nid)) { - $node->book['mlid'] = NULL; - } -} - -/** - * Implementation of hook_node_insert(). - */ -function book_node_insert($node) { - if (!empty($node->book['bid'])) { - if ($node->book['bid'] == 'new') { - // New nodes that are their own book. - $node->book['bid'] = $node->nid; - } - $node->book['nid'] = $node->nid; - $node->book['menu_name'] = book_menu_name($node->book['bid']); - _book_update_outline($node); - } -} - -/** - * Implementation of hook_node_update(). - */ -function book_node_update($node) { - if (!empty($node->book['bid'])) { - if ($node->book['bid'] == 'new') { - // New nodes that are their own book. - $node->book['bid'] = $node->nid; - } - $node->book['nid'] = $node->nid; - $node->book['menu_name'] = book_menu_name($node->book['bid']); - _book_update_outline($node); - } -} - -/** - * Implementation of hook_node_delete(). - */ -function book_node_delete($node) { - if (!empty($node->book['bid'])) { - if ($node->nid == $node->book['bid']) { - // Handle deletion of a top-level post. - $result = db_query("SELECT b.nid FROM {menu_links} ml INNER JOIN {book} b on b.mlid = ml.mlid WHERE ml.plid = :plid", array( - ':plid' => $node->book['mlid'] - )); - foreach ($result as $child) { - $child_node = node_load($child->nid); - $child_node->book['bid'] = $child_node->nid; - _book_update_outline($child_node); - } - } - menu_link_delete($node->book['mlid']); - db_delete('book') - ->condition('mlid', $node->book['mlid']) - ->execute(); - } -} - -/** - * Implementation of hook_node_prepare(). - */ -function book_node_prepare($node) { - // Prepare defaults for the add/edit form. - if (empty($node->book) && (user_access('add content to books') || user_access('administer book outlines'))) { - $node->book = array(); - - if (empty($node->nid) && isset($_GET['parent']) && is_numeric($_GET['parent'])) { - // Handle "Add child page" links: - $parent = book_link_load($_GET['parent']); - - if ($parent && $parent['access']) { - $node->book['bid'] = $parent['bid']; - $node->book['plid'] = $parent['mlid']; - $node->book['menu_name'] = $parent['menu_name']; - } - } - // Set defaults. - $node->book += _book_link_defaults(!empty($node->nid) ? $node->nid : 'new'); - } - else { - if (isset($node->book['bid']) && !isset($node->book['original_bid'])) { - $node->book['original_bid'] = $node->book['bid']; - } - } - // Find the depth limit for the parent select. - if (isset($node->book['bid']) && !isset($node->book['parent_depth_limit'])) { - $node->book['parent_depth_limit'] = _book_parent_depth_limit($node->book); - } -} - -/** * Find the depth limit for items in the parent select. */ function _book_parent_depth_limit($book_link) { @@ -845,20 +581,6 @@ function _book_parent_depth_limit($book_ } /** - * Form altering function for the confirm form for a single node deletion. - */ -function book_form_node_delete_confirm_alter(&$form, $form_state) { - $node = node_load($form['nid']['#value']); - - if (isset($node->book) && $node->book['has_children']) { - $form['book_warning'] = array( - '#markup' => '' . t('%title is part of a book outline, and has associated child pages. If you proceed with deletion, the child pages will be relocated automatically.', array('%title' => $node->title)) . '
', - '#weight' => -10, - ); - } -} - -/** * Return an array with default values for a book link. */ function _book_link_defaults($nid) { @@ -1065,58 +787,6 @@ function book_type_is_allowed($type) { } /** - * Implementation of hook_node_type(). - * - * Update book module's persistent variables if the machine-readable name of a - * node type is changed. - */ -function book_node_type($op, $type) { - switch ($op) { - case 'update': - if (!empty($type->old_type) && $type->old_type != $type->type) { - // Update the list of node types that are allowed to be added to books. - $allowed_types = variable_get('book_allowed_types', array('book')); - $key = array_search($type->old_type, $allowed_types); - - if ($key !== FALSE) { - $allowed_types[$type->type] = $allowed_types[$key] ? $type->type : 0; - unset($allowed_types[$key]); - variable_set('book_allowed_types', $allowed_types); - } - - // Update the setting for the "Add child page" link. - if (variable_get('book_child_type', 'book') == $type->old_type) { - variable_set('book_child_type', $type->type); - } - } - break; - } -} - -/** - * Implementation of hook_help(). - */ -function book_help($path, $arg) { - switch ($path) { - case 'admin/help#book': - $output = '' . t('The book module is suited for creating structured, multi-page hypertexts such as site resource guides, manuals, and Frequently Asked Questions (FAQs). It permits a document to have chapters, sections, subsections, etc. Authors with suitable permissions can add pages to a collaborative book, placing them into the existing document by adding them to a table of contents menu.') . '
'; - $output .= '' . t('Pages in the book hierarchy have navigation elements at the bottom of the page for moving through the text. These links lead to the previous and next pages in the book, and to the level above the current page in the book\'s structure. More comprehensive navigation may be provided by enabling the book navigation block on the blocks administration page.', array('@admin-block' => url('admin/build/block'))) . '
'; - $output .= '' . t('Users can select the printer-friendly version link visible at the bottom of a book page to generate a printer-friendly display of the page and all of its subsections. ') . '
'; - $output .= '' . t("Users with the administer book outlines permission can add a post of any content type to a book, by selecting the appropriate book while editing the post or by using the interface available on the post's outline tab.") . '
'; - $output .= '' . t('Administrators can view a list of all books on the book administration page. The Outline page for each book allows section titles to be edited or rearranged.', array('@admin-node-book' => url('admin/content/book'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Book module.', array('@book' => 'http://drupal.org/handbook/modules/book/')) . '
'; - - return $output; - - case 'admin/content/book': - return '' . t('The book module offers a means to organize a collection of related posts, collectively known as a book. When viewed, these posts automatically display links to adjacent book pages, providing a simple navigation system for creating and reviewing structured content.') . '
'; - - case 'node/%/outline': - return '' . t('The outline feature allows you to include posts in the book hierarchy, as well as move them within the hierarchy or to reorder an entire book.', array('@book' => url('book'), '@book-admin' => url('admin/content/book'))) . '
'; - } -} - -/** * Like menu_link_load(), but adds additional data from the {book} table. * * Do not call when loading a node, since this function may call node_load(). Index: modules/book/book.node.inc =================================================================== RCS file: modules/book/book.node.inc diff -N modules/book/book.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/book/book.node.inc 22 May 2009 23:44:14 -0000 @@ -0,0 +1,140 @@ +book['bid']) && !user_access('administer nodes')) { + $node->revision = 1; + // The database schema requires a log message for every revision. + if (!isset($node->log)) { + $node->log = ''; + } + } + // Make sure a new node gets a new menu link. + if (empty($node->nid)) { + $node->book['mlid'] = NULL; + } +} + +/** + * Implementation of hook_node_insert(). + */ +function book_node_insert($node) { + if (!empty($node->book['bid'])) { + if ($node->book['bid'] == 'new') { + // New nodes that are their own book. + $node->book['bid'] = $node->nid; + } + $node->book['nid'] = $node->nid; + $node->book['menu_name'] = book_menu_name($node->book['bid']); + _book_update_outline($node); + } +} + +/** + * Implementation of hook_node_update(). + */ +function book_node_update($node) { + if (!empty($node->book['bid'])) { + if ($node->book['bid'] == 'new') { + // New nodes that are their own book. + $node->book['bid'] = $node->nid; + } + $node->book['nid'] = $node->nid; + $node->book['menu_name'] = book_menu_name($node->book['bid']); + _book_update_outline($node); + } +} + +/** + * Implementation of hook_node_delete(). + */ +function book_node_delete($node) { + if (!empty($node->book['bid'])) { + if ($node->nid == $node->book['bid']) { + // Handle deletion of a top-level post. + $result = db_query("SELECT b.nid FROM {menu_links} ml INNER JOIN {book} b on b.mlid = ml.mlid WHERE ml.plid = :plid", array( + ':plid' => $node->book['mlid'] + )); + foreach ($result as $child) { + $child_node = node_load($child->nid); + $child_node->book['bid'] = $child_node->nid; + _book_update_outline($child_node); + } + } + menu_link_delete($node->book['mlid']); + db_delete('book') + ->condition('mlid', $node->book['mlid']) + ->execute(); + } +} + +/** + * Implementation of hook_node_prepare(). + */ +function book_node_prepare($node) { + // Prepare defaults for the add/edit form. + if (empty($node->book) && (user_access('add content to books') || user_access('administer book outlines'))) { + $node->book = array(); + + if (empty($node->nid) && isset($_GET['parent']) && is_numeric($_GET['parent'])) { + // Handle "Add child page" links: + $parent = book_link_load($_GET['parent']); + + if ($parent && $parent['access']) { + $node->book['bid'] = $parent['bid']; + $node->book['plid'] = $parent['mlid']; + $node->book['menu_name'] = $parent['menu_name']; + } + } + // Set defaults. + $node->book += _book_link_defaults(!empty($node->nid) ? $node->nid : 'new'); + } + else { + if (isset($node->book['bid']) && !isset($node->book['original_bid'])) { + $node->book['original_bid'] = $node->book['bid']; + } + } + // Find the depth limit for the parent select. + if (isset($node->book['bid']) && !isset($node->book['parent_depth_limit'])) { + $node->book['parent_depth_limit'] = _book_parent_depth_limit($node->book); + } +} + +/** + * Implementation of hook_node_type(). + * + * Update book module's persistent variables if the machine-readable name of a + * node type is changed. + */ +function book_node_type($op, $type) { + switch ($op) { + case 'update': + if (!empty($type->old_type) && $type->old_type != $type->type) { + // Update the list of node types that are allowed to be added to books. + $allowed_types = variable_get('book_allowed_types', array('book')); + $key = array_search($type->old_type, $allowed_types); + + if ($key !== FALSE) { + $allowed_types[$type->type] = $allowed_types[$key] ? $type->type : 0; + unset($allowed_types[$key]); + variable_set('book_allowed_types', $allowed_types); + } + + // Update the setting for the "Add child page" link. + if (variable_get('book_child_type', 'book') == $type->old_type) { + variable_set('book_child_type', $type->type); + } + } + break; + } +} + Index: modules/book/book.registry.inc =================================================================== RCS file: modules/book/book.registry.inc diff -N modules/book/book.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/book/book.registry.inc 22 May 2009 23:44:14 -0000 @@ -0,0 +1,106 @@ + 'Books', + 'description' => "Manage your site's book outlines.", + 'page callback' => 'book_admin_overview', + 'access arguments' => array('administer book outlines'), + ); + $items['admin/content/book/list'] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['admin/content/book/settings'] = array( + 'title' => 'Settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('book_admin_settings'), + 'access arguments' => array('administer site configuration'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 8, + ); + $items['admin/content/book/%node'] = array( + 'title' => 'Re-order book pages and change titles', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('book_admin_edit', 3), + 'access callback' => '_book_outline_access', + 'access arguments' => array(3), + 'type' => MENU_CALLBACK, + ); + $items['book'] = array( + 'title' => 'Books', + 'page callback' => 'book_render', + 'access arguments' => array('access content'), + 'type' => MENU_SUGGESTED_ITEM, + ); + $items['book/export/%/%'] = array( + 'page callback' => 'book_export', + 'page arguments' => array(2, 3), + 'access arguments' => array('access printer-friendly version'), + 'type' => MENU_CALLBACK, + ); + $items['node/%node/outline'] = array( + 'title' => 'Outline', + 'page callback' => 'book_outline', + 'page arguments' => array(1), + 'access callback' => '_book_outline_access', + 'access arguments' => array(1), + 'type' => MENU_LOCAL_TASK, + 'weight' => 2, + ); + $items['node/%node/outline/remove'] = array( + 'title' => 'Remove from outline', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('book_remove_form', 1), + 'access callback' => '_book_outline_remove_access', + 'access arguments' => array(1), + 'type' => MENU_CALLBACK, + ); + $items['book/js/form'] = array( + 'page callback' => 'book_form_update', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function book_theme() { + return array( + 'book_navigation' => array( + 'arguments' => array('book_link' => NULL), + 'template' => 'book-navigation', + ), + 'book_export_html' => array( + 'arguments' => array('title' => NULL, 'contents' => NULL, 'depth' => NULL), + 'template' => 'book-export-html', + ), + 'book_admin_table' => array( + 'arguments' => array('form' => NULL), + ), + 'book_title_link' => array( + 'arguments' => array('link' => NULL), + ), + 'book_all_books_block' => array( + 'arguments' => array('book_menus' => array()), + 'template' => 'book-all-books-block', + ), + 'book_node_export_html' => array( + 'arguments' => array('node' => NULL, 'children' => NULL), + 'template' => 'book-node-export-html', + ), + ); +} + Index: modules/book/book.user.inc =================================================================== RCS file: modules/book/book.user.inc diff -N modules/book/book.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/book/book.user.inc 22 May 2009 23:44:14 -0000 @@ -0,0 +1,32 @@ + array( + 'title' => t('Administer book outlines'), + 'description' => t('Manage books through the administration panel.'), + ), + 'create new books' => array( + 'title' => t('Create new books'), + 'description' => t('Add new top-level books.'), + ), + 'add content to books' => array( + 'title' => t('Add content to books'), + 'description' => t('Add new content and child pages to books.'), + ), + 'access printer-friendly version' => array( + 'title' => t('Access printer-friendly version'), + 'description' => t('View a book page and all of its sub-pages as a single document for ease of printing. Can be performance heavy.'), + ), + ); +} + Index: modules/color/color.form.inc =================================================================== RCS file: modules/color/color.form.inc diff -N modules/color/color.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/color/color.form.inc 22 May 2009 23:44:23 -0000 @@ -0,0 +1,229 @@ +download method is set to public.', array('@url' => url('admin/settings/file-system'))), 'warning'); + } + else { + $form['color'] = array( + '#type' => 'fieldset', + '#title' => t('Color scheme'), + '#weight' => -1, + '#attributes' => array('id' => 'color_scheme_form'), + '#theme' => 'color_scheme_form', + ); + $form['color'] += color_scheme_form($form_state, arg(4)); + $form['#submit'][] = 'color_scheme_form_submit'; + } + } +} + +/** + * Implementation of hook_form_FORM_ID_alter(). + */ +function color_form_system_themes_alter(&$form, &$form_state) { + _color_theme_select_form_alter($form, $form_state); +} + +/** + * Implementation of hook_form_FORM_ID_alter(). + */ +function color_form_system_theme_select_form_alter(&$form, &$form_state) { + _color_theme_select_form_alter($form, $form_state); +} + +/** + * Form callback. Returns the configuration form. + */ +function color_scheme_form(&$form_state, $theme) { + $base = drupal_get_path('module', 'color'); + $info = color_get_info($theme); + + // Add Farbtastic color picker. + drupal_add_css('misc/farbtastic/farbtastic.css', array('preprocess' => FALSE)); + drupal_add_js('misc/farbtastic/farbtastic.js', array('weight' => JS_LIBRARY)); + + // Add custom CSS and JS. + drupal_add_css($base . '/color.css', array('preprocess' => FALSE)); + drupal_add_js($base . '/color.js'); + drupal_add_js(array('color' => array( + 'reference' => color_get_palette($theme, TRUE) + )), 'setting'); + + // See if we're using a predefined scheme. + $current = implode(',', variable_get('color_' . $theme . '_palette', array())); + // Note: we use the original theme when the default scheme is chosen. + $current = isset($info['schemes'][$current]) ? $current : ($current == '' ? reset($info['schemes']) : ''); + + // Add scheme selector. + $info['schemes'][''] = t('Custom'); + $form['scheme'] = array( + '#type' => 'select', + '#title' => t('Color set'), + '#options' => $info['schemes'], + '#default_value' => $current, + ); + + // Add palette fields. + $palette = color_get_palette($theme); + $names = array( + 'base' => t('Base color'), + 'link' => t('Link color'), + 'top' => t('Header top'), + 'bottom' => t('Header bottom'), + 'text' => t('Text color'), + ); + $form['palette']['#tree'] = TRUE; + foreach ($palette as $name => $value) { + $form['palette'][$name] = array( + '#type' => 'textfield', + '#title' => $names[$name], + '#default_value' => $value, + '#size' => 8, + ); + } + $form['theme'] = array('#type' => 'value', '#value' => arg(4)); + $form['info'] = array('#type' => 'value', '#value' => $info); + + return $form; +} + +/** + * Submit handler for color change form. + */ +function color_scheme_form_submit($form, &$form_state) { + // Get theme coloring info. + if (!isset($form_state['values']['info'])) { + return; + } + $theme = $form_state['values']['theme']; + $info = $form_state['values']['info']; + + // Resolve palette. + $palette = $form_state['values']['palette']; + if ($form_state['values']['scheme'] != '') { + $scheme = explode(',', $form_state['values']['scheme']); + foreach ($palette as $k => $color) { + $palette[$k] = array_shift($scheme); + } + } + + // Make sure enough memory is available, if PHP's memory limit is compiled in. + if (function_exists('memory_get_usage')) { + // Fetch source image dimensions. + $source = drupal_get_path('theme', $theme) . '/' . $info['base_image']; + list($width, $height) = getimagesize($source); + + // We need at least a copy of the source and a target buffer of the same + // size (both at 32bpp). + $required = $width * $height * 8; + $usage = memory_get_usage(); + $limit = parse_size(ini_get('memory_limit')); + if ($usage + $required > $limit) { + drupal_set_message(t('There is not enough memory available to PHP to change this theme\'s color scheme. You need at least %size more. Check the PHP documentation for more information.', array('%size' => format_size($usage + $required - $limit), '@url' => 'http://www.php.net/manual/ini.core.php#ini.sect.resource-limits')), 'error'); + return; + } + } + + // Delete old files. + foreach (variable_get('color_' . $theme . '_files', array()) as $file) { + @unlink($file); + } + if (isset($file) && $file = dirname($file)) { + @rmdir($file); + } + + // Don't render the default colorscheme, use the standard theme instead. + if (implode(',', color_get_palette($theme, TRUE)) == implode(',', $palette) + || $form_state['values']['op'] == t('Reset to defaults')) { + variable_del('color_' . $theme . '_palette'); + variable_del('color_' . $theme . '_stylesheets'); + variable_del('color_' . $theme . '_logo'); + variable_del('color_' . $theme . '_files'); + variable_del('color_' . $theme . '_screenshot'); + return; + } + + // Prepare target locations for generated files. + $id = $theme . '-' . substr(md5(serialize($palette) . microtime()), 0, 8); + $paths['color'] = file_directory_path() . '/color'; + $paths['target'] = $paths['color'] . '/' . $id; + foreach ($paths as $path) { + file_check_directory($path, FILE_CREATE_DIRECTORY); + } + $paths['target'] = $paths['target'] . '/'; + $paths['id'] = $id; + $paths['source'] = drupal_get_path('theme', $theme) . '/'; + $paths['files'] = $paths['map'] = array(); + + // Save palette and logo location. + variable_set('color_' . $theme . '_palette', $palette); + variable_set('color_' . $theme . '_logo', $paths['target'] . 'logo.png'); + + // Copy over neutral images. + foreach ($info['copy'] as $file) { + $base = basename($file); + $source = $paths['source'] . $file; + $filepath = file_unmanaged_copy($source, $paths['target'] . $base); + $paths['map'][$file] = $base; + $paths['files'][] = $filepath; + } + + // Render new images, if image has been provided. + if ($info['base_image']) { + _color_render_images($theme, $info, $paths, $palette); + } + + // Rewrite theme stylesheets. + $css = array(); + foreach ($info['css'] as $stylesheet) { + // Build a temporary array with LTR and RTL files. + $files = array(); + if (file_exists($paths['source'] . $stylesheet)) { + $files[] = $stylesheet; + + $rtl_file = str_replace('.css', '-rtl.css', $stylesheet); + if (file_exists($paths['source'] . $rtl_file)) { + $files[] = $rtl_file; + } + } + + foreach ($files as $file) { + // Aggregate @imports recursively for each configured top level CSS file + // without optimization. Aggregation and optimization will be + // handled by drupal_build_css_cache() only. + $style = drupal_load_stylesheet($paths['source'] . $file, FALSE); + + // Return the path to where this CSS file originated from, stripping + // off the name of the file at the end of the path. + $base = base_path() . dirname($paths['source'] . $file) . '/'; + _drupal_build_css_path(NULL, $base); + + // Prefix all paths within this CSS file, ignoring absolute paths. + $style = preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $style); + + // Rewrite stylesheet with new colors. + $style = _color_rewrite_stylesheet($theme, $info, $paths, $palette, $style); + $base_file = basename($file); + $css[] = $paths['target'] . $base_file; + _color_save_stylesheet($paths['target'] . $base_file, $style, $paths); + } + } + + // Maintain list of files. + variable_set('color_' . $theme . '_stylesheets', $css); + variable_set('color_' . $theme . '_files', $paths['files']); +} + Index: modules/color/color.help.inc =================================================================== RCS file: modules/color/color.help.inc diff -N modules/color/color.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/color/color.help.inc 22 May 2009 23:44:13 -0000 @@ -0,0 +1,23 @@ +' . t('The color module allows a site administrator to quickly and easily change the color scheme of certain themes. Although not all themes support color module, both Garland (the default theme) and Minnelli were designed to take advantage of its features. By using color module with a compatible theme, you can easily change the color of links, backgrounds, text, and other theme elements. Color module requires that your file download method be set to public.', array('@url' => url('admin/settings/file-system'))) . ''; + $output .= '' . t("It is important to remember that color module saves a modified copy of the theme's specified stylesheets in the files directory. This means that if you make any manual changes to your theme's stylesheet, you must save your color settings again, even if they haven't changed. This causes the color module generated version of the stylesheets in the files directory to be recreated using the new version of the original file.") . '
'; + $output .= '' . t('To change the color settings for a compatible theme, select the "configure" link for the theme on the themes administration page.', array('@themes' => url('admin/build/themes'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Color module.', array('@color' => 'http://drupal.org/handbook/modules/color/')) . '
'; + + return $output; + } +} + Index: modules/color/color.info =================================================================== RCS file: /cvs/drupal/drupal/modules/color/color.info,v retrieving revision 1.9 diff -u -p -r1.9 color.info --- modules/color/color.info 11 Oct 2008 02:32:40 -0000 1.9 +++ modules/color/color.info 22 May 2009 23:44:13 -0000 @@ -7,3 +7,6 @@ version = VERSION core = 7.x files[] = color.module files[] = color.install +files[] = color.registry.inc +files[] = color.form.inc +files[] = color.help.inc Index: modules/color/color.module =================================================================== RCS file: /cvs/drupal/drupal/modules/color/color.module,v retrieving revision 1.58 diff -u -p -r1.58 color.module --- modules/color/color.module 16 May 2009 16:08:57 -0000 1.58 +++ modules/color/color.module 22 May 2009 23:44:23 -0000 @@ -2,70 +2,6 @@ // $Id: color.module,v 1.58 2009/05/16 16:08:57 dries Exp $ /** - * Implementation of hook_help(). - */ -function color_help($path, $arg) { - switch ($path) { - case 'admin/help#color': - $output = '' . t('The color module allows a site administrator to quickly and easily change the color scheme of certain themes. Although not all themes support color module, both Garland (the default theme) and Minnelli were designed to take advantage of its features. By using color module with a compatible theme, you can easily change the color of links, backgrounds, text, and other theme elements. Color module requires that your file download method be set to public.', array('@url' => url('admin/settings/file-system'))) . '
'; - $output .= '' . t("It is important to remember that color module saves a modified copy of the theme's specified stylesheets in the files directory. This means that if you make any manual changes to your theme's stylesheet, you must save your color settings again, even if they haven't changed. This causes the color module generated version of the stylesheets in the files directory to be recreated using the new version of the original file.") . '
'; - $output .= '' . t('To change the color settings for a compatible theme, select the "configure" link for the theme on the themes administration page.', array('@themes' => url('admin/build/themes'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Color module.', array('@color' => 'http://drupal.org/handbook/modules/color/')) . '
'; - - return $output; - } -} - -/** - * Implementation of hook_theme(). - */ -function color_theme() { - return array( - 'color_scheme_form' => array( - 'arguments' => array('form' => NULL), - ), - ); -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function color_form_system_theme_settings_alter(&$form, &$form_state) { - if (color_get_info(arg(4)) && function_exists('gd_info')) { - if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) != FILE_DOWNLOADS_PUBLIC) { - // Disables the color changer when the private download method is used. - // TODO: This should be solved in a different way. See issue #181003. - drupal_set_message(t('The color picker only works if the download method is set to public.', array('@url' => url('admin/settings/file-system'))), 'warning'); - } - else { - $form['color'] = array( - '#type' => 'fieldset', - '#title' => t('Color scheme'), - '#weight' => -1, - '#attributes' => array('id' => 'color_scheme_form'), - '#theme' => 'color_scheme_form', - ); - $form['color'] += color_scheme_form($form_state, arg(4)); - $form['#submit'][] = 'color_scheme_form_submit'; - } - } -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function color_form_system_themes_alter(&$form, &$form_state) { - _color_theme_select_form_alter($form, $form_state); -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function color_form_system_theme_select_form_alter(&$form, &$form_state) { - _color_theme_select_form_alter($form, $form_state); -} - -/** * Helper for hook_form_FORM_ID_alter() implementations. */ function _color_theme_select_form_alter(&$form, &$form_state) { @@ -162,62 +98,6 @@ function color_get_palette($theme, $defa } /** - * Form callback. Returns the configuration form. - */ -function color_scheme_form(&$form_state, $theme) { - $base = drupal_get_path('module', 'color'); - $info = color_get_info($theme); - - // Add Farbtastic color picker. - drupal_add_css('misc/farbtastic/farbtastic.css', array('preprocess' => FALSE)); - drupal_add_js('misc/farbtastic/farbtastic.js', array('weight' => JS_LIBRARY)); - - // Add custom CSS and JS. - drupal_add_css($base . '/color.css', array('preprocess' => FALSE)); - drupal_add_js($base . '/color.js'); - drupal_add_js(array('color' => array( - 'reference' => color_get_palette($theme, TRUE) - )), 'setting'); - - // See if we're using a predefined scheme. - $current = implode(',', variable_get('color_' . $theme . '_palette', array())); - // Note: we use the original theme when the default scheme is chosen. - $current = isset($info['schemes'][$current]) ? $current : ($current == '' ? reset($info['schemes']) : ''); - - // Add scheme selector. - $info['schemes'][''] = t('Custom'); - $form['scheme'] = array( - '#type' => 'select', - '#title' => t('Color set'), - '#options' => $info['schemes'], - '#default_value' => $current, - ); - - // Add palette fields. - $palette = color_get_palette($theme); - $names = array( - 'base' => t('Base color'), - 'link' => t('Link color'), - 'top' => t('Header top'), - 'bottom' => t('Header bottom'), - 'text' => t('Text color'), - ); - $form['palette']['#tree'] = TRUE; - foreach ($palette as $name => $value) { - $form['palette'][$name] = array( - '#type' => 'textfield', - '#title' => $names[$name], - '#default_value' => $value, - '#size' => 8, - ); - } - $form['theme'] = array('#type' => 'value', '#value' => arg(4)); - $form['info'] = array('#type' => 'value', '#value' => $info); - - return $form; -} - -/** * Theme the color form. * * @ingroup themeable @@ -249,133 +129,6 @@ function theme_color_scheme_form($form) } /** - * Submit handler for color change form. - */ -function color_scheme_form_submit($form, &$form_state) { - // Get theme coloring info. - if (!isset($form_state['values']['info'])) { - return; - } - $theme = $form_state['values']['theme']; - $info = $form_state['values']['info']; - - // Resolve palette. - $palette = $form_state['values']['palette']; - if ($form_state['values']['scheme'] != '') { - $scheme = explode(',', $form_state['values']['scheme']); - foreach ($palette as $k => $color) { - $palette[$k] = array_shift($scheme); - } - } - - // Make sure enough memory is available, if PHP's memory limit is compiled in. - if (function_exists('memory_get_usage')) { - // Fetch source image dimensions. - $source = drupal_get_path('theme', $theme) . '/' . $info['base_image']; - list($width, $height) = getimagesize($source); - - // We need at least a copy of the source and a target buffer of the same - // size (both at 32bpp). - $required = $width * $height * 8; - $usage = memory_get_usage(); - $limit = parse_size(ini_get('memory_limit')); - if ($usage + $required > $limit) { - drupal_set_message(t('There is not enough memory available to PHP to change this theme\'s color scheme. You need at least %size more. Check the PHP documentation for more information.', array('%size' => format_size($usage + $required - $limit), '@url' => 'http://www.php.net/manual/ini.core.php#ini.sect.resource-limits')), 'error'); - return; - } - } - - // Delete old files. - foreach (variable_get('color_' . $theme . '_files', array()) as $file) { - @unlink($file); - } - if (isset($file) && $file = dirname($file)) { - @rmdir($file); - } - - // Don't render the default colorscheme, use the standard theme instead. - if (implode(',', color_get_palette($theme, TRUE)) == implode(',', $palette) - || $form_state['values']['op'] == t('Reset to defaults')) { - variable_del('color_' . $theme . '_palette'); - variable_del('color_' . $theme . '_stylesheets'); - variable_del('color_' . $theme . '_logo'); - variable_del('color_' . $theme . '_files'); - variable_del('color_' . $theme . '_screenshot'); - return; - } - - // Prepare target locations for generated files. - $id = $theme . '-' . substr(md5(serialize($palette) . microtime()), 0, 8); - $paths['color'] = file_directory_path() . '/color'; - $paths['target'] = $paths['color'] . '/' . $id; - foreach ($paths as $path) { - file_check_directory($path, FILE_CREATE_DIRECTORY); - } - $paths['target'] = $paths['target'] . '/'; - $paths['id'] = $id; - $paths['source'] = drupal_get_path('theme', $theme) . '/'; - $paths['files'] = $paths['map'] = array(); - - // Save palette and logo location. - variable_set('color_' . $theme . '_palette', $palette); - variable_set('color_' . $theme . '_logo', $paths['target'] . 'logo.png'); - - // Copy over neutral images. - foreach ($info['copy'] as $file) { - $base = basename($file); - $source = $paths['source'] . $file; - $filepath = file_unmanaged_copy($source, $paths['target'] . $base); - $paths['map'][$file] = $base; - $paths['files'][] = $filepath; - } - - // Render new images, if image has been provided. - if ($info['base_image']) { - _color_render_images($theme, $info, $paths, $palette); - } - - // Rewrite theme stylesheets. - $css = array(); - foreach ($info['css'] as $stylesheet) { - // Build a temporary array with LTR and RTL files. - $files = array(); - if (file_exists($paths['source'] . $stylesheet)) { - $files[] = $stylesheet; - - $rtl_file = str_replace('.css', '-rtl.css', $stylesheet); - if (file_exists($paths['source'] . $rtl_file)) { - $files[] = $rtl_file; - } - } - - foreach ($files as $file) { - // Aggregate @imports recursively for each configured top level CSS file - // without optimization. Aggregation and optimization will be - // handled by drupal_build_css_cache() only. - $style = drupal_load_stylesheet($paths['source'] . $file, FALSE); - - // Return the path to where this CSS file originated from, stripping - // off the name of the file at the end of the path. - $base = base_path() . dirname($paths['source'] . $file) . '/'; - _drupal_build_css_path(NULL, $base); - - // Prefix all paths within this CSS file, ignoring absolute paths. - $style = preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $style); - - // Rewrite stylesheet with new colors. - $style = _color_rewrite_stylesheet($theme, $info, $paths, $palette, $style); - $base_file = basename($file); - $css[] = $paths['target'] . $base_file; - _color_save_stylesheet($paths['target'] . $base_file, $style, $paths); - } - } - - // Maintain list of files. - variable_set('color_' . $theme . '_stylesheets', $css); - variable_set('color_' . $theme . '_files', $paths['files']); -} - -/** * Rewrite the stylesheet to match the colors in the palette. */ function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette, $style) { Index: modules/color/color.registry.inc =================================================================== RCS file: modules/color/color.registry.inc diff -N modules/color/color.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/color/color.registry.inc 22 May 2009 23:44:12 -0000 @@ -0,0 +1,19 @@ + array( + 'arguments' => array('form' => NULL), + ), + ); +} + Index: modules/comment/comment.actions.inc =================================================================== RCS file: modules/comment/comment.actions.inc diff -N modules/comment/comment.actions.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/comment/comment.actions.inc 22 May 2009 23:44:10 -0000 @@ -0,0 +1,80 @@ +cid)) { + $cid = $comment->cid; + $subject = $comment->subject; + } + else { + $cid = $context['cid']; + $subject = db_query('SELECT subject FROM {comment} WHERE cid = :cid', array(':cid', $cid))->fetchField(); + } + db_update('comment') + ->fields(array('status' => COMMENT_NOT_PUBLISHED)) + ->condition('cid', $cid) + ->execute(); + watchdog('action', 'Unpublished comment %subject.', array('%subject' => $subject)); +} + +/** + * Form builder; Prepare a form for blacklisted keywords. + * + * @ingroup forms + */ +function comment_unpublish_by_keyword_action_form($context) { + $form['keywords'] = array( + '#title' => t('Keywords'), + '#type' => 'textarea', + '#description' => t('The comment will be unpublished if it contains any of the phrases above. Use a case-sensitive, comma-separated list of phrases. Example: funny, bungee jumping, "Company, Inc."'), + '#default_value' => isset($context['keywords']) ? drupal_implode_tags($context['keywords']) : '', + ); + + return $form; +} + +/** + * Process comment_unpublish_by_keyword_action_form form submissions. + */ +function comment_unpublish_by_keyword_action_submit($form, $form_state) { + return array('keywords' => drupal_explode_tags($form_state['values']['keywords'])); +} + +/** + * Implementation of a configurable Drupal action. + * + * Unpublish a comment if it contains a certain string. + * + * @param $context + * An array providing more information about the context of the call to this action. + * Unused here, since this action currently only supports the insert and update ops of + * the comment hook, both of which provide a complete $comment object. + * @param $comment + * A comment object. + */ +function comment_unpublish_by_keyword_action($comment, $context) { + foreach ($context['keywords'] as $keyword) { + if (strpos($comment->comment, $keyword) !== FALSE || strpos($comment->subject, $keyword) !== FALSE) { + db_update('comment') + ->fields(array('status' => COMMENT_NOT_PUBLISHED)) + ->condition('cid', $comment->cid) + ->execute(); + watchdog('action', 'Unpublished comment %subject.', array('%subject' => $comment->subject)); + break; + } + } +} + Index: modules/comment/comment.block.inc =================================================================== RCS file: modules/comment/comment.block.inc diff -N modules/comment/comment.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/comment/comment.block.inc 22 May 2009 23:44:10 -0000 @@ -0,0 +1,39 @@ + 'select', + '#title' => t('Number of recent comments'), + '#default_value' => variable_get('comment_block_count', 10), + '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)), + '#description' => t('Number of comments displayed in the Recent comments block.'), + ); + + return $form; +} + +/** + * Implementation of hook_block_save(). + */ +function comment_block_save($delta = '', $edit = array()) { + variable_set('comment_block_count', (int)$edit['comment_block_count']); +} + Index: modules/comment/comment.form.inc =================================================================== RCS file: modules/comment/comment.form.inc diff -N modules/comment/comment.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/comment/comment.form.inc 22 May 2009 23:44:24 -0000 @@ -0,0 +1,490 @@ + 'fieldset', + '#title' => t('Comment settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['comment']['comment'] = array( + '#type' => 'radios', + '#title' => t('Default comment setting'), + '#default_value' => variable_get('comment_' . $form['#node_type']->type, COMMENT_NODE_OPEN), + '#options' => array(t('Hidden'), t('Closed'), t('Open')), + '#description' => t('Users with the administer comments permission will be able to override this setting.'), + ); + $form['comment']['comment_default_mode'] = array( + '#type' => 'radios', + '#title' => t('Default display mode'), + '#default_value' => variable_get('comment_default_mode_' . $form['#node_type']->type, COMMENT_MODE_THREADED_EXPANDED), + '#options' => _comment_get_modes(), + '#description' => t('Expanded views display the body of the comment. Threaded views keep replies together.'), + ); + $form['comment']['comment_default_per_page'] = array( + '#type' => 'select', + '#title' => t('Comments per page'), + '#default_value' => variable_get('comment_default_per_page_' . $form['#node_type']->type, 50), + '#options' => _comment_per_page(), + '#description' => t('Additional comments will be displayed on separate pages.'), + ); + $form['comment']['comment_anonymous'] = array( + '#type' => 'radios', + '#title' => t('Anonymous commenting'), + '#default_value' => variable_get('comment_anonymous_' . $form['#node_type']->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT), + '#options' => array( + COMMENT_ANONYMOUS_MAYNOT_CONTACT => t('Anonymous posters may not enter their contact information'), + COMMENT_ANONYMOUS_MAY_CONTACT => t('Anonymous posters may leave their contact information'), + COMMENT_ANONYMOUS_MUST_CONTACT => t('Anonymous posters must leave their contact information')), + '#description' => t('This option is enabled when anonymous users have permission to post comments on the permissions page.', array('@url' => url('admin/user/permissions', array('fragment' => 'module-comment')))), + ); + + if (!user_access('post comments', drupal_anonymous_user())) { + $form['comment']['comment_anonymous']['#disabled'] = TRUE; + } + + $form['comment']['comment_subject_field'] = array( + '#type' => 'radios', + '#title' => t('Comment subject field'), + '#default_value' => variable_get('comment_subject_field_' . $form['#node_type']->type, 1), + '#options' => array(t('Disabled'), t('Enabled')), + '#description' => t('Can users provide a unique subject for their comments?'), + ); + $form['comment']['comment_preview'] = array( + '#type' => 'radios', + '#title' => t('Preview comment'), + '#default_value' => variable_get('comment_preview_' . $form['#node_type']->type, COMMENT_PREVIEW_REQUIRED), + '#options' => array(t('Optional'), t('Required')), + '#description' => t("Forces a user to look at their comment by clicking on a 'Preview' button before they can actually add the comment"), + ); + $form['comment']['comment_form_location'] = array( + '#type' => 'radios', + '#title' => t('Location of comment submission form'), + '#default_value' => variable_get('comment_form_location_' . $form['#node_type']->type, COMMENT_FORM_SEPARATE_PAGE), + '#options' => array(t('Display on separate page'), t('Display below post or comments')), + ); + } +} + +/** + * Generate the basic commenting form, for appending to a node or display on a separate page. + * + * @param $title + * Not used. + * @ingroup forms + * @see comment_form_validate() + * @see comment_form_submit() + */ +function comment_form(&$form_state, $edit, $title = NULL) { + global $user; + $op = isset($_POST['op']) ? $_POST['op'] : ''; + $node = node_load($edit['nid']); + + if (!$user->uid && variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) != COMMENT_ANONYMOUS_MAYNOT_CONTACT) { + drupal_add_js(drupal_get_path('module', 'comment') . '/comment.js'); + } + $edit += array('name' => '', 'mail' => '', 'homepage' => ''); + + if ($user->uid) { + if (!empty($edit['cid']) && user_access('administer comments')) { + if (!empty($edit['author'])) { + $author = $edit['author']; + } + elseif (!empty($edit['name'])) { + $author = $edit['name']; + } + else { + $author = $edit['registered_name']; + } + + if (!empty($edit['status'])) { + $status = $edit['status']; + } + else { + $status = 0; + } + + if (!empty($edit['date'])) { + $date = $edit['date']; + } + else { + $date = format_date($edit['timestamp'], 'custom', 'Y-m-d H:i O'); + } + + $form['admin'] = array( + '#type' => 'fieldset', + '#title' => t('Administration'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#weight' => -2, + ); + + if ($edit['registered_name'] != '') { + // The comment is by a registered user. + $form['admin']['author'] = array( + '#type' => 'textfield', + '#title' => t('Authored by'), + '#size' => 30, + '#maxlength' => 60, + '#autocomplete_path' => 'user/autocomplete', + '#default_value' => $author, + '#weight' => -1, + ); + } + else { + // The comment is by an anonymous user. + $form['is_anonymous'] = array( + '#type' => 'value', + '#value' => TRUE, + ); + $form['admin']['name'] = array( + '#type' => 'textfield', + '#title' => t('Authored by'), + '#size' => 30, + '#maxlength' => 60, + '#default_value' => $author, + '#weight' => -1, + ); + $form['admin']['mail'] = array( + '#type' => 'textfield', + '#title' => t('E-mail'), + '#maxlength' => 64, + '#size' => 30, + '#default_value' => $edit['mail'], + '#description' => t('The content of this field is kept private and will not be shown publicly.'), + ); + $form['admin']['homepage'] = array( + '#type' => 'textfield', + '#title' => t('Homepage'), + '#maxlength' => 255, + '#size' => 30, + '#default_value' => $edit['homepage'], + ); + } + $form['admin']['date'] = array( + '#type' => 'textfield', + '#parents' => array('date'), + '#title' => t('Authored on'), + '#size' => 20, + '#maxlength' => 25, + '#default_value' => $date, + '#weight' => -1, + ); + $form['admin']['status'] = array( + '#type' => 'radios', + '#parents' => array('status'), + '#title' => t('Status'), + '#default_value' => $status, + '#options' => array(t('Not published'), t('Published')), + '#weight' => -1, + ); + } + else { + $form['_author'] = array( + '#type' => 'item', + '#title' => t('Your name'), + '#markup' => theme('username', $user), + ); + $form['author'] = array( + '#type' => 'value', + '#value' => $user->name, + ); + } + } + elseif (variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MAY_CONTACT) { + $form['name'] = array( + '#type' => 'textfield', + '#title' => t('Your name'), + '#maxlength' => 60, + '#size' => 30, + '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous')), + ); + $form['mail'] = array( + '#type' => 'textfield', + '#title' => t('E-mail'), + '#maxlength' => 64, + '#size' => 30, + '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.'), + ); + $form['homepage'] = array( + '#type' => 'textfield', + '#title' => t('Homepage'), + '#maxlength' => 255, + '#size' => 30, + '#default_value' => $edit['homepage'], + ); + } + elseif (variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) { + $form['name'] = array( + '#type' => 'textfield', + '#title' => t('Your name'), + '#maxlength' => 60, + '#size' => 30, + '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous')), + '#required' => TRUE, + ); + $form['mail'] = array( + '#type' => 'textfield', + '#title' => t('E-mail'), + '#maxlength' => 64, + '#size' => 30, + '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.'), + '#required' => TRUE, + ); + $form['homepage'] = array( + '#type' => 'textfield', + '#title' => t('Homepage'), + '#maxlength' => 255, + '#size' => 30, + '#default_value' => $edit['homepage'], + ); + } + + if (variable_get('comment_subject_field_' . $node->type, 1) == 1) { + $form['subject'] = array( + '#type' => 'textfield', + '#title' => t('Subject'), + '#maxlength' => 64, + '#default_value' => !empty($edit['subject']) ? $edit['subject'] : '', + ); + } + + if (!empty($edit['comment'])) { + $default = $edit['comment']; + } + else { + $default = ''; + } + + $form['comment'] = array( + '#type' => 'textarea', + '#title' => t('Comment'), + '#rows' => 15, + '#default_value' => $default, + '#text_format' => isset($edit['format']) ? $edit['format'] : FILTER_FORMAT_DEFAULT, + '#required' => TRUE, + ); + + $form['cid'] = array( + '#type' => 'value', + '#value' => !empty($edit['cid']) ? $edit['cid'] : NULL, + ); + $form['pid'] = array( + '#type' => 'value', + '#value' => !empty($edit['pid']) ? $edit['pid'] : NULL, + ); + $form['nid'] = array( + '#type' => 'value', + '#value' => $edit['nid'], + ); + $form['uid'] = array( + '#type' => 'value', + '#value' => !empty($edit['uid']) ? $edit['uid'] : 0, + ); + + // Only show the save button if comment previews are optional or if we are + // already previewing the submission. However, if there are form errors, + // we hide the save button no matter what, so that optional form elements + // (e.g., captchas) can be updated. + if (!form_get_errors() && ((variable_get('comment_preview_' . $node->type, COMMENT_PREVIEW_REQUIRED) == COMMENT_PREVIEW_OPTIONAL) || ($op == t('Preview')) || ($op == t('Save')))) { + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save'), + '#weight' => 19, + ); + } + $form['preview'] = array( + '#type' => 'button', + '#value' => t('Preview'), + '#weight' => 20, + ); + $form['#token'] = 'comment' . $edit['nid'] . (isset($edit['pid']) ? $edit['pid'] : ''); + + if ($op == t('Preview')) { + $form['#after_build'] = array('comment_form_add_preview'); + } + + if (empty($edit['cid']) && empty($edit['pid'])) { + $form['#action'] = url('comment/reply/' . $edit['nid']); + } + + return $form; +} + +/** + * Validate comment form submissions. + */ +function comment_form_validate($form, &$form_state) { + global $user; + if ($user->uid === 0) { + foreach (array('name', 'homepage', 'mail') as $field) { + // Set cookie for 365 days. + if (isset($form_state['values'][$field])) { + setcookie('comment_info_' . $field, $form_state['values'][$field], REQUEST_TIME + 31536000, '/'); + } + } + } + comment_validate($form_state['values']); +} + +/** + * Validate comment data. + * + * @param $edit + * An associative array containing the comment data. + * @return + * The original $edit. + */ +function comment_validate($edit) { + global $user; + + // Invoke other validation handlers. + comment_invoke_comment($edit, 'validate'); + + if (isset($edit['date'])) { + if (strtotime($edit['date']) === FALSE) { + form_set_error('date', t('You have to specify a valid date.')); + } + } + if (isset($edit['author']) && !$account = user_load_by_name($edit['author'])) { + form_set_error('author', t('You have to specify a valid author.')); + } + + // Check validity of name, mail and homepage (if given). + if (!$user->uid || isset($edit['is_anonymous'])) { + $node = node_load($edit['nid']); + if (variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) > COMMENT_ANONYMOUS_MAYNOT_CONTACT) { + if ($edit['name']) { + $query = db_select('users', 'u'); + $query->addField('u', 'uid', 'uid'); + $taken = $query->where('LOWER(name) = :name', array(':name' => $edit['name'])) + ->countQuery() + ->execute() + ->fetchField(); + if ($taken != 0) { + form_set_error('name', t('The name you used belongs to a registered user.')); + } + } + elseif (variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) { + form_set_error('name', t('You have to leave your name.')); + } + + if ($edit['mail']) { + if (!valid_email_address($edit['mail'])) { + form_set_error('mail', t('The e-mail address you specified is not valid.')); + } + } + elseif (variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) { + form_set_error('mail', t('You have to leave an e-mail address.')); + } + + if ($edit['homepage']) { + if (!valid_url($edit['homepage'], TRUE)) { + form_set_error('homepage', t('The URL of your homepage is not valid. Remember that it must be fully qualified, i.e. of the formhttp://example.com/directory.'));
+ }
+ }
+ }
+ }
+
+ return $edit;
+}
+
+/**
+ * Form builder; Generate and validate a comment preview form.
+ *
+ * @ingroup forms
+ */
+function comment_form_add_preview($form, &$form_state) {
+ global $user;
+ $edit = $form_state['values'];
+ drupal_set_title(t('Preview comment'), PASS_THROUGH);
+ $output = '';
+ $node = node_load($edit['nid']);
+
+ // Invoke full validation for the form, to protect against cross site
+ // request forgeries (CSRF) and setting arbitrary values for fields such as
+ // the text format. Preview the comment only when form validation does not
+ // set any errors.
+ drupal_validate_form($form['form_id']['#value'], $form, $form_state);
+ if (!form_get_errors()) {
+ _comment_form_submit($edit);
+ $comment = (object)$edit;
+ $comment->format = $comment->comment_format;
+
+ // Attach the user and time information.
+ if (!empty($edit['author'])) {
+ $account = user_load_by_name($edit['author']);
+ }
+ elseif ($user->uid && !isset($edit['is_anonymous'])) {
+ $account = $user;
+ }
+
+ if (!empty($account)) {
+ $comment->uid = $account->uid;
+ $comment->name = check_plain($account->name);
+ }
+ elseif (empty($comment->name)) {
+ $comment->name = variable_get('anonymous', t('Anonymous'));
+ }
+
+ $comment->timestamp = !empty($edit['timestamp']) ? $edit['timestamp'] : REQUEST_TIME;
+ $output .= theme('comment_view', $comment, $node);
+ }
+
+ $form['comment_preview'] = array(
+ '#markup' => $output,
+ '#weight' => -100,
+ '#prefix' => '' . t('Comment permissions are assigned to user roles, and are used to determine whether anonymous users (or other roles) are allowed to comment on posts. If anonymous users are allowed to comment, their individual contact information may be retained in cookies stored on their local computer for use in later comment submissions. When a comment has no replies, it may be (optionally) edited by its author. The comment module uses the same text formats and HTML tags available when creating other forms of content.') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Comment module.', array('@comment' => 'http://drupal.org/handbook/modules/comment/')) . '
'; + + return $output; + } +} + Index: modules/comment/comment.info =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.info,v retrieving revision 1.9 diff -u -p -r1.9 comment.info --- modules/comment/comment.info 11 Oct 2008 02:32:41 -0000 1.9 +++ modules/comment/comment.info 22 May 2009 23:44:11 -0000 @@ -9,3 +9,11 @@ files[] = comment.module files[] = comment.admin.inc files[] = comment.pages.inc files[] = comment.install +files[] = comment.registry.inc +files[] = comment.actions.inc +files[] = comment.user.inc +files[] = comment.block.inc +files[] = comment.node.inc +files[] = comment.search.inc +files[] = comment.form.inc +files[] = comment.help.inc Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.711 diff -u -p -r1.711 comment.module --- modules/comment/comment.module 21 May 2009 10:34:55 -0000 1.711 +++ modules/comment/comment.module 22 May 2009 23:44:24 -0000 @@ -91,201 +91,6 @@ define('COMMENT_PREVIEW_OPTIONAL', 0); define('COMMENT_PREVIEW_REQUIRED', 1); /** - * Implementation of hook_help(). - */ -function comment_help($path, $arg) { - switch ($path) { - case 'admin/help#comment': - $output = '' . t('The comment module allows visitors to comment on your posts, creating ad hoc discussion boards. Any content type may have its Default comment setting set to Open to allow comments, Hidden to hide existing comments and prevent new comments or Closed to allow existing comments to be viewed but no new comments added. Comment display settings and other controls may also be customized for each content type.', array('@content-type' => url('admin/build/types'))) . '
'; - $output .= '' . t('Comment permissions are assigned to user roles, and are used to determine whether anonymous users (or other roles) are allowed to comment on posts. If anonymous users are allowed to comment, their individual contact information may be retained in cookies stored on their local computer for use in later comment submissions. When a comment has no replies, it may be (optionally) edited by its author. The comment module uses the same text formats and HTML tags available when creating other forms of content.') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Comment module.', array('@comment' => 'http://drupal.org/handbook/modules/comment/')) . '
'; - - return $output; - } -} - -/** - * Implementation of hook_theme(). - */ -function comment_theme() { - return array( - 'comment_block' => array( - 'arguments' => array(), - ), - 'comment_preview' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array(), 'visible' => 1), - ), - 'comment_view' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array(), 'visible' => 1), - ), - 'comment' => array( - 'template' => 'comment', - 'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array()), - ), - 'comment_form_box' => array( - 'arguments' => array('edit' => NULL, 'title' => NULL), - ), - 'comment_folded' => array( - 'template' => 'comment-folded', - 'arguments' => array('comment' => NULL), - ), - 'comment_flat_collapsed' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL), - ), - 'comment_flat_expanded' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL), - ), - 'comment_thread_collapsed' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL), - ), - 'comment_thread_expanded' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL), - ), - 'comment_post_forbidden' => array( - 'arguments' => array('nid' => NULL), - ), - 'comment_wrapper' => array( - 'template' => 'comment-wrapper', - 'arguments' => array('content' => NULL, 'node' => NULL), - ), - 'comment_submitted' => array( - 'arguments' => array('comment' => NULL), - ), - ); -} - -/** - * Implementation of hook_menu(). - */ -function comment_menu() { - $items['admin/content/comment'] = array( - 'title' => 'Comments', - 'description' => 'List and edit site comments and the comment approval queue.', - 'page callback' => 'comment_admin', - 'access arguments' => array('administer comments'), - ); - // Tabs begin here. - $items['admin/content/comment/new'] = array( - 'title' => 'Published comments', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['admin/content/comment/approval'] = array( - 'title' => 'Approval queue', - 'page arguments' => array('approval'), - 'access arguments' => array('administer comments'), - 'type' => MENU_LOCAL_TASK, - ); - $items['comment/delete'] = array( - 'title' => 'Delete comment', - 'page callback' => 'comment_delete', - 'access arguments' => array('administer comments'), - 'type' => MENU_CALLBACK, - ); - $items['comment/edit'] = array( - 'title' => 'Edit comment', - 'page callback' => 'comment_edit', - 'access arguments' => array('post comments'), - 'type' => MENU_CALLBACK, - ); - $items['comment/reply/%node'] = array( - 'title' => 'Reply to comment', - 'page callback' => 'comment_reply', - 'page arguments' => array(2), - 'access callback' => 'node_access', - 'access arguments' => array('view', 2), - 'type' => MENU_CALLBACK, - ); - $items['comment/approve'] = array( - 'title' => 'Approve a comment', - 'page callback' => 'comment_approve', - 'page arguments' => array(2), - 'access arguments' => array('administer comments'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** - * Implementation of hook_node_type(). - */ -function comment_node_type($op, $info) { - $settings = array( - 'comment', - 'comment_default_mode', - 'comment_default_per_page', - 'comment_anonymous', - 'comment_subject_field', - 'comment_preview', - 'comment_form_location', - ); - - switch ($op) { - case 'delete': - foreach ($settings as $setting) { - variable_del($setting . '_' . $info->type); - } - break; - } -} - -/** - * Implementation of hook_perm(). - */ -function comment_perm() { - return array( - 'administer comments' => array( - 'title' => t('Administer comments'), - 'description' => t('Manage and approve comments, and configure comment administration settings.'), - ), - 'access comments' => array( - 'title' => t('Access comments'), - 'description' => t('View comments attached to content.'), - ), - 'post comments' => array( - 'title' => t('Post comments'), - 'description' => t('Add comments to content (approval required).'), - ), - 'post comments without approval' => array( - 'title' => t('Post comments without approval'), - 'description' => t('Add comments to content (no approval required).'), - ), - ); -} - -/** - * Implementation of hook_block_list(). - */ -function comment_block_list() { - $blocks['recent']['info'] = t('Recent comments'); - - return $blocks; -} - -/** - * Implementation of hook_block_configure(). - */ -function comment_block_configure($delta = '') { - $form['comment_block_count'] = array( - '#type' => 'select', - '#title' => t('Number of recent comments'), - '#default_value' => variable_get('comment_block_count', 10), - '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)), - '#description' => t('Number of comments displayed in the Recent comments block.'), - ); - - return $form; -} - -/** - * Implementation of hook_block_save(). - */ -function comment_block_save($delta = '', $edit = array()) { - variable_set('comment_block_count', (int)$edit['comment_block_count']); -} - -/** * Implementation of hook_block_view(). * * Generates a block with the most recent comments. @@ -504,76 +309,6 @@ function comment_node_view($node, $tease } /** - * Implementation of hook_form_FORM_ID_alter(). - */ -function comment_form_node_type_form_alter(&$form, $form_state) { - if (isset($form['identity']['type'])) { - $form['comment'] = array( - '#type' => 'fieldset', - '#title' => t('Comment settings'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - ); - $form['comment']['comment'] = array( - '#type' => 'radios', - '#title' => t('Default comment setting'), - '#default_value' => variable_get('comment_' . $form['#node_type']->type, COMMENT_NODE_OPEN), - '#options' => array(t('Hidden'), t('Closed'), t('Open')), - '#description' => t('Users with the administer comments permission will be able to override this setting.'), - ); - $form['comment']['comment_default_mode'] = array( - '#type' => 'radios', - '#title' => t('Default display mode'), - '#default_value' => variable_get('comment_default_mode_' . $form['#node_type']->type, COMMENT_MODE_THREADED_EXPANDED), - '#options' => _comment_get_modes(), - '#description' => t('Expanded views display the body of the comment. Threaded views keep replies together.'), - ); - $form['comment']['comment_default_per_page'] = array( - '#type' => 'select', - '#title' => t('Comments per page'), - '#default_value' => variable_get('comment_default_per_page_' . $form['#node_type']->type, 50), - '#options' => _comment_per_page(), - '#description' => t('Additional comments will be displayed on separate pages.'), - ); - $form['comment']['comment_anonymous'] = array( - '#type' => 'radios', - '#title' => t('Anonymous commenting'), - '#default_value' => variable_get('comment_anonymous_' . $form['#node_type']->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT), - '#options' => array( - COMMENT_ANONYMOUS_MAYNOT_CONTACT => t('Anonymous posters may not enter their contact information'), - COMMENT_ANONYMOUS_MAY_CONTACT => t('Anonymous posters may leave their contact information'), - COMMENT_ANONYMOUS_MUST_CONTACT => t('Anonymous posters must leave their contact information')), - '#description' => t('This option is enabled when anonymous users have permission to post comments on the permissions page.', array('@url' => url('admin/user/permissions', array('fragment' => 'module-comment')))), - ); - - if (!user_access('post comments', drupal_anonymous_user())) { - $form['comment']['comment_anonymous']['#disabled'] = TRUE; - } - - $form['comment']['comment_subject_field'] = array( - '#type' => 'radios', - '#title' => t('Comment subject field'), - '#default_value' => variable_get('comment_subject_field_' . $form['#node_type']->type, 1), - '#options' => array(t('Disabled'), t('Enabled')), - '#description' => t('Can users provide a unique subject for their comments?'), - ); - $form['comment']['comment_preview'] = array( - '#type' => 'radios', - '#title' => t('Preview comment'), - '#default_value' => variable_get('comment_preview_' . $form['#node_type']->type, COMMENT_PREVIEW_REQUIRED), - '#options' => array(t('Optional'), t('Required')), - '#description' => t("Forces a user to look at their comment by clicking on a 'Preview' button before they can actually add the comment"), - ); - $form['comment']['comment_form_location'] = array( - '#type' => 'radios', - '#title' => t('Location of comment submission form'), - '#default_value' => variable_get('comment_form_location_' . $form['#node_type']->type, COMMENT_FORM_SEPARATE_PAGE), - '#options' => array(t('Display on separate page'), t('Display below post or comments')), - ); - } -} - -/** * Implementation of hook_form_alter(). */ function comment_form_alter(&$form, $form_state, $form_id) { @@ -670,65 +405,6 @@ function comment_node_load($nodes, $type } /** - * Implementation of hook_node_prepare(). - */ -function comment_node_prepare($node) { - if (!isset($node->comment)) { - $node->comment = variable_get("comment_$node->type", COMMENT_NODE_OPEN); - } -} - -/** - * Implementation of hook_node_insert(). - */ -function comment_node_insert($node) { - db_insert('node_comment_statistics') - ->fields(array( - 'nid' => $node->nid, - 'last_comment_timestamp' => $node->changed, - 'last_comment_name' => NULL, - 'last_comment_uid' => $node->uid, - 'comment_count' => 0, - )) - ->execute(); -} - -/** - * Implementation of hook_node_delete(). - */ -function comment_node_delete($node) { - db_delete('comment') - ->condition('nid', $node->nid) - ->execute(); - db_delete('node_comment_statistics') - ->condition('nid', $node->nid) - ->execute(); -} - -/** - * Implementation of hook_node_update_index(). - */ -function comment_node_update_index($node) { - $text = ''; - $comments = db_query('SELECT subject, comment, format FROM {comment} WHERE nid = :nid AND status = :status', array( - ':nid' => $node->nid, - ':status' => COMMENT_PUBLISHED - )); - foreach ($comments as $comment) { - $text .= 'http://example.com/directory.'));
- }
- }
- }
- }
-
- return $edit;
-}
-
-/**
- * Generate the basic commenting form, for appending to a node or display on a separate page.
- *
- * @param $title
- * Not used.
- * @ingroup forms
- * @see comment_form_validate()
- * @see comment_form_submit()
- */
-function comment_form(&$form_state, $edit, $title = NULL) {
- global $user;
- $op = isset($_POST['op']) ? $_POST['op'] : '';
- $node = node_load($edit['nid']);
-
- if (!$user->uid && variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) != COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
- drupal_add_js(drupal_get_path('module', 'comment') . '/comment.js');
- }
- $edit += array('name' => '', 'mail' => '', 'homepage' => '');
-
- if ($user->uid) {
- if (!empty($edit['cid']) && user_access('administer comments')) {
- if (!empty($edit['author'])) {
- $author = $edit['author'];
- }
- elseif (!empty($edit['name'])) {
- $author = $edit['name'];
- }
- else {
- $author = $edit['registered_name'];
- }
-
- if (!empty($edit['status'])) {
- $status = $edit['status'];
- }
- else {
- $status = 0;
- }
-
- if (!empty($edit['date'])) {
- $date = $edit['date'];
- }
- else {
- $date = format_date($edit['timestamp'], 'custom', 'Y-m-d H:i O');
- }
-
- $form['admin'] = array(
- '#type' => 'fieldset',
- '#title' => t('Administration'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- '#weight' => -2,
- );
-
- if ($edit['registered_name'] != '') {
- // The comment is by a registered user.
- $form['admin']['author'] = array(
- '#type' => 'textfield',
- '#title' => t('Authored by'),
- '#size' => 30,
- '#maxlength' => 60,
- '#autocomplete_path' => 'user/autocomplete',
- '#default_value' => $author,
- '#weight' => -1,
- );
- }
- else {
- // The comment is by an anonymous user.
- $form['is_anonymous'] = array(
- '#type' => 'value',
- '#value' => TRUE,
- );
- $form['admin']['name'] = array(
- '#type' => 'textfield',
- '#title' => t('Authored by'),
- '#size' => 30,
- '#maxlength' => 60,
- '#default_value' => $author,
- '#weight' => -1,
- );
- $form['admin']['mail'] = array(
- '#type' => 'textfield',
- '#title' => t('E-mail'),
- '#maxlength' => 64,
- '#size' => 30,
- '#default_value' => $edit['mail'],
- '#description' => t('The content of this field is kept private and will not be shown publicly.'),
- );
- $form['admin']['homepage'] = array(
- '#type' => 'textfield',
- '#title' => t('Homepage'),
- '#maxlength' => 255,
- '#size' => 30,
- '#default_value' => $edit['homepage'],
- );
- }
- $form['admin']['date'] = array(
- '#type' => 'textfield',
- '#parents' => array('date'),
- '#title' => t('Authored on'),
- '#size' => 20,
- '#maxlength' => 25,
- '#default_value' => $date,
- '#weight' => -1,
- );
- $form['admin']['status'] = array(
- '#type' => 'radios',
- '#parents' => array('status'),
- '#title' => t('Status'),
- '#default_value' => $status,
- '#options' => array(t('Not published'), t('Published')),
- '#weight' => -1,
- );
- }
- else {
- $form['_author'] = array(
- '#type' => 'item',
- '#title' => t('Your name'),
- '#markup' => theme('username', $user),
- );
- $form['author'] = array(
- '#type' => 'value',
- '#value' => $user->name,
- );
- }
- }
- elseif (variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MAY_CONTACT) {
- $form['name'] = array(
- '#type' => 'textfield',
- '#title' => t('Your name'),
- '#maxlength' => 60,
- '#size' => 30,
- '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous')),
- );
- $form['mail'] = array(
- '#type' => 'textfield',
- '#title' => t('E-mail'),
- '#maxlength' => 64,
- '#size' => 30,
- '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.'),
- );
- $form['homepage'] = array(
- '#type' => 'textfield',
- '#title' => t('Homepage'),
- '#maxlength' => 255,
- '#size' => 30,
- '#default_value' => $edit['homepage'],
- );
- }
- elseif (variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
- $form['name'] = array(
- '#type' => 'textfield',
- '#title' => t('Your name'),
- '#maxlength' => 60,
- '#size' => 30,
- '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous')),
- '#required' => TRUE,
- );
- $form['mail'] = array(
- '#type' => 'textfield',
- '#title' => t('E-mail'),
- '#maxlength' => 64,
- '#size' => 30,
- '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.'),
- '#required' => TRUE,
- );
- $form['homepage'] = array(
- '#type' => 'textfield',
- '#title' => t('Homepage'),
- '#maxlength' => 255,
- '#size' => 30,
- '#default_value' => $edit['homepage'],
- );
- }
-
- if (variable_get('comment_subject_field_' . $node->type, 1) == 1) {
- $form['subject'] = array(
- '#type' => 'textfield',
- '#title' => t('Subject'),
- '#maxlength' => 64,
- '#default_value' => !empty($edit['subject']) ? $edit['subject'] : '',
- );
- }
-
- if (!empty($edit['comment'])) {
- $default = $edit['comment'];
- }
- else {
- $default = '';
- }
-
- $form['comment'] = array(
- '#type' => 'textarea',
- '#title' => t('Comment'),
- '#rows' => 15,
- '#default_value' => $default,
- '#text_format' => isset($edit['format']) ? $edit['format'] : FILTER_FORMAT_DEFAULT,
- '#required' => TRUE,
- );
-
- $form['cid'] = array(
- '#type' => 'value',
- '#value' => !empty($edit['cid']) ? $edit['cid'] : NULL,
- );
- $form['pid'] = array(
- '#type' => 'value',
- '#value' => !empty($edit['pid']) ? $edit['pid'] : NULL,
- );
- $form['nid'] = array(
- '#type' => 'value',
- '#value' => $edit['nid'],
- );
- $form['uid'] = array(
- '#type' => 'value',
- '#value' => !empty($edit['uid']) ? $edit['uid'] : 0,
- );
-
- // Only show the save button if comment previews are optional or if we are
- // already previewing the submission. However, if there are form errors,
- // we hide the save button no matter what, so that optional form elements
- // (e.g., captchas) can be updated.
- if (!form_get_errors() && ((variable_get('comment_preview_' . $node->type, COMMENT_PREVIEW_REQUIRED) == COMMENT_PREVIEW_OPTIONAL) || ($op == t('Preview')) || ($op == t('Save')))) {
- $form['submit'] = array(
- '#type' => 'submit',
- '#value' => t('Save'),
- '#weight' => 19,
- );
- }
- $form['preview'] = array(
- '#type' => 'button',
- '#value' => t('Preview'),
- '#weight' => 20,
- );
- $form['#token'] = 'comment' . $edit['nid'] . (isset($edit['pid']) ? $edit['pid'] : '');
-
- if ($op == t('Preview')) {
- $form['#after_build'] = array('comment_form_add_preview');
- }
-
- if (empty($edit['cid']) && empty($edit['pid'])) {
- $form['#action'] = url('comment/reply/' . $edit['nid']);
- }
-
- return $form;
-}
-
-/**
* Theme the comment form box.
*
* @param $edit
@@ -1651,96 +980,6 @@ function theme_comment_form_box($edit, $
}
/**
- * Form builder; Generate and validate a comment preview form.
- *
- * @ingroup forms
- */
-function comment_form_add_preview($form, &$form_state) {
- global $user;
- $edit = $form_state['values'];
- drupal_set_title(t('Preview comment'), PASS_THROUGH);
- $output = '';
- $node = node_load($edit['nid']);
-
- // Invoke full validation for the form, to protect against cross site
- // request forgeries (CSRF) and setting arbitrary values for fields such as
- // the text format. Preview the comment only when form validation does not
- // set any errors.
- drupal_validate_form($form['form_id']['#value'], $form, $form_state);
- if (!form_get_errors()) {
- _comment_form_submit($edit);
- $comment = (object)$edit;
- $comment->format = $comment->comment_format;
-
- // Attach the user and time information.
- if (!empty($edit['author'])) {
- $account = user_load_by_name($edit['author']);
- }
- elseif ($user->uid && !isset($edit['is_anonymous'])) {
- $account = $user;
- }
-
- if (!empty($account)) {
- $comment->uid = $account->uid;
- $comment->name = check_plain($account->name);
- }
- elseif (empty($comment->name)) {
- $comment->name = variable_get('anonymous', t('Anonymous'));
- }
-
- $comment->timestamp = !empty($edit['timestamp']) ? $edit['timestamp'] : REQUEST_TIME;
- $output .= theme('comment_view', $comment, $node);
- }
-
- $form['comment_preview'] = array(
- '#markup' => $output,
- '#weight' => -100,
- '#prefix' => '' . t("Personal contact forms allow users to be contacted via e-mail, while keeping recipient e-mail addresses private. Users may enable or disable their personal contact forms by editing their My account page. If enabled, a Contact tab leading to their personal contact form is available on their user profile. Site administrators have access to all personal contact forms (even if they have been disabled). The Contact tab is only visible when viewing another user's profile (users do not see their own Contact tab).") . '
'; + $output .= '' . t('The contact page provides a simple form for visitors to leave comments, feedback, or other requests. Messages are routed by selecting a category from a list of administrator-defined options; each category has its own set of e-mail recipients. Common categories for a business site include, for example, "Website feedback" (messages are forwarded to web site administrators) and "Product information" (messages are forwarded to members of the sales department). The actual e-mail addresses defined within a category are not displayed. Only users in roles with the access site-wide contact form permission may access the contact page.', array('@contact' => url('contact'))) . '
'; + $output .= '' . t('A link to your site\'s contact page from the main Navigation menu is created, but is disabled by default. Create a similar link on another menu by adding a menu item pointing to the path "contact"', array('@contact' => url('contact'))) . '
'; + $output .= '' . t('Customize the contact page with additional information (like physical location, mailing address, and telephone number) using the contact form settings page. The settings page also provides configuration options for the maximum number of contact form submissions a user may perform per hour, and the default status of users\' personal contact forms.', array('@contact-settings' => url('admin/build/contact/settings'), '@contact' => url('contact'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Contact module.', array('@contact' => url('http://drupal.org/handbook/modules/contact/', array('absolute' => TRUE)))) . '
'; + return $output; + case 'admin/build/contact': + $output = '' . t('This page lets you set up your site-wide contact form. To do so, add one or more categories. You can associate different recipients with each category to route e-mails to different people. For example, you can route website feedback to the webmaster and direct product information requests to the sales department. On the settings page, you can customize the information shown above the contact form. This can be useful to provide additional contact information such as your postal address and telephone number.', array('@settings' => url('admin/build/contact/settings'), '@form' => url('contact'))) . '
'; + if (!module_exists('menu')) { + $menu_note = t('The menu item can be customized and configured only once the menu module has been enabled.', array('@modules-page' => url('admin/settings/modules'))); + } + else { + $menu_note = ''; + } + $output .= '' . t('The contact module also adds a menu item (disabled by default) to the navigation block.', array('@menu-settings' => url('admin/build/menu'))) . ' ' . $menu_note . '
'; + return $output; + } +} + Index: modules/contact/contact.info =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.info,v retrieving revision 1.8 diff -u -p -r1.8 contact.info --- modules/contact/contact.info 11 Oct 2008 02:32:42 -0000 1.8 +++ modules/contact/contact.info 22 May 2009 23:44:07 -0000 @@ -8,3 +8,7 @@ files[] = contact.module files[] = contact.admin.inc files[] = contact.pages.inc files[] = contact.install +files[] = contact.registry.inc +files[] = contact.mail.inc +files[] = contact.user.inc +files[] = contact.help.inc Index: modules/contact/contact.mail.inc =================================================================== RCS file: modules/contact/contact.mail.inc diff -N modules/contact/contact.mail.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/contact/contact.mail.inc 22 May 2009 23:44:07 -0000 @@ -0,0 +1,39 @@ + $contact['category'], '!subject' => $params['subject']), $language->language); + $message['body'][] = t("!name sent a message using the contact form at !form.", array('!name' => $params['name'], '!form' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language))), $language->language); + $message['body'][] = $params['message']; + break; + case 'page_autoreply': + $contact = $params['contact']; + $message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), $language->language); + $message['body'][] = $contact['reply']; + break; + case 'user_mail': + case 'user_copy': + $user = $params['user']; + $account = $params['account']; + $message['subject'] .= '[' . variable_get('site_name', 'Drupal') . '] ' . $params['subject']; + $message['body'][] = "$account->name,"; + $message['body'][] = t("!name (!name-url) has sent you a message via your contact form (!form-url) at !site.", array('!name' => $user->name, '!name-url' => url("user/$user->uid", array('absolute' => TRUE, 'language' => $language)), '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), $language->language); + $message['body'][] = t("If you don't want to receive such e-mails, you can change your settings at !url.", array('!url' => url("user/$account->uid", array('absolute' => TRUE, 'language' => $language))), $language->language); + $message['body'][] = t('Message:', NULL, $language->language); + $message['body'][] = $params['message']; + break; + } +} Index: modules/contact/contact.module =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.module,v retrieving revision 1.114 diff -u -p -r1.114 contact.module --- modules/contact/contact.module 10 May 2009 18:24:06 -0000 1.114 +++ modules/contact/contact.module 22 May 2009 23:44:07 -0000 @@ -7,111 +7,6 @@ */ /** - * Implementation of hook_help(). - */ -function contact_help($path, $arg) { - switch ($path) { - case 'admin/help#contact': - $output = '' . t('The contact module facilitates communication via e-mail, by allowing your site\'s visitors to contact one another (personal contact forms), and by providing a simple way to direct messages to a set of administrator-defined recipients (the contact page). With either form, users specify a subject, write their message, and (optionally) have a copy of their message sent to their own e-mail address.', array('@contact' => url('contact'))) . '
'; - $output .= '' . t("Personal contact forms allow users to be contacted via e-mail, while keeping recipient e-mail addresses private. Users may enable or disable their personal contact forms by editing their My account page. If enabled, a Contact tab leading to their personal contact form is available on their user profile. Site administrators have access to all personal contact forms (even if they have been disabled). The Contact tab is only visible when viewing another user's profile (users do not see their own Contact tab).") . '
'; - $output .= '' . t('The contact page provides a simple form for visitors to leave comments, feedback, or other requests. Messages are routed by selecting a category from a list of administrator-defined options; each category has its own set of e-mail recipients. Common categories for a business site include, for example, "Website feedback" (messages are forwarded to web site administrators) and "Product information" (messages are forwarded to members of the sales department). The actual e-mail addresses defined within a category are not displayed. Only users in roles with the access site-wide contact form permission may access the contact page.', array('@contact' => url('contact'))) . '
'; - $output .= '' . t('A link to your site\'s contact page from the main Navigation menu is created, but is disabled by default. Create a similar link on another menu by adding a menu item pointing to the path "contact"', array('@contact' => url('contact'))) . '
'; - $output .= '' . t('Customize the contact page with additional information (like physical location, mailing address, and telephone number) using the contact form settings page. The settings page also provides configuration options for the maximum number of contact form submissions a user may perform per hour, and the default status of users\' personal contact forms.', array('@contact-settings' => url('admin/build/contact/settings'), '@contact' => url('contact'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Contact module.', array('@contact' => url('http://drupal.org/handbook/modules/contact/', array('absolute' => TRUE)))) . '
'; - return $output; - case 'admin/build/contact': - $output = '' . t('This page lets you set up your site-wide contact form. To do so, add one or more categories. You can associate different recipients with each category to route e-mails to different people. For example, you can route website feedback to the webmaster and direct product information requests to the sales department. On the settings page, you can customize the information shown above the contact form. This can be useful to provide additional contact information such as your postal address and telephone number.', array('@settings' => url('admin/build/contact/settings'), '@form' => url('contact'))) . '
'; - if (!module_exists('menu')) { - $menu_note = t('The menu item can be customized and configured only once the menu module has been enabled.', array('@modules-page' => url('admin/settings/modules'))); - } - else { - $menu_note = ''; - } - $output .= '' . t('The contact module also adds a menu item (disabled by default) to the navigation block.', array('@menu-settings' => url('admin/build/menu'))) . ' ' . $menu_note . '
'; - return $output; - } -} - -/** - * Implementation of hook_perm(). - */ -function contact_perm() { - return array( - 'administer site-wide contact form' => array( - 'title' => t('Administer site-wide contact form'), - 'description' => t('Configure site-wide contact form administration settings.'), - ), - 'access site-wide contact form' => array( - 'title' => t('Access site-wide contact form'), - 'description' => t('Send feedback to administrators via e-mail using the site-wide contact form.'), - ), - ); -} - -/** - * Implementation of hook_menu(). - */ -function contact_menu() { - $items['admin/build/contact'] = array( - 'title' => 'Contact form', - 'description' => 'Create a system contact form and set up categories for the form to use.', - 'page callback' => 'contact_admin_categories', - 'access arguments' => array('administer site-wide contact form'), - ); - $items['admin/build/contact/list'] = array( - 'title' => 'List', - 'page callback' => 'contact_admin_categories', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/build/contact/add'] = array( - 'title' => 'Add category', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('contact_admin_edit', 3), - 'access arguments' => array('administer site-wide contact form'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 1, - ); - $items['admin/build/contact/edit/%contact'] = array( - 'title' => 'Edit contact category', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('contact_admin_edit', 3, 4), - 'access arguments' => array('administer site-wide contact form'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/contact/delete/%contact'] = array( - 'title' => 'Delete contact', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('contact_admin_delete', 4), - 'access arguments' => array('administer site-wide contact form'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/contact/settings'] = array( - 'title' => 'Settings', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('contact_admin_settings'), - 'access arguments' => array('administer site-wide contact form'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 2, - ); - $items['contact'] = array( - 'title' => 'Contact', - 'page callback' => 'contact_site_page', - 'access arguments' => array('access site-wide contact form'), - 'type' => MENU_SUGGESTED_ITEM, - ); - $items['user/%user/contact'] = array( - 'title' => 'Contact', - 'page callback' => 'contact_personal_page', - 'page arguments' => array(1), - 'type' => MENU_LOCAL_TASK, - 'access callback' => '_contact_personal_tab_access', - 'access arguments' => array(1), - 'weight' => 2, - ); - return $items; -} - -/** * Determine permission to a user's personal contact form. */ function _contact_personal_tab_access($account) { @@ -136,67 +31,3 @@ function contact_load($cid) { return empty($contact) ? FALSE : $contact; } -/** - * Implementation of hook_user_form(). - */ -function contact_user_form(&$edit, &$user, $category = NULL) { - if ($category == 'account') { - $form['contact'] = array('#type' => 'fieldset', - '#title' => t('Contact settings'), - '#weight' => 5, - '#collapsible' => TRUE, - ); - $form['contact']['contact'] = array('#type' => 'checkbox', - '#title' => t('Personal contact form'), - '#default_value' => !empty($edit['contact']) ? $edit['contact'] : FALSE, - '#description' => t('Allow other users to contact you via a personal contact form which keeps your e-mail address hidden. Note that some privileged users such as site administrators are still able to contact you even if you choose to disable this feature.', array('@url' => url("user/$user->uid/contact"))), - ); - return $form; - } -} - -/** - * Implementation of hook_user_insert(). - */ -function contact_user_insert(&$edit, &$user, $category = NULL) { - $edit['contact'] = variable_get('contact_default_status', 1); -} - -/** - * Implementation of hook_user_validate(). - */ -function contact_user_validate(&$edit, &$user, $category = NULL) { - return array('contact' => isset($edit['contact']) ? $edit['contact'] : FALSE); -} - -/** - * Implementation of hook_mail(). - */ -function contact_mail($key, &$message, $params) { - $language = $message['language']; - switch ($key) { - case 'page_mail': - case 'page_copy': - $contact = $params['contact']; - $message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), $language->language); - $message['body'][] = t("!name sent a message using the contact form at !form.", array('!name' => $params['name'], '!form' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language))), $language->language); - $message['body'][] = $params['message']; - break; - case 'page_autoreply': - $contact = $params['contact']; - $message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), $language->language); - $message['body'][] = $contact['reply']; - break; - case 'user_mail': - case 'user_copy': - $user = $params['user']; - $account = $params['account']; - $message['subject'] .= '[' . variable_get('site_name', 'Drupal') . '] ' . $params['subject']; - $message['body'][] = "$account->name,"; - $message['body'][] = t("!name (!name-url) has sent you a message via your contact form (!form-url) at !site.", array('!name' => $user->name, '!name-url' => url("user/$user->uid", array('absolute' => TRUE, 'language' => $language)), '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), $language->language); - $message['body'][] = t("If you don't want to receive such e-mails, you can change your settings at !url.", array('!url' => url("user/$account->uid", array('absolute' => TRUE, 'language' => $language))), $language->language); - $message['body'][] = t('Message:', NULL, $language->language); - $message['body'][] = $params['message']; - break; - } -} Index: modules/contact/contact.registry.inc =================================================================== RCS file: modules/contact/contact.registry.inc diff -N modules/contact/contact.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/contact/contact.registry.inc 22 May 2009 23:44:06 -0000 @@ -0,0 +1,71 @@ + 'Contact form', + 'description' => 'Create a system contact form and set up categories for the form to use.', + 'page callback' => 'contact_admin_categories', + 'access arguments' => array('administer site-wide contact form'), + ); + $items['admin/build/contact/list'] = array( + 'title' => 'List', + 'page callback' => 'contact_admin_categories', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['admin/build/contact/add'] = array( + 'title' => 'Add category', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('contact_admin_edit', 3), + 'access arguments' => array('administer site-wide contact form'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 1, + ); + $items['admin/build/contact/edit/%contact'] = array( + 'title' => 'Edit contact category', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('contact_admin_edit', 3, 4), + 'access arguments' => array('administer site-wide contact form'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/contact/delete/%contact'] = array( + 'title' => 'Delete contact', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('contact_admin_delete', 4), + 'access arguments' => array('administer site-wide contact form'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/contact/settings'] = array( + 'title' => 'Settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('contact_admin_settings'), + 'access arguments' => array('administer site-wide contact form'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 2, + ); + $items['contact'] = array( + 'title' => 'Contact', + 'page callback' => 'contact_site_page', + 'access arguments' => array('access site-wide contact form'), + 'type' => MENU_SUGGESTED_ITEM, + ); + $items['user/%user/contact'] = array( + 'title' => 'Contact', + 'page callback' => 'contact_personal_page', + 'page arguments' => array(1), + 'type' => MENU_LOCAL_TASK, + 'access callback' => '_contact_personal_tab_access', + 'access arguments' => array(1), + 'weight' => 2, + ); + return $items; +} + Index: modules/contact/contact.user.inc =================================================================== RCS file: modules/contact/contact.user.inc diff -N modules/contact/contact.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/contact/contact.user.inc 22 May 2009 23:44:07 -0000 @@ -0,0 +1,57 @@ + array( + 'title' => t('Administer site-wide contact form'), + 'description' => t('Configure site-wide contact form administration settings.'), + ), + 'access site-wide contact form' => array( + 'title' => t('Access site-wide contact form'), + 'description' => t('Send feedback to administrators via e-mail using the site-wide contact form.'), + ), + ); +} + +/** + * Implementation of hook_user_form(). + */ +function contact_user_form(&$edit, &$user, $category = NULL) { + if ($category == 'account') { + $form['contact'] = array('#type' => 'fieldset', + '#title' => t('Contact settings'), + '#weight' => 5, + '#collapsible' => TRUE, + ); + $form['contact']['contact'] = array('#type' => 'checkbox', + '#title' => t('Personal contact form'), + '#default_value' => !empty($edit['contact']) ? $edit['contact'] : FALSE, + '#description' => t('Allow other users to contact you via a personal contact form which keeps your e-mail address hidden. Note that some privileged users such as site administrators are still able to contact you even if you choose to disable this feature.', array('@url' => url("user/$user->uid/contact"))), + ); + return $form; + } +} + +/** + * Implementation of hook_user_insert(). + */ +function contact_user_insert(&$edit, &$user, $category = NULL) { + $edit['contact'] = variable_get('contact_default_status', 1); +} + +/** + * Implementation of hook_user_validate(). + */ +function contact_user_validate(&$edit, &$user, $category = NULL) { + return array('contact' => isset($edit['contact']) ? $edit['contact'] : FALSE); +} + Index: modules/dblog/dblog.cron.inc =================================================================== RCS file: modules/dblog/dblog.cron.inc diff -N modules/dblog/dblog.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/dblog/dblog.cron.inc 22 May 2009 23:44:06 -0000 @@ -0,0 +1,21 @@ +fetchField(); + db_delete('watchdog') + ->condition('wid', $max - variable_get('dblog_row_limit', 1000), '<=') + ->execute(); +} + Index: modules/dblog/dblog.help.inc =================================================================== RCS file: modules/dblog/dblog.help.inc diff -N modules/dblog/dblog.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/dblog/dblog.help.inc 22 May 2009 23:44:06 -0000 @@ -0,0 +1,23 @@ +' . t('The dblog module monitors your system, capturing system events in a log to be reviewed by an authorized individual at a later time. This is useful for site administrators who want a quick overview of activities on their site. The logs also record the sequence of events, so it can be useful for debugging site errors.') . ''; + $output .= '' . t('The dblog log is simply a list of recorded events containing usage data, performance data, errors, warnings and operational information. Administrators should check the dblog report on a regular basis to ensure their site is working properly.') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Dblog module.', array('@dblog' => 'http://drupal.org/handbook/modules/dblog/')) . '
'; + return $output; + case 'admin/reports/dblog': + return '' . t('The dblog module monitors your website, capturing system events in a log to be reviewed by an authorized individual at a later time. The dblog log is simply a list of recorded events containing usage data, performance data, errors, warnings and operational information. It is vital to check the dblog report on a regular basis as it is often the only way to tell what is going on.') . '
'; + } +} + Index: modules/dblog/dblog.info =================================================================== RCS file: /cvs/drupal/drupal/modules/dblog/dblog.info,v retrieving revision 1.6 diff -u -p -r1.6 dblog.info --- modules/dblog/dblog.info 11 Oct 2008 02:32:44 -0000 1.6 +++ modules/dblog/dblog.info 22 May 2009 23:44:06 -0000 @@ -7,3 +7,8 @@ core = 7.x files[] = dblog.module files[] = dblog.admin.inc files[] = dblog.install +files[] = dblog.registry.inc +files[] = dblog.user.inc +files[] = dblog.cron.inc +files[] = dblog.help.inc +files[] = dblog.watchdog.inc Index: modules/dblog/dblog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/dblog/dblog.module,v retrieving revision 1.37 diff -u -p -r1.37 dblog.module --- modules/dblog/dblog.module 13 Apr 2009 08:48:58 -0000 1.37 +++ modules/dblog/dblog.module 22 May 2009 23:44:06 -0000 @@ -12,67 +12,6 @@ * @see watchdog() */ -/** - * Implementation of hook_help(). - */ -function dblog_help($path, $arg) { - switch ($path) { - case 'admin/help#dblog': - $output = '' . t('The dblog module monitors your system, capturing system events in a log to be reviewed by an authorized individual at a later time. This is useful for site administrators who want a quick overview of activities on their site. The logs also record the sequence of events, so it can be useful for debugging site errors.') . '
'; - $output .= '' . t('The dblog log is simply a list of recorded events containing usage data, performance data, errors, warnings and operational information. Administrators should check the dblog report on a regular basis to ensure their site is working properly.') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Dblog module.', array('@dblog' => 'http://drupal.org/handbook/modules/dblog/')) . '
'; - return $output; - case 'admin/reports/dblog': - return '' . t('The dblog module monitors your website, capturing system events in a log to be reviewed by an authorized individual at a later time. The dblog log is simply a list of recorded events containing usage data, performance data, errors, warnings and operational information. It is vital to check the dblog report on a regular basis as it is often the only way to tell what is going on.') . '
'; - } -} - -/** - * Implementation of hook_theme(). - */ -function dblog_theme() { - return array( - 'dblog_filters' => array( - 'arguments' => array('form' => NULL), - ), - ); -} - -/** - * Implementation of hook_menu(). - */ -function dblog_menu() { - $items['admin/reports/dblog'] = array( - 'title' => 'Recent log entries', - 'description' => 'View events that have recently been logged.', - 'page callback' => 'dblog_overview', - 'access arguments' => array('access site reports'), - 'weight' => -1, - ); - $items['admin/reports/page-not-found'] = array( - 'title' => "Top 'page not found' errors", - 'description' => "View 'page not found' errors (404s).", - 'page callback' => 'dblog_top', - 'page arguments' => array('page not found'), - 'access arguments' => array('access site reports'), - ); - $items['admin/reports/access-denied'] = array( - 'title' => "Top 'access denied' errors", - 'description' => "View 'access denied' errors (403s).", - 'page callback' => 'dblog_top', - 'page arguments' => array('access denied'), - 'access arguments' => array('access site reports'), - ); - $items['admin/reports/event/%'] = array( - 'title' => 'Details', - 'page callback' => 'dblog_event', - 'page arguments' => array(3), - 'access arguments' => array('access site reports'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - function dblog_init() { if (arg(0) == 'admin' && arg(1) == 'reports') { // Add the CSS for this module @@ -82,39 +21,6 @@ function dblog_init() { -/** - * Implementation of hook_cron(). - * - * Remove expired log messages and flood control events. - */ -function dblog_cron() { - // Cleanup the watchdog table - $max = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField(); - db_delete('watchdog') - ->condition('wid', $max - variable_get('dblog_row_limit', 1000), '<=') - ->execute(); -} - -/** - * Implementation of hook_user_cancel(). - */ -function dblog_user_cancel($edit, $account, $method) { - switch ($method) { - case 'user_cancel_reassign': - db_update('watchdog') - ->fields(array('uid' => 0)) - ->condition('uid', $account->uid) - ->execute(); - break; - - case 'user_cancel_delete': - db_delete('watchdog') - ->condition('uid', $account->uid) - ->execute(); - break; - } -} - function _dblog_get_message_types() { $types = array(); @@ -127,28 +33,6 @@ function _dblog_get_message_types() { } /** - * Implementation of hook_watchdog(). - * - * Note some values may be truncated for database column size restrictions. - */ -function dblog_watchdog(array $log_entry) { - Database::getConnection('default', 'default')->insert('watchdog') - ->fields(array( - 'uid' => $log_entry['user']->uid, - 'type' => substr($log_entry['type'], 0, 64), - 'message' => $log_entry['message'], - 'variables' => serialize($log_entry['variables']), - 'severity' => $log_entry['severity'], - 'link' => substr($log_entry['link'], 0, 255), - 'location' => $log_entry['request_uri'], - 'referer' => $log_entry['referer'], - 'hostname' => substr($log_entry['ip'], 0, 128), - 'timestamp' => $log_entry['timestamp'], - )) - ->execute(); -} - -/** * Theme dblog administration filter selector. * * @ingroup themeable Index: modules/dblog/dblog.registry.inc =================================================================== RCS file: modules/dblog/dblog.registry.inc diff -N modules/dblog/dblog.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/dblog/dblog.registry.inc 22 May 2009 23:44:06 -0000 @@ -0,0 +1,54 @@ + 'Recent log entries', + 'description' => 'View events that have recently been logged.', + 'page callback' => 'dblog_overview', + 'access arguments' => array('access site reports'), + 'weight' => -1, + ); + $items['admin/reports/page-not-found'] = array( + 'title' => "Top 'page not found' errors", + 'description' => "View 'page not found' errors (404s).", + 'page callback' => 'dblog_top', + 'page arguments' => array('page not found'), + 'access arguments' => array('access site reports'), + ); + $items['admin/reports/access-denied'] = array( + 'title' => "Top 'access denied' errors", + 'description' => "View 'access denied' errors (403s).", + 'page callback' => 'dblog_top', + 'page arguments' => array('access denied'), + 'access arguments' => array('access site reports'), + ); + $items['admin/reports/event/%'] = array( + 'title' => 'Details', + 'page callback' => 'dblog_event', + 'page arguments' => array(3), + 'access arguments' => array('access site reports'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function dblog_theme() { + return array( + 'dblog_filters' => array( + 'arguments' => array('form' => NULL), + ), + ); +} + Index: modules/dblog/dblog.user.inc =================================================================== RCS file: modules/dblog/dblog.user.inc diff -N modules/dblog/dblog.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/dblog/dblog.user.inc 22 May 2009 23:44:06 -0000 @@ -0,0 +1,28 @@ +fields(array('uid' => 0)) + ->condition('uid', $account->uid) + ->execute(); + break; + + case 'user_cancel_delete': + db_delete('watchdog') + ->condition('uid', $account->uid) + ->execute(); + break; + } +} + Index: modules/dblog/dblog.watchdog.inc =================================================================== RCS file: modules/dblog/dblog.watchdog.inc diff -N modules/dblog/dblog.watchdog.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/dblog/dblog.watchdog.inc 22 May 2009 23:44:06 -0000 @@ -0,0 +1,30 @@ +insert('watchdog') + ->fields(array( + 'uid' => $log_entry['user']->uid, + 'type' => substr($log_entry['type'], 0, 64), + 'message' => $log_entry['message'], + 'variables' => serialize($log_entry['variables']), + 'severity' => $log_entry['severity'], + 'link' => substr($log_entry['link'], 0, 255), + 'location' => $log_entry['request_uri'], + 'referer' => $log_entry['referer'], + 'hostname' => substr($log_entry['ip'], 0, 128), + 'timestamp' => $log_entry['timestamp'], + )) + ->execute(); +} + Index: modules/field/field.help.inc =================================================================== RCS file: modules/field/field.help.inc diff -N modules/field/field.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/field.help.inc 22 May 2009 23:44:06 -0000 @@ -0,0 +1,20 @@ +' . t('The Field API allows custom data fields to be attached to Drupal objects and takes care of storing, loading, editing, and rendering field data. Any object type (node, user, etc.) can use the Field API to make itself "fieldable" and thus allow fields to be attached to it.') . ''; + $output .= '' .t('The Field API provides no user interface on its own. Use the Content Construction Kit (CCK) contrib module to manage custom fields via a web browser.') . '
'; + return $output; + } +} + Index: modules/field/field.info =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.info,v retrieving revision 1.2 diff -u -p -r1.2 field.info --- modules/field/field.info 10 May 2009 18:56:56 -0000 1.2 +++ modules/field/field.info 22 May 2009 23:44:06 -0000 @@ -14,3 +14,5 @@ files[] = field.form.inc files[] = field.autoload.inc dependencies[] = field_sql_storage required = TRUE +files[] = field.registry.inc +files[] = field.help.inc Index: modules/field/field.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.module,v retrieving revision 1.7 diff -u -p -r1.7 field.module --- modules/field/field.module 26 Mar 2009 13:31:24 -0000 1.7 +++ modules/field/field.module 22 May 2009 23:44:06 -0000 @@ -88,25 +88,6 @@ define('FIELD_LOAD_REVISION', 'FIELD_LOA class FieldException extends Exception {} /** - * Implementation of hook_flush_caches. - */ -function field_flush_caches() { - return array('cache_field'); -} - -/** - * Implementation of hook_help(). - */ -function field_help($path, $arg) { - switch ($path) { - case 'admin/help#field': - $output = '' . t('The Field API allows custom data fields to be attached to Drupal objects and takes care of storing, loading, editing, and rendering field data. Any object type (node, user, etc.) can use the Field API to make itself "fieldable" and thus allow fields to be attached to it.') . '
'; - $output .= '' .t('The Field API provides no user interface on its own. Use the Content Construction Kit (CCK) contrib module to manage custom fields via a web browser.') . '
'; - return $output; - } -} - -/** * Implementation of hook_init(). * * TODO D7: Determine which functions need to always be "loaded", and @@ -120,92 +101,6 @@ function field_init() { } /** - * Implementation of hook_menu(). - */ -function field_menu() { - $items = array(); - - // Callback for AHAH add more buttons. - $items['field/js_add_more'] = array( - 'page callback' => 'field_add_more_js', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** - * Implementation of hook_theme(). - */ -function field_theme() { - $path = drupal_get_path('module', 'field') . '/theme'; - - return array( - 'field' => array( - 'template' => 'field', - 'arguments' => array('element' => NULL), - 'path' => $path, - ), - // TODO D7 : do we need exclude in core? See [#367215]. - // This is just adding '#post_render' => array('field_wrapper_post_render') - // at the right places in the render array generated by field_default_view(). - // Can be done in hook_field_attach_post_view if we want. - 'field_exclude' => array( - 'arguments' => array('content' => NULL, 'object' => array(), 'context' => NULL), - ), - 'field_multiple_value_form' => array( - 'arguments' => array('element' => NULL), - ), - ); -} - -/** - * Implementation of hook_modules_installed(). - */ -function field_modules_installed($modules) { - field_cache_clear(); -} - -/** - * Implementation of hook_modules_uninstalled(). - */ -function field_modules_uninstalled($modules) { - module_load_include('inc', 'field', 'field.crud'); - foreach ($modules as $module) { - // TODO D7: field_module_delete is not yet implemented - // field_module_delete($module); - } -} - -/** - * Implementation of hook_modules_enabled(). - */ -function field_modules_enabled($modules) { - foreach ($modules as $module) { - field_associate_fields($module); - } - field_cache_clear(); -} - -/** - * Implementation of hook_modules_disabled(). - */ -function field_modules_disabled($modules) { - foreach ($modules as $module) { - db_update('field_config') - ->fields(array('active' => 0)) - ->condition('module', $module) - ->execute(); - db_update('field_config_instance') - ->fields(array('widget_active' => 0)) - ->condition('widget_module', $module) - ->execute(); - field_cache_clear(TRUE); - } -} - -/** * Allows a module to update the database for fields and columns it controls. * * @param string $module Index: modules/field/field.registry.inc =================================================================== RCS file: modules/field/field.registry.inc diff -N modules/field/field.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/field.registry.inc 22 May 2009 23:44:05 -0000 @@ -0,0 +1,101 @@ + 'field_add_more_js', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function field_theme() { + $path = drupal_get_path('module', 'field') . '/theme'; + + return array( + 'field' => array( + 'template' => 'field', + 'arguments' => array('element' => NULL), + 'path' => $path, + ), + // TODO D7 : do we need exclude in core? See [#367215]. + // This is just adding '#post_render' => array('field_wrapper_post_render') + // at the right places in the render array generated by field_default_view(). + // Can be done in hook_field_attach_post_view if we want. + 'field_exclude' => array( + 'arguments' => array('content' => NULL, 'object' => array(), 'context' => NULL), + ), + 'field_multiple_value_form' => array( + 'arguments' => array('element' => NULL), + ), + ); +} + +/** + * Implementation of hook_flush_caches. + */ +function field_flush_caches() { + return array('cache_field'); +} + +/** + * Implementation of hook_modules_installed(). + */ +function field_modules_installed($modules) { + field_cache_clear(); +} + +/** + * Implementation of hook_modules_uninstalled(). + */ +function field_modules_uninstalled($modules) { + module_load_include('inc', 'field', 'field.crud'); + foreach ($modules as $module) { + // TODO D7: field_module_delete is not yet implemented + // field_module_delete($module); + } +} + +/** + * Implementation of hook_modules_enabled(). + */ +function field_modules_enabled($modules) { + foreach ($modules as $module) { + field_associate_fields($module); + } + field_cache_clear(); +} + +/** + * Implementation of hook_modules_disabled(). + */ +function field_modules_disabled($modules) { + foreach ($modules as $module) { + db_update('field_config') + ->fields(array('active' => 0)) + ->condition('module', $module) + ->execute(); + db_update('field_config_instance') + ->fields(array('widget_active' => 0)) + ->condition('widget_module', $module) + ->execute(); + field_cache_clear(TRUE); + } +} + Index: modules/field/modules/field_sql_storage/field_sql_storage.field_storage.inc =================================================================== RCS file: modules/field/modules/field_sql_storage/field_sql_storage.field_storage.inc diff -N modules/field/modules/field_sql_storage/field_sql_storage.field_storage.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/field_sql_storage/field_sql_storage.field_storage.inc 22 May 2009 23:44:05 -0000 @@ -0,0 +1,170 @@ + $table) { + db_create_table($ret, $name, $table); + } +} + +/** + * Implementation of hook_field_storage_delete_field(). + */ +function field_sql_storage_field_storage_delete_field($field_name) { + // Mark all data associated with the field for deletion. + $table = _field_sql_storage_tablename($field_name); + db_update($table) + ->fields(array('deleted' => 1)) + ->execute(); +} + +/** + * Implementation of hook_field_storage_write(). + */ +function field_sql_storage_field_storage_write($obj_type, $object, $op, $skip_fields) { + list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); + $etid = _field_sql_storage_etid($obj_type); + + $instances = field_info_instances($bundle); + foreach ($instances as $instance) { + $field_name = $instance['field_name']; + if (isset($skip_fields[$field_name])) { + continue; + } + + $table_name = _field_sql_storage_tablename($field_name); + $revision_name = _field_sql_storage_revision_tablename($field_name); + $field = field_info_field($field_name); + + // Leave the field untouched if $object comes with no $field_name property. + // Empty the field if $object->$field_name is NULL or an empty array. + + // Function property_exists() is slower, so we catch the more frequent cases + // where it's an empty array with the faster isset(). + if (isset($object->$field_name) || property_exists($object, $field_name)) { + // Delete and insert, rather than update, in case a value was added. + if ($op == FIELD_STORAGE_UPDATE) { + db_delete($table_name)->condition('etid', $etid)->condition('entity_id', $id)->execute(); + if (isset($vid)) { + db_delete($revision_name)->condition('etid', $etid)->condition('entity_id', $id)->condition('revision_id', $vid)->execute(); + } + } + + if ($object->$field_name) { + // Prepare the multi-insert query. + $columns = array('etid', 'entity_id', 'revision_id', 'bundle', 'delta'); + foreach ($field['columns'] as $column => $attributes) { + $columns[] = _field_sql_storage_columnname($field_name, $column); + } + $query = db_insert($table_name)->fields($columns); + if (isset($vid)) { + $revision_query = db_insert($revision_name)->fields($columns); + } + + $delta_count = 0; + foreach ($object->$field_name as $delta => $item) { + $record = array( + 'etid' => $etid, + 'entity_id' => $id, + 'revision_id' => $vid, + 'bundle' => $bundle, + 'delta' => $delta, + ); + foreach ($field['columns'] as $column => $attributes) { + $record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL; + } + $query->values($record); + if (isset($vid)) { + $revision_query->values($record); + } + + if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) { + break; + } + } + + // Execute the insert. + $query->execute(); + if (isset($vid)) { + $revision_query->execute(); + } + } + } + } +} + +/** + * Implementation of hook_field_storage_delete(). + * + * This function actually deletes the data from the database. + */ +function field_sql_storage_field_storage_delete($obj_type, $object) { + list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); + $etid = _field_sql_storage_etid($obj_type); + + $instances = field_info_instances($bundle); + foreach ($instances as $instance) { + $field_name = $instance['field_name']; + $table_name = _field_sql_storage_tablename($field_name); + $revision_name = _field_sql_storage_revision_tablename($field_name); + db_delete($table_name) + ->condition('etid', $etid) + ->condition('entity_id', $id) + ->execute(); + db_delete($revision_name) + ->condition('etid', $etid) + ->condition('entity_id', $id) + ->execute(); + } +} + +/** + * Implementation of hook_field_storage_delete_revision(). + * + * This function actually deletes the data from the database. + */ +function field_sql_storage_field_storage_delete_revision($obj_type, $object) { + list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); + $etid = _field_sql_storage_etid($obj_type); + + if (isset($vid)) { + $instances = field_info_instances($bundle); + foreach ($instances as $instance) { + $field_name = $instance['field_name']; + $revision_name = _field_sql_storage_revision_tablename($field_name); + db_delete($revision_name) + ->condition('etid', $etid) + ->condition('entity_id', $id) + ->condition('revision_id', $vid) + ->execute(); + } + } +} + +/** + * Implementation of hook_field_storage_delete_instance(). + * + * This function simply marks for deletion all data associated with the field. + */ +function field_sql_storage_field_storage_delete_instance($field_name, $bundle) { + $table_name = _field_sql_storage_tablename($field_name); + $revision_name = _field_sql_storage_revision_tablename($field_name); + db_update($table_name) + ->fields(array('deleted' => 1)) + ->condition('bundle', $bundle) + ->execute(); + db_update($revision_name) + ->fields(array('deleted' => 1)) + ->condition('bundle', $bundle) + ->execute(); +} + Index: modules/field/modules/field_sql_storage/field_sql_storage.help.inc =================================================================== RCS file: modules/field/modules/field_sql_storage/field_sql_storage.help.inc diff -N modules/field/modules/field_sql_storage/field_sql_storage.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/field_sql_storage/field_sql_storage.help.inc 22 May 2009 23:44:05 -0000 @@ -0,0 +1,19 @@ +' . t('The Field SQL Storage module stores Field API data in the database. It is the default field storage module, but other field storage modules may be available in the contributions repository.') . ''; + return $output; + } +} + Index: modules/field/modules/field_sql_storage/field_sql_storage.info =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.info,v retrieving revision 1.2 diff -u -p -r1.2 field_sql_storage.info --- modules/field/modules/field_sql_storage/field_sql_storage.info 10 May 2009 18:56:56 -0000 1.2 +++ modules/field/modules/field_sql_storage/field_sql_storage.info 22 May 2009 23:44:05 -0000 @@ -7,3 +7,5 @@ core = 7.x files[] = field_sql_storage.module files[] = field_sql_storage.install required = TRUE +files[] = field_sql_storage.help.inc +files[] = field_sql_storage.field_storage.inc Index: modules/field/modules/field_sql_storage/field_sql_storage.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.module,v retrieving revision 1.9 diff -u -p -r1.9 field_sql_storage.module --- modules/field/modules/field_sql_storage/field_sql_storage.module 20 May 2009 09:48:47 -0000 1.9 +++ modules/field/modules/field_sql_storage/field_sql_storage.module 22 May 2009 23:44:05 -0000 @@ -7,17 +7,6 @@ */ /** - * Implementation of hook_help(). - */ -function field_sql_storage_help($path, $arg) { - switch ($path) { - case 'admin/help#field_sql_storage': - $output = '' . t('The Field SQL Storage module stores Field API data in the database. It is the default field storage module, but other field storage modules may be available in the contributions repository.') . '
'; - return $output; - } -} - -/** * Generate a table name for a field data table. * * @param $name @@ -177,27 +166,6 @@ function _field_sql_storage_schema($fiel } /** - * Implementation of hook_field_storage_create_field(). - */ -function field_sql_storage_field_storage_create_field($field) { - $schema = _field_sql_storage_schema($field); - foreach ($schema as $name => $table) { - db_create_table($ret, $name, $table); - } -} - -/** - * Implementation of hook_field_storage_delete_field(). - */ -function field_sql_storage_field_storage_delete_field($field_name) { - // Mark all data associated with the field for deletion. - $table = _field_sql_storage_tablename($field_name); - db_update($table) - ->fields(array('deleted' => 1)) - ->execute(); -} - -/** * Implementation of hook_field_storage_load(). */ function field_sql_storage_field_storage_load($obj_type, &$objects, $age, $skip_fields = array()) { @@ -248,147 +216,6 @@ function field_sql_storage_field_storage } /** - * Implementation of hook_field_storage_write(). - */ -function field_sql_storage_field_storage_write($obj_type, $object, $op, $skip_fields) { - list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); - $etid = _field_sql_storage_etid($obj_type); - - $instances = field_info_instances($bundle); - foreach ($instances as $instance) { - $field_name = $instance['field_name']; - if (isset($skip_fields[$field_name])) { - continue; - } - - $table_name = _field_sql_storage_tablename($field_name); - $revision_name = _field_sql_storage_revision_tablename($field_name); - $field = field_info_field($field_name); - - // Leave the field untouched if $object comes with no $field_name property. - // Empty the field if $object->$field_name is NULL or an empty array. - - // Function property_exists() is slower, so we catch the more frequent cases - // where it's an empty array with the faster isset(). - if (isset($object->$field_name) || property_exists($object, $field_name)) { - // Delete and insert, rather than update, in case a value was added. - if ($op == FIELD_STORAGE_UPDATE) { - db_delete($table_name)->condition('etid', $etid)->condition('entity_id', $id)->execute(); - if (isset($vid)) { - db_delete($revision_name)->condition('etid', $etid)->condition('entity_id', $id)->condition('revision_id', $vid)->execute(); - } - } - - if ($object->$field_name) { - // Prepare the multi-insert query. - $columns = array('etid', 'entity_id', 'revision_id', 'bundle', 'delta'); - foreach ($field['columns'] as $column => $attributes) { - $columns[] = _field_sql_storage_columnname($field_name, $column); - } - $query = db_insert($table_name)->fields($columns); - if (isset($vid)) { - $revision_query = db_insert($revision_name)->fields($columns); - } - - $delta_count = 0; - foreach ($object->$field_name as $delta => $item) { - $record = array( - 'etid' => $etid, - 'entity_id' => $id, - 'revision_id' => $vid, - 'bundle' => $bundle, - 'delta' => $delta, - ); - foreach ($field['columns'] as $column => $attributes) { - $record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL; - } - $query->values($record); - if (isset($vid)) { - $revision_query->values($record); - } - - if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) { - break; - } - } - - // Execute the insert. - $query->execute(); - if (isset($vid)) { - $revision_query->execute(); - } - } - } - } -} - -/** - * Implementation of hook_field_storage_delete(). - * - * This function actually deletes the data from the database. - */ -function field_sql_storage_field_storage_delete($obj_type, $object) { - list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); - $etid = _field_sql_storage_etid($obj_type); - - $instances = field_info_instances($bundle); - foreach ($instances as $instance) { - $field_name = $instance['field_name']; - $table_name = _field_sql_storage_tablename($field_name); - $revision_name = _field_sql_storage_revision_tablename($field_name); - db_delete($table_name) - ->condition('etid', $etid) - ->condition('entity_id', $id) - ->execute(); - db_delete($revision_name) - ->condition('etid', $etid) - ->condition('entity_id', $id) - ->execute(); - } -} - -/** - * Implementation of hook_field_storage_delete_revision(). - * - * This function actually deletes the data from the database. - */ -function field_sql_storage_field_storage_delete_revision($obj_type, $object) { - list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); - $etid = _field_sql_storage_etid($obj_type); - - if (isset($vid)) { - $instances = field_info_instances($bundle); - foreach ($instances as $instance) { - $field_name = $instance['field_name']; - $revision_name = _field_sql_storage_revision_tablename($field_name); - db_delete($revision_name) - ->condition('etid', $etid) - ->condition('entity_id', $id) - ->condition('revision_id', $vid) - ->execute(); - } - } -} - -/** - * Implementation of hook_field_storage_delete_instance(). - * - * This function simply marks for deletion all data associated with the field. - */ -function field_sql_storage_field_storage_delete_instance($field_name, $bundle) { - $table_name = _field_sql_storage_tablename($field_name); - $revision_name = _field_sql_storage_revision_tablename($field_name); - db_update($table_name) - ->fields(array('deleted' => 1)) - ->condition('bundle', $bundle) - ->execute(); - db_update($revision_name) - ->fields(array('deleted' => 1)) - ->condition('bundle', $bundle) - ->execute(); -} - -/** * Implementation of hook_field_storage_rename_bundle(). */ function field_sql_storage_field_storage_rename_bundle($bundle_old, $bundle_new) { Index: modules/field/modules/list/list.field.inc =================================================================== RCS file: modules/field/modules/list/list.field.inc diff -N modules/field/modules/list/list.field.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/list/list.field.inc 22 May 2009 23:44:04 -0000 @@ -0,0 +1,79 @@ + array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + ), + ); + break; + case 'list_number': + $columns = array( + 'value' => array( + 'type' => 'float', + 'unsigned' => TRUE, + 'not null' => FALSE, + ), + ); + break; + default: + $columns = array( + 'value' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => FALSE, + ), + ); + break; + } + return array( + 'columns' => $columns, + 'indexes' => array( + 'value' => array('value'), + ), + ); +} + +/** + * Implementation of hook_field_validate(). + * + * Possible error codes: + * - 'list_illegal_value': The value is not part of the list of allowed values. + */ +function list_field_validate($obj_type, $object, $field, $instance, $items, &$errors) { + $allowed_values = list_allowed_values($field); + foreach ($items as $delta => $item) { + if (!empty($item['value'])) { + if (count($allowed_values) && !array_key_exists($item['value'], $allowed_values)) { + $errors[$field['field_name']][$delta][] = array( + 'error' => 'list_illegal_value', + 'message' => t('%name: illegal value.', array('%name' => t($instance['label']))), + ); + } + } + } +} + +/** + * Implementation of hook_field_is_empty(). + */ +function list_field_is_empty($item, $field) { + if (empty($item['value']) && (string)$item['value'] !== '0') { + return TRUE; + } + return FALSE; +} + Index: modules/field/modules/list/list.info =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/list/list.info,v retrieving revision 1.3 diff -u -p -r1.3 list.info --- modules/field/modules/list/list.info 10 May 2009 18:56:56 -0000 1.3 +++ modules/field/modules/list/list.info 22 May 2009 23:44:04 -0000 @@ -5,3 +5,5 @@ package = Core - fields version = VERSION core = 7.x files[]=list.module +files[] = list.registry.inc +files[] = list.field.inc Index: modules/field/modules/list/list.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/list/list.module,v retrieving revision 1.5 diff -u -p -r1.5 list.module --- modules/field/modules/list/list.module 20 May 2009 09:48:47 -0000 1.5 +++ modules/field/modules/list/list.module 22 May 2009 23:44:04 -0000 @@ -7,149 +7,6 @@ */ /** - * Implementation of hook_theme(). - */ -function list_theme() { - return array( - 'field_formatter_list_default' => array( - 'arguments' => array('element' => NULL), - ), - 'field_formatter_list_key' => array( - 'arguments' => array('element' => NULL), - ), - ); -} - -/** - * Implementation of hook_field_info(). - */ -function list_field_info() { - return array( - 'list' => array( - 'label' => t('List'), - 'description' => t('This field stores numeric keys from key/value lists of allowed values where the key is a simple alias for the position of the value, i.e. 0|First option, 1|Second option, 2|Third option.'), - 'settings' => array('allowed_values_function' => ''), - 'default_widget' => 'options_select', - 'default_formatter' => 'list_default', - ), - 'list_boolean' => array( - 'label' => t('Boolean'), - 'description' => t('This field stores simple on/off or yes/no options.'), - 'settings' => array('allowed_values_function' => ''), - 'default_widget' => 'options_select', - 'default_formatter' => 'list_default', - ), - 'list_number' => array( - 'label' => t('List (numeric)'), - 'description' => t('This field stores keys from key/value lists of allowed numbers where the stored numeric key has significance and must be preserved, i.e. \'Lifetime in days\': 1|1 day, 7|1 week, 31|1 month.'), - 'settings' => array('allowed_values_function' => ''), - 'default_widget' => 'options_select', - 'default_formatter' => 'list_default', - ), - 'list_text' => array( - 'label' => t('List (text)'), - 'description' => t('This field stores keys from key/value lists of allowed values where the stored key has significance and must be a varchar, i.e. \'US States\': IL|Illinois, IA|Iowa, IN|Indiana'), - 'settings' => array('allowed_values_function' => ''), - 'default_widget' => 'options_select', - 'default_formatter' => 'list_default', - ), - ); -} - -/** - * Implementation of hook_field_schema(). - */ -function list_field_schema($field) { - switch ($field['type']) { - case 'list_text': - $columns = array( - 'value' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => FALSE, - ), - ); - break; - case 'list_number': - $columns = array( - 'value' => array( - 'type' => 'float', - 'unsigned' => TRUE, - 'not null' => FALSE, - ), - ); - break; - default: - $columns = array( - 'value' => array( - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => FALSE, - ), - ); - break; - } - return array( - 'columns' => $columns, - 'indexes' => array( - 'value' => array('value'), - ), - ); -} - -/** - * Implementation of hook_field_validate(). - * - * Possible error codes: - * - 'list_illegal_value': The value is not part of the list of allowed values. - */ -function list_field_validate($obj_type, $object, $field, $instance, $items, &$errors) { - $allowed_values = list_allowed_values($field); - foreach ($items as $delta => $item) { - if (!empty($item['value'])) { - if (count($allowed_values) && !array_key_exists($item['value'], $allowed_values)) { - $errors[$field['field_name']][$delta][] = array( - 'error' => 'list_illegal_value', - 'message' => t('%name: illegal value.', array('%name' => t($instance['label']))), - ); - } - } - } -} - -/** - * Implementation of hook_field_is_empty(). - */ -function list_field_is_empty($item, $field) { - if (empty($item['value']) && (string)$item['value'] !== '0') { - return TRUE; - } - return FALSE; -} - -/** - * Implementation of hook_field_formatter_info(). - */ -function list_field_formatter_info() { - return array( - 'list_default' => array( - 'label' => t('Default'), - 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'list_key' => array( - 'label' => t('Key'), - 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - ); -} - -/** * Theme function for 'default' list field formatter. */ function theme_field_formatter_list_default($element) { Index: modules/field/modules/list/list.registry.inc =================================================================== RCS file: modules/field/modules/list/list.registry.inc diff -N modules/field/modules/list/list.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/list/list.registry.inc 22 May 2009 23:44:04 -0000 @@ -0,0 +1,80 @@ + array( + 'arguments' => array('element' => NULL), + ), + 'field_formatter_list_key' => array( + 'arguments' => array('element' => NULL), + ), + ); +} + +/** + * Implementation of hook_field_info(). + */ +function list_field_info() { + return array( + 'list' => array( + 'label' => t('List'), + 'description' => t('This field stores numeric keys from key/value lists of allowed values where the key is a simple alias for the position of the value, i.e. 0|First option, 1|Second option, 2|Third option.'), + 'settings' => array('allowed_values_function' => ''), + 'default_widget' => 'options_select', + 'default_formatter' => 'list_default', + ), + 'list_boolean' => array( + 'label' => t('Boolean'), + 'description' => t('This field stores simple on/off or yes/no options.'), + 'settings' => array('allowed_values_function' => ''), + 'default_widget' => 'options_select', + 'default_formatter' => 'list_default', + ), + 'list_number' => array( + 'label' => t('List (numeric)'), + 'description' => t('This field stores keys from key/value lists of allowed numbers where the stored numeric key has significance and must be preserved, i.e. \'Lifetime in days\': 1|1 day, 7|1 week, 31|1 month.'), + 'settings' => array('allowed_values_function' => ''), + 'default_widget' => 'options_select', + 'default_formatter' => 'list_default', + ), + 'list_text' => array( + 'label' => t('List (text)'), + 'description' => t('This field stores keys from key/value lists of allowed values where the stored key has significance and must be a varchar, i.e. \'US States\': IL|Illinois, IA|Iowa, IN|Indiana'), + 'settings' => array('allowed_values_function' => ''), + 'default_widget' => 'options_select', + 'default_formatter' => 'list_default', + ), + ); +} + +/** + * Implementation of hook_field_formatter_info(). + */ +function list_field_formatter_info() { + return array( + 'list_default' => array( + 'label' => t('Default'), + 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'list_key' => array( + 'label' => t('Key'), + 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + ); +} + Index: modules/field/modules/number/number.field.inc =================================================================== RCS file: modules/field/modules/number/number.field.inc diff -N modules/field/modules/number/number.field.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/number/number.field.inc 22 May 2009 23:44:25 -0000 @@ -0,0 +1,261 @@ + array( + 'type' => 'int', + 'not null' => FALSE + ), + ); + break; + + case 'number_float' : + $columns = array( + 'value' => array( + 'type' => 'float', + 'not null' => FALSE + ), + ); + break; + + case 'number_decimal' : + $columns = array( + 'value' => array( + 'type' => 'numeric', + 'precision' => $field['settings']['precision'], + 'scale' => $field['settings']['scale'], + 'not null' => FALSE + ), + ); + break; + } + return array( + 'columns' => $columns, + ); +} + +/** + * Implementation of hook_field_validate(). + * + * Possible error codes: + * - 'number_min': The value is smaller than the allowed minimum value. + * - 'number_max': The value is larger than the allowed maximum value. + */ +function number_field_validate($obj_type, $node, $field, $instance, $items, &$errors) { + foreach ($items as $delta => $item) { + if ($item['value'] != '') { + if (is_numeric($instance['settings']['min']) && $item['value'] < $instance['settings']['min']) { + $errors[$field['field_name']][$delta][] = array( + 'error' => 'number_min', + 'message' => t('%name: the value may be no smaller than %min.', array('%name' => t($instance['label']), '%min' => $instance['settings']['min'])), + ); + } + if (is_numeric($instance['settings']['max']) && $item['value'] > $instance['settings']['max']) { + $errors[$field['field_name']][$delta][] = array( + 'error' => 'number_max', + 'message' => t('%name: the value may be no larger than %max.', array('%name' => t($instance['label']), '%max' => $instance['settings']['max'])), + ); + } + } + } +} + +/** + * Implementation of hook_content_is_empty(). + */ +function number_field_is_empty($item, $field) { + if (empty($item['value']) && (string)$item['value'] !== '0') { + return TRUE; + } + return FALSE; +} + +/** + * Implementation of hook_field_widget(). + * + * Attach a single form element to the form. It will be built out and + * validated in the callback(s) listed in hook_elements. We build it + * out in the callbacks rather than here in hook_widget so it can be + * plugged into any module that can provide it with valid + * $field information. + * + * Field module will set the weight, field name and delta values + * for each form element. + * + * If there are multiple values for this field, the Field module will + * call this function as many times as needed. + * + * @param $form + * the entire form array, $form['#node'] holds node information + * @param $form_state + * the form_state, $form_state['values'] holds the form values. + * @param $field + * The field structure. + * @param $instance + * the field instance array + * @param $delta + * the order of this item in the array of subelements (0, 1, 2, etc) + * + * @return + * the form item for a single element for this field + */ +function number_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) { + $element = array( + '#type' => $instance['widget']['type'], + '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL, + ); + return $element; +} + +/** + * Implementation of hook_field_widget_error(). + */ +function number_field_widget_error($element, $error) { + form_error($element['value'], $error['message']); +} + +/** + * Process an individual element. + * + * Build the form element. When creating a form using FAPI #process, + * note that $element['#value'] is already set. + * + * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. + */ +function number_process($element, $form_state, $form) { + $field_name = $element['#field_name']; + $field = field_info_field($element['#field_name']); + $instance = field_info_instance($element['#field_name'], $element['#bundle']); + $field_key = $element['#columns'][0]; + + $value = isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : ''; + if ($field['type'] == 'number_decimal') { + $value = str_replace('.', $field['settings']['decimal'], $value); + } + + $element[$field_key] = array( + '#type' => 'textfield', + '#default_value' => $value, + // Need to allow a slightly larger size that the field length to allow + // for some configurations where all characters won't fit in input field. + '#size' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] + 2 : 12, + '#maxlength' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] : 10, + '#attributes' => array('class' => 'number'), + // The following values were set by the Field module and need + // to be passed down to the nested element. + '#title' => $element['#title'], + '#description' => $element['#description'], + '#required' => $element['#required'], + '#field_name' => $element['#field_name'], + '#bundle' => $element['#bundle'], + '#delta' => $element['#delta'], + '#columns' => $element['#columns'], + ); + + if (!empty($instance['settings']['prefix'])) { + $prefixes = explode('|', $instance['settings']['prefix']); + $element[$field_key]['#field_prefix'] = field_filter_xss(array_pop($prefixes)); + } + if (!empty($instance['settings']['suffix'])) { + $suffixes = explode('|', $instance['settings']['suffix']); + $element[$field_key]['#field_suffix'] = field_filter_xss(array_pop($suffixes)); + } + + // Make sure we don't wipe out element validation added elsewhere. + if (empty($element['#element_validate'])) { + $element['#element_validate'] = array(); + } + switch ($field['type']) { + case 'number_float': + $element['#element_validate'][] = 'number_float_validate'; + break; + case 'number_integer': + $element['#element_validate'][] = 'number_integer_validate'; + break; + case 'number_decimal': + $element['#element_validate'][] = 'number_decimal_validate'; + break; + } + + return $element; +} + +/** + * FAPI validation of an individual float element. + */ +function number_float_validate($element, &$form_state) { + $field = field_info_field($element['#field_name']); + $instance = field_info_instance($element['#field_name'], $element['#bundle']); + $field_key = $element['#columns'][0]; + $value = $element['#value'][$field_key]; + + if (($element[$field_key]['#required'] || !empty($value))) { + $start = $value; + $value = preg_replace('@[^-0-9\.]@', '', $value); + if ($start != $value) { + $error_field = implode('][', $element['#parents']) . '][' . $field_key; + form_set_error($error_field, t('Only numbers and decimals are allowed in %field.', array('%field' => t($instance['label'])))); + } + else { + form_set_value($element[$field_key], $value, $form_state); + } + } +} + +/** + * FAPI validation of an individual integer element. + */ +function number_integer_validate($element, &$form_state) { + $field = field_info_field($element['#field_name']); + $instance = field_info_instance($element['#field_name'], $element['#bundle']); + $field_key = $element['#columns'][0]; + $value = $element['#value'][$field_key]; + + if (($element[$field_key]['#required'] || !empty($value))) { + $start = $value; + $value = preg_replace('@[^-0-9]@', '', $value); + if ($start != $value) { + $error_field = implode('][', $element['#parents']) . '][' . $field_key; + form_set_error($error_field, t('Only numbers are allowed in %field.', array('%field' => t($instance['label'])))); + } + else { + form_set_value($element[$field_key], $value, $form_state); + } + } +} + +/** + * FAPI validation of an individual decimal element. + */ +function number_decimal_validate($element, &$form_state) { + $field = field_info_field($element['#field_name']); + $instance = field_info_instance($element['#field_name'], $element['#bundle']); + $field_key = $element['#columns'][0]; + $value = $element['#value'][$field_key]; + + if (($element[$field_key]['#required'] || !empty($value))) { + $start = $value; + $value = preg_replace('@[^-0-9\\' . $field['settings']['decimal'] . ']@', '', $value); + if ($start != $value) { + $error_field = implode('][', $element['#parents']) . '][' . $field_key; + form_set_error($error_field, t('Only numbers and the decimal character (%decimal) are allowed in %field.', array('%decimal' => $field['settings']['decimal'], '%field' => t($instance['label'])))); + } + else { + $value = str_replace($field['settings']['decimal'], ' .', $value); + $value = round($value, $field['settings']['scale']); + form_set_value($element[$field_key], $value, $form_state); + } + } +} + Index: modules/field/modules/number/number.info =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/number/number.info,v retrieving revision 1.3 diff -u -p -r1.3 number.info --- modules/field/modules/number/number.info 10 May 2009 18:56:56 -0000 1.3 +++ modules/field/modules/number/number.info 22 May 2009 23:44:04 -0000 @@ -5,3 +5,5 @@ package = Core - fields version = VERSION core = 7.x files[]=number.module +files[] = number.registry.inc +files[] = number.field.inc Index: modules/field/modules/number/number.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/number/number.module,v retrieving revision 1.8 diff -u -p -r1.8 number.module --- modules/field/modules/number/number.module 20 May 2009 09:48:47 -0000 1.8 +++ modules/field/modules/number/number.module 22 May 2009 23:44:25 -0000 @@ -7,164 +7,6 @@ */ /** - * Implementation of hook_theme(). - */ -function number_theme() { - return array( - 'number' => array('arguments' => array('element' => NULL)), - 'field_formatter_number_integer' => array('arguments' => array('element' => NULL), 'function' => 'theme_field_formatter_number'), - 'field_formatter_number_decimal' => array('arguments' => array('element' => NULL), 'function' => 'theme_field_formatter_number'), - 'field_formatter_number_unformatted' => array('arguments' => array('element' => NULL)), - ); -} - -/** - * Implementation of hook_field_info(). - */ -function number_field_info() { - return array( - 'number_integer' => array( - 'label' => t('Integer'), - 'description' => t('This field stores a number in the database as an integer.'), - 'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''), - 'default_widget' => 'number', - 'default_formatter' => 'number_integer', - ), - 'number_decimal' => array( - 'label' => t('Decimal'), - 'description' => t('This field stores a number in the database in a fixed decimal format.'), - 'settings' => array('precision' => 10, 'scale' => 2, 'decimal' => ' .'), - 'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''), - 'default_widget' => 'number', - 'default_formatter' => 'number_integer', - ), - 'number_float' => array( - 'label' => t('Float'), - 'description' => t('This field stores a number in the database in a floating point format.'), - 'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''), - 'default_widget' => 'number', - 'default_formatter' => 'number_integer', - ), - ); -} - -/** - * Implementation of hook_field_schema(). - */ -function number_field_schema($field) { - switch ($field['type']) { - case 'number_integer' : - $columns = array( - 'value' => array( - 'type' => 'int', - 'not null' => FALSE - ), - ); - break; - - case 'number_float' : - $columns = array( - 'value' => array( - 'type' => 'float', - 'not null' => FALSE - ), - ); - break; - - case 'number_decimal' : - $columns = array( - 'value' => array( - 'type' => 'numeric', - 'precision' => $field['settings']['precision'], - 'scale' => $field['settings']['scale'], - 'not null' => FALSE - ), - ); - break; - } - return array( - 'columns' => $columns, - ); -} - -/** - * Implementation of hook_field_validate(). - * - * Possible error codes: - * - 'number_min': The value is smaller than the allowed minimum value. - * - 'number_max': The value is larger than the allowed maximum value. - */ -function number_field_validate($obj_type, $node, $field, $instance, $items, &$errors) { - foreach ($items as $delta => $item) { - if ($item['value'] != '') { - if (is_numeric($instance['settings']['min']) && $item['value'] < $instance['settings']['min']) { - $errors[$field['field_name']][$delta][] = array( - 'error' => 'number_min', - 'message' => t('%name: the value may be no smaller than %min.', array('%name' => t($instance['label']), '%min' => $instance['settings']['min'])), - ); - } - if (is_numeric($instance['settings']['max']) && $item['value'] > $instance['settings']['max']) { - $errors[$field['field_name']][$delta][] = array( - 'error' => 'number_max', - 'message' => t('%name: the value may be no larger than %max.', array('%name' => t($instance['label']), '%max' => $instance['settings']['max'])), - ); - } - } - } -} - -/** - * Implementation of hook_content_is_empty(). - */ -function number_field_is_empty($item, $field) { - if (empty($item['value']) && (string)$item['value'] !== '0') { - return TRUE; - } - return FALSE; -} - -/** - * Implementation of hook_field_formatter_info(). - */ -function number_field_formatter_info() { - return array( - 'number_integer' => array( - 'label' => t('default'), - 'field types' => array('number_integer'), - 'settings' => array( - 'thousand_separator' => ' ', - 'decimal_separator' => '.', - 'scale' => 0, - 'prefix_suffix' => TRUE, - ), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'number_decimal' => array( - 'label' => t('default'), - 'field types' => array('number_decimal', 'number_float'), - 'settings' => array( - 'thousand_separator' => ' ', - 'decimal_separator' => '.', - 'scale' => 2, - 'prefix_suffix' => TRUE, - ), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'number_unformatted' => array( - 'label' => t('unformatted'), - 'field types' => array('number_integer', 'number_decimal', 'number_float'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - ); -} - -/** * Theme function for 'unformatted' number field formatter. */ function theme_field_formatter_number_unformatted($element) { @@ -199,230 +41,6 @@ function theme_field_formatter_number($e } /** - * Implementation of hook_field_widget_info(). - * - * Here we indicate that the Field module will handle - * multiple values for these widgets. - * - * Callbacks can be omitted if default handing is used. - * They're included here just so this module can be used - * as an example for custom modules that might do things - * differently. - */ -function number_field_widget_info() { - return array( - 'number' => array( - 'label' => t('Text field'), - 'field types' => array('number_integer', 'number_decimal', 'number_float'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - 'default value' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - ); -} - -/** - * Implementation of FAPI hook_elements(). - * - * Any FAPI callbacks needed for individual widgets can be declared here, - * and the element will be passed to those callbacks for processing. - * - * Drupal will automatically theme the element using a theme with - * the same name as the hook_elements key. - * - * Includes a regex to check for valid values as an additional parameter - * the validator can use. The regex can be overridden if necessary. - */ -function number_elements() { - return array( - 'number' => array( - '#input' => TRUE, - '#columns' => array('value'), '#delta' => 0, - '#process' => array('number_process'), - ), - ); -} - -/** - * Implementation of hook_field_widget(). - * - * Attach a single form element to the form. It will be built out and - * validated in the callback(s) listed in hook_elements. We build it - * out in the callbacks rather than here in hook_widget so it can be - * plugged into any module that can provide it with valid - * $field information. - * - * Field module will set the weight, field name and delta values - * for each form element. - * - * If there are multiple values for this field, the Field module will - * call this function as many times as needed. - * - * @param $form - * the entire form array, $form['#node'] holds node information - * @param $form_state - * the form_state, $form_state['values'] holds the form values. - * @param $field - * The field structure. - * @param $instance - * the field instance array - * @param $delta - * the order of this item in the array of subelements (0, 1, 2, etc) - * - * @return - * the form item for a single element for this field - */ -function number_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) { - $element = array( - '#type' => $instance['widget']['type'], - '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL, - ); - return $element; -} - -/** - * Implementation of hook_field_widget_error(). - */ -function number_field_widget_error($element, $error) { - form_error($element['value'], $error['message']); -} - -/** - * Process an individual element. - * - * Build the form element. When creating a form using FAPI #process, - * note that $element['#value'] is already set. - * - * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. - */ -function number_process($element, $form_state, $form) { - $field_name = $element['#field_name']; - $field = field_info_field($element['#field_name']); - $instance = field_info_instance($element['#field_name'], $element['#bundle']); - $field_key = $element['#columns'][0]; - - $value = isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : ''; - if ($field['type'] == 'number_decimal') { - $value = str_replace('.', $field['settings']['decimal'], $value); - } - - $element[$field_key] = array( - '#type' => 'textfield', - '#default_value' => $value, - // Need to allow a slightly larger size that the field length to allow - // for some configurations where all characters won't fit in input field. - '#size' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] + 2 : 12, - '#maxlength' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] : 10, - '#attributes' => array('class' => 'number'), - // The following values were set by the Field module and need - // to be passed down to the nested element. - '#title' => $element['#title'], - '#description' => $element['#description'], - '#required' => $element['#required'], - '#field_name' => $element['#field_name'], - '#bundle' => $element['#bundle'], - '#delta' => $element['#delta'], - '#columns' => $element['#columns'], - ); - - if (!empty($instance['settings']['prefix'])) { - $prefixes = explode('|', $instance['settings']['prefix']); - $element[$field_key]['#field_prefix'] = field_filter_xss(array_pop($prefixes)); - } - if (!empty($instance['settings']['suffix'])) { - $suffixes = explode('|', $instance['settings']['suffix']); - $element[$field_key]['#field_suffix'] = field_filter_xss(array_pop($suffixes)); - } - - // Make sure we don't wipe out element validation added elsewhere. - if (empty($element['#element_validate'])) { - $element['#element_validate'] = array(); - } - switch ($field['type']) { - case 'number_float': - $element['#element_validate'][] = 'number_float_validate'; - break; - case 'number_integer': - $element['#element_validate'][] = 'number_integer_validate'; - break; - case 'number_decimal': - $element['#element_validate'][] = 'number_decimal_validate'; - break; - } - - return $element; -} - -/** - * FAPI validation of an individual float element. - */ -function number_float_validate($element, &$form_state) { - $field = field_info_field($element['#field_name']); - $instance = field_info_instance($element['#field_name'], $element['#bundle']); - $field_key = $element['#columns'][0]; - $value = $element['#value'][$field_key]; - - if (($element[$field_key]['#required'] || !empty($value))) { - $start = $value; - $value = preg_replace('@[^-0-9\.]@', '', $value); - if ($start != $value) { - $error_field = implode('][', $element['#parents']) . '][' . $field_key; - form_set_error($error_field, t('Only numbers and decimals are allowed in %field.', array('%field' => t($instance['label'])))); - } - else { - form_set_value($element[$field_key], $value, $form_state); - } - } -} - -/** - * FAPI validation of an individual integer element. - */ -function number_integer_validate($element, &$form_state) { - $field = field_info_field($element['#field_name']); - $instance = field_info_instance($element['#field_name'], $element['#bundle']); - $field_key = $element['#columns'][0]; - $value = $element['#value'][$field_key]; - - if (($element[$field_key]['#required'] || !empty($value))) { - $start = $value; - $value = preg_replace('@[^-0-9]@', '', $value); - if ($start != $value) { - $error_field = implode('][', $element['#parents']) . '][' . $field_key; - form_set_error($error_field, t('Only numbers are allowed in %field.', array('%field' => t($instance['label'])))); - } - else { - form_set_value($element[$field_key], $value, $form_state); - } - } -} - -/** - * FAPI validation of an individual decimal element. - */ -function number_decimal_validate($element, &$form_state) { - $field = field_info_field($element['#field_name']); - $instance = field_info_instance($element['#field_name'], $element['#bundle']); - $field_key = $element['#columns'][0]; - $value = $element['#value'][$field_key]; - - if (($element[$field_key]['#required'] || !empty($value))) { - $start = $value; - $value = preg_replace('@[^-0-9\\' . $field['settings']['decimal'] . ']@', '', $value); - if ($start != $value) { - $error_field = implode('][', $element['#parents']) . '][' . $field_key; - form_set_error($error_field, t('Only numbers and the decimal character (%decimal) are allowed in %field.', array('%decimal' => $field['settings']['decimal'], '%field' => t($instance['label'])))); - } - else { - $value = str_replace($field['settings']['decimal'], ' .', $value); - $value = round($value, $field['settings']['scale']); - form_set_value($element[$field_key], $value, $form_state); - } - } -} - -/** * FAPI theme for an individual number element. * * The textfield is already rendered by the textfield Index: modules/field/modules/number/number.registry.inc =================================================================== RCS file: modules/field/modules/number/number.registry.inc diff -N modules/field/modules/number/number.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/number/number.registry.inc 22 May 2009 23:44:04 -0000 @@ -0,0 +1,137 @@ + array('arguments' => array('element' => NULL)), + 'field_formatter_number_integer' => array('arguments' => array('element' => NULL), 'function' => 'theme_field_formatter_number'), + 'field_formatter_number_decimal' => array('arguments' => array('element' => NULL), 'function' => 'theme_field_formatter_number'), + 'field_formatter_number_unformatted' => array('arguments' => array('element' => NULL)), + ); +} + +/** + * Implementation of FAPI hook_elements(). + * + * Any FAPI callbacks needed for individual widgets can be declared here, + * and the element will be passed to those callbacks for processing. + * + * Drupal will automatically theme the element using a theme with + * the same name as the hook_elements key. + * + * Includes a regex to check for valid values as an additional parameter + * the validator can use. The regex can be overridden if necessary. + */ +function number_elements() { + return array( + 'number' => array( + '#input' => TRUE, + '#columns' => array('value'), '#delta' => 0, + '#process' => array('number_process'), + ), + ); +} + +/** + * Implementation of hook_field_info(). + */ +function number_field_info() { + return array( + 'number_integer' => array( + 'label' => t('Integer'), + 'description' => t('This field stores a number in the database as an integer.'), + 'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''), + 'default_widget' => 'number', + 'default_formatter' => 'number_integer', + ), + 'number_decimal' => array( + 'label' => t('Decimal'), + 'description' => t('This field stores a number in the database in a fixed decimal format.'), + 'settings' => array('precision' => 10, 'scale' => 2, 'decimal' => ' .'), + 'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''), + 'default_widget' => 'number', + 'default_formatter' => 'number_integer', + ), + 'number_float' => array( + 'label' => t('Float'), + 'description' => t('This field stores a number in the database in a floating point format.'), + 'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''), + 'default_widget' => 'number', + 'default_formatter' => 'number_integer', + ), + ); +} + +/** + * Implementation of hook_field_formatter_info(). + */ +function number_field_formatter_info() { + return array( + 'number_integer' => array( + 'label' => t('default'), + 'field types' => array('number_integer'), + 'settings' => array( + 'thousand_separator' => ' ', + 'decimal_separator' => '.', + 'scale' => 0, + 'prefix_suffix' => TRUE, + ), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'number_decimal' => array( + 'label' => t('default'), + 'field types' => array('number_decimal', 'number_float'), + 'settings' => array( + 'thousand_separator' => ' ', + 'decimal_separator' => '.', + 'scale' => 2, + 'prefix_suffix' => TRUE, + ), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'number_unformatted' => array( + 'label' => t('unformatted'), + 'field types' => array('number_integer', 'number_decimal', 'number_float'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + ); +} + +/** + * Implementation of hook_field_widget_info(). + * + * Here we indicate that the Field module will handle + * multiple values for these widgets. + * + * Callbacks can be omitted if default handing is used. + * They're included here just so this module can be used + * as an example for custom modules that might do things + * differently. + */ +function number_field_widget_info() { + return array( + 'number' => array( + 'label' => t('Text field'), + 'field types' => array('number_integer', 'number_decimal', 'number_float'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + 'default value' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + ); +} + Index: modules/field/modules/options/options.field.inc =================================================================== RCS file: modules/field/modules/options/options.field.inc diff -N modules/field/modules/options/options.field.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/options/options.field.inc 22 May 2009 23:44:25 -0000 @@ -0,0 +1,193 @@ + $instance['widget']['type'], + '#default_value' => !empty($items) ? $items : array(), + ); + return $element; +} + +/** + * Implementation of hook_field_widget_error(). + */ +function options_field_widget_error($element, $error) { + $field_key = $element['#columns'][0]; + form_error($element[$field_key], $error['message']); +} + +/** + * Process an individual element. + * + * Build the form element. When creating a form using FAPI #process, + * note that $element['#value'] is already set. + * + * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. + */ +function options_buttons_process($element, &$form_state, $form) { + $field = $form['#fields'][$element['#field_name']]['field']; + $instance = $form['#fields'][$element['#field_name']]['instance']; + $field_key = $element['#columns'][0]; + + // See if this element is in the database format or the transformed format, + // and transform it if necessary. + if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) { + $element['#value'] = options_data2form($element, $element['#default_value'], $field); + } + $options = options_options($field, $instance); + $multiple = isset($element['#multiple']) ? $element['#multiple'] : $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED; + + $value = array(); + foreach ($element['#value'][$field_key] as $key) { + // Multiple (checkboxes) need the default value in the form of an array. + if ($multiple) { + $value[$key] = 1; + } + // Non-multiple (radios) need single default value. + else { + $value = $key; + break; + } + } + + $element[$field_key] = array( + '#type' => $multiple ? 'checkboxes' : 'radios', + '#title' => $element['#title'], + '#description' => $element['#description'], + '#required' => isset($element['#required']) ? $element['#required'] : $instance['required'], + '#multiple' => $multiple, + '#options' => $options, + '#default_value' => $value, + ); + + // Set #element_validate in a way that it will not wipe out other + // validation functions already set by other modules. + if (empty($element['#element_validate'])) { + $element['#element_validate'] = array(); + } + array_unshift($element['#element_validate'], 'options_validate'); + + // Make sure field info will be available to the validator which + // does not get the values in $form. + $form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']]; + return $element; +} + +/** + * Process an individual element. + * + * Build the form element. When creating a form using FAPI #process, + * note that $element['#value'] is already set. + * + * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. + */ +function options_select_process($element, &$form_state, $form) { + $field = $form['#fields'][$element['#field_name']]['field']; + $instance = $form['#fields'][$element['#field_name']]['instance']; + $field_key = $element['#columns'][0]; + + // See if this element is in the database format or the transformed format, + // and transform it if necessary. + if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) { + $element['#value'] = options_data2form($element, $element['#default_value'], $field); + } + + $options = options_options($field, $instance); + $element[$field_key] = array( + '#type' => 'select', + '#title' => $element['#title'], + '#description' => $element['#description'], + '#required' => isset($element['#required']) ? $element['#required'] : $instance['required'], + '#multiple' => isset($element['#multiple']) ? $element['#multiple'] : $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED, + '#options' => $options, + '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, + ); + + // Set #element_validate in a way that it will not wipe out other + // validation functions already set by other modules. + if (empty($element['#element_validate'])) { + $element['#element_validate'] = array(); + } + array_unshift($element['#element_validate'], 'options_validate'); + + // Make sure field info will be available to the validator which + // does not get the values in $form. + $form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']]; + return $element; +} + +/** + * Process an individual element. + * + * Build the form element. When creating a form using FAPI #process, + * note that $element['#value'] is already set. + */ +function options_onoff_process($element, &$form_state, $form) { + $field = $form['#fields'][$element['#field_name']]['field']; + $instance = $form['#fields'][$element['#field_name']]['instance']; + $field_key = $element['#columns'][0]; + + // See if this element is in the database format or the transformed format, + // and transform it if necessary. + if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) { + $element['#value'] = options_data2form($element, $element['#default_value'], $field); + } + $options = options_options($field, $instance); + $keys = array_keys($options); + $on_value = (!empty($keys) && isset($keys[1])) ? $keys[1] : NULL; + $element[$field_key] = array( + '#type' => 'checkbox', + '#title' => isset($options[$on_value]) ? $options[$on_value] : '', + '#description' => $element['#description'], + '#default_value' => isset($element['#value'][$field_key][0]) ? $element['#value'][$field_key][0] == $on_value : FALSE, + '#return_value' => $on_value, + ); + + // Set #element_validate in a way that it will not wipe out other + // validation functions already set by other modules. + if (empty($element['#element_validate'])) { + $element['#element_validate'] = array(); + } + array_unshift($element['#element_validate'], 'options_validate'); + + // Make sure field info will be available to the validator which + // does not get the values in $form. + $form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']]; + return $element; +} + +/** + * FAPI function to validate options element. + */ +function options_validate($element, &$form_state) { + // Transpose selections from field => delta to delta => field, + // turning cardinality selected options into cardinality parent elements. + // Immediate parent is the delta, need to get back to parent's parent + // to create cardinality elements. + $field = $form_state['#fields'][$element['#field_name']]['field']; + $items = options_form2data($element, $field); + form_set_value($element, $items, $form_state); + + // Check we don't exceed the allowed number of values. + if ($field['cardinality'] >= 2) { + // Filter out 'none' value (if present, will always be in key 0) + $field_key = $element['#columns'][0]; + if (isset($items[0][$field_key]) && $items[0][$field_key] === '') { + unset($items[0]); + } + if (count($items) > $field['cardinality']) { + $field_key = $element['#columns'][0]; + form_error($element[$field_key], t('%name: this field cannot hold more that @count values.', array('%name' => t($field['widget']['label']), '@count' => $field['cardinality']))); + } + } +} + Index: modules/field/modules/options/options.info =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/options/options.info,v retrieving revision 1.2 diff -u -p -r1.2 options.info --- modules/field/modules/options/options.info 10 May 2009 18:56:57 -0000 1.2 +++ modules/field/modules/options/options.info 22 May 2009 23:44:03 -0000 @@ -5,3 +5,5 @@ package = Core - fields version = VERSION core = 7.x files[]=options.module +files[] = options.registry.inc +files[] = options.field.inc Index: modules/field/modules/options/options.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/options/options.module,v retrieving revision 1.5 diff -u -p -r1.5 options.module --- modules/field/modules/options/options.module 12 Apr 2009 02:18:51 -0000 1.5 +++ modules/field/modules/options/options.module 22 May 2009 23:44:25 -0000 @@ -7,283 +7,6 @@ */ /** - * Implementation of hook_theme(). - */ -function options_theme() { - return array( - 'options_select' => array( - 'arguments' => array('element' => NULL), - ), - 'options_buttons' => array( - 'arguments' => array('element' => NULL), - ), - 'options_onoff' => array( - 'arguments' => array('element' => NULL), - ), - 'options_none' => array( - 'arguments' => array('widget_type' => NULL, 'field_name' => NULL, 'node_type' => NULL), - ), - ); -} - -/** - * Implementation of hook_field_widget_info(). - * - * We need custom handling of multiple values because we need - * to combine them into a options list rather than display - * cardinality elements. We will use the field module's default - * handling for default values. - * - * Callbacks can be omitted if default handing is used. - * They're included here just so this module can be used - * as an example for custom modules that might do things - * differently. - */ -function options_field_widget_info() { - - return array( - 'options_select' => array( - 'label' => t('Select list'), - 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_CUSTOM, - 'default value' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'options_buttons' => array( - 'label' => t('Check boxes/radio buttons'), - 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_CUSTOM, - 'default value' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'options_onoff' => array( - 'label' => t('Single on/off checkbox'), - 'field types' => array('list_boolean'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_CUSTOM, - 'default value' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - ); -} - -/** - * Implementation of FAPI hook_elements(). - * - * Any FAPI callbacks needed for individual widgets can be declared here, - * and the element will be passed to those callbacks for processing. - * - * Drupal will automatically theme the element using a theme with - * the same name as the hook_elements key. - */ -function options_elements() { - return array( - 'options_select' => array( - '#input' => TRUE, - '#columns' => array('value'), '#delta' => 0, - '#process' => array('options_select_process'), - ), - 'options_buttons' => array( - '#input' => TRUE, - '#columns' => array('value'), '#delta' => 0, - '#process' => array('options_buttons_process'), - ), - 'options_onoff' => array( - '#input' => TRUE, - '#columns' => array('value'), '#delta' => 0, - '#process' => array('options_onoff_process'), - ), - ); -} - -/** - * Implementation of hook_field_widget(). - */ -function options_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = NULL) { - $element = array( - '#type' => $instance['widget']['type'], - '#default_value' => !empty($items) ? $items : array(), - ); - return $element; -} - -/** - * Implementation of hook_field_widget_error(). - */ -function options_field_widget_error($element, $error) { - $field_key = $element['#columns'][0]; - form_error($element[$field_key], $error['message']); -} - -/** - * Process an individual element. - * - * Build the form element. When creating a form using FAPI #process, - * note that $element['#value'] is already set. - * - * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. - */ -function options_buttons_process($element, &$form_state, $form) { - $field = $form['#fields'][$element['#field_name']]['field']; - $instance = $form['#fields'][$element['#field_name']]['instance']; - $field_key = $element['#columns'][0]; - - // See if this element is in the database format or the transformed format, - // and transform it if necessary. - if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) { - $element['#value'] = options_data2form($element, $element['#default_value'], $field); - } - $options = options_options($field, $instance); - $multiple = isset($element['#multiple']) ? $element['#multiple'] : $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED; - - $value = array(); - foreach ($element['#value'][$field_key] as $key) { - // Multiple (checkboxes) need the default value in the form of an array. - if ($multiple) { - $value[$key] = 1; - } - // Non-multiple (radios) need single default value. - else { - $value = $key; - break; - } - } - - $element[$field_key] = array( - '#type' => $multiple ? 'checkboxes' : 'radios', - '#title' => $element['#title'], - '#description' => $element['#description'], - '#required' => isset($element['#required']) ? $element['#required'] : $instance['required'], - '#multiple' => $multiple, - '#options' => $options, - '#default_value' => $value, - ); - - // Set #element_validate in a way that it will not wipe out other - // validation functions already set by other modules. - if (empty($element['#element_validate'])) { - $element['#element_validate'] = array(); - } - array_unshift($element['#element_validate'], 'options_validate'); - - // Make sure field info will be available to the validator which - // does not get the values in $form. - $form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']]; - return $element; -} - -/** - * Process an individual element. - * - * Build the form element. When creating a form using FAPI #process, - * note that $element['#value'] is already set. - * - * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. - */ -function options_select_process($element, &$form_state, $form) { - $field = $form['#fields'][$element['#field_name']]['field']; - $instance = $form['#fields'][$element['#field_name']]['instance']; - $field_key = $element['#columns'][0]; - - // See if this element is in the database format or the transformed format, - // and transform it if necessary. - if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) { - $element['#value'] = options_data2form($element, $element['#default_value'], $field); - } - - $options = options_options($field, $instance); - $element[$field_key] = array( - '#type' => 'select', - '#title' => $element['#title'], - '#description' => $element['#description'], - '#required' => isset($element['#required']) ? $element['#required'] : $instance['required'], - '#multiple' => isset($element['#multiple']) ? $element['#multiple'] : $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED, - '#options' => $options, - '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, - ); - - // Set #element_validate in a way that it will not wipe out other - // validation functions already set by other modules. - if (empty($element['#element_validate'])) { - $element['#element_validate'] = array(); - } - array_unshift($element['#element_validate'], 'options_validate'); - - // Make sure field info will be available to the validator which - // does not get the values in $form. - $form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']]; - return $element; -} - -/** - * Process an individual element. - * - * Build the form element. When creating a form using FAPI #process, - * note that $element['#value'] is already set. - */ -function options_onoff_process($element, &$form_state, $form) { - $field = $form['#fields'][$element['#field_name']]['field']; - $instance = $form['#fields'][$element['#field_name']]['instance']; - $field_key = $element['#columns'][0]; - - // See if this element is in the database format or the transformed format, - // and transform it if necessary. - if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) { - $element['#value'] = options_data2form($element, $element['#default_value'], $field); - } - $options = options_options($field, $instance); - $keys = array_keys($options); - $on_value = (!empty($keys) && isset($keys[1])) ? $keys[1] : NULL; - $element[$field_key] = array( - '#type' => 'checkbox', - '#title' => isset($options[$on_value]) ? $options[$on_value] : '', - '#description' => $element['#description'], - '#default_value' => isset($element['#value'][$field_key][0]) ? $element['#value'][$field_key][0] == $on_value : FALSE, - '#return_value' => $on_value, - ); - - // Set #element_validate in a way that it will not wipe out other - // validation functions already set by other modules. - if (empty($element['#element_validate'])) { - $element['#element_validate'] = array(); - } - array_unshift($element['#element_validate'], 'options_validate'); - - // Make sure field info will be available to the validator which - // does not get the values in $form. - $form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']]; - return $element; -} - -/** - * FAPI function to validate options element. - */ -function options_validate($element, &$form_state) { - // Transpose selections from field => delta to delta => field, - // turning cardinality selected options into cardinality parent elements. - // Immediate parent is the delta, need to get back to parent's parent - // to create cardinality elements. - $field = $form_state['#fields'][$element['#field_name']]['field']; - $items = options_form2data($element, $field); - form_set_value($element, $items, $form_state); - - // Check we don't exceed the allowed number of values. - if ($field['cardinality'] >= 2) { - // Filter out 'none' value (if present, will always be in key 0) - $field_key = $element['#columns'][0]; - if (isset($items[0][$field_key]) && $items[0][$field_key] === '') { - unset($items[0]); - } - if (count($items) > $field['cardinality']) { - $field_key = $element['#columns'][0]; - form_error($element[$field_key], t('%name: this field cannot hold more that @count values.', array('%name' => t($field['widget']['label']), '@count' => $field['cardinality']))); - } - } -} - -/** * Helper function to transpose the values as stored in the database * to the format the widget needs. Can be called anywhere this * transformation is needed. Index: modules/field/modules/options/options.registry.inc =================================================================== RCS file: modules/field/modules/options/options.registry.inc diff -N modules/field/modules/options/options.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/options/options.registry.inc 22 May 2009 23:44:03 -0000 @@ -0,0 +1,100 @@ + array( + 'arguments' => array('element' => NULL), + ), + 'options_buttons' => array( + 'arguments' => array('element' => NULL), + ), + 'options_onoff' => array( + 'arguments' => array('element' => NULL), + ), + 'options_none' => array( + 'arguments' => array('widget_type' => NULL, 'field_name' => NULL, 'node_type' => NULL), + ), + ); +} + +/** + * Implementation of FAPI hook_elements(). + * + * Any FAPI callbacks needed for individual widgets can be declared here, + * and the element will be passed to those callbacks for processing. + * + * Drupal will automatically theme the element using a theme with + * the same name as the hook_elements key. + */ +function options_elements() { + return array( + 'options_select' => array( + '#input' => TRUE, + '#columns' => array('value'), '#delta' => 0, + '#process' => array('options_select_process'), + ), + 'options_buttons' => array( + '#input' => TRUE, + '#columns' => array('value'), '#delta' => 0, + '#process' => array('options_buttons_process'), + ), + 'options_onoff' => array( + '#input' => TRUE, + '#columns' => array('value'), '#delta' => 0, + '#process' => array('options_onoff_process'), + ), + ); +} + +/** + * Implementation of hook_field_widget_info(). + * + * We need custom handling of multiple values because we need + * to combine them into a options list rather than display + * cardinality elements. We will use the field module's default + * handling for default values. + * + * Callbacks can be omitted if default handing is used. + * They're included here just so this module can be used + * as an example for custom modules that might do things + * differently. + */ +function options_field_widget_info() { + + return array( + 'options_select' => array( + 'label' => t('Select list'), + 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_CUSTOM, + 'default value' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'options_buttons' => array( + 'label' => t('Check boxes/radio buttons'), + 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_CUSTOM, + 'default value' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'options_onoff' => array( + 'label' => t('Single on/off checkbox'), + 'field types' => array('list_boolean'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_CUSTOM, + 'default value' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + ); +} + Index: modules/field/modules/text/text.field.inc =================================================================== RCS file: modules/field/modules/text/text.field.inc diff -N modules/field/modules/text/text.field.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/text/text.field.inc 22 May 2009 23:44:25 -0000 @@ -0,0 +1,228 @@ + array( + 'type' => 'text', + 'size' => 'big', + 'not null' => FALSE, + ), + ); + } + else { + $columns = array( + 'value' => array( + 'type' => 'varchar', + 'length' => $field['settings']['max_length'], + 'not null' => FALSE, + ), + ); + } + $columns += array( + 'format' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => FALSE, + ), + ); + return array( + 'columns' => $columns, + 'indexes' => array( + 'format' => array('format'), + ), + ); +} + +/** + * Implementation of hook_field_validate(). + * + * Possible error codes: + * - 'text_max_length': The value exceeds the maximum length. + */ +function text_field_validate($obj_type, $object, $field, $instance, $items, &$errors) { + foreach ($items as $delta => $item) { + if (!empty($item['value'])) { + if (!empty($field['settings']['max_length']) && drupal_strlen($item['value']) > $field['settings']['max_length']) { + $errors[$field['field_name']][$delta][] = array( + 'error' => 'text_max_length', + 'message' => t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length'])), + ); + } + } + } +} + +/** + * @file + * Defines simple text field types. + */ + +function text_field_sanitize($obj_type, $object, $field, $instance, &$items) { + global $language; + foreach ($items as $delta => $item) { + // TODO D7 : this code is really node-related. + if (!empty($instance['settings']['text_processing'])) { + $check = is_null($object) || (isset($object->build_mode) && $object->build_mode == NODE_BUILD_PREVIEW); + $text = isset($item['value']) ? check_markup($item['value'], $item['format'], isset($object->language) ? $object->language : $language->language, $check) : ''; + } + else { + $text = check_plain($item['value']); + } + $items[$delta]['safe'] = $text; + } +} + +/** + * Implementation of hook_field_is_empty(). + */ +function text_field_is_empty($item, $field) { + if (empty($item['value']) && (string)$item['value'] !== '0') { + return TRUE; + } + return FALSE; +} + +/** + * Implementation of hook_field_widget(). + * + * Attach a single form element to the form. It will be built out and + * validated in the callback(s) listed in hook_elements. We build it + * out in the callbacks rather than here in hook_field_widget so it can be + * plugged into any module that can provide it with valid + * $field information. + * + * Field module will set the weight, field name and delta values + * for each form element. + * + * If there are multiple values for this field, the field module will + * call this function as many times as needed. + * + * @param $form + * the entire form array, $form['#node'] holds node information + * @param $form_state + * the form_state, $form_state['values'][$field['field_name']] + * holds the field's form values. + * @param $field + * The field structure. + * @param $instance + * the field instance array + * @param $items + * array of default values for this field + * @param $delta + * the order of this item in the array of subelements (0, 1, 2, etc) + * + * @return + * the form item for a single element for this field + */ +function text_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) { + $element = array( + '#type' => $instance['widget']['type'], + '#default_value' => isset($items[$delta]) ? $items[$delta] : '', + ); + return $element; +} + +/** + * Implementation of hook_field_widget_error(). + */ +function text_field_widget_error($element, $error) { + form_error($element['value'], $error['message']); +} + +/** + * Process an individual element. + * + * Build the form element. When creating a form using FAPI #process, + * note that $element['#value'] is already set. + * + * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. + * + * TODO: For widgets to be actual FAPI 'elements', reusable outside of a + * 'field' context, they shoudn't rely on $field and $instance. The bits of + * information needed to adjust the behavior of the 'element' should be + * extracted in hook_field_widget() above. + */ +function text_textfield_process($element, $form_state, $form) { + $field = $form['#fields'][$element['#field_name']]['field']; + $instance = $form['#fields'][$element['#field_name']]['instance']; + $field_key = $element['#columns'][0]; + $delta = $element['#delta']; + + $element[$field_key] = array( + '#type' => 'textfield', + '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, + '#autocomplete_path' => $element['#autocomplete_path'], + '#size' => $instance['widget']['settings']['size'], + '#attributes' => array('class' => 'text'), + // The following values were set by the field module and need + // to be passed down to the nested element. + '#title' => $element['#title'], + '#description' => $element['#description'], + '#required' => $element['#required'], + '#field_name' => $element['#field_name'], + '#bundle' => $element['#bundle'], + '#delta' => $element['#delta'], + '#columns' => $element['#columns'], + ); + + $element[$field_key]['#maxlength'] = !empty($field['settings']['max_length']) ? $field['settings']['max_length'] : NULL; + + if (!empty($instance['settings']['text_processing'])) { + $filter_key = $element['#columns'][1]; + $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT; + $parents = array_merge($element['#parents'] , array($filter_key)); + $element[$filter_key] = filter_form($format, 1, $parents); + } + + return $element; +} + +/** + * Process an individual element. + * + * Build the form element. When creating a form using FAPI #process, + * note that $element['#value'] is already set. + * + * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. + */ +function text_textarea_process($element, $form_state, $form) { + $field = $form['#fields'][$element['#field_name']]['field']; + $instance = $form['#fields'][$element['#field_name']]['instance']; + $field_key = $element['#columns'][0]; + $delta = $element['#delta']; + $element[$field_key] = array( + '#type' => 'textarea', + '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, + '#rows' => $instance['widget']['settings']['rows'], + '#weight' => 0, + // The following values were set by the field module and need + // to be passed down to the nested element. + '#title' => $element['#title'], + '#description' => $element['#description'], + '#required' => $element['#required'], + '#field_name' => $element['#field_name'], + '#bundle' => $element['#bundle'], + '#delta' => $element['#delta'], + '#columns' => $element['#columns'], + ); + + if (!empty($instance['settings']['text_processing'])) { + $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format'; + $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT; + $parents = array_merge($element['#parents'] , array($filter_key)); + $element[$filter_key] = filter_form($format, 1, $parents); + } + + return $element; +} + Index: modules/field/modules/text/text.info =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.info,v retrieving revision 1.3 diff -u -p -r1.3 text.info --- modules/field/modules/text/text.info 10 May 2009 18:56:57 -0000 1.3 +++ modules/field/modules/text/text.info 22 May 2009 23:44:02 -0000 @@ -5,3 +5,5 @@ package = Core - fields version = VERSION core = 7.x files[]=text.module +files[] = text.registry.inc +files[] = text.field.inc Index: modules/field/modules/text/text.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.module,v retrieving revision 1.7 diff -u -p -r1.7 text.module --- modules/field/modules/text/text.module 20 May 2009 09:48:47 -0000 1.7 +++ modules/field/modules/text/text.module 22 May 2009 23:44:25 -0000 @@ -2,169 +2,6 @@ // $Id: text.module,v 1.7 2009/05/20 09:48:47 dries Exp $ /** - * @file - * Defines simple text field types. - */ - -/** - * Implementation of hook_theme(). - */ -function text_theme() { - return array( - 'text_textarea' => array( - 'arguments' => array('element' => NULL), - ), - 'text_textfield' => array( - 'arguments' => array('element' => NULL), - ), - 'field_formatter_text_default' => array( - 'arguments' => array('element' => NULL), - ), - 'field_formatter_text_plain' => array( - 'arguments' => array('element' => NULL), - ), - 'field_formatter_text_trimmed' => array( - 'arguments' => array('element' => NULL), - ), - ); -} - -/** - * Implementation of hook_field_info(). - */ -function text_field_info() { - return array( - 'text' => array( - 'label' => t('Text'), - 'description' => t('This field stores varchar text in the database.'), - 'settings' => array('max_length' => 255), - 'instance_settings' => array('text_processing' => 0), - 'widget_settings' => array('size' => 60), - 'default_widget' => 'text_textfield', - 'default_formatter' => 'text_default', - ), - 'text_long' => array( - 'label' => t('Long text'), - 'description' => t('This field stores long text in the database.'), - 'instance_settings' => array('text_processing' => 0), - 'widget_settings' => array('rows' => 5), - 'default_widget' => 'text_textarea', - 'default_formatter' => 'text_default', - ), - ); -} - -/** - * Implementation of hook_field_schema(). - */ -function text_field_schema($field) { - if ($field['type'] == 'text_long') { - $columns = array( - 'value' => array( - 'type' => 'text', - 'size' => 'big', - 'not null' => FALSE, - ), - ); - } - else { - $columns = array( - 'value' => array( - 'type' => 'varchar', - 'length' => $field['settings']['max_length'], - 'not null' => FALSE, - ), - ); - } - $columns += array( - 'format' => array( - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => FALSE, - ), - ); - return array( - 'columns' => $columns, - 'indexes' => array( - 'format' => array('format'), - ), - ); -} - -/** - * Implementation of hook_field_validate(). - * - * Possible error codes: - * - 'text_max_length': The value exceeds the maximum length. - */ -function text_field_validate($obj_type, $object, $field, $instance, $items, &$errors) { - foreach ($items as $delta => $item) { - if (!empty($item['value'])) { - if (!empty($field['settings']['max_length']) && drupal_strlen($item['value']) > $field['settings']['max_length']) { - $errors[$field['field_name']][$delta][] = array( - 'error' => 'text_max_length', - 'message' => t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length'])), - ); - } - } - } -} - -function text_field_sanitize($obj_type, $object, $field, $instance, &$items) { - global $language; - foreach ($items as $delta => $item) { - // TODO D7 : this code is really node-related. - if (!empty($instance['settings']['text_processing'])) { - $check = is_null($object) || (isset($object->build_mode) && $object->build_mode == NODE_BUILD_PREVIEW); - $text = isset($item['value']) ? check_markup($item['value'], $item['format'], isset($object->language) ? $object->language : $language->language, $check) : ''; - } - else { - $text = check_plain($item['value']); - } - $items[$delta]['safe'] = $text; - } -} - -/** - * Implementation of hook_field_is_empty(). - */ -function text_field_is_empty($item, $field) { - if (empty($item['value']) && (string)$item['value'] !== '0') { - return TRUE; - } - return FALSE; -} - -/** - * Implementation of hook_field_formatter_info(). - */ -function text_field_formatter_info() { - return array( - 'text_default' => array( - 'label' => t('Default'), - 'field types' => array('text', 'text_long'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'text_plain' => array( - 'label' => t('Plain text'), - 'field types' => array('text', 'text_long'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'text_trimmed' => array( - 'label' => t('Trimmed'), - 'field types' => array('text', 'text_long'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - ); -} - -/** * Theme function for 'default' text field formatter. */ function theme_field_formatter_text_default($element) { @@ -188,203 +25,6 @@ function theme_field_formatter_text_trim } /** - * Implementation of hook_field_widget_info(). - * - * Here we indicate that the field module will handle - * the default value and multiple values for these widgets. - * - * Callbacks can be omitted if default handing is used. - * They're included here just so this module can be used - * as an example for custom modules that might do things - * differently. - */ -function text_field_widget_info() { - return array( - 'text_textfield' => array( - 'label' => t('Text field'), - 'field types' => array('text'), - 'settings' => array('size' => 60), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - 'default value' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'text_textarea' => array( - 'label' => t('Text area (multiple rows)'), - 'field types' => array('text_long'), - 'settings' => array('rows' => 5), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - 'default value' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - ); -} - -/** - * Implementation of FAPI hook_elements(). - * - * Any FAPI callbacks needed for individual widgets can be declared here, - * and the element will be passed to those callbacks for processing. - * - * Drupal will automatically theme the element using a theme with - * the same name as the hook_elements key. - * - * Autocomplete_path is not used by text_field_widget but other - * widgets can use it (see nodereference and userreference). - */ -function text_elements() { - return array( - 'text_textfield' => array( - '#input' => TRUE, - '#columns' => array('value'), '#delta' => 0, - '#process' => array('text_textfield_process'), - '#autocomplete_path' => FALSE, - ), - 'text_textarea' => array( - '#input' => TRUE, - '#columns' => array('value', 'format'), '#delta' => 0, - '#process' => array('text_textarea_process'), - '#filter_value' => FILTER_FORMAT_DEFAULT, - ), - ); -} - -/** - * Implementation of hook_field_widget(). - * - * Attach a single form element to the form. It will be built out and - * validated in the callback(s) listed in hook_elements. We build it - * out in the callbacks rather than here in hook_field_widget so it can be - * plugged into any module that can provide it with valid - * $field information. - * - * Field module will set the weight, field name and delta values - * for each form element. - * - * If there are multiple values for this field, the field module will - * call this function as many times as needed. - * - * @param $form - * the entire form array, $form['#node'] holds node information - * @param $form_state - * the form_state, $form_state['values'][$field['field_name']] - * holds the field's form values. - * @param $field - * The field structure. - * @param $instance - * the field instance array - * @param $items - * array of default values for this field - * @param $delta - * the order of this item in the array of subelements (0, 1, 2, etc) - * - * @return - * the form item for a single element for this field - */ -function text_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) { - $element = array( - '#type' => $instance['widget']['type'], - '#default_value' => isset($items[$delta]) ? $items[$delta] : '', - ); - return $element; -} - -/** - * Implementation of hook_field_widget_error(). - */ -function text_field_widget_error($element, $error) { - form_error($element['value'], $error['message']); -} - -/** - * Process an individual element. - * - * Build the form element. When creating a form using FAPI #process, - * note that $element['#value'] is already set. - * - * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. - * - * TODO: For widgets to be actual FAPI 'elements', reusable outside of a - * 'field' context, they shoudn't rely on $field and $instance. The bits of - * information needed to adjust the behavior of the 'element' should be - * extracted in hook_field_widget() above. - */ -function text_textfield_process($element, $form_state, $form) { - $field = $form['#fields'][$element['#field_name']]['field']; - $instance = $form['#fields'][$element['#field_name']]['instance']; - $field_key = $element['#columns'][0]; - $delta = $element['#delta']; - - $element[$field_key] = array( - '#type' => 'textfield', - '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, - '#autocomplete_path' => $element['#autocomplete_path'], - '#size' => $instance['widget']['settings']['size'], - '#attributes' => array('class' => 'text'), - // The following values were set by the field module and need - // to be passed down to the nested element. - '#title' => $element['#title'], - '#description' => $element['#description'], - '#required' => $element['#required'], - '#field_name' => $element['#field_name'], - '#bundle' => $element['#bundle'], - '#delta' => $element['#delta'], - '#columns' => $element['#columns'], - ); - - $element[$field_key]['#maxlength'] = !empty($field['settings']['max_length']) ? $field['settings']['max_length'] : NULL; - - if (!empty($instance['settings']['text_processing'])) { - $filter_key = $element['#columns'][1]; - $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT; - $parents = array_merge($element['#parents'] , array($filter_key)); - $element[$filter_key] = filter_form($format, 1, $parents); - } - - return $element; -} - -/** - * Process an individual element. - * - * Build the form element. When creating a form using FAPI #process, - * note that $element['#value'] is already set. - * - * The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. - */ -function text_textarea_process($element, $form_state, $form) { - $field = $form['#fields'][$element['#field_name']]['field']; - $instance = $form['#fields'][$element['#field_name']]['instance']; - $field_key = $element['#columns'][0]; - $delta = $element['#delta']; - $element[$field_key] = array( - '#type' => 'textarea', - '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, - '#rows' => $instance['widget']['settings']['rows'], - '#weight' => 0, - // The following values were set by the field module and need - // to be passed down to the nested element. - '#title' => $element['#title'], - '#description' => $element['#description'], - '#required' => $element['#required'], - '#field_name' => $element['#field_name'], - '#bundle' => $element['#bundle'], - '#delta' => $element['#delta'], - '#columns' => $element['#columns'], - ); - - if (!empty($instance['settings']['text_processing'])) { - $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format'; - $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT; - $parents = array_merge($element['#parents'] , array($filter_key)); - $element[$filter_key] = filter_form($format, 1, $parents); - } - - return $element; -} - -/** * FAPI theme for an individual text elements. * * The textfield or textarea is already rendered by the Index: modules/field/modules/text/text.registry.inc =================================================================== RCS file: modules/field/modules/text/text.registry.inc diff -N modules/field/modules/text/text.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/field/modules/text/text.registry.inc 22 May 2009 23:44:02 -0000 @@ -0,0 +1,148 @@ + array( + 'arguments' => array('element' => NULL), + ), + 'text_textfield' => array( + 'arguments' => array('element' => NULL), + ), + 'field_formatter_text_default' => array( + 'arguments' => array('element' => NULL), + ), + 'field_formatter_text_plain' => array( + 'arguments' => array('element' => NULL), + ), + 'field_formatter_text_trimmed' => array( + 'arguments' => array('element' => NULL), + ), + ); +} + +/** + * Implementation of FAPI hook_elements(). + * + * Any FAPI callbacks needed for individual widgets can be declared here, + * and the element will be passed to those callbacks for processing. + * + * Drupal will automatically theme the element using a theme with + * the same name as the hook_elements key. + * + * Autocomplete_path is not used by text_field_widget but other + * widgets can use it (see nodereference and userreference). + */ +function text_elements() { + return array( + 'text_textfield' => array( + '#input' => TRUE, + '#columns' => array('value'), '#delta' => 0, + '#process' => array('text_textfield_process'), + '#autocomplete_path' => FALSE, + ), + 'text_textarea' => array( + '#input' => TRUE, + '#columns' => array('value', 'format'), '#delta' => 0, + '#process' => array('text_textarea_process'), + '#filter_value' => FILTER_FORMAT_DEFAULT, + ), + ); +} + +/** + * Implementation of hook_field_info(). + */ +function text_field_info() { + return array( + 'text' => array( + 'label' => t('Text'), + 'description' => t('This field stores varchar text in the database.'), + 'settings' => array('max_length' => 255), + 'instance_settings' => array('text_processing' => 0), + 'widget_settings' => array('size' => 60), + 'default_widget' => 'text_textfield', + 'default_formatter' => 'text_default', + ), + 'text_long' => array( + 'label' => t('Long text'), + 'description' => t('This field stores long text in the database.'), + 'instance_settings' => array('text_processing' => 0), + 'widget_settings' => array('rows' => 5), + 'default_widget' => 'text_textarea', + 'default_formatter' => 'text_default', + ), + ); +} + +/** + * Implementation of hook_field_formatter_info(). + */ +function text_field_formatter_info() { + return array( + 'text_default' => array( + 'label' => t('Default'), + 'field types' => array('text', 'text_long'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'text_plain' => array( + 'label' => t('Plain text'), + 'field types' => array('text', 'text_long'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'text_trimmed' => array( + 'label' => t('Trimmed'), + 'field types' => array('text', 'text_long'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + ); +} + +/** + * Implementation of hook_field_widget_info(). + * + * Here we indicate that the field module will handle + * the default value and multiple values for these widgets. + * + * Callbacks can be omitted if default handing is used. + * They're included here just so this module can be used + * as an example for custom modules that might do things + * differently. + */ +function text_field_widget_info() { + return array( + 'text_textfield' => array( + 'label' => t('Text field'), + 'field types' => array('text'), + 'settings' => array('size' => 60), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + 'default value' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'text_textarea' => array( + 'label' => t('Text area (multiple rows)'), + 'field types' => array('text_long'), + 'settings' => array('rows' => 5), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + 'default value' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + ); +} + Index: modules/filter/filter.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.admin.inc,v retrieving revision 1.27 diff -u -p -r1.27 filter.admin.inc --- modules/filter/filter.admin.inc 26 Apr 2009 06:00:31 -0000 1.27 +++ modules/filter/filter.admin.inc 22 May 2009 23:44:26 -0000 @@ -442,3 +442,10 @@ function filter_admin_order_submit($form cache_clear_all($form_state['values']['format'] . ':', 'cache_filter', TRUE); } +/** + * Display a text format form title. + */ +function filter_admin_format_title($format) { + return $format->name; +} + Index: modules/filter/filter.cron.inc =================================================================== RCS file: modules/filter/filter.cron.inc diff -N modules/filter/filter.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/filter/filter.cron.inc 22 May 2009 23:44:01 -0000 @@ -0,0 +1,17 @@ +' . t("The filter module allows administrators to configure text formats for use on your site. A text format defines the HTML tags, codes, and other input allowed in both content and comments, and is a key feature in guarding against potentially damaging input from malicious users. Two formats included by default are Filtered HTML (which allows only an administrator-approved subset of HTML tags) and Full HTML (which allows the full set of HTML tags). Additional formats may be created by an administrator.") . ''; + $output .= '' . t('Each text format uses filters to manipulate text, and most formats apply several different filters to text in a specific order. Each filter is designed for a specific purpose, and generally either adds, removes or transforms elements within user-entered text before it is displayed. A filter does not change the actual content of a post, but instead, modifies it temporarily before it is displayed. A filter may remove unapproved HTML tags, for instance, while another automatically adds HTML to make links referenced in text clickable.') . '
'; + $output .= '' . t('Users with access to more than one text format can use the Text format fieldset to choose between available text formats when creating or editing multi-line content. Administrators determine the text formats available to each user role, select a default text format, and control the order of formats listed in the Text format fieldset.') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Filter module.', array('@filter' => 'http://drupal.org/handbook/modules/filter/')) . '
'; + return $output; + case 'admin/settings/filter': + $output = '' . t('Use the list below to review the text formats available to each user role, to select a default text format, and to control the order of formats listed in the Text format fieldset. (The Text format fieldset is displayed below textareas when users with access to more than one text format create multi-line content.) The text format selected as Default is available to all users and, unless another format is selected, is applied to all content. All text formats are available to users in roles with the "administer filters" permission.') . '
'; + $output .= '' . t('Since text formats, if available, are presented in the same order as the list below, it may be helpful to arrange the formats in descending order of your preference for their use. To change the order of an text format, grab a drag-and-drop handle under the Name column and drag to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save changes button at the bottom of the page.') . '
'; + return $output; + case 'admin/settings/filter/%': + return '' . t('Every filter performs one particular change on the user input, for example stripping out malicious HTML or making URLs clickable. Choose which filters you want to apply to text in this format. If you notice some filters are causing conflicts in the output, you can rearrange them.', array('@rearrange' => url('admin/settings/filter/' . $arg[3] . '/order'))) . '
'; + case 'admin/settings/filter/%/configure': + return '' . t('If you cannot find the settings for a certain filter, make sure you have enabled it on the edit tab first.', array('@url' => url('admin/settings/filter/' . $arg[3]))) . '
'; + case 'admin/settings/filter/%/order': + $output = '' . t('Because of the flexible filtering system, you might encounter a situation where one filter prevents another from doing its job. For example: a word in an URL gets converted into a glossary term, before the URL can be converted to a clickable link. When this happens, rearrange the order of the filters.') . '
'; + $output .= '' . t("Filters are executed from top-to-bottom. To change the order of the filters, modify the values in the Weight column or grab a drag-and-drop handle under the Name column and drag filters to new locations in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.") . '
'; + return $output; + } +} + Index: modules/filter/filter.info =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.info,v retrieving revision 1.11 diff -u -p -r1.11 filter.info --- modules/filter/filter.info 12 Oct 2008 01:23:03 -0000 1.11 +++ modules/filter/filter.info 22 May 2009 23:44:02 -0000 @@ -9,3 +9,7 @@ files[] = filter.admin.inc files[] = filter.pages.inc files[] = filter.install required = TRUE +files[] = filter.registry.inc +files[] = filter.user.inc +files[] = filter.cron.inc +files[] = filter.help.inc Index: modules/filter/filter.module =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v retrieving revision 1.251 diff -u -p -r1.251 filter.module --- modules/filter/filter.module 21 May 2009 23:07:15 -0000 1.251 +++ modules/filter/filter.module 22 May 2009 23:44:26 -0000 @@ -14,158 +14,11 @@ */ define('FILTER_FORMAT_DEFAULT', 0); -/** - * Implementation of hook_help(). - */ -function filter_help($path, $arg) { - switch ($path) { - case 'admin/help#filter': - $output = '' . t("The filter module allows administrators to configure text formats for use on your site. A text format defines the HTML tags, codes, and other input allowed in both content and comments, and is a key feature in guarding against potentially damaging input from malicious users. Two formats included by default are Filtered HTML (which allows only an administrator-approved subset of HTML tags) and Full HTML (which allows the full set of HTML tags). Additional formats may be created by an administrator.") . '
'; - $output .= '' . t('Each text format uses filters to manipulate text, and most formats apply several different filters to text in a specific order. Each filter is designed for a specific purpose, and generally either adds, removes or transforms elements within user-entered text before it is displayed. A filter does not change the actual content of a post, but instead, modifies it temporarily before it is displayed. A filter may remove unapproved HTML tags, for instance, while another automatically adds HTML to make links referenced in text clickable.') . '
'; - $output .= '' . t('Users with access to more than one text format can use the Text format fieldset to choose between available text formats when creating or editing multi-line content. Administrators determine the text formats available to each user role, select a default text format, and control the order of formats listed in the Text format fieldset.') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Filter module.', array('@filter' => 'http://drupal.org/handbook/modules/filter/')) . '
'; - return $output; - case 'admin/settings/filter': - $output = '' . t('Use the list below to review the text formats available to each user role, to select a default text format, and to control the order of formats listed in the Text format fieldset. (The Text format fieldset is displayed below textareas when users with access to more than one text format create multi-line content.) The text format selected as Default is available to all users and, unless another format is selected, is applied to all content. All text formats are available to users in roles with the "administer filters" permission.') . '
'; - $output .= '' . t('Since text formats, if available, are presented in the same order as the list below, it may be helpful to arrange the formats in descending order of your preference for their use. To change the order of an text format, grab a drag-and-drop handle under the Name column and drag to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save changes button at the bottom of the page.') . '
'; - return $output; - case 'admin/settings/filter/%': - return '' . t('Every filter performs one particular change on the user input, for example stripping out malicious HTML or making URLs clickable. Choose which filters you want to apply to text in this format. If you notice some filters are causing conflicts in the output, you can rearrange them.', array('@rearrange' => url('admin/settings/filter/' . $arg[3] . '/order'))) . '
'; - case 'admin/settings/filter/%/configure': - return '' . t('If you cannot find the settings for a certain filter, make sure you have enabled it on the edit tab first.', array('@url' => url('admin/settings/filter/' . $arg[3]))) . '
'; - case 'admin/settings/filter/%/order': - $output = '' . t('Because of the flexible filtering system, you might encounter a situation where one filter prevents another from doing its job. For example: a word in an URL gets converted into a glossary term, before the URL can be converted to a clickable link. When this happens, rearrange the order of the filters.') . '
'; - $output .= '' . t("Filters are executed from top-to-bottom. To change the order of the filters, modify the values in the Weight column or grab a drag-and-drop handle under the Name column and drag filters to new locations in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.") . '
'; - return $output; - } -} - -/** - * Implementation of hook_theme(). - */ -function filter_theme() { - return array( - 'filter_admin_overview' => array( - 'arguments' => array('form' => NULL), - 'file' => 'filter.admin.inc', - ), - 'filter_admin_order' => array( - 'arguments' => array('form' => NULL), - 'file' => 'filter.admin.inc', - ), - 'filter_tips' => array( - 'arguments' => array('tips' => NULL, 'long' => FALSE), - 'file' => 'filter.pages.inc', - ), - 'filter_tips_more_info' => array( - 'arguments' => array(), - ), - 'filter_guidelines' => array( - 'arguments' => array('format' => NULL), - ), - ); -} - -/** - * Implementation of hook_menu(). - */ -function filter_menu() { - $items['admin/settings/filter'] = array( - 'title' => 'Text formats', - 'description' => 'Configure how content input by users is filtered, including allowed HTML tags. Also allows enabling of module-provided filters.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('filter_admin_overview'), - 'access arguments' => array('administer filters'), - ); - $items['admin/settings/filter/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/settings/filter/add'] = array( - 'title' => 'Add text format', - 'page callback' => 'filter_admin_format_page', - 'access arguments' => array('administer filters'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 1, - ); - $items['admin/settings/filter/delete'] = array( - 'title' => 'Delete text format', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('filter_admin_delete'), - 'access arguments' => array('administer filters'), - 'type' => MENU_CALLBACK, - ); - $items['filter/tips'] = array( - 'title' => 'Compose tips', - 'page callback' => 'filter_tips_long', - 'access callback' => TRUE, - 'type' => MENU_SUGGESTED_ITEM, - ); - $items['admin/settings/filter/%filter_format'] = array( - 'type' => MENU_CALLBACK, - 'title callback' => 'filter_admin_format_title', - 'title arguments' => array(3), - 'page callback' => 'filter_admin_format_page', - 'page arguments' => array(3), - 'access arguments' => array('administer filters'), - ); - $items['admin/settings/filter/%filter_format/edit'] = array( - 'title' => 'Edit', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => 0, - ); - $items['admin/settings/filter/%filter_format/configure'] = array( - 'title' => 'Configure', - 'page callback' => 'filter_admin_configure_page', - 'page arguments' => array(3), - 'access arguments' => array('administer filters'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 1, - ); - $items['admin/settings/filter/%filter_format/order'] = array( - 'title' => 'Rearrange', - 'page callback' => 'filter_admin_order_page', - 'page arguments' => array(3), - 'access arguments' => array('administer filters'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 2, - ); - return $items; -} - function filter_format_load($arg) { return filter_formats($arg); } /** - * Display a text format form title. - */ -function filter_admin_format_title($format) { - return $format->name; -} - -/** - * Implementation of hook_perm(). - */ -function filter_perm() { - return array( - 'administer filters' => array( - 'title' => t('Administer filters'), - 'description' => t('Manage text formats and filters, and select which roles may use them. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), - ), - ); -} - -/** - * Implementation of hook_cron(). - * - * Expire outdated filter cache entries - */ -function filter_cron() { - cache_clear_all(NULL, 'cache_filter'); -} - -/** * Implementation of hook_filter_tips(). */ function filter_filter_tips($delta, $format, $long = FALSE) { Index: modules/filter/filter.registry.inc =================================================================== RCS file: modules/filter/filter.registry.inc diff -N modules/filter/filter.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/filter/filter.registry.inc 22 May 2009 23:44:01 -0000 @@ -0,0 +1,101 @@ + 'Text formats', + 'description' => 'Configure how content input by users is filtered, including allowed HTML tags. Also allows enabling of module-provided filters.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('filter_admin_overview'), + 'access arguments' => array('administer filters'), + ); + $items['admin/settings/filter/list'] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['admin/settings/filter/add'] = array( + 'title' => 'Add text format', + 'page callback' => 'filter_admin_format_page', + 'access arguments' => array('administer filters'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 1, + ); + $items['admin/settings/filter/delete'] = array( + 'title' => 'Delete text format', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('filter_admin_delete'), + 'access arguments' => array('administer filters'), + 'type' => MENU_CALLBACK, + ); + $items['filter/tips'] = array( + 'title' => 'Compose tips', + 'page callback' => 'filter_tips_long', + 'access callback' => TRUE, + 'type' => MENU_SUGGESTED_ITEM, + ); + $items['admin/settings/filter/%filter_format'] = array( + 'type' => MENU_CALLBACK, + 'title callback' => 'filter_admin_format_title', + 'title arguments' => array(3), + 'page callback' => 'filter_admin_format_page', + 'page arguments' => array(3), + 'access arguments' => array('administer filters'), + ); + $items['admin/settings/filter/%filter_format/edit'] = array( + 'title' => 'Edit', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => 0, + ); + $items['admin/settings/filter/%filter_format/configure'] = array( + 'title' => 'Configure', + 'page callback' => 'filter_admin_configure_page', + 'page arguments' => array(3), + 'access arguments' => array('administer filters'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 1, + ); + $items['admin/settings/filter/%filter_format/order'] = array( + 'title' => 'Rearrange', + 'page callback' => 'filter_admin_order_page', + 'page arguments' => array(3), + 'access arguments' => array('administer filters'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 2, + ); + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function filter_theme() { + return array( + 'filter_admin_overview' => array( + 'arguments' => array('form' => NULL), + 'file' => 'filter.admin.inc', + ), + 'filter_admin_order' => array( + 'arguments' => array('form' => NULL), + 'file' => 'filter.admin.inc', + ), + 'filter_tips' => array( + 'arguments' => array('tips' => NULL, 'long' => FALSE), + 'file' => 'filter.pages.inc', + ), + 'filter_tips_more_info' => array( + 'arguments' => array(), + ), + 'filter_guidelines' => array( + 'arguments' => array('format' => NULL), + ), + ); +} + Index: modules/filter/filter.user.inc =================================================================== RCS file: modules/filter/filter.user.inc diff -N modules/filter/filter.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/filter/filter.user.inc 22 May 2009 23:44:01 -0000 @@ -0,0 +1,20 @@ + array( + 'title' => t('Administer filters'), + 'description' => t('Manage text formats and filters, and select which roles may use them. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), + ), + ); +} + Index: modules/forum/forum.block.inc =================================================================== RCS file: modules/forum/forum.block.inc diff -N modules/forum/forum.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/forum/forum.block.inc 22 May 2009 23:43:59 -0000 @@ -0,0 +1,32 @@ + 'select', '#title' => t('Number of topics'), '#default_value' => variable_get('forum_block_num_' . $delta, '5'), '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))); + return $form; +} + +/** + * Implementation of hook_block_save(). + */ +function forum_block_save($delta = '', $edit = array()) { + variable_set('forum_block_num_' . $delta, $edit['forum_block_num_' . $delta]); +} + Index: modules/forum/forum.help.inc =================================================================== RCS file: modules/forum/forum.help.inc diff -N modules/forum/forum.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/forum/forum.help.inc 22 May 2009 23:43:59 -0000 @@ -0,0 +1,34 @@ +' . t('The forum module lets you create threaded discussion forums with functionality similar to other message board systems. Forums are useful because they allow community members to discuss topics with one another while ensuring those conversations are archived for later reference. The forum topic menu item (under Create content on the Navigation menu) creates the initial post of a new threaded discussion, or thread.', array('@create-topic' => url('node/add/forum'))) . ''; + $output .= '' . t('A threaded discussion occurs as people leave comments on a forum topic (or on other comments within that topic). A forum topic is contained within a forum, which may hold many similar or related forum topics. Forums are (optionally) nested within a container, which may hold many similar or related forums. Both containers and forums may be nested within other containers and forums, and provide structure for your message board. By carefully planning this structure, you make it easier for users to find and comment on a specific forum topic.') . '
'; + $output .= '' . t('When administering a forum, note that:') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Forum module.', array('@forum' => 'http://drupal.org/handbook/modules/forum/')) . '
'; + return $output; + case 'admin/build/forum': + return '' . t('This page displays a list of existing forums and containers. Containers (optionally) hold forums, and forums hold forum topics (a forum topic is the initial post to a threaded discussion). To provide structure, both containers and forums may be placed inside other containers and forums. To rearrange forums and containers, grab a drag-and-drop handle under the Name column and drag the forum or container to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save button at the bottom of the page.') . '
'; + case 'admin/build/forum/add/container': + return '' . t('By grouping related or similar forums, containers help organize forums. For example, a container named "Food" may hold two forums named "Fruit" and "Vegetables", respectively.') . '
'; + case 'admin/build/forum/add/forum': + return '' . t('A forum holds related or similar forum topics (a forum topic is the initial post to a threaded discussion). For example, a forum named "Fruit" may contain forum topics titled "Apples" and "Bananas", respectively.') . '
'; + case 'admin/build/forum/settings': + return '' . t('These settings allow you to adjust the display of your forum topics. The content types available for use within a forum may be selected by editing the Content types on the forum vocabulary page.', array('@forum-vocabulary' => url('admin/content/taxonomy/edit/vocabulary/' . variable_get('forum_nav_vocabulary', '')))) . '
'; + } +} + Index: modules/forum/forum.info =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.info,v retrieving revision 1.11 diff -u -p -r1.11 forum.info --- modules/forum/forum.info 11 Oct 2008 02:32:46 -0000 1.11 +++ modules/forum/forum.info 22 May 2009 23:43:59 -0000 @@ -10,3 +10,9 @@ files[] = forum.module files[] = forum.admin.inc files[] = forum.pages.inc files[] = forum.install +files[] = forum.registry.inc +files[] = forum.user.inc +files[] = forum.block.inc +files[] = forum.node.inc +files[] = forum.taxonomy.inc +files[] = forum.help.inc Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.492 diff -u -p -r1.492 forum.module --- modules/forum/forum.module 9 May 2009 18:28:12 -0000 1.492 +++ modules/forum/forum.module 22 May 2009 23:44:26 -0000 @@ -7,64 +7,6 @@ */ /** - * Implementation of hook_help(). - */ -function forum_help($path, $arg) { - switch ($path) { - case 'admin/help#forum': - $output = '' . t('The forum module lets you create threaded discussion forums with functionality similar to other message board systems. Forums are useful because they allow community members to discuss topics with one another while ensuring those conversations are archived for later reference. The forum topic menu item (under Create content on the Navigation menu) creates the initial post of a new threaded discussion, or thread.', array('@create-topic' => url('node/add/forum'))) . '
'; - $output .= '' . t('A threaded discussion occurs as people leave comments on a forum topic (or on other comments within that topic). A forum topic is contained within a forum, which may hold many similar or related forum topics. Forums are (optionally) nested within a container, which may hold many similar or related forums. Both containers and forums may be nested within other containers and forums, and provide structure for your message board. By carefully planning this structure, you make it easier for users to find and comment on a specific forum topic.') . '
'; - $output .= '' . t('When administering a forum, note that:') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Forum module.', array('@forum' => 'http://drupal.org/handbook/modules/forum/')) . '
'; - return $output; - case 'admin/build/forum': - return '' . t('This page displays a list of existing forums and containers. Containers (optionally) hold forums, and forums hold forum topics (a forum topic is the initial post to a threaded discussion). To provide structure, both containers and forums may be placed inside other containers and forums. To rearrange forums and containers, grab a drag-and-drop handle under the Name column and drag the forum or container to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save button at the bottom of the page.') . '
'; - case 'admin/build/forum/add/container': - return '' . t('By grouping related or similar forums, containers help organize forums. For example, a container named "Food" may hold two forums named "Fruit" and "Vegetables", respectively.') . '
'; - case 'admin/build/forum/add/forum': - return '' . t('A forum holds related or similar forum topics (a forum topic is the initial post to a threaded discussion). For example, a forum named "Fruit" may contain forum topics titled "Apples" and "Bananas", respectively.') . '
'; - case 'admin/build/forum/settings': - return '' . t('These settings allow you to adjust the display of your forum topics. The content types available for use within a forum may be selected by editing the Content types on the forum vocabulary page.', array('@forum-vocabulary' => url('admin/content/taxonomy/edit/vocabulary/' . variable_get('forum_nav_vocabulary', '')))) . '
'; - } -} - -/** - * Implementation of hook_theme(). - */ -function forum_theme() { - return array( - 'forums' => array( - 'template' => 'forums', - 'arguments' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), - ), - 'forum_list' => array( - 'template' => 'forum-list', - 'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL), - ), - 'forum_topic_list' => array( - 'template' => 'forum-topic-list', - 'arguments' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), - ), - 'forum_icon' => array( - 'template' => 'forum-icon', - 'arguments' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0), - ), - 'forum_topic_navigation' => array( - 'template' => 'forum-topic-navigation', - 'arguments' => array('node' => NULL), - ), - 'forum_submitted' => array( - 'template' => 'forum-submitted', - 'arguments' => array('topic' => NULL), - ), - ); -} - -/** * Fetch a forum term. * * @param $tid @@ -79,76 +21,6 @@ function forum_term_load($tid) { } /** - * Implementation of hook_menu(). - */ -function forum_menu() { - $items['forum'] = array( - 'title' => 'Forums', - 'page callback' => 'forum_page', - 'access arguments' => array('access content'), - 'type' => MENU_SUGGESTED_ITEM, - ); - $items['admin/build/forum'] = array( - 'title' => 'Forums', - 'description' => 'Control forums and their hierarchy and change forum settings.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('forum_overview'), - 'access arguments' => array('administer forums'), - ); - $items['admin/build/forum/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['admin/build/forum/add/container'] = array( - 'title' => 'Add container', - 'page callback' => 'forum_form_main', - 'page arguments' => array('container'), - 'access arguments' => array('administer forums'), - 'type' => MENU_LOCAL_TASK, - 'parent' => 'admin/build/forum', - ); - $items['admin/build/forum/add/forum'] = array( - 'title' => 'Add forum', - 'page callback' => 'forum_form_main', - 'page arguments' => array('forum'), - 'access arguments' => array('administer forums'), - 'type' => MENU_LOCAL_TASK, - 'parent' => 'admin/build/forum', - ); - $items['admin/build/forum/settings'] = array( - 'title' => 'Settings', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('forum_admin_settings'), - 'access arguments' => array('administer forums'), - 'weight' => 5, - 'type' => MENU_LOCAL_TASK, - 'parent' => 'admin/build/forum', - ); - $items['admin/build/forum/edit/%forum_term'] = array( - 'page callback' => 'forum_form_main', - 'access arguments' => array('administer forums'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/forum/edit/container/%forum_term'] = array( - 'title' => 'Edit container', - 'page callback' => 'forum_form_main', - 'page arguments' => array('container', 5), - 'access arguments' => array('administer forums'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/forum/edit/forum/%forum_term'] = array( - 'title' => 'Edit forum', - 'page callback' => 'forum_form_main', - 'page arguments' => array('forum', 5), - 'access arguments' => array('administer forums'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - - -/** * Implementation of hook_init(). */ function forum_init() { @@ -219,128 +91,6 @@ function forum_node_view($node, $teaser) } /** - * Implementation of hook_node_prepare(). - */ -function forum_node_prepare($node) { - $vid = variable_get('forum_nav_vocabulary', ''); - $vocabulary = taxonomy_vocabulary_load($vid); - if (_forum_node_check_node_type($node, $vocabulary)) { - if (empty($node->nid)) { - // New topic - $node->taxonomy[arg(3)] = (object) array( - 'vid' => $vid, - 'tid' => arg(3), - ); - } - } -} - -/** - * Implementation of hook_node_validate(). - * - * Check in particular that only a "leaf" term in the associated taxonomy. - */ -function forum_node_validate($node, $form) { - $vid = variable_get('forum_nav_vocabulary', ''); - $vocabulary = taxonomy_vocabulary_load($vid); - if (_forum_node_check_node_type($node, $vocabulary)) { - // vocabulary is selected, not a "container" term. - if ($node->taxonomy) { - // Extract the node's proper topic ID. - $vocabulary = $vid; - $containers = variable_get('forum_containers', array()); - foreach ($node->taxonomy as $term) { - if (db_result(db_query('SELECT COUNT(*) FROM {taxonomy_term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) { - if (in_array($term, $containers)) { - $term = taxonomy_term_load($term); - form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => $term->name))); - } - } - } - } - } -} - -/** - * Implementation of hook_node_presave(). - * - * Assign forum taxonomy when adding a topic from within a forum. - */ -function forum_node_presave($node) { - $vid = variable_get('forum_nav_vocabulary', ''); - $vocabulary = taxonomy_vocabulary_load($vid); - if (_forum_node_check_node_type($node, $vocabulary)) { - // Make sure all fields are set properly: - $node->icon = !empty($node->icon) ? $node->icon : ''; - - if ($node->taxonomy && $tree = taxonomy_get_tree($vid)) { - // Get the forum terms from the (cached) tree if we have a taxonomy. - foreach ($tree as $term) { - $forum_terms[] = $term->tid; - } - foreach ($node->taxonomy as $term_id) { - if (in_array($term_id, $forum_terms)) { - $node->tid = $term_id; - } - } - $old_tid = db_result(db_query_range("SELECT t.tid FROM {taxonomy_term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.nid = %d ORDER BY t.vid DESC", $node->nid, 0, 1)); - if ($old_tid && isset($node->tid) && ($node->tid != $old_tid) && !empty($node->shadow)) { - // A shadow copy needs to be created. Retain new term and add old term. - $node->taxonomy[] = $old_tid; - } - } - } -} - -/** - * Implementation of hook_node_update(). - */ -function forum_node_update($node) { - $vid = variable_get('forum_nav_vocabulary', ''); - $vocabulary = taxonomy_vocabulary_load($vid); - if (_forum_node_check_node_type($node, $vocabulary)) { - if (empty($node->revision) && db_result(db_query('SELECT tid FROM {forum} WHERE nid=%d', $node->nid))) { - if (!empty($node->tid)) { - db_query('UPDATE {forum} SET tid = %d WHERE vid = %d', $node->tid, $node->vid); - } - // The node is removed from the forum. - else { - db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid); - } - } - else { - if (!empty($node->tid)) { - db_query('INSERT INTO {forum} (tid, vid, nid) VALUES (%d, %d, %d)', $node->tid, $node->vid, $node->nid); - } - } - } -} - -/** - * Implementation of hook_node_insert(). - */ -function forum_node_insert($node) { - $vid = variable_get('forum_nav_vocabulary', ''); - $vocabulary = taxonomy_vocabulary_load($vid); - if (_forum_node_check_node_type($node, $vocabulary)) { - if (!empty($node->tid)) { - db_query('INSERT INTO {forum} (tid, vid, nid) VALUES (%d, %d, %d)', $node->tid, $node->vid, $node->nid); - } - } -} - -/** - * Implementation of hook_node_delete(). - */ -function forum_node_delete($node) { - $vid = variable_get('forum_nav_vocabulary', ''); - $vocabulary = taxonomy_vocabulary_load($vid); - if (_forum_node_check_node_type($node, $vocabulary)) { - db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid); - } -} - -/** * Implementation of hook_node_load(). */ function forum_node_load($nodes, $types) { @@ -366,20 +116,6 @@ function forum_node_load($nodes, $types) } /** - * Implementation of hook_node_info(). - */ -function forum_node_info() { - return array( - 'forum' => array( - 'name' => t('Forum topic'), - 'base' => 'forum', - 'description' => t('A forum topic is the initial post to a new discussion thread within a forum.'), - 'title_label' => t('Subject'), - ) - ); -} - -/** * Implementation of hook_access(). */ function forum_access($op, $node, $account) { @@ -394,47 +130,6 @@ function forum_access($op, $node, $accou } /** - * Implementation of hook_perm(). - */ -function forum_perm() { - $perms = array( - 'administer forums' => array( - 'title' => t('Administer forums'), - 'description' => t('Manage forums and configure forum administration settings.'), - ), - ); - $perms += node_list_permissions('forum'); - return $perms; -} - -/** - * Implementation of hook_taxonomy(). - */ -function forum_taxonomy($op, $type, $term = NULL) { - if ($op == 'delete' && $term['vid'] == variable_get('forum_nav_vocabulary', '')) { - switch ($type) { - case 'term': - $results = db_query('SELECT tn.nid FROM {taxonomy_term_node} tn WHERE tn.tid = %d', $term['tid']); - while ($node = db_fetch_object($results)) { - // node_delete will also remove any association with non-forum vocabularies. - node_delete($node->nid); - } - - // For containers, remove the tid from the forum_containers variable. - $containers = variable_get('forum_containers', array()); - $key = array_search($term['tid'], $containers); - if ($key !== FALSE) { - unset($containers[$key]); - } - variable_set('forum_containers', $containers); - break; - case 'vocabulary': - variable_del('forum_nav_vocabulary'); - } - } -} - -/** * Implementation of hook_form_alter(). */ function forum_form_alter(&$form, $form_state, $form_id) { @@ -468,30 +163,6 @@ function forum_form_alter(&$form, $form_ } /** - * Implementation of hook_block_list(). - */ -function forum_block_list() { - $blocks['active']['info'] = t('Active forum topics'); - $blocks['new']['info'] = t('New forum topics'); - return $blocks; -} - -/** - * Implementation of hook_block_configure(). - */ -function forum_block_configure($delta = '') { - $form['forum_block_num_' . $delta] = array('#type' => 'select', '#title' => t('Number of topics'), '#default_value' => variable_get('forum_block_num_' . $delta, '5'), '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))); - return $form; -} - -/** - * Implementation of hook_block_save(). - */ -function forum_block_save($delta = '', $edit = array()) { - variable_set('forum_block_num_' . $delta, $edit['forum_block_num_' . $delta]); -} - -/** * Implementation of hook_block_view(). * * Generates a block containing the currently active forum topics and the @@ -536,29 +207,6 @@ function forum_block_view($delta = '') { } /** - * Implementation of hook_form(). - */ -function forum_form($node, $form_state) { - $type = node_get_types('type', $node); - $form['title'] = array('#type' => 'textfield', '#title' => check_plain($type->title_label), '#default_value' => !empty($node->title) ? $node->title : '', '#required' => TRUE, '#weight' => -5); - - if (!empty($node->nid)) { - $vid = variable_get('forum_nav_vocabulary', ''); - $forum_terms = taxonomy_node_get_terms_by_vocabulary($node, $vid); - // if editing, give option to leave shadows - $shadow = (count($forum_terms) > 1); - $form['shadow'] = array('#type' => 'checkbox', '#title' => t('Leave shadow copy'), '#default_value' => $shadow, '#description' => t('If you move this topic, you can leave a link in the old forum to the new forum.')); - } - - $form['body_field'] = node_body_field($node, $type->body_label, 1); - - $form['#submit'][] = 'forum_submit'; - // Assign the forum topic submit handler. - - return $form; -} - -/** * Implementation of hook_term_path(). */ function forum_term_path($term) { Index: modules/forum/forum.node.inc =================================================================== RCS file: modules/forum/forum.node.inc diff -N modules/forum/forum.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/forum/forum.node.inc 22 May 2009 23:44:26 -0000 @@ -0,0 +1,153 @@ +nid)) { + // New topic + $node->taxonomy[arg(3)] = (object) array( + 'vid' => $vid, + 'tid' => arg(3), + ); + } + } +} + +/** + * Implementation of hook_node_validate(). + * + * Check in particular that only a "leaf" term in the associated taxonomy. + */ +function forum_node_validate($node, $form) { + $vid = variable_get('forum_nav_vocabulary', ''); + $vocabulary = taxonomy_vocabulary_load($vid); + if (_forum_node_check_node_type($node, $vocabulary)) { + // vocabulary is selected, not a "container" term. + if ($node->taxonomy) { + // Extract the node's proper topic ID. + $vocabulary = $vid; + $containers = variable_get('forum_containers', array()); + foreach ($node->taxonomy as $term) { + if (db_result(db_query('SELECT COUNT(*) FROM {taxonomy_term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) { + if (in_array($term, $containers)) { + $term = taxonomy_term_load($term); + form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => $term->name))); + } + } + } + } + } +} + +/** + * Implementation of hook_node_presave(). + * + * Assign forum taxonomy when adding a topic from within a forum. + */ +function forum_node_presave($node) { + $vid = variable_get('forum_nav_vocabulary', ''); + $vocabulary = taxonomy_vocabulary_load($vid); + if (_forum_node_check_node_type($node, $vocabulary)) { + // Make sure all fields are set properly: + $node->icon = !empty($node->icon) ? $node->icon : ''; + + if ($node->taxonomy && $tree = taxonomy_get_tree($vid)) { + // Get the forum terms from the (cached) tree if we have a taxonomy. + foreach ($tree as $term) { + $forum_terms[] = $term->tid; + } + foreach ($node->taxonomy as $term_id) { + if (in_array($term_id, $forum_terms)) { + $node->tid = $term_id; + } + } + $old_tid = db_result(db_query_range("SELECT t.tid FROM {taxonomy_term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.nid = %d ORDER BY t.vid DESC", $node->nid, 0, 1)); + if ($old_tid && isset($node->tid) && ($node->tid != $old_tid) && !empty($node->shadow)) { + // A shadow copy needs to be created. Retain new term and add old term. + $node->taxonomy[] = $old_tid; + } + } + } +} + +/** + * Implementation of hook_node_update(). + */ +function forum_node_update($node) { + $vid = variable_get('forum_nav_vocabulary', ''); + $vocabulary = taxonomy_vocabulary_load($vid); + if (_forum_node_check_node_type($node, $vocabulary)) { + if (empty($node->revision) && db_result(db_query('SELECT tid FROM {forum} WHERE nid=%d', $node->nid))) { + if (!empty($node->tid)) { + db_query('UPDATE {forum} SET tid = %d WHERE vid = %d', $node->tid, $node->vid); + } + // The node is removed from the forum. + else { + db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid); + } + } + else { + if (!empty($node->tid)) { + db_query('INSERT INTO {forum} (tid, vid, nid) VALUES (%d, %d, %d)', $node->tid, $node->vid, $node->nid); + } + } + } +} + +/** + * Implementation of hook_node_insert(). + */ +function forum_node_insert($node) { + $vid = variable_get('forum_nav_vocabulary', ''); + $vocabulary = taxonomy_vocabulary_load($vid); + if (_forum_node_check_node_type($node, $vocabulary)) { + if (!empty($node->tid)) { + db_query('INSERT INTO {forum} (tid, vid, nid) VALUES (%d, %d, %d)', $node->tid, $node->vid, $node->nid); + } + } +} + +/** + * Implementation of hook_node_delete(). + */ +function forum_node_delete($node) { + $vid = variable_get('forum_nav_vocabulary', ''); + $vocabulary = taxonomy_vocabulary_load($vid); + if (_forum_node_check_node_type($node, $vocabulary)) { + db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid); + } +} + +/** + * Implementation of hook_form(). + */ +function forum_form($node, $form_state) { + $type = node_get_types('type', $node); + $form['title'] = array('#type' => 'textfield', '#title' => check_plain($type->title_label), '#default_value' => !empty($node->title) ? $node->title : '', '#required' => TRUE, '#weight' => -5); + + if (!empty($node->nid)) { + $vid = variable_get('forum_nav_vocabulary', ''); + $forum_terms = taxonomy_node_get_terms_by_vocabulary($node, $vid); + // if editing, give option to leave shadows + $shadow = (count($forum_terms) > 1); + $form['shadow'] = array('#type' => 'checkbox', '#title' => t('Leave shadow copy'), '#default_value' => $shadow, '#description' => t('If you move this topic, you can leave a link in the old forum to the new forum.')); + } + + $form['body_field'] = node_body_field($node, $type->body_label, 1); + + $form['#submit'][] = 'forum_submit'; + // Assign the forum topic submit handler. + + return $form; +} + Index: modules/forum/forum.registry.inc =================================================================== RCS file: modules/forum/forum.registry.inc diff -N modules/forum/forum.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/forum/forum.registry.inc 22 May 2009 23:43:58 -0000 @@ -0,0 +1,124 @@ + 'Forums', + 'page callback' => 'forum_page', + 'access arguments' => array('access content'), + 'type' => MENU_SUGGESTED_ITEM, + ); + $items['admin/build/forum'] = array( + 'title' => 'Forums', + 'description' => 'Control forums and their hierarchy and change forum settings.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('forum_overview'), + 'access arguments' => array('administer forums'), + ); + $items['admin/build/forum/list'] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + $items['admin/build/forum/add/container'] = array( + 'title' => 'Add container', + 'page callback' => 'forum_form_main', + 'page arguments' => array('container'), + 'access arguments' => array('administer forums'), + 'type' => MENU_LOCAL_TASK, + 'parent' => 'admin/build/forum', + ); + $items['admin/build/forum/add/forum'] = array( + 'title' => 'Add forum', + 'page callback' => 'forum_form_main', + 'page arguments' => array('forum'), + 'access arguments' => array('administer forums'), + 'type' => MENU_LOCAL_TASK, + 'parent' => 'admin/build/forum', + ); + $items['admin/build/forum/settings'] = array( + 'title' => 'Settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('forum_admin_settings'), + 'access arguments' => array('administer forums'), + 'weight' => 5, + 'type' => MENU_LOCAL_TASK, + 'parent' => 'admin/build/forum', + ); + $items['admin/build/forum/edit/%forum_term'] = array( + 'page callback' => 'forum_form_main', + 'access arguments' => array('administer forums'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/forum/edit/container/%forum_term'] = array( + 'title' => 'Edit container', + 'page callback' => 'forum_form_main', + 'page arguments' => array('container', 5), + 'access arguments' => array('administer forums'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/forum/edit/forum/%forum_term'] = array( + 'title' => 'Edit forum', + 'page callback' => 'forum_form_main', + 'page arguments' => array('forum', 5), + 'access arguments' => array('administer forums'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + + +/** + * Implementation of hook_theme(). + */ +function forum_theme() { + return array( + 'forums' => array( + 'template' => 'forums', + 'arguments' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), + ), + 'forum_list' => array( + 'template' => 'forum-list', + 'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL), + ), + 'forum_topic_list' => array( + 'template' => 'forum-topic-list', + 'arguments' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), + ), + 'forum_icon' => array( + 'template' => 'forum-icon', + 'arguments' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0), + ), + 'forum_topic_navigation' => array( + 'template' => 'forum-topic-navigation', + 'arguments' => array('node' => NULL), + ), + 'forum_submitted' => array( + 'template' => 'forum-submitted', + 'arguments' => array('topic' => NULL), + ), + ); +} + +/** + * Implementation of hook_node_info(). + */ +function forum_node_info() { + return array( + 'forum' => array( + 'name' => t('Forum topic'), + 'base' => 'forum', + 'description' => t('A forum topic is the initial post to a new discussion thread within a forum.'), + 'title_label' => t('Subject'), + ) + ); +} + Index: modules/forum/forum.taxonomy.inc =================================================================== RCS file: modules/forum/forum.taxonomy.inc diff -N modules/forum/forum.taxonomy.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/forum/forum.taxonomy.inc 22 May 2009 23:43:59 -0000 @@ -0,0 +1,35 @@ +nid); + } + + // For containers, remove the tid from the forum_containers variable. + $containers = variable_get('forum_containers', array()); + $key = array_search($term['tid'], $containers); + if ($key !== FALSE) { + unset($containers[$key]); + } + variable_set('forum_containers', $containers); + break; + case 'vocabulary': + variable_del('forum_nav_vocabulary'); + } + } +} + Index: modules/forum/forum.user.inc =================================================================== RCS file: modules/forum/forum.user.inc diff -N modules/forum/forum.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/forum/forum.user.inc 22 May 2009 23:43:58 -0000 @@ -0,0 +1,22 @@ + array( + 'title' => t('Administer forums'), + 'description' => t('Manage forums and configure forum administration settings.'), + ), + ); + $perms += node_list_permissions('forum'); + return $perms; +} + Index: modules/help/help.help.inc =================================================================== RCS file: modules/help/help.help.inc diff -N modules/help/help.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/help/help.help.inc 22 May 2009 23:43:57 -0000 @@ -0,0 +1,22 @@ +' . t('This guide provides context sensitive help on the use and configuration of Drupal and its modules, and is a supplement to the more extensive online Drupal handbook. The online handbook may contain more up-to-date information, is annotated with helpful user-contributed comments, and serves as the definitive reference point for all Drupal documentation.', array('@drupal' => 'http://drupal.org', '@handbook' => 'http://drupal.org/handbook')) . ''; + return $output; + case 'admin/help#help': + $output = '' . t('The help module provides context sensitive help on the use and configuration of Drupal and its modules, and is a supplement to the more extensive online Drupal handbook. The online handbook may contain more up-to-date information, is annotated with helpful user-contributed comments, and serves as the definitive reference point for all Drupal documentation.', array('@drupal' => 'http://drupal.org', '@handbook' => 'http://drupal.org/handbook')) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Help module.', array('@help' => 'http://drupal.org/handbook/modules/help/')) . '
'; + return $output; + } +} Index: modules/help/help.info =================================================================== RCS file: /cvs/drupal/drupal/modules/help/help.info,v retrieving revision 1.7 diff -u -p -r1.7 help.info --- modules/help/help.info 11 Oct 2008 02:32:47 -0000 1.7 +++ modules/help/help.info 22 May 2009 23:43:57 -0000 @@ -6,3 +6,5 @@ version = VERSION core = 7.x files[] = help.module files[] = help.admin.inc +files[] = help.registry.inc +files[] = help.help.inc Index: modules/help/help.module =================================================================== RCS file: /cvs/drupal/drupal/modules/help/help.module,v retrieving revision 1.81 diff -u -p -r1.81 help.module --- modules/help/help.module 6 May 2008 12:18:47 -0000 1.81 +++ modules/help/help.module 22 May 2009 23:43:57 -0000 @@ -6,41 +6,3 @@ * Manages displaying online help. */ -/** - * Implementation of hook_menu(). - */ -function help_menu() { - $items['admin/help'] = array( - 'title' => 'Help', - 'page callback' => 'help_main', - 'access arguments' => array('access administration pages'), - 'weight' => 9, - ); - - foreach (module_implements('help', TRUE) as $module) { - $items['admin/help/' . $module] = array( - 'title' => $module, - 'page callback' => 'help_page', - 'page arguments' => array(2), - 'access arguments' => array('access administration pages'), - 'type' => MENU_CALLBACK, - ); - } - - return $items; -} - -/** - * Implementation of hook_help(). - */ -function help_help($path, $arg) { - switch ($path) { - case 'admin/help': - $output = '' . t('This guide provides context sensitive help on the use and configuration of Drupal and its modules, and is a supplement to the more extensive online Drupal handbook. The online handbook may contain more up-to-date information, is annotated with helpful user-contributed comments, and serves as the definitive reference point for all Drupal documentation.', array('@drupal' => 'http://drupal.org', '@handbook' => 'http://drupal.org/handbook')) . '
'; - return $output; - case 'admin/help#help': - $output = '' . t('The help module provides context sensitive help on the use and configuration of Drupal and its modules, and is a supplement to the more extensive online Drupal handbook. The online handbook may contain more up-to-date information, is annotated with helpful user-contributed comments, and serves as the definitive reference point for all Drupal documentation.', array('@drupal' => 'http://drupal.org', '@handbook' => 'http://drupal.org/handbook')) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Help module.', array('@help' => 'http://drupal.org/handbook/modules/help/')) . '
'; - return $output; - } -} Index: modules/help/help.registry.inc =================================================================== RCS file: modules/help/help.registry.inc diff -N modules/help/help.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/help/help.registry.inc 22 May 2009 23:43:57 -0000 @@ -0,0 +1,32 @@ + 'Help', + 'page callback' => 'help_main', + 'access arguments' => array('access administration pages'), + 'weight' => 9, + ); + + foreach (module_implements('help', TRUE) as $module) { + $items['admin/help/' . $module] = array( + 'title' => $module, + 'page callback' => 'help_page', + 'page arguments' => array(2), + 'access arguments' => array('access administration pages'), + 'type' => MENU_CALLBACK, + ); + } + + return $items; +} + Index: modules/locale/locale.block.inc =================================================================== RCS file: modules/locale/locale.block.inc diff -N modules/locale/locale.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/locale/locale.block.inc 22 May 2009 23:43:57 -0000 @@ -0,0 +1,18 @@ + 'select', + '#title' => t('Language'), + '#options' => array('' => t('All languages')) + locale_language_list('name'), + '#default_value' => $form['language']['#value'], + '#weight' => -10, + '#description' => t('A path alias set for a specific language will always be used when displaying this page in that language, and takes precedence over path aliases set for All languages.'), + ); +} + +/** + * Implementation of hook_form_FORM_ID_alter(). + */ +function locale_form_node_type_form_alter(&$form, &$form_state) { + if (isset($form['identity']['type'])) { + $form['workflow']['language_content_type'] = array( + '#type' => 'radios', + '#title' => t('Multilingual support'), + '#default_value' => variable_get('language_content_type_' . $form['#node_type']->type, 0), + '#options' => array(t('Disabled'), t('Enabled')), + '#description' => t('Enable multilingual support for this content type. If enabled, a language selection field will be added to the editing form, allowing you to select from one of the enabled languages. If disabled, new posts are saved with the default language. Existing content will not be affected by changing this option.', array('!languages' => url('admin/international/language'))), + ); + } +} + Index: modules/locale/locale.help.inc =================================================================== RCS file: modules/locale/locale.help.inc diff -N modules/locale/locale.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/locale/locale.help.inc 22 May 2009 23:43:57 -0000 @@ -0,0 +1,58 @@ +' . t('The locale module allows your Drupal site to be presented in languages other than the default English, a defining feature of multi-lingual websites. The locale module works by examining text as it is about to be displayed: when a translation of the text is available in the language to be displayed, the translation is displayed rather than the original text. When a translation is unavailable, the original text is displayed, and then stored for later review by a translator.') . ''; + $output .= '' . t('Beyond translation of the Drupal interface, the locale module provides a feature set tailored to the needs of a multi-lingual site. Language negotiation allows your site to automatically change language based on the domain or path used for each request. Users may (optionally) select their preferred language on their My account page, and your site can be configured to honor a web browser\'s preferred language settings. Your site content can be created in (and translated to) any enabled language, and each post may have a language-appropriate alias for each of its translations. The locale module works in concert with the content translation module to manage translated content.', array('@content-help' => url('admin/help/translation'))) . '
'; + $output .= '' . t('Translations may be provided by:') . '
'; + $output .= '' . t('If an existing translation package does not meet your needs, the Gettext Portable Object (.po) files within a package may be modified, or new .po files may be created, using a desktop Gettext editor. The locale module\'s import feature allows the translated strings from a new or modified .po file to be added to your site. The locale module\'s export feature generates files from your site\'s translated strings, that can either be shared with others or edited offline by a Gettext translation editor.', array('@import' => url('admin/international/translate/import'), '@export' => url('admin/international/translate/export'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Locale module.', array('@locale' => 'http://drupal.org/handbook/modules/locale/')) . '
'; + return $output; + case 'admin/international/language': + $output = '' . t("This page provides an overview of your site's enabled languages. If multiple languages are available and enabled, the text on your site interface may be translated, registered users may select their preferred language on the My account page, and site authors may indicate a specific language when creating posts. Languages will be displayed in the order you specify in places such as the language switcher block, or the language dropdown when creating or editing posts. The site's default language is used for anonymous visitors and for users who have not selected a preferred language.") . '
'; + $output .= '' . t('For each language available on the site, use the edit link to configure language details, including name, an optional language-specific path or domain, and whether the language is natively presented either left-to-right or right-to-left. These languages also appear in the Language selection when creating a post of a content type with multilingual support.') . '
'; + $output .= '' . t('Use the add language page to enable additional languages (and automatically import files from a translation package, if available), the translate interface page to locate strings for manual translation, or the import page to add translations from individual .po files. A number of contributed translation packages containing .po files are available on the Drupal.org translations page.', array('@add-language' => url('admin/international/language/add'), '@search' => url('admin/international/translate/translate'), '@import' => url('admin/international/translate/import'), '@translations' => 'http://drupal.org/project/translations')) . '
'; + $output .= '' . t('To rearrange languages, grab a drag-and-drop handle under the English name column and drag the item to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.') . '
'; + return $output; + case 'admin/international/language/add': + return '' . t('Add all languages to be supported by your site. If your desired language is not available in the Language name drop-down, click Custom language and provide a language code and other details manually. When providing a language code manually, be sure to enter a standardized language code, since this code may be used by browsers to determine an appropriate display language.') . '
'; + case 'admin/international/language/configure': + $output = '' . t("Language negotiation settings determine the site's presentation language. Available options include:") . '
'; + $output .= '' . t('The path prefix or domain name for a language may be set by editing the available languages. In the absence of an appropriate match, the site is displayed in the default language.', array('@languages' => url('admin/international/language'))) . '
'; + return $output; + case 'admin/international/translate': + $output = '' . t('This page provides an overview of available translatable strings. Drupal displays translatable strings in text groups; modules may define additional text groups containing other translatable strings. Because text groups provide a method of grouping related strings, they are often used to focus translation efforts on specific areas of the Drupal interface.') . '
'; + $output .= '' . t('Review the languages page for more information on adding support for additional languages.', array('@languages' => url('admin/international/language'))) . '
'; + return $output; + case 'admin/international/translate/import': + $output = '' . t('This page imports the translated strings contained in an individual Gettext Portable Object (.po) file. Normally distributed as part of a translation package (each translation package may contain several .po files), a .po file may need to be imported after offline editing in a Gettext translation editor. Importing an individual .po file may be a lengthy process.') . '
'; + $output .= '' . t('Note that the .po files within a translation package are imported automatically (if available) when new modules or themes are enabled, or as new languages are added. Since this page only allows the import of one .po file at a time, it may be simpler to download and extract a translation package into your Drupal installation directory and add the language (which automatically imports all .po files within the package). Translation packages are available for download on the Drupal translation page.', array('@language-add' => url('admin/international/language/add'), '@translations' => 'http://drupal.org/project/translations')) . '
'; + return $output; + case 'admin/international/translate/export': + return '' . t('This page exports the translated strings used by your site. An export file may be in Gettext Portable Object (.po) form, which includes both the original string and the translation (used to share translations with others), or in Gettext Portable Object Template (.pot) form, which includes the original strings only (used to create new translations with a Gettext translation editor).') . '
'; + case 'admin/international/translate/translate': + return '' . t('This page allows a translator to search for specific translated and untranslated strings, and is used when creating or editing translations. (Note: For translation tasks involving many strings, it may be more convenient to export strings for offline editing in a desktop Gettext translation editor.) Searches may be limited to strings found within a specific text group or in a specific language.', array('@export' => url('admin/international/translate/export'))) . '
'; + case 'admin/build/block/configure': + if ($arg[4] == 'locale' && $arg[5] == 0) { + return '' . t('This block is only shown if at least two languages are enabled and language negotiation is set to something other than None.', array('@languages' => url('admin/international/language'), '@configuration' => url('admin/international/language/configure'))) . '
'; + } + break; + } +} + Index: modules/locale/locale.info =================================================================== RCS file: /cvs/drupal/drupal/modules/locale/locale.info,v retrieving revision 1.10 diff -u -p -r1.10 locale.info --- modules/locale/locale.info 11 Oct 2008 02:32:49 -0000 1.10 +++ modules/locale/locale.info 22 May 2009 23:43:57 -0000 @@ -6,3 +6,8 @@ version = VERSION core = 7.x files[] = locale.module files[] = locale.install +files[] = locale.registry.inc +files[] = locale.user.inc +files[] = locale.block.inc +files[] = locale.form.inc +files[] = locale.help.inc Index: modules/locale/locale.module =================================================================== RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v retrieving revision 1.238 diff -u -p -r1.238 locale.module --- modules/locale/locale.module 31 Mar 2009 02:02:21 -0000 1.238 +++ modules/locale/locale.module 22 May 2009 23:43:57 -0000 @@ -16,163 +16,6 @@ // Hook implementations /** - * Implementation of hook_help(). - */ -function locale_help($path, $arg) { - switch ($path) { - case 'admin/help#locale': - $output = '' . t('The locale module allows your Drupal site to be presented in languages other than the default English, a defining feature of multi-lingual websites. The locale module works by examining text as it is about to be displayed: when a translation of the text is available in the language to be displayed, the translation is displayed rather than the original text. When a translation is unavailable, the original text is displayed, and then stored for later review by a translator.') . '
'; - $output .= '' . t('Beyond translation of the Drupal interface, the locale module provides a feature set tailored to the needs of a multi-lingual site. Language negotiation allows your site to automatically change language based on the domain or path used for each request. Users may (optionally) select their preferred language on their My account page, and your site can be configured to honor a web browser\'s preferred language settings. Your site content can be created in (and translated to) any enabled language, and each post may have a language-appropriate alias for each of its translations. The locale module works in concert with the content translation module to manage translated content.', array('@content-help' => url('admin/help/translation'))) . '
'; - $output .= '' . t('Translations may be provided by:') . '
'; - $output .= '' . t('If an existing translation package does not meet your needs, the Gettext Portable Object (.po) files within a package may be modified, or new .po files may be created, using a desktop Gettext editor. The locale module\'s import feature allows the translated strings from a new or modified .po file to be added to your site. The locale module\'s export feature generates files from your site\'s translated strings, that can either be shared with others or edited offline by a Gettext translation editor.', array('@import' => url('admin/international/translate/import'), '@export' => url('admin/international/translate/export'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Locale module.', array('@locale' => 'http://drupal.org/handbook/modules/locale/')) . '
'; - return $output; - case 'admin/international/language': - $output = '' . t("This page provides an overview of your site's enabled languages. If multiple languages are available and enabled, the text on your site interface may be translated, registered users may select their preferred language on the My account page, and site authors may indicate a specific language when creating posts. Languages will be displayed in the order you specify in places such as the language switcher block, or the language dropdown when creating or editing posts. The site's default language is used for anonymous visitors and for users who have not selected a preferred language.") . '
'; - $output .= '' . t('For each language available on the site, use the edit link to configure language details, including name, an optional language-specific path or domain, and whether the language is natively presented either left-to-right or right-to-left. These languages also appear in the Language selection when creating a post of a content type with multilingual support.') . '
'; - $output .= '' . t('Use the add language page to enable additional languages (and automatically import files from a translation package, if available), the translate interface page to locate strings for manual translation, or the import page to add translations from individual .po files. A number of contributed translation packages containing .po files are available on the Drupal.org translations page.', array('@add-language' => url('admin/international/language/add'), '@search' => url('admin/international/translate/translate'), '@import' => url('admin/international/translate/import'), '@translations' => 'http://drupal.org/project/translations')) . '
'; - $output .= '' . t('To rearrange languages, grab a drag-and-drop handle under the English name column and drag the item to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.') . '
'; - return $output; - case 'admin/international/language/add': - return '' . t('Add all languages to be supported by your site. If your desired language is not available in the Language name drop-down, click Custom language and provide a language code and other details manually. When providing a language code manually, be sure to enter a standardized language code, since this code may be used by browsers to determine an appropriate display language.') . '
'; - case 'admin/international/language/configure': - $output = '' . t("Language negotiation settings determine the site's presentation language. Available options include:") . '
'; - $output .= '' . t('The path prefix or domain name for a language may be set by editing the available languages. In the absence of an appropriate match, the site is displayed in the default language.', array('@languages' => url('admin/international/language'))) . '
'; - return $output; - case 'admin/international/translate': - $output = '' . t('This page provides an overview of available translatable strings. Drupal displays translatable strings in text groups; modules may define additional text groups containing other translatable strings. Because text groups provide a method of grouping related strings, they are often used to focus translation efforts on specific areas of the Drupal interface.') . '
'; - $output .= '' . t('Review the languages page for more information on adding support for additional languages.', array('@languages' => url('admin/international/language'))) . '
'; - return $output; - case 'admin/international/translate/import': - $output = '' . t('This page imports the translated strings contained in an individual Gettext Portable Object (.po) file. Normally distributed as part of a translation package (each translation package may contain several .po files), a .po file may need to be imported after offline editing in a Gettext translation editor. Importing an individual .po file may be a lengthy process.') . '
'; - $output .= '' . t('Note that the .po files within a translation package are imported automatically (if available) when new modules or themes are enabled, or as new languages are added. Since this page only allows the import of one .po file at a time, it may be simpler to download and extract a translation package into your Drupal installation directory and add the language (which automatically imports all .po files within the package). Translation packages are available for download on the Drupal translation page.', array('@language-add' => url('admin/international/language/add'), '@translations' => 'http://drupal.org/project/translations')) . '
'; - return $output; - case 'admin/international/translate/export': - return '' . t('This page exports the translated strings used by your site. An export file may be in Gettext Portable Object (.po) form, which includes both the original string and the translation (used to share translations with others), or in Gettext Portable Object Template (.pot) form, which includes the original strings only (used to create new translations with a Gettext translation editor).') . '
'; - case 'admin/international/translate/translate': - return '' . t('This page allows a translator to search for specific translated and untranslated strings, and is used when creating or editing translations. (Note: For translation tasks involving many strings, it may be more convenient to export strings for offline editing in a desktop Gettext translation editor.) Searches may be limited to strings found within a specific text group or in a specific language.', array('@export' => url('admin/international/translate/export'))) . '
'; - case 'admin/build/block/configure': - if ($arg[4] == 'locale' && $arg[5] == 0) { - return '' . t('This block is only shown if at least two languages are enabled and language negotiation is set to something other than None.', array('@languages' => url('admin/international/language'), '@configuration' => url('admin/international/language/configure'))) . '
'; - } - break; - } -} - -/** - * Implementation of hook_menu(). - */ -function locale_menu() { - // Manage languages - $items['admin/international'] = array( - 'title' => 'International', - 'description' => 'Localization and translation.', - 'position' => 'left', - 'weight' => -7, - 'page callback' => 'system_admin_menu_block_page', - 'access arguments' => array('access administration pages'), - ); - $items['admin/international/language'] = array( - 'title' => 'Languages', - 'description' => 'Configure languages for content and the user interface.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('locale_languages_overview_form'), - 'access arguments' => array('administer languages'), - ); - $items['admin/international/language/overview'] = array( - 'title' => 'List', - 'weight' => 0, - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/international/language/add'] = array( - 'title' => 'Add language', - 'page callback' => 'locale_languages_add_screen', // two forms concatenated - 'access arguments' => array('administer languages'), - 'weight' => 5, - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/international/language/configure'] = array( - 'title' => 'Configure', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('locale_languages_configure_form'), - 'access arguments' => array('administer languages'), - 'weight' => 10, - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/international/language/edit/%'] = array( - 'title' => 'Edit language', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('locale_languages_edit_form', 4), - 'access arguments' => array('administer languages'), - 'type' => MENU_CALLBACK, - ); - $items['admin/international/language/delete/%'] = array( - 'title' => 'Confirm', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('locale_languages_delete_form', 4), - 'access arguments' => array('administer languages'), - 'type' => MENU_CALLBACK, - ); - - // Translation functionality - $items['admin/international/translate'] = array( - 'title' => 'Translate interface', - 'description' => 'Translate the built in interface and optionally other text.', - 'page callback' => 'locale_translate_overview_screen', // not a form, just a table - 'access arguments' => array('translate interface'), - ); - $items['admin/international/translate/overview'] = array( - 'title' => 'Overview', - 'weight' => 0, - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/international/translate/translate'] = array( - 'title' => 'Translate', - 'weight' => 10, - 'type' => MENU_LOCAL_TASK, - 'page callback' => 'locale_translate_seek_screen', // search results and form concatenated - 'access arguments' => array('translate interface'), - ); - $items['admin/international/translate/import'] = array( - 'title' => 'Import', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('locale_translate_import_form'), - 'access arguments' => array('translate interface'), - 'weight' => 20, - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/international/translate/export'] = array( - 'title' => 'Export', - 'page callback' => 'locale_translate_export_screen', // possibly multiple forms concatenated - 'access arguments' => array('translate interface'), - 'weight' => 30, - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/international/translate/edit/%'] = array( - 'title' => 'Edit string', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('locale_translate_edit_form', 4), - 'access arguments' => array('translate interface'), - 'type' => MENU_CALLBACK, - ); - $items['admin/international/translate/delete/%'] = array( - 'title' => 'Delete string', - 'page callback' => 'locale_translate_delete_page', - 'page arguments' => array(4), - 'access arguments' => array('translate interface'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** * Wrapper function to be able to set callbacks in locale.inc */ function locale_inc_callback() { @@ -183,22 +26,6 @@ function locale_inc_callback() { } /** - * Implementation of hook_perm(). - */ -function locale_perm() { - return array( - 'administer languages' => array( - 'title' => t('Administer languages'), - 'description' => t('Manage the languages in which the website content and interface text may be displayed.'), - ), - 'translate interface' => array( - 'title' => t('Translate the interface'), - 'description' => t('Translate the text of the website interface.'), - ), - ); -} - -/** * Implementation of hook_locale(). */ function locale_locale($op = 'groups') { @@ -208,28 +35,6 @@ function locale_locale($op = 'groups') { } } -/** - * Implementation of hook_user_register(). - */ -function locale_user_register(&$edit, &$user, $category = NULL) { - // If we have more then one language and either creating a user on the - // admin interface or edit the user, show the language selector. - if (variable_get('language_count', 1) > 1 && user_access('administer users')) { - return locale_language_selector_form($user); - } -} - -/** - * Implementation of hook_user_form(). - */ -function locale_user_form(&$edit, &$user, $category = NULL) { - // If we have more then one language and either creating a user on the - // admin interface or edit the user, show the language selector. - if (variable_get('language_count', 1) > 1 && $category == 'account') { - return locale_language_selector_form($user); - } -} - function locale_language_selector_form($user) { global $language; $languages = language_list('enabled'); @@ -262,35 +67,6 @@ function locale_language_selector_form($ } /** - * Implementation of hook_form_FORM_ID_alter(). - */ -function locale_form_path_admin_form_alter(&$form, &$form_state) { - $form['language'] = array( - '#type' => 'select', - '#title' => t('Language'), - '#options' => array('' => t('All languages')) + locale_language_list('name'), - '#default_value' => $form['language']['#value'], - '#weight' => -10, - '#description' => t('A path alias set for a specific language will always be used when displaying this page in that language, and takes precedence over path aliases set for All languages.'), - ); -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function locale_form_node_type_form_alter(&$form, &$form_state) { - if (isset($form['identity']['type'])) { - $form['workflow']['language_content_type'] = array( - '#type' => 'radios', - '#title' => t('Multilingual support'), - '#default_value' => variable_get('language_content_type_' . $form['#node_type']->type, 0), - '#options' => array(t('Disabled'), t('Enabled')), - '#description' => t('Enable multilingual support for this content type. If enabled, a language selection field will be added to the editing form, allowing you to select from one of the enabled languages. If disabled, new posts are saved with the default language. Existing content will not be affected by changing this option.', array('!languages' => url('admin/international/language'))), - ); - } -} - -/** * Implementation of hook_form_alter(). Adds language fields to forms. */ function locale_form_alter(&$form, &$form_state, $form_id) { @@ -314,20 +90,6 @@ function locale_form_alter(&$form, &$for } } -/** - * Implementation of hook_theme(). - */ -function locale_theme() { - return array( - 'locale_languages_overview_form' => array( - 'arguments' => array('form' => array()), - ), - 'locale_translation_filters' => array( - 'arguments' => array('form' => array()), - ), - ); -} - // --------------------------------------------------------------------------------- // Locale core functionality @@ -569,16 +331,6 @@ function locale_js_alter(&$javascript) { // Language switcher block /** - * Implementation of hook_block_list(). - */ -function locale_block_list() { - $block['language-switcher']['info'] = t('Language switcher'); - // Not worth caching. - $block['language-switcher']['cache'] = BLOCK_NO_CACHE; - return $block; -} - -/** * Implementation of hook_block_view(). * * Displays a language switcher. Translation links may be provided by other modules. Index: modules/locale/locale.registry.inc =================================================================== RCS file: modules/locale/locale.registry.inc diff -N modules/locale/locale.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/locale/locale.registry.inc 22 May 2009 23:43:56 -0000 @@ -0,0 +1,129 @@ + 'International', + 'description' => 'Localization and translation.', + 'position' => 'left', + 'weight' => -7, + 'page callback' => 'system_admin_menu_block_page', + 'access arguments' => array('access administration pages'), + ); + $items['admin/international/language'] = array( + 'title' => 'Languages', + 'description' => 'Configure languages for content and the user interface.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('locale_languages_overview_form'), + 'access arguments' => array('administer languages'), + ); + $items['admin/international/language/overview'] = array( + 'title' => 'List', + 'weight' => 0, + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['admin/international/language/add'] = array( + 'title' => 'Add language', + 'page callback' => 'locale_languages_add_screen', // two forms concatenated + 'access arguments' => array('administer languages'), + 'weight' => 5, + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/international/language/configure'] = array( + 'title' => 'Configure', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('locale_languages_configure_form'), + 'access arguments' => array('administer languages'), + 'weight' => 10, + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/international/language/edit/%'] = array( + 'title' => 'Edit language', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('locale_languages_edit_form', 4), + 'access arguments' => array('administer languages'), + 'type' => MENU_CALLBACK, + ); + $items['admin/international/language/delete/%'] = array( + 'title' => 'Confirm', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('locale_languages_delete_form', 4), + 'access arguments' => array('administer languages'), + 'type' => MENU_CALLBACK, + ); + + // Translation functionality + $items['admin/international/translate'] = array( + 'title' => 'Translate interface', + 'description' => 'Translate the built in interface and optionally other text.', + 'page callback' => 'locale_translate_overview_screen', // not a form, just a table + 'access arguments' => array('translate interface'), + ); + $items['admin/international/translate/overview'] = array( + 'title' => 'Overview', + 'weight' => 0, + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['admin/international/translate/translate'] = array( + 'title' => 'Translate', + 'weight' => 10, + 'type' => MENU_LOCAL_TASK, + 'page callback' => 'locale_translate_seek_screen', // search results and form concatenated + 'access arguments' => array('translate interface'), + ); + $items['admin/international/translate/import'] = array( + 'title' => 'Import', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('locale_translate_import_form'), + 'access arguments' => array('translate interface'), + 'weight' => 20, + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/international/translate/export'] = array( + 'title' => 'Export', + 'page callback' => 'locale_translate_export_screen', // possibly multiple forms concatenated + 'access arguments' => array('translate interface'), + 'weight' => 30, + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/international/translate/edit/%'] = array( + 'title' => 'Edit string', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('locale_translate_edit_form', 4), + 'access arguments' => array('translate interface'), + 'type' => MENU_CALLBACK, + ); + $items['admin/international/translate/delete/%'] = array( + 'title' => 'Delete string', + 'page callback' => 'locale_translate_delete_page', + 'page arguments' => array(4), + 'access arguments' => array('translate interface'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function locale_theme() { + return array( + 'locale_languages_overview_form' => array( + 'arguments' => array('form' => array()), + ), + 'locale_translation_filters' => array( + 'arguments' => array('form' => array()), + ), + ); +} + Index: modules/locale/locale.user.inc =================================================================== RCS file: modules/locale/locale.user.inc diff -N modules/locale/locale.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/locale/locale.user.inc 22 May 2009 23:43:56 -0000 @@ -0,0 +1,46 @@ + array( + 'title' => t('Administer languages'), + 'description' => t('Manage the languages in which the website content and interface text may be displayed.'), + ), + 'translate interface' => array( + 'title' => t('Translate the interface'), + 'description' => t('Translate the text of the website interface.'), + ), + ); +} + +/** + * Implementation of hook_user_register(). + */ +function locale_user_register(&$edit, &$user, $category = NULL) { + // If we have more then one language and either creating a user on the + // admin interface or edit the user, show the language selector. + if (variable_get('language_count', 1) > 1 && user_access('administer users')) { + return locale_language_selector_form($user); + } +} + +/** + * Implementation of hook_user_form(). + */ +function locale_user_form(&$edit, &$user, $category = NULL) { + // If we have more then one language and either creating a user on the + // admin interface or edit the user, show the language selector. + if (variable_get('language_count', 1) > 1 && $category == 'account') { + return locale_language_selector_form($user); + } +} + Index: modules/menu/menu.block.inc =================================================================== RCS file: modules/menu/menu.block.inc diff -N modules/menu/menu.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/menu/menu.block.inc 22 May 2009 23:43:55 -0000 @@ -0,0 +1,25 @@ + $title) { + // Default "Navigation" block is handled by user.module. + $blocks[$name]['info'] = check_plain($title); + // Menu blocks can't be cached because each menu item can have + // a custom access callback. menu.inc manages its own caching. + $blocks[$name]['cache'] = BLOCK_NO_CACHE; + } + return $blocks; +} + Index: modules/menu/menu.form.inc =================================================================== RCS file: modules/menu/menu.form.inc diff -N modules/menu/menu.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/menu/menu.form.inc 22 May 2009 23:44:27 -0000 @@ -0,0 +1,15 @@ +' . t("The menu module provides an interface to control and customize Drupal's powerful menu system. Menus are a hierarchical collection of links used to navigate a website. Each menu is rendered in a block that may be positioned and displayed using Drupal's flexible block system. Five menus are provided by Drupal and are always present: Navigation, Management, User menu, Main menu, and Secondary menu. The Management menu contains links for administration and content creation, while the Navigation menu is the default location for site navigation links created by newly enabled modules. Both of these are often displayed in either the left or right sidebar. Most Drupal themes also provide support for the Main links and Secondary links, by displaying them in either the header or footer of each page. The Main menu is the default source for the Main links and the User menu is the default source for the Secondary links. By default, the User menu has links to take the current user to their account or allow them to log out, while the Main menu and Secondary menu contain no menu links but may be configured to contain custom menu items specific to your site. You may create an unlimited number of additional menus, each of which will automatically have an associated block.") . ''; + $output .= '' . t('The menus page displays all menus currently available on your site. Select a menu from this list to add or edit a menu link, or to rearrange links within the menu. Create new menus using the add menu page (the block containing a new menu must also be enabled on the blocks administration page).', array('@menu' => url('admin/build/menu'), '@add-menu' => url('admin/build/menu/add'), '@blocks' => url('admin/build/block'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Menu module.', array('@menu' => 'http://drupal.org/handbook/modules/menu/')) . '
'; + return $output; + case 'admin/build/menu/add': + return '' . t('Enter the name for your new menu. Remember to enable the newly created block in the blocks administration page.', array('@blocks' => url('admin/build/block'))) . '
'; + case 'admin/build/menu-customize/%': + return '' . t('To rearrange menu links, grab a drag-and-drop handle under the Menu link column and drag the link (or group of links) to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.') . '
'; + case 'admin/build/menu/item/add': + return '' . t('Enter the title and path for your new menu link.') . '
'; + } + if ($path == 'admin/build/menu' && module_exists('block')) { + return '' . t('Each menu has a corresponding block that is managed on the blocks administration page.', array('@blocks' => url('admin/build/block'))) . '
'; + } +} + Index: modules/menu/menu.info =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.info,v retrieving revision 1.8 diff -u -p -r1.8 menu.info --- modules/menu/menu.info 11 Oct 2008 02:32:50 -0000 1.8 +++ modules/menu/menu.info 22 May 2009 23:44:27 -0000 @@ -7,3 +7,9 @@ core = 7.x files[] = menu.module files[] = menu.admin.inc files[] = menu.install +files[] = menu.registry.inc +files[] = menu.user.inc +files[] = menu.block.inc +files[] = menu.node.inc +files[] = menu.help.inc +files[] = menu.form.inc Index: modules/menu/menu.install =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.install,v retrieving revision 1.17 diff -u -p -r1.17 menu.install --- modules/menu/menu.install 13 May 2009 19:42:15 -0000 1.17 +++ modules/menu/menu.install 22 May 2009 23:43:55 -0000 @@ -69,3 +69,32 @@ function menu_schema() { return $schema; } +/** + * Implementation of hook_enable(). + * + * Add a link for each custom menu. + */ +function menu_enable() { + menu_rebuild(); + $base_link = db_query("SELECT mlid AS plid, menu_name from {menu_links} WHERE link_path = 'admin/build/menu' AND module = 'system'")->fetchAssoc(); + $base_link['router_path'] = 'admin/build/menu-customize/%'; + $base_link['module'] = 'menu'; + $result = db_query("SELECT * FROM {menu_custom}", array(), array('fetch' => PDO::FETCH_ASSOC)); + foreach ($result as $menu) { + // $link is passed by reference to menu_link_save(), so we make a copy of $base_link. + $link = $base_link; + $link['mlid'] = 0; + $link['link_title'] = $menu['title']; + $link['link_path'] = 'admin/build/menu-customize/' . $menu['menu_name']; + $menu_link = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND plid = :plid", array( + ':path' => $link['link_path'], + ':plid' => $link['plid'] + )) + ->fetchField(); + if (!$menu_link) { + menu_link_save($link); + } + } + menu_cache_clear_all(); +} + Index: modules/menu/menu.module =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v retrieving revision 1.189 diff -u -p -r1.189 menu.module --- modules/menu/menu.module 21 May 2009 23:07:15 -0000 1.189 +++ modules/menu/menu.module 22 May 2009 23:44:27 -0000 @@ -13,175 +13,6 @@ define('MENU_MAX_MENU_NAME_LENGTH_UI', 27); /** - * Implementation of hook_help(). - */ -function menu_help($path, $arg) { - switch ($path) { - case 'admin/help#menu': - $output = '' . t("The menu module provides an interface to control and customize Drupal's powerful menu system. Menus are a hierarchical collection of links used to navigate a website. Each menu is rendered in a block that may be positioned and displayed using Drupal's flexible block system. Five menus are provided by Drupal and are always present: Navigation, Management, User menu, Main menu, and Secondary menu. The Management menu contains links for administration and content creation, while the Navigation menu is the default location for site navigation links created by newly enabled modules. Both of these are often displayed in either the left or right sidebar. Most Drupal themes also provide support for the Main links and Secondary links, by displaying them in either the header or footer of each page. The Main menu is the default source for the Main links and the User menu is the default source for the Secondary links. By default, the User menu has links to take the current user to their account or allow them to log out, while the Main menu and Secondary menu contain no menu links but may be configured to contain custom menu items specific to your site. You may create an unlimited number of additional menus, each of which will automatically have an associated block.") . '
'; - $output .= '' . t('The menus page displays all menus currently available on your site. Select a menu from this list to add or edit a menu link, or to rearrange links within the menu. Create new menus using the add menu page (the block containing a new menu must also be enabled on the blocks administration page).', array('@menu' => url('admin/build/menu'), '@add-menu' => url('admin/build/menu/add'), '@blocks' => url('admin/build/block'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Menu module.', array('@menu' => 'http://drupal.org/handbook/modules/menu/')) . '
'; - return $output; - case 'admin/build/menu/add': - return '' . t('Enter the name for your new menu. Remember to enable the newly created block in the blocks administration page.', array('@blocks' => url('admin/build/block'))) . '
'; - case 'admin/build/menu-customize/%': - return '' . t('To rearrange menu links, grab a drag-and-drop handle under the Menu link column and drag the link (or group of links) to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.') . '
'; - case 'admin/build/menu/item/add': - return '' . t('Enter the title and path for your new menu link.') . '
'; - } - if ($path == 'admin/build/menu' && module_exists('block')) { - return '' . t('Each menu has a corresponding block that is managed on the blocks administration page.', array('@blocks' => url('admin/build/block'))) . '
'; - } -} - -/** - * Implementation of hook_perm(). - */ -function menu_perm() { - return array( - 'administer menu' => array( - 'title' => t('Administer menu'), - 'description' => t('Manage menus and menu items.'), - ), - ); -} - -/** - * Implementation of hook_menu(). - */ -function menu_menu() { - $items['admin/build/menu'] = array( - 'title' => 'Menus', - 'description' => 'Add new menus to your site, edit existing menus, and rename and reorganize menu links.', - 'page callback' => 'menu_overview_page', - 'access callback' => 'user_access', - 'access arguments' => array('administer menu'), - ); - $items['admin/build/menu/list'] = array( - 'title' => 'List menus', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['admin/build/menu/add'] = array( - 'title' => 'Add menu', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('menu_edit_menu', 'add'), - 'access arguments' => array('administer menu'), - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/build/menu/settings'] = array( - 'title' => 'Settings', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('menu_configure'), - 'access arguments' => array('administer menu'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 5, - ); - $items['admin/build/menu-customize/%menu'] = array( - 'title' => 'Customize menu', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('menu_overview_form', 3), - 'title callback' => 'menu_overview_title', - 'title arguments' => array(3), - 'access arguments' => array('administer menu'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/menu-customize/%menu/list'] = array( - 'title' => 'List links', - 'weight' => -10, - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/build/menu-customize/%menu/add'] = array( - 'title' => 'Add link', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('menu_edit_item', 'add', NULL, 3), - 'access arguments' => array('administer menu'), - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/build/menu-customize/%menu/edit'] = array( - 'title' => 'Edit menu', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('menu_edit_menu', 'edit', 3), - 'access arguments' => array('administer menu'), - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/build/menu-customize/%menu/delete'] = array( - 'title' => 'Delete menu', - 'page callback' => 'menu_delete_menu_page', - 'page arguments' => array(3), - 'access arguments' => array('administer menu'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/menu/item/%menu_link/edit'] = array( - 'title' => 'Edit menu link', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('menu_edit_item', 'edit', 4, NULL), - 'access arguments' => array('administer menu'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/menu/item/%menu_link/reset'] = array( - 'title' => 'Reset menu link', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('menu_reset_item_confirm', 4), - 'access arguments' => array('administer menu'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/menu/item/%menu_link/delete'] = array( - 'title' => 'Delete menu link', - 'page callback' => 'menu_item_delete_page', - 'page arguments' => array(4), - 'access arguments' => array('administer menu'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** - * Implementation of hook_theme(). - */ -function menu_theme() { - return array( - 'menu_overview_form' => array( - 'file' => 'menu.admin.inc', - 'arguments' => array('form' => NULL), - ), - 'menu_admin_overview' => array( - 'file' => 'menu.admin.inc', - 'arguments' => array('title' => NULL, 'name' => NULL, 'description' => NULL), - ), - ); -} - -/** - * Implementation of hook_enable(). - * - * Add a link for each custom menu. - */ -function menu_enable() { - menu_rebuild(); - $base_link = db_query("SELECT mlid AS plid, menu_name from {menu_links} WHERE link_path = 'admin/build/menu' AND module = 'system'")->fetchAssoc(); - $base_link['router_path'] = 'admin/build/menu-customize/%'; - $base_link['module'] = 'menu'; - $result = db_query("SELECT * FROM {menu_custom}", array(), array('fetch' => PDO::FETCH_ASSOC)); - foreach ($result as $menu) { - // $link is passed by reference to menu_link_save(), so we make a copy of $base_link. - $link = $base_link; - $link['mlid'] = 0; - $link['link_title'] = $menu['title']; - $link['link_path'] = 'admin/build/menu-customize/' . $menu['menu_name']; - $menu_link = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND plid = :plid", array( - ':path' => $link['link_path'], - ':plid' => $link['plid'] - )) - ->fetchField(); - if (!$menu_link) { - menu_link_save($link); - } - } - menu_cache_clear_all(); -} - -/** * Title callback for the menu overview page and links. */ function menu_overview_title($menu) { @@ -266,23 +97,6 @@ function menu_reset_item($item) { } /** - * Implementation of hook_block_list(). - */ -function menu_block_list() { - $menus = menu_get_menus(FALSE); - - $blocks = array(); - foreach ($menus as $name => $title) { - // Default "Navigation" block is handled by user.module. - $blocks[$name]['info'] = check_plain($title); - // Menu blocks can't be cached because each menu item can have - // a custom access callback. menu.inc manages its own caching. - $blocks[$name]['cache'] = BLOCK_NO_CACHE; - } - return $blocks; -} - -/** * Implementation of hook_block_view(). */ function menu_block_view($delta = '') { @@ -293,96 +107,6 @@ function menu_block_view($delta = '') { } /** - * Implementation of hook_node_insert(). - */ -function menu_node_insert($node) { - if (isset($node->menu)) { - $item = &$node->menu; - if (!empty($item['delete'])) { - menu_link_delete($item['mlid']); - } - elseif (trim($item['link_title'])) { - $item['link_title'] = trim($item['link_title']); - $item['link_path'] = "node/$node->nid"; - if (!$item['customized']) { - $item['options']['attributes']['title'] = trim($node->title); - } - if (!menu_link_save($item)) { - drupal_set_message(t('There was an error saving the menu link.'), 'error'); - } - } - } -} - -/** - * Implementation of hook_node_update(). - */ -function menu_node_update($node) { - if (isset($node->menu)) { - $item = &$node->menu; - if (!empty($item['delete'])) { - menu_link_delete($item['mlid']); - } - elseif (trim($item['link_title'])) { - $item['link_title'] = trim($item['link_title']); - $item['link_path'] = "node/$node->nid"; - if (!$item['customized']) { - $item['options']['attributes']['title'] = trim($node->title); - } - if (!menu_link_save($item)) { - drupal_set_message(t('There was an error saving the menu link.'), 'error'); - } - } - } -} - -/** - * Implementation of hook_node_delete(). - */ -function menu_node_delete($node) { - // Delete all menu module links that point to this node. - $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu'", array(':path' => 'node/'. $node->nid), array('fetch' => PDO::FETCH_ASSOC)); - foreach ($result as $m) { - menu_link_delete($m['mlid']); - } -} - -/** - * Implementation of hook_node_prepare(). - */ -function menu_node_prepare($node) { - if (empty($node->menu)) { - // Prepare the node for the edit form so that $node->menu always exists. - $menu_name = variable_get('menu_default_node_menu', 'main-menu'); - $item = array(); - if (isset($node->nid)) { - // Give priority to the default menu - $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND menu_name = :menu_name AND module = 'menu' ORDER BY mlid ASC", array( - ':path' => 'node/'. $node->nid, - ':menu_name' => $menu_name, - ), 0, 1) - ->fetchField(); - // Check all menus if a link does not exist in the default menu. - if (!$mlid) { - $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu' ORDER BY mlid ASC", array( - ':path' => 'node/'. $node->nid, - ), 0, 1) - ->fetchField(); - } - if ($mlid) { - $item = menu_link_load($mlid); - } - } - // Set default values. - $node->menu = $item + array('link_title' => '', 'mlid' => 0, 'plid' => 0, 'menu_name' => $menu_name, 'weight' => 0, 'options' => array(), 'module' => 'menu', 'expanded' => 0, 'hidden' => 0, 'has_children' => 0, 'customized' => 0); - } - // Find the depth limit for the parent select. - if (!isset($node->menu['parent_depth_limit'])) { - $node->menu['parent_depth_limit'] = _menu_parent_depth_limit($node->menu); - } -} - -/** * Find the depth limit for items in the parent select. */ function _menu_parent_depth_limit($item) { @@ -460,13 +184,6 @@ function menu_form_alter(&$form, $form_s } /** - * Decompose the selected menu parent option into the menu_name and plid. - */ -function menu_node_form_submit($form, &$form_state) { - list($form_state['values']['menu']['menu_name'], $form_state['values']['menu']['plid']) = explode(':', $form_state['values']['menu']['parent']); -} - -/** * Return an associative array of the custom menus names. * * @param $all Index: modules/menu/menu.node.inc =================================================================== RCS file: modules/menu/menu.node.inc diff -N modules/menu/menu.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/menu/menu.node.inc 22 May 2009 23:43:55 -0000 @@ -0,0 +1,98 @@ +menu)) { + $item = &$node->menu; + if (!empty($item['delete'])) { + menu_link_delete($item['mlid']); + } + elseif (trim($item['link_title'])) { + $item['link_title'] = trim($item['link_title']); + $item['link_path'] = "node/$node->nid"; + if (!$item['customized']) { + $item['options']['attributes']['title'] = trim($node->title); + } + if (!menu_link_save($item)) { + drupal_set_message(t('There was an error saving the menu link.'), 'error'); + } + } + } +} + +/** + * Implementation of hook_node_update(). + */ +function menu_node_update($node) { + if (isset($node->menu)) { + $item = &$node->menu; + if (!empty($item['delete'])) { + menu_link_delete($item['mlid']); + } + elseif (trim($item['link_title'])) { + $item['link_title'] = trim($item['link_title']); + $item['link_path'] = "node/$node->nid"; + if (!$item['customized']) { + $item['options']['attributes']['title'] = trim($node->title); + } + if (!menu_link_save($item)) { + drupal_set_message(t('There was an error saving the menu link.'), 'error'); + } + } + } +} + +/** + * Implementation of hook_node_delete(). + */ +function menu_node_delete($node) { + // Delete all menu module links that point to this node. + $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu'", array(':path' => 'node/'. $node->nid), array('fetch' => PDO::FETCH_ASSOC)); + foreach ($result as $m) { + menu_link_delete($m['mlid']); + } +} + +/** + * Implementation of hook_node_prepare(). + */ +function menu_node_prepare($node) { + if (empty($node->menu)) { + // Prepare the node for the edit form so that $node->menu always exists. + $menu_name = variable_get('menu_default_node_menu', 'main-menu'); + $item = array(); + if (isset($node->nid)) { + // Give priority to the default menu + $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND menu_name = :menu_name AND module = 'menu' ORDER BY mlid ASC", array( + ':path' => 'node/'. $node->nid, + ':menu_name' => $menu_name, + ), 0, 1) + ->fetchField(); + // Check all menus if a link does not exist in the default menu. + if (!$mlid) { + $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu' ORDER BY mlid ASC", array( + ':path' => 'node/'. $node->nid, + ), 0, 1) + ->fetchField(); + } + if ($mlid) { + $item = menu_link_load($mlid); + } + } + // Set default values. + $node->menu = $item + array('link_title' => '', 'mlid' => 0, 'plid' => 0, 'menu_name' => $menu_name, 'weight' => 0, 'options' => array(), 'module' => 'menu', 'expanded' => 0, 'hidden' => 0, 'has_children' => 0, 'customized' => 0); + } + // Find the depth limit for the parent select. + if (!isset($node->menu['parent_depth_limit'])) { + $node->menu['parent_depth_limit'] = _menu_parent_depth_limit($node->menu); + } +} + Index: modules/menu/menu.registry.inc =================================================================== RCS file: modules/menu/menu.registry.inc diff -N modules/menu/menu.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/menu/menu.registry.inc 22 May 2009 23:43:55 -0000 @@ -0,0 +1,114 @@ + 'Menus', + 'description' => 'Add new menus to your site, edit existing menus, and rename and reorganize menu links.', + 'page callback' => 'menu_overview_page', + 'access callback' => 'user_access', + 'access arguments' => array('administer menu'), + ); + $items['admin/build/menu/list'] = array( + 'title' => 'List menus', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + $items['admin/build/menu/add'] = array( + 'title' => 'Add menu', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('menu_edit_menu', 'add'), + 'access arguments' => array('administer menu'), + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/build/menu/settings'] = array( + 'title' => 'Settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('menu_configure'), + 'access arguments' => array('administer menu'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 5, + ); + $items['admin/build/menu-customize/%menu'] = array( + 'title' => 'Customize menu', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('menu_overview_form', 3), + 'title callback' => 'menu_overview_title', + 'title arguments' => array(3), + 'access arguments' => array('administer menu'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/menu-customize/%menu/list'] = array( + 'title' => 'List links', + 'weight' => -10, + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['admin/build/menu-customize/%menu/add'] = array( + 'title' => 'Add link', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('menu_edit_item', 'add', NULL, 3), + 'access arguments' => array('administer menu'), + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/build/menu-customize/%menu/edit'] = array( + 'title' => 'Edit menu', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('menu_edit_menu', 'edit', 3), + 'access arguments' => array('administer menu'), + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/build/menu-customize/%menu/delete'] = array( + 'title' => 'Delete menu', + 'page callback' => 'menu_delete_menu_page', + 'page arguments' => array(3), + 'access arguments' => array('administer menu'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/menu/item/%menu_link/edit'] = array( + 'title' => 'Edit menu link', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('menu_edit_item', 'edit', 4, NULL), + 'access arguments' => array('administer menu'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/menu/item/%menu_link/reset'] = array( + 'title' => 'Reset menu link', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('menu_reset_item_confirm', 4), + 'access arguments' => array('administer menu'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/menu/item/%menu_link/delete'] = array( + 'title' => 'Delete menu link', + 'page callback' => 'menu_item_delete_page', + 'page arguments' => array(4), + 'access arguments' => array('administer menu'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function menu_theme() { + return array( + 'menu_overview_form' => array( + 'file' => 'menu.admin.inc', + 'arguments' => array('form' => NULL), + ), + 'menu_admin_overview' => array( + 'file' => 'menu.admin.inc', + 'arguments' => array('title' => NULL, 'name' => NULL, 'description' => NULL), + ), + ); +} + Index: modules/menu/menu.user.inc =================================================================== RCS file: modules/menu/menu.user.inc diff -N modules/menu/menu.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/menu/menu.user.inc 22 May 2009 23:43:55 -0000 @@ -0,0 +1,20 @@ + array( + 'title' => t('Administer menu'), + 'description' => t('Manage menus and menu items.'), + ), + ); +} + Index: modules/node/node.actions.inc =================================================================== RCS file: modules/node/node.actions.inc diff -N modules/node/node.actions.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/node/node.actions.inc 22 May 2009 23:43:52 -0000 @@ -0,0 +1,164 @@ +status = 1; + watchdog('action', 'Set @type %title to published.', array('@type' => node_get_types('name', $node), '%title' => $node->title)); +} + +/** + * Implementation of a Drupal action. + * Sets the status of a node to 0, meaning unpublished. + */ +function node_unpublish_action($node, $context = array()) { + $node->status = 0; + watchdog('action', 'Set @type %title to unpublished.', array('@type' => node_get_types('name', $node), '%title' => $node->title)); +} + +/** + * Implementation of a Drupal action. + * Sets the sticky-at-top-of-list property of a node to 1. + */ +function node_make_sticky_action($node, $context = array()) { + $node->sticky = 1; + watchdog('action', 'Set @type %title to sticky.', array('@type' => node_get_types('name', $node), '%title' => $node->title)); +} + +/** + * Implementation of a Drupal action. + * Sets the sticky-at-top-of-list property of a node to 0. + */ +function node_make_unsticky_action($node, $context = array()) { + $node->sticky = 0; + watchdog('action', 'Set @type %title to unsticky.', array('@type' => node_get_types('name', $node), '%title' => $node->title)); +} + +/** + * Implementation of a Drupal action. + * Sets the promote property of a node to 1. + */ +function node_promote_action($node, $context = array()) { + $node->promote = 1; + watchdog('action', 'Promoted @type %title to front page.', array('@type' => node_get_types('name', $node), '%title' => $node->title)); +} + +/** + * Implementation of a Drupal action. + * Sets the promote property of a node to 0. + */ +function node_unpromote_action($node, $context = array()) { + $node->promote = 0; + watchdog('action', 'Removed @type %title from front page.', array('@type' => node_get_types('name', $node), '%title' => $node->title)); +} + +/** + * Implementation of a Drupal action. + * Saves a node. + */ +function node_save_action($node) { + node_save($node); + watchdog('action', 'Saved @type %title', array('@type' => node_get_types('name', $node), '%title' => $node->title)); +} + +/** + * Implementation of a configurable Drupal action. + * Assigns ownership of a node to a user. + */ +function node_assign_owner_action($node, $context) { + $node->uid = $context['owner_uid']; + $owner_name = db_query("SELECT name FROM {users} WHERE uid = :uid", array(':uid' => $context['owner_uid']))->fetchField(); + watchdog('action', 'Changed owner of @type %title to uid %name.', array('@type' => node_get_types('type', $node), '%title' => $node->title, '%name' => $owner_name)); +} + +function node_assign_owner_action_form($context) { + $description = t('The username of the user to which you would like to assign ownership.'); + $count = db_query("SELECT COUNT(*) FROM {users}")->fetchField(); + $owner_name = ''; + if (isset($context['owner_uid'])) { + $owner_name = db_query("SELECT name FROM {users} WHERE uid = :uid", array(':uid' => $context['owner_uid']))->fetchField(); + } + + // Use dropdown for fewer than 200 users; textbox for more than that. + if (intval($count) < 200) { + $options = array(); + $result = db_query("SELECT uid, name FROM {users} WHERE uid > 0 ORDER BY name"); + foreach ($result as $data) { + $options[$data->name] = $data->name; + } + $form['owner_name'] = array( + '#type' => 'select', + '#title' => t('Username'), + '#default_value' => $owner_name, + '#options' => $options, + '#description' => $description, + ); + } + else { + $form['owner_name'] = array( + '#type' => 'textfield', + '#title' => t('Username'), + '#default_value' => $owner_name, + '#autocomplete_path' => 'user/autocomplete', + '#size' => '6', + '#maxlength' => '7', + '#description' => $description, + ); + } + return $form; +} + +function node_assign_owner_action_validate($form, $form_state) { + $exists = (bool) db_query_range('SELECT 1 FROM {users} WHERE name = :name', array(':name' => $form_state['values']['owner_name']), 0, 1)->fetchField(); + if (!$exists) { + form_set_error('owner_name', t('Please enter a valid username.')); + } +} + +function node_assign_owner_action_submit($form, $form_state) { + // Username can change, so we need to store the ID, not the username. + $uid = db_query('SELECT uid from {users} WHERE name = :name', array(':name' => $form_state['values']['owner_name']))->fetchField(); + return array('owner_uid' => $uid); +} + +function node_unpublish_by_keyword_action_form($context) { + $form['keywords'] = array( + '#title' => t('Keywords'), + '#type' => 'textarea', + '#description' => t('The post will be unpublished if it contains any of the phrases above. Use a case-sensitive, comma-separated list of phrases. Example: funny, bungee jumping, "Company, Inc."'), + '#default_value' => isset($context['keywords']) ? drupal_implode_tags($context['keywords']) : '', + ); + return $form; +} + +function node_unpublish_by_keyword_action_submit($form, $form_state) { + return array('keywords' => drupal_explode_tags($form_state['values']['keywords'])); +} + +/** + * Implementation of a configurable Drupal action. + * Unpublish a node if it contains a certain string. + * + * @param $context + * An array providing more information about the context of the call to this action. + * @param $comment + * A node object. + */ +function node_unpublish_by_keyword_action($node, $context) { + foreach ($context['keywords'] as $keyword) { + if (strpos(drupal_render(node_build(clone $node)), $keyword) !== FALSE || strpos($node->title, $keyword) !== FALSE) { + $node->status = 0; + watchdog('action', 'Set @type %title to unpublished.', array('@type' => node_get_types('name', $node), '%title' => $node->title)); + break; + } + } +} + Index: modules/node/node.block.inc =================================================================== RCS file: modules/node/node.block.inc diff -N modules/node/node.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/node/node.block.inc 22 May 2009 23:43:53 -0000 @@ -0,0 +1,18 @@ +condition('timestamp', NODE_NEW_LIMIT, '<') + ->execute(); +} + Index: modules/node/node.form.inc =================================================================== RCS file: modules/node/node.form.inc diff -N modules/node/node.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/node/node.form.inc 22 May 2009 23:44:28 -0000 @@ -0,0 +1,157 @@ + 'fieldset', + '#title' => t('Advanced search'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#attributes' => array('class' => 'search-advanced'), + ); + $form['advanced']['keywords'] = array( + '#prefix' => '' . t('The node module manages content on your site, and stores all posts (regardless of type) as a "node" . In addition to basic publishing settings, including whether the post has been published, promoted to the site front page, or should remain present (or sticky) at the top of lists, the node module also records basic information about the author of a post. Optional revision control over edits is available. For additional functionality, the node module is often extended by other modules.') . '
'; + $output .= '' . t('Though each post on your site is a node, each post is also of a particular content type. Content types are used to define the characteristics of a post, including the title and description of the fields displayed on its add and edit pages. Each content type may have different default settings for Publishing options and other workflow controls. By default, the two content types in a standard Drupal installation are Page and Story. Use the content types page to add new or edit existing content types. Additional content types also become available as you enable additional core, contributed and custom modules.', array('@content-type' => url('admin/build/types'))) . '
'; + $output .= '' . t('The administrative content page allows you to review and manage your site content. The post settings page sets certain options for the display of posts. The node module makes a number of permissions available for each content type, which may be set by role on the permissions page.', array('@content' => url('admin/content/node'), '@post-settings' => url('admin/content/node-settings'), '@permissions' => url('admin/user/permissions'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Node module.', array('@node' => 'http://drupal.org/handbook/modules/node/')) . '
'; + return $output; + case 'admin/content/node': + return ' '; // Return a non-null value so that the 'more help' link is shown. + case 'admin/build/types/add': + return '' . t('To create a new content type, enter the human-readable name, the machine-readable name, and all other relevant fields that are on this page. Once created, users of your site will be able to create posts that are instances of this content type.') . '
'; + case 'node/%/revisions': + return '' . t('The revisions let you track differences between multiple versions of a post.') . '
'; + case 'node/%/edit': + $node = node_load($arg[1]); + $type = node_get_types('type', $node->type); + return (!empty($type->help) ? '' . filter_xss_admin($type->help) . '
' : ''); + } + + if ($arg[0] == 'node' && $arg[1] == 'add' && $arg[2]) { + $type = node_get_types('type', str_replace('-', '_', $arg[2])); + return (!empty($type->help) ? '' . filter_xss_admin($type->help) . '
' : ''); + } +} + Index: modules/node/node.info =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.info,v retrieving revision 1.10 diff -u -p -r1.10 node.info --- modules/node/node.info 12 Oct 2008 01:23:04 -0000 1.10 +++ modules/node/node.info 22 May 2009 23:43:54 -0000 @@ -10,3 +10,11 @@ files[] = node.admin.inc files[] = node.pages.inc files[] = node.install required = TRUE +files[] = node.registry.inc +files[] = node.actions.inc +files[] = node.user.inc +files[] = node.block.inc +files[] = node.search.inc +files[] = node.cron.inc +files[] = node.form.inc +files[] = node.help.inc Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1054 diff -u -p -r1.1054 node.module --- modules/node/node.module 22 May 2009 11:34:05 -0000 1.1054 +++ modules/node/node.module 22 May 2009 23:44:28 -0000 @@ -46,155 +46,6 @@ define('NODE_BUILD_RSS', 4); define('NODE_BUILD_PRINT', 5); /** - * Implementation of hook_help(). - */ -function node_help($path, $arg) { - // Remind site administrators about the {node_access} table being flagged - // for rebuild. We don't need to issue the message on the confirm form, or - // while the rebuild is being processed. - if ($path != 'admin/content/node-settings/rebuild' && $path != 'batch' && strpos($path, '#') === FALSE - && user_access('access administration pages') && node_access_needs_rebuild()) { - if ($path == 'admin/content/node-settings') { - $message = t('The content access permissions need to be rebuilt.'); - } - else { - $message = t('The content access permissions need to be rebuilt. Please visit this page.', array('@node_access_rebuild' => url('admin/content/node-settings/rebuild'))); - } - drupal_set_message($message, 'error'); - } - - switch ($path) { - case 'admin/help#node': - $output = '' . t('The node module manages content on your site, and stores all posts (regardless of type) as a "node" . In addition to basic publishing settings, including whether the post has been published, promoted to the site front page, or should remain present (or sticky) at the top of lists, the node module also records basic information about the author of a post. Optional revision control over edits is available. For additional functionality, the node module is often extended by other modules.') . '
'; - $output .= '' . t('Though each post on your site is a node, each post is also of a particular content type. Content types are used to define the characteristics of a post, including the title and description of the fields displayed on its add and edit pages. Each content type may have different default settings for Publishing options and other workflow controls. By default, the two content types in a standard Drupal installation are Page and Story. Use the content types page to add new or edit existing content types. Additional content types also become available as you enable additional core, contributed and custom modules.', array('@content-type' => url('admin/build/types'))) . '
'; - $output .= '' . t('The administrative content page allows you to review and manage your site content. The post settings page sets certain options for the display of posts. The node module makes a number of permissions available for each content type, which may be set by role on the permissions page.', array('@content' => url('admin/content/node'), '@post-settings' => url('admin/content/node-settings'), '@permissions' => url('admin/user/permissions'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Node module.', array('@node' => 'http://drupal.org/handbook/modules/node/')) . '
'; - return $output; - case 'admin/content/node': - return ' '; // Return a non-null value so that the 'more help' link is shown. - case 'admin/build/types/add': - return '' . t('To create a new content type, enter the human-readable name, the machine-readable name, and all other relevant fields that are on this page. Once created, users of your site will be able to create posts that are instances of this content type.') . '
'; - case 'node/%/revisions': - return '' . t('The revisions let you track differences between multiple versions of a post.') . '
'; - case 'node/%/edit': - $node = node_load($arg[1]); - $type = node_get_types('type', $node->type); - return (!empty($type->help) ? '' . filter_xss_admin($type->help) . '
' : ''); - } - - if ($arg[0] == 'node' && $arg[1] == 'add' && $arg[2]) { - $type = node_get_types('type', str_replace('-', '_', $arg[2])); - return (!empty($type->help) ? '' . filter_xss_admin($type->help) . '
' : ''); - } -} - -/** - * Implementation of hook_theme(). - */ -function node_theme() { - return array( - 'node' => array( - 'arguments' => array('elements' => NULL), - 'template' => 'node', - ), - 'node_list' => array( - 'arguments' => array('items' => NULL, 'title' => NULL), - ), - 'node_search_admin' => array( - 'arguments' => array('form' => NULL), - ), - 'node_filter_form' => array( - 'arguments' => array('form' => NULL), - 'file' => 'node.admin.inc', - ), - 'node_filters' => array( - 'arguments' => array('form' => NULL), - 'file' => 'node.admin.inc', - ), - 'node_admin_nodes' => array( - 'arguments' => array('form' => NULL), - 'file' => 'node.admin.inc', - ), - 'node_add_list' => array( - 'arguments' => array('content' => NULL), - 'file' => 'node.pages.inc', - ), - 'node_form' => array( - 'arguments' => array('form' => NULL), - 'file' => 'node.pages.inc', - ), - 'node_preview' => array( - 'arguments' => array('node' => NULL), - 'file' => 'node.pages.inc', - ), - 'node_log_message' => array( - 'arguments' => array('log' => NULL), - ), - 'node_submitted' => array( - 'arguments' => array('node' => NULL), - ), - 'node_admin_overview' => array( - 'arguments' => array('name' => NULL, 'type' => NULL), - ), - 'node_links' => array( - 'arguments' => array('element' => NULL), - ), - ); -} - -/** - * Implementation of hook_cron(). - */ -function node_cron() { - db_delete('history') - ->condition('timestamp', NODE_NEW_LIMIT, '<') - ->execute(); -} - -/** - * Implementation of hook_fieldable_info(). - */ -function node_fieldable_info() { - $return = array( - 'node' => array( - 'name' => t('Node'), - 'id key' => 'nid', - 'revision key' => 'vid', - 'bundle key' => 'type', - // Node.module handles its own caching. - // 'cacheable' => FALSE, - // Bundles must provide human readable name so - // we can create help and error messages about them. - 'bundles' => node_get_types('names'), - ), - ); - return $return; -} - - -/** - * Implementation of hook_field_build_modes(). - */ -function node_field_build_modes($obj_type) { - $modes = array(); - if ($obj_type == 'node') { - $modes = array( - 'teaser' => t('Teaser'), - 'full' => t('Full node'), - NODE_BUILD_RSS => t('RSS'), - NODE_BUILD_PRINT => t('Print'), - ); - if (module_exists('search')) { - $modes += array( - NODE_BUILD_SEARCH_INDEX => t('Search Index'), - NODE_BUILD_SEARCH_RESULT => t('Search Result'), - ); - } - } - return $modes; -} - -/** * Gather a listing of links to nodes. * * @param $result @@ -1406,50 +1257,6 @@ function theme_node_log_message($log) { } /** - * Implementation of hook_perm(). - */ -function node_perm() { - $perms = array( - 'administer content types' => array( - 'title' => t('Administer content types'), - 'description' => t('Manage content types and content type administration settings.'), - ), - 'administer nodes' => array( - 'title' => t('Administer nodes'), - 'description' => t('Manage all information associated with site content, such as author, publication date and current revision. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), - ), - 'access content' => array( - 'title' => t('Access content'), - 'description' => t('View published content.'), - ), - 'bypass node access' => array( - 'title' => t('Bypass node access'), - 'description' => t('View, edit and delete all site content. Users with this permission will bypass any content-related access control. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), - ), - 'view revisions' => array( - 'title' => t('View revisions'), - 'description' => t('View content revisions.'), - ), - 'revert revisions' => array( - 'title' => t('Revert revisions'), - 'description' => t('Replace content with an older revision.'), - ), - 'delete revisions' => array( - 'title' => t('Delete revisions'), - 'description' => t('Delete content revisions.'), - ), - ); - - foreach (node_get_types() as $type) { - if ($type->base == 'node_content') { - $perms += node_list_permissions($type); - } - } - - return $perms; -} - -/** * Gather the rankings from the the hook_ranking implementations. */ function _node_rankings() { @@ -1483,234 +1290,6 @@ function _node_rankings() { /** - * Implementation of hook_search(). - */ -function node_search($op = 'search', $keys = NULL) { - switch ($op) { - case 'name': - return t('Content'); - - case 'reset': - db_update('search_dataset') - ->fields(array('reindex' => REQUEST_TIME)) - ->condition('type', 'node') - ->execute(); - return; - - case 'status': - $total = db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')->fetchField(); - $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField(); - return array('remaining' => $remaining, 'total' => $total); - - case 'admin': - $form = array(); - // Output form for defining rank factor weights. - $form['content_ranking'] = array( - '#type' => 'fieldset', - '#title' => t('Content ranking'), - ); - $form['content_ranking']['#theme'] = 'node_search_admin'; - $form['content_ranking']['info'] = array( - '#value' => '' . t('The following numbers control which properties the content search should favor when ordering the results. Higher numbers mean more influence, zero means the property is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '' - ); - - // Note: reversed to reflect that higher number = higher ranking. - $options = drupal_map_assoc(range(0, 10)); - foreach (module_invoke_all('ranking') as $var => $values) { - $form['content_ranking']['factors']['node_rank_'. $var] = array( - '#title' => $values['title'], - '#type' => 'select', - '#options' => $options, - '#default_value' => variable_get('node_rank_'. $var, 0), - ); - } - return $form; - - case 'search': - // Build matching conditions - list($join1, $where1) = _db_rewrite_sql(); - $arguments1 = array(); - $conditions1 = 'n.status = 1'; - - if ($type = search_query_extract($keys, 'type')) { - $types = array(); - foreach (explode(',', $type) as $t) { - $types[] = "n.type = '%s'"; - $arguments1[] = $t; - } - $conditions1 .= ' AND (' . implode(' OR ', $types) . ')'; - $keys = search_query_insert($keys, 'type'); - } - - if ($term = search_query_extract($keys, 'term')) { - $terms = array(); - foreach (explode(',', $term) as $c) { - $terms[] = "tn.tid = %d"; - $arguments1[] = $c; - } - $conditions1 .= ' AND (' . implode(' OR ', $terms) . ')'; - $join1 .= ' INNER JOIN {taxonomy_term_node} tn ON n.vid = tn.vid'; - $keys = search_query_insert($keys, 'term'); - } - - if ($languages = search_query_extract($keys, 'language')) { - $terms = array(); - foreach (explode(',', $languages) as $l) { - $terms[] = "n.language = '%s'"; - $arguments1[] = $l; - } - $conditions1 .= ' AND (' . implode(' OR ', $terms) . ')'; - $keys = search_query_insert($keys, 'language'); - } - - // Get the ranking expressions. - $rankings = _node_rankings(); - - // When all search factors are disabled (ie they have a weight of zero), - // The default score is based only on keyword relevance. - if ($rankings['total'] == 0) { - $total = 1; - $arguments2 = array(); - $join2 = ''; - $select2 = 'SUM(i.relevance) AS calculated_score'; - } - else { - $total = $rankings['total']; - $arguments2 = $rankings['arguments']; - $join2 = implode(' ', $rankings['join']); - $select2 = 'SUM('. implode(' + ', $rankings['score']) .') AS calculated_score'; - } - - // Do search. - $find = do_search($keys, 'node', 'INNER JOIN {node} n ON n.nid = i.sid ' . $join1, $conditions1 . (empty($where1) ? '' : ' AND ' . $where1), $arguments1, $select2, $join2, $arguments2); - - // Load results. - $results = array(); - foreach ($find as $item) { - // Build the node body. - $node = node_load($item->sid); - $node->build_mode = NODE_BUILD_SEARCH_RESULT; - $node = node_build_content($node, FALSE, FALSE); - $node->body = drupal_render($node->content); - - // Fetch comments for snippet. - $node->body .= module_invoke('comment', 'node_update_index', $node); - // Fetch terms for snippet. - $node->body .= module_invoke('taxonomy', 'node_update_index', $node); - - $extra = module_invoke_all('node_search_result', $node); - - $results[] = array( - 'link' => url('node/' . $item->sid, array('absolute' => TRUE)), - 'type' => check_plain(node_get_types('name', $node)), - 'title' => $node->title, - 'user' => theme('username', $node), - 'date' => $node->changed, - 'node' => $node, - 'extra' => $extra, - 'score' => $total ? ($item->calculated_score / $total) : 0, - 'snippet' => search_excerpt($keys, $node->body), - ); - } - return $results; - } -} - -/** - * Implementation of hook_ranking(). - */ -function node_ranking() { - // Create the ranking array and add the basic ranking options. - $ranking = array( - 'relevance' => array( - 'title' => t('Keyword relevance'), - // Average relevance values hover around 0.15 - 'score' => 'i.relevance', - ), - 'sticky' => array( - 'title' => t('Content is sticky at top of lists'), - // The sticky flag is either 0 or 1, which is automatically normalized. - 'score' => 'n.sticky', - ), - 'promote' => array( - 'title' => t('Content is promoted to the front page'), - // The promote flag is either 0 or 1, which is automatically normalized. - 'score' => 'n.promote', - ), - ); - - // Add relevance based on creation or changed date. - if ($node_cron_last = variable_get('node_cron_last', 0)) { - $ranking['recent'] = array( - 'title' => t('Recently posted'), - // Exponential decay with half-life of 6 months, starting at last indexed node - 'score' => 'POW(2.0, (GREATEST(n.created, n.changed) - %d) * 6.43e-8)', - 'arguments' => array($node_cron_last), - ); - } - return $ranking; -} - -/** - * Implementation of hook_user_cancel(). - */ -function node_user_cancel($edit, $account, $method) { - switch ($method) { - case 'user_cancel_block_unpublish': - // Unpublish nodes (current revisions). - module_load_include('inc', 'node', 'node.admin'); - $nodes = db_select('node', 'n') - ->fields('n', array('nid')) - ->condition('uid', $account->uid) - ->execute() - ->fetchCol(); - node_mass_update($nodes, array('status' => 0)); - break; - - case 'user_cancel_reassign': - // Anonymize nodes (current revisions). - module_load_include('inc', 'node', 'node.admin'); - $nodes = db_select('node', 'n') - ->fields('n', array('nid')) - ->condition('uid', $account->uid) - ->execute() - ->fetchCol(); - node_mass_update($nodes, array('uid' => 0)); - // Anonymize old revisions. - db_update('node_revision') - ->fields(array('uid' => 0)) - ->condition('uid', $account->uid) - ->execute(); - // Clean history. - db_delete('history') - ->condition('uid', $account->uid) - ->execute(); - break; - - case 'user_cancel_delete': - // Delete nodes (current revisions). - // @todo Introduce node_mass_delete() or make node_mass_update() more flexible. - $nodes = db_select('node', 'n') - ->fields('n', array('nid')) - ->condition('uid', $account->uid) - ->execute() - ->fetchCol(); - foreach ($nodes as $nid) { - node_delete($nid); - } - // Delete old revisions. - db_delete('node_revision') - ->condition('uid', $account->uid) - ->execute(); - // Clean history. - db_delete('history') - ->condition('uid', $account->uid) - ->execute(); - break; - } -} - -/** * Theme the content ranking part of the search settings admin page. * * @ingroup themeable @@ -1791,174 +1370,6 @@ function _node_add_access() { } /** - * Implementation of hook_menu(). - */ -function node_menu() { - $items['admin/content/node'] = array( - 'title' => 'Content', - 'description' => "View, edit, and delete your site's content.", - 'page callback' => 'drupal_get_form', - 'page arguments' => array('node_admin_content'), - 'access arguments' => array('administer nodes'), - ); - - $items['admin/content/node/overview'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - - $items['admin/content/node-settings'] = array( - 'title' => 'Post settings', - 'description' => 'Control posting behavior, such as teaser length, requiring previews before posting, and the number of posts on the front page.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('node_configure'), - 'access arguments' => array('administer nodes'), - ); - $items['admin/content/node-settings/rebuild'] = array( - 'title' => 'Rebuild permissions', - 'page arguments' => array('node_configure_rebuild_confirm'), - // Any user than can potentially trigger a node_access_needs_rebuild(TRUE) - // has to be allowed access to the 'node access rebuild' confirm form. - 'access arguments' => array('access administration pages'), - 'type' => MENU_CALLBACK, - ); - - $items['admin/build/types'] = array( - 'title' => 'Content types', - 'description' => 'Manage posts by content type, including default status, front page promotion, comment settings, etc.', - 'page callback' => 'node_overview_types', - 'access arguments' => array('administer content types'), - ); - $items['admin/build/types/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['admin/build/types/add'] = array( - 'title' => 'Add content type', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('node_type_form'), - 'access arguments' => array('administer content types'), - 'type' => MENU_LOCAL_TASK, - ); - $items['node'] = array( - 'title' => 'Content', - 'page callback' => 'node_page_default', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['node/add'] = array( - 'title' => 'Create content', - 'page callback' => 'node_add_page', - 'access callback' => '_node_add_access', - 'weight' => 1, - 'menu_name' => 'management', - ); - $items['rss.xml'] = array( - 'title' => 'RSS feed', - 'page callback' => 'node_feed', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - foreach (node_get_types('types', NULL, TRUE) as $type) { - $type_url_str = str_replace('_', '-', $type->type); - $items['node/add/' . $type_url_str] = array( - 'title' => $type->name, - 'title callback' => 'check_plain', - 'page callback' => 'node_add', - 'page arguments' => array(2), - 'access callback' => 'node_access', - 'access arguments' => array('create', $type->type), - 'description' => $type->description, - ); - $items['admin/build/node-type/' . $type_url_str] = array( - 'title' => $type->name, - 'page callback' => 'drupal_get_form', - 'page arguments' => array('node_type_form', $type), - 'access arguments' => array('administer content types'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/node-type/' . $type_url_str . '/edit'] = array( - 'title' => 'Edit', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/build/node-type/' . $type_url_str . '/delete'] = array( - 'title' => 'Delete', - 'page arguments' => array('node_type_delete_confirm', $type), - 'access arguments' => array('administer content types'), - 'type' => MENU_CALLBACK, - ); - } - $items['node/%node'] = array( - 'title callback' => 'node_page_title', - 'title arguments' => array(1), - 'page callback' => 'node_page_view', - 'page arguments' => array(1), - 'access callback' => 'node_access', - 'access arguments' => array('view', 1), - 'type' => MENU_CALLBACK); - $items['node/%node/view'] = array( - 'title' => 'View', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10); - $items['node/%node/edit'] = array( - 'title' => 'Edit', - 'page callback' => 'node_page_edit', - 'page arguments' => array(1), - 'access callback' => 'node_access', - 'access arguments' => array('update', 1), - 'weight' => 1, - 'type' => MENU_LOCAL_TASK, - ); - $items['node/%node/delete'] = array( - 'title' => 'Delete', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('node_delete_confirm', 1), - 'access callback' => 'node_access', - 'access arguments' => array('delete', 1), - 'weight' => 1, - 'type' => MENU_CALLBACK); - $items['node/%node/revisions'] = array( - 'title' => 'Revisions', - 'page callback' => 'node_revision_overview', - 'page arguments' => array(1), - 'access callback' => '_node_revision_access', - 'access arguments' => array(1), - 'weight' => 2, - 'type' => MENU_LOCAL_TASK, - ); - $items['node/%node/revisions/%/view'] = array( - 'title' => 'Revisions', - 'load arguments' => array(3), - 'page callback' => 'node_show', - 'page arguments' => array(1, TRUE), - 'access callback' => '_node_revision_access', - 'access arguments' => array(1), - 'type' => MENU_CALLBACK, - ); - $items['node/%node/revisions/%/revert'] = array( - 'title' => 'Revert to earlier revision', - 'load arguments' => array(3), - 'page callback' => 'drupal_get_form', - 'page arguments' => array('node_revision_revert_confirm', 1), - 'access callback' => '_node_revision_access', - 'access arguments' => array(1, 'update'), - 'type' => MENU_CALLBACK, - ); - $items['node/%node/revisions/%/delete'] = array( - 'title' => 'Delete earlier revision', - 'load arguments' => array(3), - 'page callback' => 'drupal_get_form', - 'page arguments' => array('node_revision_delete_confirm', 1), - 'access callback' => '_node_revision_access', - 'access arguments' => array(1, 'delete'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** * Title callback. */ function node_page_title($node) { @@ -1990,16 +1401,6 @@ function node_revision_list($node) { } /** - * Implementation of hook_block_list(). - */ -function node_block_list() { - $blocks['syndicate']['info'] = t('Syndicate'); - // Not worth caching. - $blocks['syndicate']['cache'] = BLOCK_NO_CACHE; - return $blocks; -} - -/** * Implementation of hook_block_view(). */ function node_block_view($delta = '') { @@ -2113,53 +1514,6 @@ function node_build_multiple($nodes, $te } /** - * Menu callback; Generate a listing of promoted nodes. - */ -function node_page_default() { - $select = db_select('node', 'n') - ->fields('n', array('nid')) - ->condition('promote', 1) - ->condition('status', 1) - ->orderBy('sticky', 'DESC') - ->orderBy('created', 'DESC') - ->extend('PagerDefault') - ->limit(variable_get('default_nodes_main', 10)) - ->addTag('node_access'); - - $nids = $select->execute()->fetchCol(); - - if (!empty($nids)) { - $nodes = node_load_multiple($nids); - $build = node_build_multiple($nodes); - - $feed_url = url('rss.xml', array('absolute' => TRUE)); - drupal_add_feed($feed_url, variable_get('site_name', 'Drupal') . ' ' . t('RSS')); - $build['pager'] = array( - '#markup' => theme('pager', NULL), - '#weight' => 5, - ); - } - else { - $default_message = '' . t('Please follow these steps to set up and start using your website:') . '
'; - $default_message .= '' . t('For more information, please refer to the help section, or the online Drupal handbooks. You may also post at the Drupal forum, or view the wide range of other support options available.', array('@help' => url('admin/help'), '@handbook' => 'http://drupal.org/handbooks', '@forum' => 'http://drupal.org/forum', '@support' => 'http://drupal.org/support')) . '
'; - $build['default_message'] = array( - '#markup' => $default_message, - '#prefix' => '' . t('Please follow these steps to set up and start using your website:') . '
'; + $default_message .= '' . t('For more information, please refer to the help section, or the online Drupal handbooks. You may also post at the Drupal forum, or view the wide range of other support options available.', array('@help' => url('admin/help'), '@handbook' => 'http://drupal.org/handbooks', '@forum' => 'http://drupal.org/forum', '@support' => 'http://drupal.org/support')) . '
'; + $build['default_message'] = array( + '#markup' => $default_message, + '#prefix' => '' . t('To use OpenID you must first establish an identity on a public or private OpenID server. If you do not have an OpenID and would like one, look into one of the free public providers. You can find out more about OpenID at this website.', array('@openid-providers' => url('http://openid.net/get/'), '@openid-net' => url('http://openid.net'))) . '
'; + $output .= '' . t('If you already have an OpenID, enter the URL to your OpenID server below (e.g. myusername.openidprovider.com). Next time you login, you will be able to use this URL instead of a regular username and password. You can have multiple OpenID servers if you like; just keep adding them here.') . '
'; + return $output; + + case 'admin/help#openid': + $output = '' . t('OpenID is a secure method for logging into many websites with a single username and password. It does not require special software, and it does not share passwords with any site to which it is associated; including your site.') . '
'; + $output .= '' . t('Users can create accounts using their OpenID, assign one or more OpenIDs to an existing account, and log in using an OpenID. This lowers the barrier to registration, which is good for the site, and offers convenience and security to the users. OpenID is not a trust system, so email verification is still necessary. The benefit stems from the fact that users can have a single password that they can use on many websites. This means they can easily update their single password from a centralized location, rather than having to change dozens of passwords individually.') . '
'; + $output .= '' . t('The basic concept is as follows: A user has an account on an OpenID server. This account provides them with a unique URL (such as myusername.openidprovider.com). When the user comes to your site, they are presented with the option of entering this URL. Your site then communicates with the OpenID server, asking it to verify the identity of the user. If the user is logged into their OpenID server, the server communicates back to your site, verifying the user. If they are not logged in, the OpenID server will ask the user for their password. At no point does your site record, or need to record the user\'s password.') . '
'; + $output .= '' . t('More information on OpenID is available at OpenID.net.', array('@openid-net' => url('http://openid.net'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for OpenID module.', array('@handbook' => 'http://drupal.org/handbook/modules/openid')) . '
'; + return $output; + } +} + Index: modules/openid/openid.info =================================================================== RCS file: /cvs/drupal/drupal/modules/openid/openid.info,v retrieving revision 1.6 diff -u -p -r1.6 openid.info --- modules/openid/openid.info 11 Oct 2008 02:32:53 -0000 1.6 +++ modules/openid/openid.info 22 May 2009 23:43:46 -0000 @@ -9,3 +9,7 @@ files[] = openid.inc files[] = openid.pages.inc files[] = xrds.inc files[] = openid.install +files[] = openid.registry.inc +files[] = openid.user.inc +files[] = openid.form.inc +files[] = openid.help.inc Index: modules/openid/openid.module =================================================================== RCS file: /cvs/drupal/drupal/modules/openid/openid.module,v retrieving revision 1.45 diff -u -p -r1.45 openid.module --- modules/openid/openid.module 29 Apr 2009 07:29:59 -0000 1.45 +++ modules/openid/openid.module 22 May 2009 23:44:29 -0000 @@ -6,83 +6,6 @@ * Implement OpenID Relying Party support for Drupal */ -/** - * Implementation of hook_menu(). - */ -function openid_menu() { - $items['openid/authenticate'] = array( - 'title' => 'OpenID Login', - 'page callback' => 'openid_authentication_page', - 'access callback' => 'user_is_anonymous', - 'type' => MENU_CALLBACK, - ); - $items['user/%user/openid'] = array( - 'title' => 'OpenID identities', - 'page callback' => 'openid_user_identities', - 'page arguments' => array(1), - 'access callback' => 'user_edit_access', - 'access arguments' => array(1), - 'type' => MENU_LOCAL_TASK, - ); - $items['user/%user/openid/delete'] = array( - 'title' => 'Delete OpenID', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('openid_user_delete_form', 1), - 'access callback' => 'user_edit_access', - 'access arguments' => array(1), - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** - * Implementation of hook_help(). - */ -function openid_help($path, $arg) { - switch ($path) { - case 'user/%/openid': - $output = '' . t('This site supports OpenID, a secure way to log into many websites using a single username and password. OpenID can reduce the necessity of managing many usernames and passwords for many websites.', array('@openid-net' => url('http://openid.net'))) . '
'; - $output .= '' . t('To use OpenID you must first establish an identity on a public or private OpenID server. If you do not have an OpenID and would like one, look into one of the free public providers. You can find out more about OpenID at this website.', array('@openid-providers' => url('http://openid.net/get/'), '@openid-net' => url('http://openid.net'))) . '
'; - $output .= '' . t('If you already have an OpenID, enter the URL to your OpenID server below (e.g. myusername.openidprovider.com). Next time you login, you will be able to use this URL instead of a regular username and password. You can have multiple OpenID servers if you like; just keep adding them here.') . '
'; - return $output; - - case 'admin/help#openid': - $output = '' . t('OpenID is a secure method for logging into many websites with a single username and password. It does not require special software, and it does not share passwords with any site to which it is associated; including your site.') . '
'; - $output .= '' . t('Users can create accounts using their OpenID, assign one or more OpenIDs to an existing account, and log in using an OpenID. This lowers the barrier to registration, which is good for the site, and offers convenience and security to the users. OpenID is not a trust system, so email verification is still necessary. The benefit stems from the fact that users can have a single password that they can use on many websites. This means they can easily update their single password from a centralized location, rather than having to change dozens of passwords individually.') . '
'; - $output .= '' . t('The basic concept is as follows: A user has an account on an OpenID server. This account provides them with a unique URL (such as myusername.openidprovider.com). When the user comes to your site, they are presented with the option of entering this URL. Your site then communicates with the OpenID server, asking it to verify the identity of the user. If the user is logged into their OpenID server, the server communicates back to your site, verifying the user. If they are not logged in, the OpenID server will ask the user for their password. At no point does your site record, or need to record the user\'s password.') . '
'; - $output .= '' . t('More information on OpenID is available at OpenID.net.', array('@openid-net' => url('http://openid.net'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for OpenID module.', array('@handbook' => 'http://drupal.org/handbook/modules/openid')) . '
'; - return $output; - } -} - -/** - * Implementation of hook_user_insert(). - */ -function openid_user_insert(&$edit, &$account, $category = NULL) { - if (isset($_SESSION['openid']['values'])) { - // The user has registered after trying to login via OpenID. - if (variable_get('user_email_verification', TRUE)) { - drupal_set_message(t('Once you have verified your email address, you may log in via OpenID.')); - } - unset($_SESSION['openid']); - } -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function openid_form_user_login_block_alter(&$form, &$form_state) { - _openid_user_login_form_alter($form, $form_state); -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function openid_form_user_login_alter(&$form, &$form_state) { - _openid_user_login_form_alter($form, $form_state); -} - function _openid_user_login_form_alter(&$form, &$form_state) { drupal_add_css(drupal_get_path('module', 'openid') . '/openid.css'); drupal_add_js(drupal_get_path('module', 'openid') . '/openid.js'); @@ -122,37 +45,6 @@ function _openid_user_login_form_alter(& } /** - * Implementation of hook_form_alter(). Adds OpenID login to the login forms. - */ -function openid_form_user_register_alter(&$form, &$form_state) { - if (isset($_SESSION['openid']['values'])) { - // We were unable to auto-register a new user. Prefill the registration - // form with the values we have. - $form['name']['#default_value'] = $_SESSION['openid']['values']['name']; - $form['mail']['#default_value'] = $_SESSION['openid']['values']['mail']; - // If user_email_verification is off, hide the password field and just fill - // with random password to avoid confusion. - if (!variable_get('user_email_verification', TRUE)) { - $form['pass']['#type'] = 'hidden'; - $form['pass']['#value'] = user_password(); - } - $form['auth_openid'] = array('#type' => 'hidden', '#value' => $_SESSION['openid']['values']['auth_openid']); - } -} - -/** - * Login form _validate hook - */ -function openid_login_validate($form, &$form_state) { - $return_to = $form_state['values']['openid.return_to']; - if (empty($return_to)) { - $return_to = url('', array('absolute' => TRUE)); - } - - openid_begin($form_state['values']['openid_identifier'], $return_to, $form_state['values']); -} - -/** * The initial step of OpenID authentication responsible for the following: * - Perform discovery on the claimed OpenID. * - If possible, create an association with the Provider's endpoint. Index: modules/openid/openid.registry.inc =================================================================== RCS file: modules/openid/openid.registry.inc diff -N modules/openid/openid.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/openid/openid.registry.inc 22 May 2009 23:43:46 -0000 @@ -0,0 +1,37 @@ + 'OpenID Login', + 'page callback' => 'openid_authentication_page', + 'access callback' => 'user_is_anonymous', + 'type' => MENU_CALLBACK, + ); + $items['user/%user/openid'] = array( + 'title' => 'OpenID identities', + 'page callback' => 'openid_user_identities', + 'page arguments' => array(1), + 'access callback' => 'user_edit_access', + 'access arguments' => array(1), + 'type' => MENU_LOCAL_TASK, + ); + $items['user/%user/openid/delete'] = array( + 'title' => 'Delete OpenID', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('openid_user_delete_form', 1), + 'access callback' => 'user_edit_access', + 'access arguments' => array(1), + 'type' => MENU_CALLBACK, + ); + return $items; +} + Index: modules/openid/openid.user.inc =================================================================== RCS file: modules/openid/openid.user.inc diff -N modules/openid/openid.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/openid/openid.user.inc 22 May 2009 23:43:46 -0000 @@ -0,0 +1,21 @@ + 'XRDS service document', - 'page callback' => 'openid_test_yadis_xrds', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['openid-test/yadis/x-xrds-location'] = array( - 'title' => 'Yadis discovery using X-XRDS-Location header', - 'page callback' => 'openid_test_yadis_x_xrds_location', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['openid-test/yadis/http-equiv'] = array( - 'title' => 'Yadis discovery using ', - 'page callback' => 'openid_test_yadis_http_equiv', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['openid-test/html/openid1'] = array( - 'title' => 'HTML-based discovery using ', - 'page callback' => 'openid_test_html_openid1', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['openid-test/html/openid2'] = array( - 'title' => 'HTML-based discovery using ', - 'page callback' => 'openid_test_html_openid2', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['openid-test/endpoint'] = array( - 'title' => 'OpenID Provider Endpoint', - 'page callback' => 'openid_test_endpoint', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** * Menu callback; XRDS document that references the OP Endpoint URL. */ function openid_test_yadis_xrds() { Index: modules/openid/tests/openid_test.registry.inc =================================================================== RCS file: modules/openid/tests/openid_test.registry.inc diff -N modules/openid/tests/openid_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/openid/tests/openid_test.registry.inc 22 May 2009 23:43:45 -0000 @@ -0,0 +1,51 @@ + 'XRDS service document', + 'page callback' => 'openid_test_yadis_xrds', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + $items['openid-test/yadis/x-xrds-location'] = array( + 'title' => 'Yadis discovery using X-XRDS-Location header', + 'page callback' => 'openid_test_yadis_x_xrds_location', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + $items['openid-test/yadis/http-equiv'] = array( + 'title' => 'Yadis discovery using ', + 'page callback' => 'openid_test_yadis_http_equiv', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + $items['openid-test/html/openid1'] = array( + 'title' => 'HTML-based discovery using ', + 'page callback' => 'openid_test_html_openid1', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + $items['openid-test/html/openid2'] = array( + 'title' => 'HTML-based discovery using ', + 'page callback' => 'openid_test_html_openid2', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + $items['openid-test/endpoint'] = array( + 'title' => 'OpenID Provider Endpoint', + 'page callback' => 'openid_test_endpoint', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + return $items; +} + Index: modules/path/path.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/path/path.admin.inc,v retrieving revision 1.22 diff -u -p -r1.22 path.admin.inc --- modules/path/path.admin.inc 22 May 2009 11:33:17 -0000 1.22 +++ modules/path/path.admin.inc 22 May 2009 23:44:29 -0000 @@ -254,3 +254,13 @@ function path_admin_filter_get_keys() { $path = explode('/', $_GET['q'], 5); return count($path) == 5 ? $path[4] : ''; } +/** + * Post-confirmation; delete an URL alias. + */ +function path_admin_delete($pid = 0) { + db_delete('url_alias') + ->condition('pid', $pid) + ->execute(); + drupal_set_message(t('The alias has been deleted.')); +} + Index: modules/path/path.help.inc =================================================================== RCS file: modules/path/path.help.inc diff -N modules/path/path.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/path/path.help.inc 22 May 2009 23:43:45 -0000 @@ -0,0 +1,31 @@ +' . t('The path module allows you to specify aliases for Drupal URLs. Such aliases improve readability of URLs for your users and may help internet search engines to index your content more effectively. More than one alias may be created for a given page.') . ''; + $output .= '' . t('Some examples of URL aliases are:') . '
'; + $output .= '' . t('The path module enables appropriately permissioned users to specify an optional alias in all node input and editing forms, and provides an interface to view and edit all URL aliases. The two permissions related to URL aliasing are administer url aliases and create url aliases.') . '
'; + $output .= '' . t('This module also provides user-defined mass URL aliasing capabilities, which is useful if you wish to uniformly use URLs different from the default. For example, you may want to have your URLs presented in a different language. Access to the Drupal source code on the web server is required to set up mass URL aliasing.') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Path module.', array('@path' => 'http://drupal.org/handbook/modules/path/')) . '
'; + return $output; + case 'admin/build/path': + return '' . t("Drupal provides complete control over URLs through aliasing, which is often used to make URLs more readable or easy to remember. For example, the alias 'about' may be mapped onto the post at the system path 'node/1', creating a more meaningful URL. Each system path can have multiple aliases.") . '
'; + case 'admin/build/path/add': + return '' . t('Enter the path you wish to create the alias for, followed by the name of the new alias.') . '
'; + } +} + Index: modules/path/path.info =================================================================== RCS file: /cvs/drupal/drupal/modules/path/path.info,v retrieving revision 1.7 diff -u -p -r1.7 path.info --- modules/path/path.info 11 Oct 2008 02:32:54 -0000 1.7 +++ modules/path/path.info 22 May 2009 23:43:45 -0000 @@ -6,3 +6,7 @@ version = VERSION core = 7.x files[] = path.module files[] = path.admin.inc +files[] = path.registry.inc +files[] = path.user.inc +files[] = path.node.inc +files[] = path.help.inc Index: modules/path/path.module =================================================================== RCS file: /cvs/drupal/drupal/modules/path/path.module,v retrieving revision 1.157 diff -u -p -r1.157 path.module --- modules/path/path.module 10 May 2009 16:50:19 -0000 1.157 +++ modules/path/path.module 22 May 2009 23:44:29 -0000 @@ -7,77 +7,6 @@ */ /** - * Implementation of hook_help(). - */ -function path_help($path, $arg) { - switch ($path) { - case 'admin/help#path': - $output = '' . t('The path module allows you to specify aliases for Drupal URLs. Such aliases improve readability of URLs for your users and may help internet search engines to index your content more effectively. More than one alias may be created for a given page.') . '
'; - $output .= '' . t('Some examples of URL aliases are:') . '
'; - $output .= '' . t('The path module enables appropriately permissioned users to specify an optional alias in all node input and editing forms, and provides an interface to view and edit all URL aliases. The two permissions related to URL aliasing are administer url aliases and create url aliases.') . '
'; - $output .= '' . t('This module also provides user-defined mass URL aliasing capabilities, which is useful if you wish to uniformly use URLs different from the default. For example, you may want to have your URLs presented in a different language. Access to the Drupal source code on the web server is required to set up mass URL aliasing.') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Path module.', array('@path' => 'http://drupal.org/handbook/modules/path/')) . '
'; - return $output; - case 'admin/build/path': - return '' . t("Drupal provides complete control over URLs through aliasing, which is often used to make URLs more readable or easy to remember. For example, the alias 'about' may be mapped onto the post at the system path 'node/1', creating a more meaningful URL. Each system path can have multiple aliases.") . '
'; - case 'admin/build/path/add': - return '' . t('Enter the path you wish to create the alias for, followed by the name of the new alias.') . '
'; - } -} - -/** - * Implementation of hook_menu(). - */ -function path_menu() { - $items['admin/build/path'] = array( - 'title' => 'URL aliases', - 'description' => "Change your site's URL paths by aliasing them.", - 'page callback' => 'path_admin_overview', - 'access arguments' => array('administer url aliases'), - ); - $items['admin/build/path/edit'] = array( - 'title' => 'Edit alias', - 'page callback' => 'path_admin_edit', - 'access arguments' => array('administer url aliases'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/path/delete'] = array( - 'title' => 'Delete alias', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('path_admin_delete_confirm'), - 'access arguments' => array('administer url aliases'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/path/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['admin/build/path/add'] = array( - 'title' => 'Add alias', - 'page callback' => 'path_admin_edit', - 'access arguments' => array('administer url aliases'), - 'type' => MENU_LOCAL_TASK, - ); - - return $items; -} - -/** - * Post-confirmation; delete an URL alias. - */ -function path_admin_delete($pid = 0) { - db_delete('url_alias') - ->condition('pid', $pid) - ->execute(); - drupal_set_message(t('The alias has been deleted.')); -} - -/** * Set an aliased path for a given Drupal path, preventing duplicates. */ function path_set_alias($path = NULL, $alias = NULL, $pid = NULL, $language = '') { @@ -145,28 +74,6 @@ function path_set_alias($path = NULL, $a } /** - * Implementation of hook_node_validate(). - */ -function path_node_validate($node, $form) { - if (user_access('create url aliases') || user_access('administer url aliases')) { - if (isset($node->path)) { - $language = isset($node->language) ? $node->language : ''; - $node->path = trim($node->path); - $has_alias = db_query("SELECT COUNT(dst) FROM {url_alias} WHERE src <> :src AND dst = :dst AND language = :language", array( - ':src' => "node/$node->nid", - ':dst' => $node->path, - ':language' => $language, - )) - ->fetchField(); - - if ($has_alias) { - form_set_error('path', t('The path is already in use.')); - } - } - } -} - -/** * Implementation of hook_node_load(). */ function path_node_load($nodes, $types) { @@ -181,43 +88,6 @@ function path_node_load($nodes, $types) } /** - * Implementation of hook_node_insert(). - */ -function path_node_insert($node) { - if (user_access('create url aliases') || user_access('administer url aliases')) { - $language = isset($node->language) ? $node->language : ''; - // Don't try to insert if path is NULL. We may have already set - // the alias ahead of time. - if (isset($node->path)) { - path_set_alias('node/' . $node->nid, $node->path, NULL, $language); - } - } -} - -/** - * Implementation of hook_node_update(). - */ -function path_node_update($node) { - if (user_access('create url aliases') || user_access('administer url aliases')) { - $language = isset($node->language) ? $node->language : ''; - path_set_alias('node/' . $node->nid, isset($node->path) ? $node->path : NULL, isset($node->pid) ? $node->pid : NULL, $language); - } -} - -/** - * Implementation of hook_node_delete(). - */ -function path_node_delete($node) { - if (user_access('create url aliases') || user_access('administer url aliases')) { - $language = isset($node->language) ? $node->language : ''; - $path = 'node/' . $node->nid; - if (drupal_get_path_alias($path) != $path) { - path_set_alias($path); - } - } -} - -/** * Implementation of hook_form_alter(). */ function path_form_alter(&$form, $form_state, $form_id) { @@ -256,22 +126,6 @@ function path_form_alter(&$form, $form_s } /** - * Implementation of hook_perm(). - */ -function path_perm() { - return array( - 'administer url aliases' => array( - 'title' => t('Administer URL aliases'), - 'description' => t('Manage URL aliases across the entire website.'), - ), - 'create url aliases' => array( - 'title' => t('Create URL aliases'), - 'description' => t('Manage URL aliases on content.'), - ), - ); -} - -/** * Fetch a specific URL alias from the database. */ function path_load($pid) { Index: modules/path/path.node.inc =================================================================== RCS file: modules/path/path.node.inc diff -N modules/path/path.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/path/path.node.inc 22 May 2009 23:43:45 -0000 @@ -0,0 +1,67 @@ +path)) { + $language = isset($node->language) ? $node->language : ''; + $node->path = trim($node->path); + $has_alias = db_query("SELECT COUNT(dst) FROM {url_alias} WHERE src <> :src AND dst = :dst AND language = :language", array( + ':src' => "node/$node->nid", + ':dst' => $node->path, + ':language' => $language, + )) + ->fetchField(); + + if ($has_alias) { + form_set_error('path', t('The path is already in use.')); + } + } + } +} + +/** + * Implementation of hook_node_insert(). + */ +function path_node_insert($node) { + if (user_access('create url aliases') || user_access('administer url aliases')) { + $language = isset($node->language) ? $node->language : ''; + // Don't try to insert if path is NULL. We may have already set + // the alias ahead of time. + if (isset($node->path)) { + path_set_alias('node/' . $node->nid, $node->path, NULL, $language); + } + } +} + +/** + * Implementation of hook_node_update(). + */ +function path_node_update($node) { + if (user_access('create url aliases') || user_access('administer url aliases')) { + $language = isset($node->language) ? $node->language : ''; + path_set_alias('node/' . $node->nid, isset($node->path) ? $node->path : NULL, isset($node->pid) ? $node->pid : NULL, $language); + } +} + +/** + * Implementation of hook_node_delete(). + */ +function path_node_delete($node) { + if (user_access('create url aliases') || user_access('administer url aliases')) { + $language = isset($node->language) ? $node->language : ''; + $path = 'node/' . $node->nid; + if (drupal_get_path_alias($path) != $path) { + path_set_alias($path); + } + } +} + Index: modules/path/path.registry.inc =================================================================== RCS file: modules/path/path.registry.inc diff -N modules/path/path.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/path/path.registry.inc 22 May 2009 23:43:45 -0000 @@ -0,0 +1,46 @@ + 'URL aliases', + 'description' => "Change your site's URL paths by aliasing them.", + 'page callback' => 'path_admin_overview', + 'access arguments' => array('administer url aliases'), + ); + $items['admin/build/path/edit'] = array( + 'title' => 'Edit alias', + 'page callback' => 'path_admin_edit', + 'access arguments' => array('administer url aliases'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/path/delete'] = array( + 'title' => 'Delete alias', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('path_admin_delete_confirm'), + 'access arguments' => array('administer url aliases'), + 'type' => MENU_CALLBACK, + ); + $items['admin/build/path/list'] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + $items['admin/build/path/add'] = array( + 'title' => 'Add alias', + 'page callback' => 'path_admin_edit', + 'access arguments' => array('administer url aliases'), + 'type' => MENU_LOCAL_TASK, + ); + + return $items; +} + Index: modules/path/path.user.inc =================================================================== RCS file: modules/path/path.user.inc diff -N modules/path/path.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/path/path.user.inc 22 May 2009 23:43:45 -0000 @@ -0,0 +1,24 @@ + array( + 'title' => t('Administer URL aliases'), + 'description' => t('Manage URL aliases across the entire website.'), + ), + 'create url aliases' => array( + 'title' => t('Create URL aliases'), + 'description' => t('Manage URL aliases on content.'), + ), + ); +} + Index: modules/php/php.help.inc =================================================================== RCS file: modules/php/php.help.inc diff -N modules/php/php.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/php/php.help.inc 22 May 2009 23:43:44 -0000 @@ -0,0 +1,22 @@ +' . t('The PHP filter adds the ability to include PHP code in posts. PHP is a general-purpose scripting language widely-used for web development; the content management system used by this website has been developed using PHP.') . ''; + $output .= '' . t('Through the PHP filter, users with the proper permission may include custom PHP code within a page of the site. While this is a powerful and flexible feature if used by a trusted user with PHP experience, it is a significant and dangerous security risk in the hands of a malicious user. Even a trusted user may accidentally compromise the site by entering malformed or incorrect PHP code. Only the most trusted users should be granted permission to use the PHP filter, and all PHP code added through the PHP filter should be carefully examined before use.') . '
'; + $output .= '' . t('Drupal.org offers some example PHP snippets, or you can create your own with some PHP experience and knowledge of the Drupal system.', array('@drupal' => url('http://drupal.org'), '@php-snippets' => url('http://drupal.org/handbook/customization/php-snippets'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for PHP module.', array('@php' => 'http://drupal.org/handbook/modules/php/')) . '
'; + return $output; + } +} + Index: modules/php/php.info =================================================================== RCS file: /cvs/drupal/drupal/modules/php/php.info,v retrieving revision 1.6 diff -u -p -r1.6 php.info --- modules/php/php.info 11 Oct 2008 02:32:56 -0000 1.6 +++ modules/php/php.info 22 May 2009 23:43:44 -0000 @@ -6,3 +6,5 @@ version = VERSION core = 7.x files[] = php.module files[] = php.install +files[] = php.user.inc +files[] = php.help.inc Index: modules/php/php.module =================================================================== RCS file: /cvs/drupal/drupal/modules/php/php.module,v retrieving revision 1.13 diff -u -p -r1.13 php.module --- modules/php/php.module 7 May 2009 15:29:08 -0000 1.13 +++ modules/php/php.module 22 May 2009 23:43:44 -0000 @@ -8,32 +8,6 @@ /** - * Implementation of hook_help(). - */ -function php_help($path, $arg) { - switch ($path) { - case 'admin/help#php': - $output = '' . t('The PHP filter adds the ability to include PHP code in posts. PHP is a general-purpose scripting language widely-used for web development; the content management system used by this website has been developed using PHP.') . '
'; - $output .= '' . t('Through the PHP filter, users with the proper permission may include custom PHP code within a page of the site. While this is a powerful and flexible feature if used by a trusted user with PHP experience, it is a significant and dangerous security risk in the hands of a malicious user. Even a trusted user may accidentally compromise the site by entering malformed or incorrect PHP code. Only the most trusted users should be granted permission to use the PHP filter, and all PHP code added through the PHP filter should be carefully examined before use.') . '
'; - $output .= '' . t('Drupal.org offers some example PHP snippets, or you can create your own with some PHP experience and knowledge of the Drupal system.', array('@drupal' => url('http://drupal.org'), '@php-snippets' => url('http://drupal.org/handbook/customization/php-snippets'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for PHP module.', array('@php' => 'http://drupal.org/handbook/modules/php/')) . '
'; - return $output; - } -} - -/** - * Implementation of hook_perm(). - */ -function php_perm() { - return array( - 'use PHP for settings' => array( - 'title' => t('Use PHP for settings'), - 'description' => t('Enter PHP in settings fields where PHP is allowed. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), - ), - ); -} - -/** * Evaluate a string of PHP code. * * This is a wrapper around PHP's eval(). It uses output buffering to capture both Index: modules/php/php.user.inc =================================================================== RCS file: modules/php/php.user.inc diff -N modules/php/php.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/php/php.user.inc 22 May 2009 23:43:44 -0000 @@ -0,0 +1,20 @@ + array( + 'title' => t('Use PHP for settings'), + 'description' => t('Enter PHP in settings fields where PHP is allowed. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), + ), + ); +} + Index: modules/poll/poll.block.inc =================================================================== RCS file: modules/poll/poll.block.inc diff -N modules/poll/poll.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/poll/poll.block.inc 22 May 2009 23:43:43 -0000 @@ -0,0 +1,18 @@ + :runtime', array(':request_time' => REQUEST_TIME, ':active' => 1, ':runtime' => 0))->fetchCol(); + if (!empty($nids)) { + db_update('poll') + ->fields(array('active' => 0)) + ->condition('nid', $nids, 'IN') + ->execute(); + } +} + Index: modules/poll/poll.form.inc =================================================================== RCS file: modules/poll/poll.form.inc diff -N modules/poll/poll.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/poll/poll.form.inc 22 May 2009 23:44:30 -0000 @@ -0,0 +1,125 @@ +choice) { + $list = array(); + foreach ($node->choice as $i => $choice) { + $list[$i] = check_plain($choice['chtext']); + } + $form['choice'] = array( + '#type' => 'radios', + '#default_value' => -1, + '#options' => $list, + ); + } + + $form['vote'] = array( + '#type' => 'submit', + '#value' => t('Vote'), + '#submit' => array('poll_vote'), + ); + + // Store the node so we can get to it in submit functions. + $form['#node'] = $node; + $form['#block'] = $block; + + // Set form caching because we could have multiple of these forms on + // the same page, and we want to ensure the right one gets picked. + $form['#cache'] = TRUE; + + // Provide a more cleanly named voting form theme. + $form['#theme'] = 'poll_vote'; + return $form; +} + +/** + * Validation function for processing votes + */ +function poll_view_voting_validate($form, &$form_state) { + if ($form_state['values']['choice'] == -1) { + form_set_error( 'choice', t('Your vote could not be recorded because you did not select any of the choices.')); + } +} + +/** + * Submit handler for processing a vote + */ +function poll_vote($form, &$form_state) { + $node = $form['#node']; + $choice = $form_state['values']['choice']; + + global $user; + db_insert('poll_vote') + ->fields(array( + 'nid' => $node->nid, + 'chid' => $choice, + 'uid' => $user->uid, + 'hostname' => $user->uid ? ip_address() : '', + )) + ->execute(); + + // Add one to the votes. + db_update('poll_choice') + ->expression('chvotes', 'chvotes + 1') + ->condition('chid', $choice) + ->execute(); + + cache_clear_all(); + drupal_set_message(t('Your vote was recorded.')); + + // Return the user to whatever page they voted from. +} + +/** + * Builds the cancel form for a poll. + * + * @ingroup forms + * @see poll_cancel() + */ +function poll_cancel_form(&$form_state, $nid) { + // Store the nid so we can get to it in submit functions. + $form['#nid'] = $nid; + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Cancel your vote'), + '#submit' => array('poll_cancel') + ); + + $form['#cache'] = TRUE; + + return $form; +} + +/** + * Submit callback for poll_cancel_form + */ +function poll_cancel($form, &$form_state) { + global $user; + $node = node_load($form['#nid']); + + db_delete('poll_vote') + ->condition('nid', $node->nid) + ->condition($user->uid ? 'uid' : 'hostname', $user->uid ? $user->uid : ip_address()) + ->execute(); + + // Subtract from the votes. + db_update('poll_choice') + ->expression('chvotes', 'chvotes - 1') + ->condition('chid', $node->vote) + ->execute(); +} + Index: modules/poll/poll.help.inc =================================================================== RCS file: modules/poll/poll.help.inc diff -N modules/poll/poll.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/poll/poll.help.inc 22 May 2009 23:43:44 -0000 @@ -0,0 +1,21 @@ +' . t('The poll module can be used to create simple polls for site users. A poll is a simple, multiple choice questionnaire which displays the cumulative results of the answers to the poll. Having polls on the site is a good way to receive feedback from community members.') . ''; + $output .= '' . t('When creating a poll, enter the question being posed, as well as the potential choices (and beginning vote counts for each choice). The status and duration (length of time the poll remains active for new votes) can also be specified. Use the poll menu item to view all current polls. To vote in or view the results of a specific poll, click on the poll itself.', array('@poll' => url('poll'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Poll module.', array('@poll' => 'http://drupal.org/handbook/modules/poll/')) . '
'; + return $output; + } +} + Index: modules/poll/poll.info =================================================================== RCS file: /cvs/drupal/drupal/modules/poll/poll.info,v retrieving revision 1.8 diff -u -p -r1.8 poll.info --- modules/poll/poll.info 11 Oct 2008 02:32:57 -0000 1.8 +++ modules/poll/poll.info 22 May 2009 23:44:30 -0000 @@ -7,3 +7,10 @@ core = 7.x files[] = poll.module files[] = poll.pages.inc files[] = poll.install +files[] = poll.registry.inc +files[] = poll.user.inc +files[] = poll.block.inc +files[] = poll.node.inc +files[] = poll.cron.inc +files[] = poll.help.inc +files[] = poll.form.inc Index: modules/poll/poll.module =================================================================== RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v retrieving revision 1.294 diff -u -p -r1.294 poll.module --- modules/poll/poll.module 12 May 2009 08:37:45 -0000 1.294 +++ modules/poll/poll.module 22 May 2009 23:44:30 -0000 @@ -8,19 +8,6 @@ */ /** - * Implementation of hook_help(). - */ -function poll_help($path, $arg) { - switch ($path) { - case 'admin/help#poll': - $output = '' . t('The poll module can be used to create simple polls for site users. A poll is a simple, multiple choice questionnaire which displays the cumulative results of the answers to the poll. Having polls on the site is a good way to receive feedback from community members.') . '
'; - $output .= '' . t('When creating a poll, enter the question being posed, as well as the potential choices (and beginning vote counts for each choice). The status and duration (length of time the poll remains active for new votes) can also be specified. Use the poll menu item to view all current polls. To vote in or view the results of a specific poll, click on the poll itself.', array('@poll' => url('poll'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Poll module.', array('@poll' => 'http://drupal.org/handbook/modules/poll/')) . '
'; - return $output; - } -} - -/** * Implementation of hook_init(). */ function poll_init() { @@ -28,52 +15,6 @@ function poll_init() { } /** - * Implementation of hook_theme(). - */ -function poll_theme() { - return array( - 'poll_vote' => array( - 'template' => 'poll-vote', - 'arguments' => array('form' => NULL), - ), - 'poll_choices' => array( - 'arguments' => array('form' => NULL), - ), - 'poll_results' => array( - 'template' => 'poll-results', - 'arguments' => array('raw_title' => NULL, 'results' => NULL, 'votes' => NULL, 'raw_links' => NULL, 'block' => NULL, 'nid' => NULL, 'vote' => NULL), - ), - 'poll_bar' => array( - 'template' => 'poll-bar', - 'arguments' => array('title' => NULL, 'votes' => NULL, 'total_votes' => NULL, 'vote' => NULL, 'block' => NULL), - ), - ); -} - -/** - * Implementation of hook_perm(). - */ -function poll_perm() { - $perms = node_list_permissions('poll'); - $perms += array( - 'vote on polls' => array( - 'title' => t('Vote on polls'), - 'description' => t('Cast votes on polls.'), - ), - 'cancel own vote' => array( - 'title' => t('Cancel own vote'), - 'description' => t('Retract and optionally change own votes.'), - ), - 'inspect all votes' => array( - 'title' => t('Inspect all votes'), - 'description' => t('View voting results.'), - ), - ); - - return $perms; -} - -/** * Implementation of hook_access(). */ function poll_access($op, $node, $account) { @@ -88,40 +29,6 @@ function poll_access($op, $node, $accoun } /** - * Implementation of hook_menu(). - */ -function poll_menu() { - $items['poll'] = array( - 'title' => 'Polls', - 'page callback' => 'poll_page', - 'access arguments' => array('access content'), - 'type' => MENU_SUGGESTED_ITEM, - ); - - $items['node/%node/votes'] = array( - 'title' => 'Votes', - 'page callback' => 'poll_votes', - 'page arguments' => array(1), - 'access callback' => '_poll_menu_access', - 'access arguments' => array(1, 'inspect all votes', FALSE), - 'weight' => 3, - 'type' => MENU_LOCAL_TASK, - ); - - $items['node/%node/results'] = array( - 'title' => 'Results', - 'page callback' => 'poll_results', - 'page arguments' => array(1), - 'access callback' => '_poll_menu_access', - 'access arguments' => array(1, 'access content', TRUE), - 'weight' => 3, - 'type' => MENU_LOCAL_TASK, - ); - - return $items; -} - -/** * Callback function to see if a node is acceptable for poll menu items. */ function _poll_menu_access($node, $perm, $inspect_allowvotes) { @@ -129,16 +36,6 @@ function _poll_menu_access($node, $perm, } /** - * Implementation of hook_block_list(). - */ -function poll_block_list() { - if (user_access('access content')) { - $blocks['recent']['info'] = t('Most recent poll'); - return $blocks; - } -} - -/** * Implementation of hook_block_view(). * * Generates a block containing the latest poll. @@ -168,163 +65,6 @@ function poll_block_view($delta = '') { } } -/** - * Implementation of hook_cron(). - * - * Closes polls that have exceeded their allowed runtime. - */ -function poll_cron() { - $nids = db_query('SELECT p.nid FROM {poll} p INNER JOIN {node} n ON p.nid = n.nid WHERE (n.created + p.runtime) < :request_time AND p.active = :active AND p.runtime <> :runtime', array(':request_time' => REQUEST_TIME, ':active' => 1, ':runtime' => 0))->fetchCol(); - if (!empty($nids)) { - db_update('poll') - ->fields(array('active' => 0)) - ->condition('nid', $nids, 'IN') - ->execute(); - } -} - -/** - * Implementation of hook_node_info(). - */ -function poll_node_info() { - return array( - 'poll' => array( - 'name' => t('Poll'), - 'base' => 'poll', - 'description' => t('A poll is a question with a set of possible responses. A poll, once created, automatically provides a simple running count of the number of votes received for each response.'), - 'title_label' => t('Question'), - 'has_body' => FALSE, - ) - ); -} - -/** - * Implementation of hook_form(). - */ -function poll_form($node, $form_state) { - global $user; - - $admin = user_access('administer nodes') || user_access('edit any poll content') || (user_access('edit own poll content') && $user->uid == $node->uid); - - $type = node_get_types('type', $node); - - $form = array( - '#cache' => TRUE, - ); - - $form['title'] = array( - '#type' => 'textfield', - '#title' => check_plain($type->title_label), - '#required' => TRUE, - '#default_value' => $node->title, - '#weight' => -5, - ); - - if (isset($form_state['choice_count'])) { - $choice_count = $form_state['choice_count']; - } - else { - $choice_count = max(2, empty($node->choice) ? 2 : count($node->choice)); - } - - // Add a wrapper for the choices and more button. - $form['choice_wrapper'] = array( - '#tree' => FALSE, - '#weight' => -4, - '#prefix' => '' . t('The following types of fields can be added to a user profile:') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Profile module.', array('@profile' => 'http://drupal.org/handbook/modules/profile/')) . '
'; + return $output; + case 'admin/user/profile': + return '' . t("This page displays a list of the existing custom profile fields to be displayed on a user's My Account page. To provide structure, similar or related fields may be placed inside a category. To add a new category (or edit an existing one), edit a profile field and provide a new category name. To change the category of a field or the order of fields within a category, grab a drag-and-drop handle under the Title column and drag the field to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.") . '
'; + } +} + Index: modules/profile/profile.info =================================================================== RCS file: /cvs/drupal/drupal/modules/profile/profile.info,v retrieving revision 1.8 diff -u -p -r1.8 profile.info --- modules/profile/profile.info 11 Oct 2008 02:32:59 -0000 1.8 +++ modules/profile/profile.info 22 May 2009 23:43:42 -0000 @@ -8,3 +8,7 @@ files[] = profile.module files[] = profile.admin.inc files[] = profile.pages.inc files[] = profile.install +files[] = profile.registry.inc +files[] = profile.user.inc +files[] = profile.block.inc +files[] = profile.help.inc Index: modules/profile/profile.module =================================================================== RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v retrieving revision 1.255 diff -u -p -r1.255 profile.module --- modules/profile/profile.module 21 May 2009 23:07:15 -0000 1.255 +++ modules/profile/profile.module 22 May 2009 23:44:31 -0000 @@ -27,142 +27,6 @@ define('PROFILE_PUBLIC_LISTINGS', 3); define('PROFILE_HIDDEN', 4); /** - * Implementation of hook_help(). - */ -function profile_help($path, $arg) { - switch ($path) { - case 'admin/help#profile': - $output = '' . t('The profile module allows custom fields (such as country, full name, or age) to be defined and displayed in the My Account section. This permits users of a site to share more information about themselves, and can help community-based sites organize users around specific information.') . '
'; - $output .= '' . t('The following types of fields can be added to a user profile:') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Profile module.', array('@profile' => 'http://drupal.org/handbook/modules/profile/')) . '
'; - return $output; - case 'admin/user/profile': - return '' . t("This page displays a list of the existing custom profile fields to be displayed on a user's My Account page. To provide structure, similar or related fields may be placed inside a category. To add a new category (or edit an existing one), edit a profile field and provide a new category name. To change the category of a field or the order of fields within a category, grab a drag-and-drop handle under the Title column and drag the field to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save configuration button at the bottom of the page.") . '
'; - } -} - -/** - * Implementation of hook_theme(). - */ -function profile_theme() { - return array( - 'profile_block' => array( - 'arguments' => array('account' => NULL, 'fields' => array()), - 'template' => 'profile-block', - ), - 'profile_listing' => array( - 'arguments' => array('account' => NULL, 'fields' => array()), - 'template' => 'profile-listing', - ), - 'profile_wrapper' => array( - 'arguments' => array('content' => NULL), - 'template' => 'profile-wrapper', - ), - 'profile_admin_overview' => array( - 'arguments' => array('form' => NULL), - 'file' => 'profile.admin.inc', - ) - ); -} - -/** - * Implementation of hook_menu(). - */ -function profile_menu() { - $items['profile'] = array( - 'title' => 'User list', - 'page callback' => 'profile_browse', - 'access arguments' => array('access user profiles'), - 'type' => MENU_SUGGESTED_ITEM, - ); - $items['admin/user/profile'] = array( - 'title' => 'Profiles', - 'description' => 'Create customizable fields for your users.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('profile_admin_overview'), - 'access arguments' => array('administer users'), - ); - $items['admin/user/profile/add'] = array( - 'title' => 'Add field', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('profile_field_form'), - 'access arguments' => array('administer users'), - 'type' => MENU_CALLBACK, - ); - $items['admin/user/profile/autocomplete'] = array( - 'title' => 'Profile category autocomplete', - 'page callback' => 'profile_admin_settings_autocomplete', - 'access arguments' => array('administer users'), - 'type' => MENU_CALLBACK, - ); - $items['admin/user/profile/edit'] = array( - 'title' => 'Edit field', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('profile_field_form'), - 'access arguments' => array('administer users'), - 'type' => MENU_CALLBACK, - ); - $items['admin/user/profile/delete'] = array( - 'title' => 'Delete field', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('profile_field_delete'), - 'access arguments' => array('administer users'), - 'type' => MENU_CALLBACK, - ); - $items['profile/autocomplete'] = array( - 'title' => 'Profile autocomplete', - 'page callback' => 'profile_autocomplete', - 'access arguments' => array('access user profiles'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** - * Implementation of hook_block_list(). - */ -function profile_block_list() { - $blocks['author-information']['info'] = t('Author information'); - $blocks['author-information']['cache'] = BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_ROLE; - return $blocks; -} - -/** - * Implementation of hook_block_configure(). - */ -function profile_block_configure($delta = '') { - // Compile a list of fields to show - $fields = array(); - $result = db_query('SELECT name, title, weight, visibility FROM {profile_field} WHERE visibility IN (%d, %d) ORDER BY weight', PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS); - while ($record = db_fetch_object($result)) { - $fields[$record->name] = check_plain($record->title); - } - $fields['user_profile'] = t('Link to full user profile'); - $form['profile_block_author_fields'] = array( - '#type' => 'checkboxes', - '#title' => t('Profile fields to display'), - '#default_value' => variable_get('profile_block_author_fields', array()), - '#options' => $fields, - '#description' => t('Select which profile fields you wish to display in the block. Only fields designated as public in the profile field configuration are available.', array('@profile-admin' => url('admin/user/profile'))), - ); - return $form; -} - -/** - * Implementation of hook_block_save(). - */ -function profile_block_save($delta = '', $edit = array()) { - variable_set('profile_block_author_fields', $edit['profile_block_author_fields']); -} - -/** * Implementation of hook_block_view(). */ function profile_block_view($delta = '') { @@ -203,27 +67,6 @@ function profile_block_view($delta = '') } /** - * Implementation of hook_user_register(). - */ -function profile_user_register(&$edit, &$user, $category = NULL) { - return profile_form_profile($edit, $user, $category, TRUE); -} - -/** - * Implementation of hook_user_update(). - */ -function profile_user_update(&$edit, &$user, $category = NULL) { - return profile_save_profile($edit, $user, $category); -} - -/** - * Implementation of hook_user_insert(). - */ -function profile_user_insert(&$edit, &$user, $category = NULL) { - return profile_save_profile($edit, $user, $category, TRUE); -} - -/** * Implementation of hook_user_view(). */ function profile_user_view(&$edit, &$user, $category = NULL) { @@ -231,39 +74,6 @@ function profile_user_view(&$edit, &$use } /** - * Implementation of hook_user_form(). - */ -function profile_user_form(&$edit, &$user, $category = NULL) { - return profile_form_profile($edit, $user, $category); -} - -/** - * Implementation of hook_user_validate(). - */ -function profile_user_validate(&$edit, &$user, $category = NULL) { - return profile_validate_profile($edit, $category); -} - -/** - * Implementation of hook_user_categories(). - */ -function profile_user_categories($edit, $user, $category = NULL) { - return profile_categories(); -} - -/** - * Implementation of hook_user_cancel(). - */ -function profile_user_cancel(&$edit, &$account, $method) { - switch ($method) { - case 'user_cancel_reassign': - case 'user_cancel_delete': - db_delete('profile_value')->condition('uid', $account->uid)->execute(); - break; - } -} - -/** * Implementation of hook_user_load(). */ function profile_user_load($users) { @@ -275,19 +85,6 @@ function profile_user_load($users) { } } -function profile_save_profile(&$edit, &$user, $category, $register = FALSE) { - $result = _profile_get_fields($category, $register); - while ($field = db_fetch_object($result)) { - if (_profile_field_serialize($field->type)) { - $edit[$field->name] = serialize($edit[$field->name]); - } - db_query("DELETE FROM {profile_value} WHERE fid = %d AND uid = %d", $field->fid, $user->uid); - db_query("INSERT INTO {profile_value} (fid, uid, value) VALUES (%d, %d, '%s')", $field->fid, $user->uid, $edit[$field->name]); - // Mark field as handled (prevents saving to user->data). - $edit[$field->name] = NULL; - } -} - function profile_view_field($user, $field) { // Only allow browsing of private fields for admins, if browsing is enabled, // and if a user has permission to view profiles. Note that this check is @@ -385,82 +182,6 @@ function _profile_form_explanation($fiel return $output; } -function profile_form_profile($edit, $user, $category, $register = FALSE) { - $result = _profile_get_fields($category, $register); - $weight = 1; - $fields = array(); - while ($field = db_fetch_object($result)) { - $category = $field->category; - if (!isset($fields[$category])) { - $fields[$category] = array('#type' => 'fieldset', '#title' => check_plain($category), '#weight' => $weight++); - } - switch ($field->type) { - case 'textfield': - case 'url': - $fields[$category][$field->name] = array('#type' => 'textfield', - '#title' => check_plain($field->title), - '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', - '#maxlength' => 255, - '#description' => _profile_form_explanation($field), - '#required' => $field->required, - ); - if ($field->autocomplete) { - $fields[$category][$field->name]['#autocomplete_path'] = "profile/autocomplete/" . $field->fid; - } - break; - case 'textarea': - $fields[$category][$field->name] = array('#type' => 'textarea', - '#title' => check_plain($field->title), - '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', - '#description' => _profile_form_explanation($field), - '#required' => $field->required, - ); - break; - case 'list': - $fields[$category][$field->name] = array('#type' => 'textarea', - '#title' => check_plain($field->title), - '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', - '#description' => _profile_form_explanation($field), - '#required' => $field->required, - ); - break; - case 'checkbox': - $fields[$category][$field->name] = array('#type' => 'checkbox', - '#title' => check_plain($field->title), - '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', - '#description' => _profile_form_explanation($field), - '#required' => $field->required, - ); - break; - case 'selection': - $options = $field->required ? array() : array('--'); - $lines = preg_split("/[\n\r]/", $field->options); - foreach ($lines as $line) { - if ($line = trim($line)) { - $options[$line] = $line; - } - } - $fields[$category][$field->name] = array('#type' => 'select', - '#title' => check_plain($field->title), - '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', - '#options' => $options, - '#description' => _profile_form_explanation($field), - '#required' => $field->required, - ); - break; - case 'date': - $fields[$category][$field->name] = array('#type' => 'date', - '#title' => check_plain($field->title), - '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', - '#description' => _profile_form_explanation($field), - '#required' => $field->required, - ); - break; - } - } - return $fields; -} - /** * Helper function: update an array of user fields by calling profile_view_field */ @@ -471,39 +192,6 @@ function _profile_update_user_fields($fi return $fields; } -function profile_validate_profile($edit, $category) { - $result = _profile_get_fields($category); - while ($field = db_fetch_object($result)) { - if ($edit[$field->name]) { - if ($field->type == 'url') { - if (!valid_url($edit[$field->name], TRUE)) { - form_set_error($field->name, t('The value provided for %field is not a valid URL.', array('%field' => $field->title))); - } - } - } - elseif ($field->required && !user_access('administer users')) { - form_set_error($field->name, t('The field %field is required.', array('%field' => $field->title))); - } - } - - return $edit; -} - -function profile_categories() { - $result = db_query("SELECT DISTINCT(category) FROM {profile_field}"); - $data = array(); - while ($category = db_fetch_object($result)) { - $data[] = array( - 'name' => $category->category, - 'title' => $category->category, - 'weight' => 3, - 'access callback' => 'profile_category_access', - 'access arguments' => array(1, $category->category) - ); - } - return $data; -} - /** * Menu item access callback - check if a user has access to a profile category. */ Index: modules/profile/profile.registry.inc =================================================================== RCS file: modules/profile/profile.registry.inc diff -N modules/profile/profile.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/profile/profile.registry.inc 22 May 2009 23:43:42 -0000 @@ -0,0 +1,85 @@ + 'User list', + 'page callback' => 'profile_browse', + 'access arguments' => array('access user profiles'), + 'type' => MENU_SUGGESTED_ITEM, + ); + $items['admin/user/profile'] = array( + 'title' => 'Profiles', + 'description' => 'Create customizable fields for your users.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('profile_admin_overview'), + 'access arguments' => array('administer users'), + ); + $items['admin/user/profile/add'] = array( + 'title' => 'Add field', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('profile_field_form'), + 'access arguments' => array('administer users'), + 'type' => MENU_CALLBACK, + ); + $items['admin/user/profile/autocomplete'] = array( + 'title' => 'Profile category autocomplete', + 'page callback' => 'profile_admin_settings_autocomplete', + 'access arguments' => array('administer users'), + 'type' => MENU_CALLBACK, + ); + $items['admin/user/profile/edit'] = array( + 'title' => 'Edit field', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('profile_field_form'), + 'access arguments' => array('administer users'), + 'type' => MENU_CALLBACK, + ); + $items['admin/user/profile/delete'] = array( + 'title' => 'Delete field', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('profile_field_delete'), + 'access arguments' => array('administer users'), + 'type' => MENU_CALLBACK, + ); + $items['profile/autocomplete'] = array( + 'title' => 'Profile autocomplete', + 'page callback' => 'profile_autocomplete', + 'access arguments' => array('access user profiles'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function profile_theme() { + return array( + 'profile_block' => array( + 'arguments' => array('account' => NULL, 'fields' => array()), + 'template' => 'profile-block', + ), + 'profile_listing' => array( + 'arguments' => array('account' => NULL, 'fields' => array()), + 'template' => 'profile-listing', + ), + 'profile_wrapper' => array( + 'arguments' => array('content' => NULL), + 'template' => 'profile-wrapper', + ), + 'profile_admin_overview' => array( + 'arguments' => array('form' => NULL), + 'file' => 'profile.admin.inc', + ) + ); +} + Index: modules/profile/profile.user.inc =================================================================== RCS file: modules/profile/profile.user.inc diff -N modules/profile/profile.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/profile/profile.user.inc 22 May 2009 23:44:31 -0000 @@ -0,0 +1,184 @@ +condition('uid', $account->uid)->execute(); + break; + } +} + +function profile_form_profile($edit, $user, $category, $register = FALSE) { + $result = _profile_get_fields($category, $register); + $weight = 1; + $fields = array(); + while ($field = db_fetch_object($result)) { + $category = $field->category; + if (!isset($fields[$category])) { + $fields[$category] = array('#type' => 'fieldset', '#title' => check_plain($category), '#weight' => $weight++); + } + switch ($field->type) { + case 'textfield': + case 'url': + $fields[$category][$field->name] = array('#type' => 'textfield', + '#title' => check_plain($field->title), + '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', + '#maxlength' => 255, + '#description' => _profile_form_explanation($field), + '#required' => $field->required, + ); + if ($field->autocomplete) { + $fields[$category][$field->name]['#autocomplete_path'] = "profile/autocomplete/" . $field->fid; + } + break; + case 'textarea': + $fields[$category][$field->name] = array('#type' => 'textarea', + '#title' => check_plain($field->title), + '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', + '#description' => _profile_form_explanation($field), + '#required' => $field->required, + ); + break; + case 'list': + $fields[$category][$field->name] = array('#type' => 'textarea', + '#title' => check_plain($field->title), + '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', + '#description' => _profile_form_explanation($field), + '#required' => $field->required, + ); + break; + case 'checkbox': + $fields[$category][$field->name] = array('#type' => 'checkbox', + '#title' => check_plain($field->title), + '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', + '#description' => _profile_form_explanation($field), + '#required' => $field->required, + ); + break; + case 'selection': + $options = $field->required ? array() : array('--'); + $lines = preg_split("/[\n\r]/", $field->options); + foreach ($lines as $line) { + if ($line = trim($line)) { + $options[$line] = $line; + } + } + $fields[$category][$field->name] = array('#type' => 'select', + '#title' => check_plain($field->title), + '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', + '#options' => $options, + '#description' => _profile_form_explanation($field), + '#required' => $field->required, + ); + break; + case 'date': + $fields[$category][$field->name] = array('#type' => 'date', + '#title' => check_plain($field->title), + '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '', + '#description' => _profile_form_explanation($field), + '#required' => $field->required, + ); + break; + } + } + return $fields; +} + +function profile_validate_profile($edit, $category) { + $result = _profile_get_fields($category); + while ($field = db_fetch_object($result)) { + if ($edit[$field->name]) { + if ($field->type == 'url') { + if (!valid_url($edit[$field->name], TRUE)) { + form_set_error($field->name, t('The value provided for %field is not a valid URL.', array('%field' => $field->title))); + } + } + } + elseif ($field->required && !user_access('administer users')) { + form_set_error($field->name, t('The field %field is required.', array('%field' => $field->title))); + } + } + + return $edit; +} + +function profile_save_profile(&$edit, &$user, $category, $register = FALSE) { + $result = _profile_get_fields($category, $register); + while ($field = db_fetch_object($result)) { + if (_profile_field_serialize($field->type)) { + $edit[$field->name] = serialize($edit[$field->name]); + } + db_query("DELETE FROM {profile_value} WHERE fid = %d AND uid = %d", $field->fid, $user->uid); + db_query("INSERT INTO {profile_value} (fid, uid, value) VALUES (%d, %d, '%s')", $field->fid, $user->uid, $edit[$field->name]); + // Mark field as handled (prevents saving to user->data). + $edit[$field->name] = NULL; + } +} + +function profile_categories() { + $result = db_query("SELECT DISTINCT(category) FROM {profile_field}"); + $data = array(); + while ($category = db_fetch_object($result)) { + $data[] = array( + 'name' => $category->category, + 'title' => $category->category, + 'weight' => 3, + 'access callback' => 'profile_category_access', + 'access arguments' => array(1, $category->category) + ); + } + return $data; +} + Index: modules/search/search.block.inc =================================================================== RCS file: modules/search/search.block.inc diff -N modules/search/search.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/search/search.block.inc 22 May 2009 23:43:40 -0000 @@ -0,0 +1,18 @@ +nid); +} + +/** + * Implementation of hook_comment_publish(). + */ +function search_comment_publish($form_values) { + // Reindex the node when comments are published. + search_touch_node($form_values['nid']); +} + +/** + * Implementation of hook_comment_unpublish(). + */ +function search_comment_unpublish($comment) { + // Reindex the node when comments are unpublished. + search_touch_node($comment->nid); +} + Index: modules/search/search.cron.inc =================================================================== RCS file: modules/search/search.cron.inc diff -N modules/search/search.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/search/search.cron.inc 22 May 2009 23:43:41 -0000 @@ -0,0 +1,23 @@ + FALSE)); + + if (!$action) { + $action = url('search/' . $type); + } + if (is_null($prompt)) { + $prompt = t('Enter your keywords'); + } + + $form = array( + '#action' => $action, + '#attributes' => array('class' => 'search-form'), + ); + $form['module'] = array('#type' => 'value', '#value' => $type); + $form['basic'] = array('#type' => 'item', '#title' => $prompt, '#id' => 'edit-keys'); + $form['basic']['inline'] = array('#prefix' => '' . t('To provide keyword searching, the search engine maintains an index of words found in your site\'s content. To build and maintain this index, a correctly configured cron maintenance task is required. Indexing behavior can be adjusted using the search settings page; for example, the Number of items to index per cron run sets the maximum number of items indexed in each pass of a cron maintenance task. If necessary, reduce this number to prevent timeouts and memory errors when indexing.', array('@cron' => url('admin/reports/status'), '@searchsettings' => url('admin/settings/search'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Search module.', array('@search' => 'http://drupal.org/handbook/modules/search/')) . '
'; + return $output; + case 'admin/settings/search': + return '' . t('The search engine maintains an index of words found in your site\'s content. To build and maintain this index, a correctly configured cron maintenance task is required. Indexing behavior can be adjusted using the settings below.', array('@cron' => url('admin/reports/status'))) . '
'; + case 'search#noresults': + return t('' . t('The search module adds the ability to search for content by keywords. Search is often the only practical way to find content on a large site, and is useful for finding both users and posts.') . '
'; - $output .= '' . t('To provide keyword searching, the search engine maintains an index of words found in your site\'s content. To build and maintain this index, a correctly configured cron maintenance task is required. Indexing behavior can be adjusted using the search settings page; for example, the Number of items to index per cron run sets the maximum number of items indexed in each pass of a cron maintenance task. If necessary, reduce this number to prevent timeouts and memory errors when indexing.', array('@cron' => url('admin/reports/status'), '@searchsettings' => url('admin/settings/search'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Search module.', array('@search' => 'http://drupal.org/handbook/modules/search/')) . '
'; - return $output; - case 'admin/settings/search': - return '' . t('The search engine maintains an index of words found in your site\'s content. To build and maintain this index, a correctly configured cron maintenance task is required. Indexing behavior can be adjusted using the settings below.', array('@cron' => url('admin/reports/status'))) . '
'; - case 'search#noresults': - return t('' . t('Visit Administer >> Site building >> SimpleTest to display a list of available tests. For comprehensive testing, select all tests, or individually select tests for more targeted testing. Note that it might take several minutes for all tests to complete.)', array('@admin-simpletest' => url('admin/development/testing'))) .'
'; + $output .= '' . t('After the tests have run, a message will be displayed next to each test group indicating whether tests within it passed, failed, or had exceptions. A pass means that a test returned the expected results, while fail means that it did not. An exception normally indicates an error outside of the test, such as a PHP warning or notice. If there were fails or exceptions, the results are expanded, and the tests that had issues will be indicated in red or pink rows. Use these results to refine your code and tests until all tests return a pass.') .'
'; + $output .= '' . t('For more information on creating and modifying your own tests, see the SimpleTest API Documentation in the Drupal handbook.', array('@simpletest-api' => 'http://drupal.org/simpletest')) .'
'; + $output .= '' . t('For more information, see the online handbook entry for SimpleTest module.', array('@simpletest' => 'http://drupal.org/handbook/modules/simpletest')) .'
'; + return $output; + } +} + Index: modules/simpletest/simpletest.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.info,v retrieving revision 1.5 diff -u -p -r1.5 simpletest.info --- modules/simpletest/simpletest.info 1 May 2009 11:01:53 -0000 1.5 +++ modules/simpletest/simpletest.info 22 May 2009 23:43:38 -0000 @@ -7,3 +7,6 @@ core = 7.x files[] = simpletest.module files[] = simpletest.pages.inc files[] = simpletest.install +files[] = simpletest.registry.inc +files[] = simpletest.user.inc +files[] = simpletest.help.inc Index: modules/simpletest/simpletest.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.module,v retrieving revision 1.45 diff -u -p -r1.45 simpletest.module --- modules/simpletest/simpletest.module 21 May 2009 23:07:16 -0000 1.45 +++ modules/simpletest/simpletest.module 22 May 2009 23:43:38 -0000 @@ -7,79 +7,6 @@ */ /** - * Implementation of hook_help(). - */ -function simpletest_help($path, $arg) { - switch ($path) { - case 'admin/help#simpletest': - $output = '' . t('The SimpleTest module is a framework for running automated unit tests in Drupal. It can be used to verify a working state of Drupal before and after any code changes, or as a means for developers to write and execute tests for their modules.') .'
'; - $output .= '' . t('Visit Administer >> Site building >> SimpleTest to display a list of available tests. For comprehensive testing, select all tests, or individually select tests for more targeted testing. Note that it might take several minutes for all tests to complete.)', array('@admin-simpletest' => url('admin/development/testing'))) .'
'; - $output .= '' . t('After the tests have run, a message will be displayed next to each test group indicating whether tests within it passed, failed, or had exceptions. A pass means that a test returned the expected results, while fail means that it did not. An exception normally indicates an error outside of the test, such as a PHP warning or notice. If there were fails or exceptions, the results are expanded, and the tests that had issues will be indicated in red or pink rows. Use these results to refine your code and tests until all tests return a pass.') .'
'; - $output .= '' . t('For more information on creating and modifying your own tests, see the SimpleTest API Documentation in the Drupal handbook.', array('@simpletest-api' => 'http://drupal.org/simpletest')) .'
'; - $output .= '' . t('For more information, see the online handbook entry for SimpleTest module.', array('@simpletest' => 'http://drupal.org/handbook/modules/simpletest')) .'
'; - return $output; - } -} - -/** - * Implementation of hook_menu(). - */ -function simpletest_menu() { - $items['admin/development'] = array( - 'title' => 'Development', - 'description' => 'Development tools.', - 'position' => 'right', - 'weight' => -7, - 'page callback' => 'system_admin_menu_block_page', - 'access arguments' => array('access administration pages'), - ); - $items['admin/development/testing'] = array( - 'title' => 'Testing', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('simpletest_test_form'), - 'description' => 'Run tests against Drupal core and your active modules. These tests help assure that your site code is working as designed.', - 'access arguments' => array('administer unit tests'), - ); - $items['admin/development/testing/results/%'] = array( - 'title' => 'Test result', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('simpletest_result_form', 4), - 'description' => 'View result of tests.', - 'access arguments' => array('administer unit tests'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** - * Implementation of hook_perm(). - */ -function simpletest_perm() { - return array( - 'administer unit tests' => array( - 'title' => t('Administer unit tests'), - 'description' => t('Manage and run automated testing. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), - ), - ); -} - -/** - * Implementation of hook_theme(). - */ -function simpletest_theme() { - return array( - 'simpletest_test_table' => array( - 'arguments' => array('table' => NULL), - 'file' => 'simpletest.pages.inc', - ), - 'simpletest_result_summary' => array( - 'arguments' => array('form' => NULL), - 'file' => 'simpletest.pages.inc', - ), - ); -} - -/** * Implementation of hook_js_alter(). */ function simpletest_js_alter(&$javascript) { Index: modules/simpletest/simpletest.registry.inc =================================================================== RCS file: modules/simpletest/simpletest.registry.inc diff -N modules/simpletest/simpletest.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/simpletest.registry.inc 22 May 2009 23:43:38 -0000 @@ -0,0 +1,54 @@ + 'Development', + 'description' => 'Development tools.', + 'position' => 'right', + 'weight' => -7, + 'page callback' => 'system_admin_menu_block_page', + 'access arguments' => array('access administration pages'), + ); + $items['admin/development/testing'] = array( + 'title' => 'Testing', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('simpletest_test_form'), + 'description' => 'Run tests against Drupal core and your active modules. These tests help assure that your site code is working as designed.', + 'access arguments' => array('administer unit tests'), + ); + $items['admin/development/testing/results/%'] = array( + 'title' => 'Test result', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('simpletest_result_form', 4), + 'description' => 'View result of tests.', + 'access arguments' => array('administer unit tests'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function simpletest_theme() { + return array( + 'simpletest_test_table' => array( + 'arguments' => array('table' => NULL), + 'file' => 'simpletest.pages.inc', + ), + 'simpletest_result_summary' => array( + 'arguments' => array('form' => NULL), + 'file' => 'simpletest.pages.inc', + ), + ); +} + Index: modules/simpletest/simpletest.user.inc =================================================================== RCS file: modules/simpletest/simpletest.user.inc diff -N modules/simpletest/simpletest.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/simpletest.user.inc 22 May 2009 23:43:38 -0000 @@ -0,0 +1,20 @@ + array( + 'title' => t('Administer unit tests'), + 'description' => t('Manage and run automated testing. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), + ), + ); +} + Index: modules/simpletest/tests/database_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.info,v retrieving revision 1.2 diff -u -p -r1.2 database_test.info --- modules/simpletest/tests/database_test.info 9 Oct 2008 22:51:40 -0000 1.2 +++ modules/simpletest/tests/database_test.info 22 May 2009 23:43:35 -0000 @@ -7,3 +7,4 @@ files[] = database_test.module files[] = database_test.install version = VERSION hidden = TRUE +files[] = database_test.registry.inc Index: modules/simpletest/tests/database_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.module,v retrieving revision 1.8 diff -u -p -r1.8 database_test.module --- modules/simpletest/tests/database_test.module 22 May 2009 11:33:17 -0000 1.8 +++ modules/simpletest/tests/database_test.module 22 May 2009 23:43:35 -0000 @@ -41,34 +41,6 @@ function database_test_query_database_te } /** - * Implementation of hook_menu(). - */ -function database_test_menu() { - $items['database_test/db_query_temporary'] = array( - 'access callback' => TRUE, - 'page callback' => 'database_test_db_query_temporary', - ); - $items['database_test/pager_query_even'] = array( - 'access callback' => TRUE, - 'page callback' => 'database_test_even_pager_query', - ); - $items['database_test/pager_query_odd'] = array( - 'access callback' => TRUE, - 'page callback' => 'database_test_odd_pager_query', - ); - $items['database_test/tablesort'] = array( - 'access callback' => TRUE, - 'page callback' => 'database_test_tablesort', - ); - $items['database_test/tablesort_first'] = array( - 'access callback' => TRUE, - 'page callback' => 'database_test_tablesort_first', - ); - - return $items; -} - -/** * Run a db_query_temporary and output the table name and its number of rows. * * We need to test that the table created is temporary, so we run it here, in a Index: modules/simpletest/tests/database_test.registry.inc =================================================================== RCS file: modules/simpletest/tests/database_test.registry.inc diff -N modules/simpletest/tests/database_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/database_test.registry.inc 22 May 2009 23:43:35 -0000 @@ -0,0 +1,36 @@ + TRUE, + 'page callback' => 'database_test_db_query_temporary', + ); + $items['database_test/pager_query_even'] = array( + 'access callback' => TRUE, + 'page callback' => 'database_test_even_pager_query', + ); + $items['database_test/pager_query_odd'] = array( + 'access callback' => TRUE, + 'page callback' => 'database_test_odd_pager_query', + ); + $items['database_test/tablesort'] = array( + 'access callback' => TRUE, + 'page callback' => 'database_test_tablesort', + ); + $items['database_test/tablesort_first'] = array( + 'access callback' => TRUE, + 'page callback' => 'database_test_tablesort_first', + ); + + return $items; +} + Index: modules/simpletest/tests/field_test.field.inc =================================================================== RCS file: modules/simpletest/tests/field_test.field.inc diff -N modules/simpletest/tests/field_test.field.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/field_test.field.inc 22 May 2009 23:43:36 -0000 @@ -0,0 +1,112 @@ + array( + 'value' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => FALSE, + ), + ), + 'indexes' => array( + 'value' => array('value'), + ), + ); +} + +/** + * Implementation of hook_field_validate(). + * + * Possible error codes: + * - 'field_test_invalid': The value is invalid. + */ +function field_test_field_validate($obj_type, $object, $field, $instance, $items, &$errors) { + foreach ($items as $delta => $item) { + if ($item['value'] == -1) { + $errors[$field['field_name']][$delta][] = array( + 'error' => 'field_test_invalid', + 'message' => t('%name does not accept the value -1.', array('%name' => $instance['label'])), + ); + } + } +} + +/** + * Implementation of hook_field_sanitize(). + */ +function field_test_field_sanitize($obj_type, $object, $field, $instance, &$items) { + foreach ($items as $delta => $item) { + $value = check_plain($item['value']); + $items[$delta]['safe'] = $value; + } +} + +/** + * Implementation of hook_field_is_empty(). + */ +function field_test_field_is_empty($item, $field) { + return empty($item['value']); +} + +/** + * Implementation of hook_field_widget(). + * + * Attach a single form element to the form. It will be built out and + * validated in the callback(s) listed in hook_elements. We build it + * out in the callbacks rather than here in hook_widget so it can be + * plugged into any module that can provide it with valid + * $field information. + * + * Content module will set the weight, field name and delta values + * for each form element. This is a change from earlier CCK versions + * where the widget managed its own multiple values. + * + * If there are multiple values for this field, the content module will + * call this function as many times as needed. + * + * @param $form + * the entire form array, $form['#node'] holds node information + * @param $form_state + * the form_state, $form_state['values'][$field['field_name']] + * holds the field's form values. + * @param $field + * The field structure. + * @param $insatnce + * the insatnce array + * @param $items + * array of default values for this field + * @param $delta + * the order of this item in the array of subelements (0, 1, 2, etc) + * + * @return + * the form item for a single element for this field + */ +function field_test_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) { + $element = array( + 'value' => array( + '#title' => $instance['label'], + '#type' => 'textfield', + '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : '', + '#required' => $instance['required'], + ), + ); + return $element; +} + +/** + * Implementation of hook_field_widget_error(). + */ +function field_test_field_widget_error($element, $error) { + form_error($element['value'], $error['message']); +} + Index: modules/simpletest/tests/field_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/field_test.info,v retrieving revision 1.2 diff -u -p -r1.2 field_test.info --- modules/simpletest/tests/field_test.info 8 Feb 2009 21:22:59 -0000 1.2 +++ modules/simpletest/tests/field_test.info 22 May 2009 23:43:36 -0000 @@ -7,3 +7,6 @@ files[] = field_test.module files[] = field_test.install version = VERSION hidden = TRUE +files[] = field_test.registry.inc +files[] = field_test.user.inc +files[] = field_test.field.inc Index: modules/simpletest/tests/field_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/field_test.module,v retrieving revision 1.8 diff -u -p -r1.8 field_test.module --- modules/simpletest/tests/field_test.module 20 May 2009 09:48:47 -0000 1.8 +++ modules/simpletest/tests/field_test.module 22 May 2009 23:43:36 -0000 @@ -5,52 +5,6 @@ define('FIELD_TEST_ELEMENT_ID', 1); define('FIELD_TEST_BUNDLE', 'test_bundle'); /** - * Implementation of hook_perm(). - */ -function field_test_perm() { - $perms = array( - 'access field_test content' => array( - 'title' => t('Access field_test content'), - 'description' => t('View published field_test content.'), - ), - 'administer field_test content' => array( - 'title' => t('Administer field_test content'), - 'description' => t('Manage field_test content'), - ), - ); - return $perms; -} - -/** - * Implementation of hook_menu(). - */ -function field_test_menu() { - $items = array(); - $info = field_test_fieldable_info(); - - foreach (array_keys($info['test_entity']['bundles']) as $bundle) { - $bundle_url_str = str_replace('_', '-', $bundle); - $items['test-entity/add/' . $bundle_url_str] = array( - 'title' => "Add $bundle test_entity", - 'page callback' => 'field_test_entity_add', - 'page arguments' => array(2), - 'access arguments' => array('administer field_test content'), - 'type' => MENU_NORMAL_ITEM, - ); - } - $items['test-entity/%field_test_entity/edit'] = array( - 'title' => 'Edit test entity', - 'page callback' => 'field_test_entity_edit', - 'page arguments' => array(1), - 'access arguments' => array('administer field_test content'), - 'type' => MENU_NORMAL_ITEM, - ); - - return $items; -} - - -/** * * 'Field attach' API. * @@ -58,32 +12,6 @@ function field_test_menu() { /** - * Define a test fieldable entity. - */ -function field_test_fieldable_info() { - $bundles = variable_get('field_test_bundles', array('test_bundle' => 'Test Bundle')); - return array( - 'test_entity' => array( - 'name' => t('Test Entity'), - 'id key' => 'ftid', - 'revision key' => 'ftvid', - 'cacheable' => FALSE, - 'bundle key' => 'fttype', - 'bundles' => $bundles, - ), - // This entity type doesn't get form handling for now... - 'test_cacheable_entity' => array( - 'name' => t('Test Entity, cacheable'), - 'id key' => 'ftid', - 'revision key' => 'ftvid', - 'cacheable' => TRUE, - 'bundle key' => 'fttype', - 'bundles' => $bundles, - ), - ); -} - -/** * Create a new bundle for test_entity objects. * * @param $bundle @@ -132,20 +60,6 @@ function field_test_delete_bundle($bundl } /** - * Implementation of hook_field_build_modes(). - */ -function field_test_field_build_modes($obj_type) { - $modes = array(); - if ($obj_type == 'test_entity' || $obj_type == 'test_cacheable_entity') { - $modes = array( - 'full' => t('Full node'), - 'teaser' => t('Teaser'), - ); - } - return $modes; -} - -/** * Helper function to create a basic 'test entity' structure. * * TODO : do we stil need this now that we can actualy load and save test_entities ? @@ -326,194 +240,6 @@ function field_test_entity_form_submit_b */ /** - * Implementation of hook_field_info(). - * - * This field provides a textfield which only accepts the value 1. - */ -function field_test_field_info() { - return array( - 'test_field' => array( - 'label' => t('Test Field'), - 'settings' => array( - 'test_field_setting' => 'dummy test string', - ), - 'instance_settings' => array( - 'test_instance_setting' => 'dummy test string', - 'test_hook_field_load' => FALSE, - ), - 'default_widget' => 'test_field_widget', - 'default_formatter' => 'field_test_default', - ), - ); -} - -/** - * Implementation of hook_field_schema(). - */ -function field_test_field_schema($field) { - return array( - 'columns' => array( - 'value' => array( - 'type' => 'int', - 'size' => 'tiny', - 'not null' => FALSE, - ), - ), - 'indexes' => array( - 'value' => array('value'), - ), - ); -} - -/** - * Implementation of hook_field_validate(). - * - * Possible error codes: - * - 'field_test_invalid': The value is invalid. - */ -function field_test_field_validate($obj_type, $object, $field, $instance, $items, &$errors) { - foreach ($items as $delta => $item) { - if ($item['value'] == -1) { - $errors[$field['field_name']][$delta][] = array( - 'error' => 'field_test_invalid', - 'message' => t('%name does not accept the value -1.', array('%name' => $instance['label'])), - ); - } - } -} - -/** - * Implementation of hook_field_sanitize(). - */ -function field_test_field_sanitize($obj_type, $object, $field, $instance, &$items) { - foreach ($items as $delta => $item) { - $value = check_plain($item['value']); - $items[$delta]['safe'] = $value; - } -} - -/** - * Implementation of hook_field_is_empty(). - */ -function field_test_field_is_empty($item, $field) { - return empty($item['value']); -} - -/** - * Implementation of hook_field_widget_info(). - * - * Here we indicate that the content module will handle - * the default value and multiple values for these widgets. - * - * Callbacks can be omitted if default handing is used. - * They're included here just so this module can be used - * as an example for custom modules that might do things - * differently. - */ -function field_test_field_widget_info() { - return array( - 'test_field_widget' => array( - 'label' => t('Test field'), - 'field types' => array('test_field'), - 'settings' => array('test_widget_setting' => 'dummy test string'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - 'default value' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'test_field_widget_multiple' => array( - 'label' => t('Test field 1'), - 'field types' => array('test_field'), - 'settings' => array('test_widget_setting_multiple' => 'dummy test string'), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_CUSTOM, - 'default value' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - ); -} - -/** - * Implementation of hook_field_widget(). - * - * Attach a single form element to the form. It will be built out and - * validated in the callback(s) listed in hook_elements. We build it - * out in the callbacks rather than here in hook_widget so it can be - * plugged into any module that can provide it with valid - * $field information. - * - * Content module will set the weight, field name and delta values - * for each form element. This is a change from earlier CCK versions - * where the widget managed its own multiple values. - * - * If there are multiple values for this field, the content module will - * call this function as many times as needed. - * - * @param $form - * the entire form array, $form['#node'] holds node information - * @param $form_state - * the form_state, $form_state['values'][$field['field_name']] - * holds the field's form values. - * @param $field - * The field structure. - * @param $insatnce - * the insatnce array - * @param $items - * array of default values for this field - * @param $delta - * the order of this item in the array of subelements (0, 1, 2, etc) - * - * @return - * the form item for a single element for this field - */ -function field_test_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) { - $element = array( - 'value' => array( - '#title' => $instance['label'], - '#type' => 'textfield', - '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : '', - '#required' => $instance['required'], - ), - ); - return $element; -} - -/** - * Implementation of hook_field_widget_error(). - */ -function field_test_field_widget_error($element, $error) { - form_error($element['value'], $error['message']); -} - -/** - * Implementation of hook_field_formatter_info(). - */ -function field_test_field_formatter_info() { - return array( - 'field_test_default' => array( - 'label' => t('Default'), - 'field types' => array('test_field'), - 'settings' => array( - 'test_formatter_setting' => 'dummy test string', - ), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_DEFAULT, - ), - ), - 'field_test_multiple' => array( - 'label' => t('Default'), - 'field types' => array('test_field'), - 'settings' => array( - 'test_formatter_setting_multiple' => 'dummy test string', - ), - 'behaviors' => array( - 'multiple values' => FIELD_BEHAVIOR_CUSTOM, - ), - ), - ); -} - -/** * Implementation of hook_field_load(). */ function field_test_field_load($obj_type, $objects, $field, $instances, &$items, $age) { @@ -532,20 +258,6 @@ function field_test_field_load($obj_type } /** - * Implementation of hook_theme(). - */ -function field_test_theme() { - return array( - 'field_formatter_field_test_default' => array( - 'arguments' => array('element' => NULL), - ), - 'field_formatter_field_test_multiple' => array( - 'arguments' => array('element' => NULL), - ), - ); -} - -/** * Theme function for 'field_test_default' formatter. */ function theme_field_formatter_field_test_default($element) { Index: modules/simpletest/tests/field_test.registry.inc =================================================================== RCS file: modules/simpletest/tests/field_test.registry.inc diff -N modules/simpletest/tests/field_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/field_test.registry.inc 22 May 2009 23:43:36 -0000 @@ -0,0 +1,175 @@ + "Add $bundle test_entity", + 'page callback' => 'field_test_entity_add', + 'page arguments' => array(2), + 'access arguments' => array('administer field_test content'), + 'type' => MENU_NORMAL_ITEM, + ); + } + $items['test-entity/%field_test_entity/edit'] = array( + 'title' => 'Edit test entity', + 'page callback' => 'field_test_entity_edit', + 'page arguments' => array(1), + 'access arguments' => array('administer field_test content'), + 'type' => MENU_NORMAL_ITEM, + ); + + return $items; +} + + +/** + * Implementation of hook_theme(). + */ +function field_test_theme() { + return array( + 'field_formatter_field_test_default' => array( + 'arguments' => array('element' => NULL), + ), + 'field_formatter_field_test_multiple' => array( + 'arguments' => array('element' => NULL), + ), + ); +} + +/** + * Define a test fieldable entity. + */ +function field_test_fieldable_info() { + $bundles = variable_get('field_test_bundles', array('test_bundle' => 'Test Bundle')); + return array( + 'test_entity' => array( + 'name' => t('Test Entity'), + 'id key' => 'ftid', + 'revision key' => 'ftvid', + 'cacheable' => FALSE, + 'bundle key' => 'fttype', + 'bundles' => $bundles, + ), + // This entity type doesn't get form handling for now... + 'test_cacheable_entity' => array( + 'name' => t('Test Entity, cacheable'), + 'id key' => 'ftid', + 'revision key' => 'ftvid', + 'cacheable' => TRUE, + 'bundle key' => 'fttype', + 'bundles' => $bundles, + ), + ); +} + +/** + * Implementation of hook_field_build_modes(). + */ +function field_test_field_build_modes($obj_type) { + $modes = array(); + if ($obj_type == 'test_entity' || $obj_type == 'test_cacheable_entity') { + $modes = array( + 'full' => t('Full node'), + 'teaser' => t('Teaser'), + ); + } + return $modes; +} + +/** + * Implementation of hook_field_info(). + * + * This field provides a textfield which only accepts the value 1. + */ +function field_test_field_info() { + return array( + 'test_field' => array( + 'label' => t('Test Field'), + 'settings' => array( + 'test_field_setting' => 'dummy test string', + ), + 'instance_settings' => array( + 'test_instance_setting' => 'dummy test string', + 'test_hook_field_load' => FALSE, + ), + 'default_widget' => 'test_field_widget', + 'default_formatter' => 'field_test_default', + ), + ); +} + +/** + * Implementation of hook_field_formatter_info(). + */ +function field_test_field_formatter_info() { + return array( + 'field_test_default' => array( + 'label' => t('Default'), + 'field types' => array('test_field'), + 'settings' => array( + 'test_formatter_setting' => 'dummy test string', + ), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'field_test_multiple' => array( + 'label' => t('Default'), + 'field types' => array('test_field'), + 'settings' => array( + 'test_formatter_setting_multiple' => 'dummy test string', + ), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_CUSTOM, + ), + ), + ); +} + +/** + * Implementation of hook_field_widget_info(). + * + * Here we indicate that the content module will handle + * the default value and multiple values for these widgets. + * + * Callbacks can be omitted if default handing is used. + * They're included here just so this module can be used + * as an example for custom modules that might do things + * differently. + */ +function field_test_field_widget_info() { + return array( + 'test_field_widget' => array( + 'label' => t('Test field'), + 'field types' => array('test_field'), + 'settings' => array('test_widget_setting' => 'dummy test string'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_DEFAULT, + 'default value' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + 'test_field_widget_multiple' => array( + 'label' => t('Test field 1'), + 'field types' => array('test_field'), + 'settings' => array('test_widget_setting_multiple' => 'dummy test string'), + 'behaviors' => array( + 'multiple values' => FIELD_BEHAVIOR_CUSTOM, + 'default value' => FIELD_BEHAVIOR_DEFAULT, + ), + ), + ); +} + Index: modules/simpletest/tests/field_test.user.inc =================================================================== RCS file: modules/simpletest/tests/field_test.user.inc diff -N modules/simpletest/tests/field_test.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/field_test.user.inc 22 May 2009 23:43:36 -0000 @@ -0,0 +1,25 @@ + array( + 'title' => t('Access field_test content'), + 'description' => t('View published field_test content.'), + ), + 'administer field_test content' => array( + 'title' => t('Administer field_test content'), + 'description' => t('Manage field_test content'), + ), + ); + return $perms; +} + Index: modules/simpletest/tests/file_test.file.inc =================================================================== RCS file: modules/simpletest/tests/file_test.file.inc diff -N modules/simpletest/tests/file_test.file.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/file_test.file.inc 22 May 2009 23:43:37 -0000 @@ -0,0 +1,66 @@ + t('Upload test'), - 'page callback' => 'drupal_get_form', - 'page arguments' => array('_file_test_form'), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** * Form to test file uploads. */ function _file_test_form(&$form_state) { @@ -181,61 +167,3 @@ function file_test_file_load($files) { } } -/** - * Implementation of hook_file_validate(). - */ -function file_test_file_validate($file) { - _file_test_log_call('validate', array($file)); - return _file_test_get_return('validate'); -} - -/** - * Implementation of hook_file_download(). - */ -function file_test_file_download($file) { - _file_test_log_call('download', array($file)); - return _file_test_get_return('download'); -} - -/** - * Implementation of hook_file_references(). - */ -function file_test_file_references($file) { - _file_test_log_call('references', array($file)); - return _file_test_get_return('references'); -} - -/** - * Implementation of hook_file_insert(). - */ -function file_test_file_insert($file) { - _file_test_log_call('insert', array($file)); -} - -/** - * Implementation of hook_file_update(). - */ -function file_test_file_update($file) { - _file_test_log_call('update', array($file)); -} - -/** - * Implementation of hook_file_copy(). - */ -function file_test_file_copy($file, $source) { - _file_test_log_call('copy', array($file, $source)); -} - -/** - * Implementation of hook_file_move(). - */ -function file_test_file_move($file, $source) { - _file_test_log_call('move', array($file, $source)); -} - -/** - * Implementation of hook_file_delete(). - */ -function file_test_file_delete($file) { - _file_test_log_call('delete', array($file)); -} Index: modules/simpletest/tests/file_test.registry.inc =================================================================== RCS file: modules/simpletest/tests/file_test.registry.inc diff -N modules/simpletest/tests/file_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/file_test.registry.inc 22 May 2009 23:43:36 -0000 @@ -0,0 +1,22 @@ + t('Upload test'), + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_file_test_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + Index: modules/simpletest/tests/form_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.info,v retrieving revision 1.1 diff -u -p -r1.1 form_test.info --- modules/simpletest/tests/form_test.info 28 Jan 2009 07:43:26 -0000 1.1 +++ modules/simpletest/tests/form_test.info 22 May 2009 23:43:37 -0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = form_test.module hidden = TRUE +files[] = form_test.registry.inc Index: modules/simpletest/tests/form_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form_test.module,v retrieving revision 1.6 diff -u -p -r1.6 form_test.module --- modules/simpletest/tests/form_test.module 12 May 2009 08:37:45 -0000 1.6 +++ modules/simpletest/tests/form_test.module 22 May 2009 23:43:37 -0000 @@ -7,69 +7,6 @@ */ /** - * Implementation of hook_menu(). - */ -function form_test_menu() { - $items = array(); - - $items['form_test/tableselect/multiple-true'] = array( - 'title' => 'Tableselect checkboxes test', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('_form_test_tableselect_multiple_true_form'), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - $items['form_test/tableselect/multiple-false'] = array( - 'title' => 'Tableselect radio button test', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('_form_test_tableselect_multiple_false_form'), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - $items['form_test/tableselect/empty-text'] = array( - 'title' => 'Tableselect empty text test', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('_form_test_tableselect_empty_form'), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - $items['form_test/tableselect/advanced-select'] = array( - 'title' => 'Tableselect js_select tests', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('_form_test_tableselect_js_select_form'), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - $items['form_test/form_clean_id'] = array( - 'title' => 'form_clean_id test', - 'page callback' => 'form_test_form_clean_id_page', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - $items['form_test/drupal_form_submit_batch_api'] = array( - 'title' => 'BatchAPI Drupal_form_submit tests', - 'page callback' => 'form_test_drupal_form_submit_batch_api', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - $items['form_test/form-storage'] = array( - 'title' => 'Form storage test', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('form_storage_test_form'), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** * Generate a page with three forms, to test the clean_id generation. */ function form_test_form_clean_id_page() { Index: modules/simpletest/tests/form_test.registry.inc =================================================================== RCS file: modules/simpletest/tests/form_test.registry.inc diff -N modules/simpletest/tests/form_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/form_test.registry.inc 22 May 2009 23:43:37 -0000 @@ -0,0 +1,71 @@ + 'Tableselect checkboxes test', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_form_test_tableselect_multiple_true_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['form_test/tableselect/multiple-false'] = array( + 'title' => 'Tableselect radio button test', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_form_test_tableselect_multiple_false_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['form_test/tableselect/empty-text'] = array( + 'title' => 'Tableselect empty text test', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_form_test_tableselect_empty_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['form_test/tableselect/advanced-select'] = array( + 'title' => 'Tableselect js_select tests', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_form_test_tableselect_js_select_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['form_test/form_clean_id'] = array( + 'title' => 'form_clean_id test', + 'page callback' => 'form_test_form_clean_id_page', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['form_test/drupal_form_submit_batch_api'] = array( + 'title' => 'BatchAPI Drupal_form_submit tests', + 'page callback' => 'form_test_drupal_form_submit_batch_api', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['form_test/form-storage'] = array( + 'title' => 'Form storage test', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('form_storage_test_form'), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + Index: modules/simpletest/tests/image_test.file.inc =================================================================== RCS file: modules/simpletest/tests/image_test.file.inc diff -N modules/simpletest/tests/image_test.file.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/image_test.file.inc 22 May 2009 23:43:37 -0000 @@ -0,0 +1,24 @@ + array( + 'title' => t('A dummy toolkit that works'), + 'available' => TRUE, + ), + 'broken' => array( + 'title' => t('A dummy toolkit that is "broken"'), + 'available' => FALSE, + ), + ); +} + Index: modules/simpletest/tests/image_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/image_test.info,v retrieving revision 1.1 diff -u -p -r1.1 image_test.info --- modules/simpletest/tests/image_test.info 9 Mar 2009 11:44:54 -0000 1.1 +++ modules/simpletest/tests/image_test.info 22 May 2009 23:43:37 -0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = image_test.module hidden = TRUE +files[] = image_test.file.inc Index: modules/simpletest/tests/image_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/image_test.module,v retrieving revision 1.2 diff -u -p -r1.2 image_test.module --- modules/simpletest/tests/image_test.module 10 Mar 2009 09:43:01 -0000 1.2 +++ modules/simpletest/tests/image_test.module 22 May 2009 23:43:37 -0000 @@ -7,22 +7,6 @@ */ /** - * Implementation of hook_image_toolkits(). - */ -function image_test_image_toolkits() { - return array( - 'test' => array( - 'title' => t('A dummy toolkit that works'), - 'available' => TRUE, - ), - 'broken' => array( - 'title' => t('A dummy toolkit that is "broken"'), - 'available' => FALSE, - ), - ); -} - -/** * Reset/initialize the history of calls to the toolkit functions. * * @see image_test_get_all_calls(). Index: modules/simpletest/tests/menu_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/menu_test.info,v retrieving revision 1.1 diff -u -p -r1.1 menu_test.info --- modules/simpletest/tests/menu_test.info 28 Dec 2008 18:27:14 -0000 1.1 +++ modules/simpletest/tests/menu_test.info 22 May 2009 23:43:37 -0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = menu_test.module hidden = TRUE +files[] = menu_test.registry.inc Index: modules/simpletest/tests/menu_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/menu_test.module,v retrieving revision 1.4 diff -u -p -r1.4 menu_test.module --- modules/simpletest/tests/menu_test.module 13 Apr 2009 12:18:52 -0000 1.4 +++ modules/simpletest/tests/menu_test.module 22 May 2009 23:43:37 -0000 @@ -7,47 +7,6 @@ */ /** - * Implementation of hook_menu(). - */ -function menu_test_menu() { - // The name of the menu changes during the course of the test. Using a $_GET. - $items['menu_name_test'] = array( - 'title' => 'Test menu_name router item', - 'page callback' => 'node_save', - 'menu_name' => isset($_GET["hook_menu_name"]) ? $_GET["hook_menu_name"] : 'original', - ); - // Use FALSE as 'title callback' to bypass t(). - $items['menu_no_title_callback'] = array( - 'title' => 'A title with @placeholder', - 'title callback' => FALSE, - 'title arguments' => array('@placeholder' => 'some other text'), - 'page callback' => 'menu_test_callback', - 'access arguments' => array('access content'), - ); - - // Hidden link for menu_link_maintain tests - $items['menu_test_maintain/%'] = array( - 'title' => 'Menu maintain test', - 'page callback' => 'node_page_default', - 'access arguments' => array('access content'), - ); - // Hierarchical tests. - $items['menu-test/hierarchy/parent'] = array( - 'title' => 'Parent menu router', - 'page callback' => 'node_page_default', - ); - $items['menu-test/hierarchy/parent/child'] = array( - 'title' => 'Child menu router', - 'page callback' => 'node_page_default', - ); - $items['menu-test/hierarchy/parent/child2/child'] = array( - 'title' => 'Unattached subchild router', - 'page callback' => 'node_page_default', - ); - return $items; -} - -/** * Dummy callback for hook_menu() to point to. * * @return Index: modules/simpletest/tests/menu_test.registry.inc =================================================================== RCS file: modules/simpletest/tests/menu_test.registry.inc diff -N modules/simpletest/tests/menu_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/menu_test.registry.inc 22 May 2009 23:43:37 -0000 @@ -0,0 +1,49 @@ + 'Test menu_name router item', + 'page callback' => 'node_save', + 'menu_name' => isset($_GET["hook_menu_name"]) ? $_GET["hook_menu_name"] : 'original', + ); + // Use FALSE as 'title callback' to bypass t(). + $items['menu_no_title_callback'] = array( + 'title' => 'A title with @placeholder', + 'title callback' => FALSE, + 'title arguments' => array('@placeholder' => 'some other text'), + 'page callback' => 'menu_test_callback', + 'access arguments' => array('access content'), + ); + + // Hidden link for menu_link_maintain tests + $items['menu_test_maintain/%'] = array( + 'title' => 'Menu maintain test', + 'page callback' => 'node_page_default', + 'access arguments' => array('access content'), + ); + // Hierarchical tests. + $items['menu-test/hierarchy/parent'] = array( + 'title' => 'Parent menu router', + 'page callback' => 'node_page_default', + ); + $items['menu-test/hierarchy/parent/child'] = array( + 'title' => 'Child menu router', + 'page callback' => 'node_page_default', + ); + $items['menu-test/hierarchy/parent/child2/child'] = array( + 'title' => 'Unattached subchild router', + 'page callback' => 'node_page_default', + ); + return $items; +} + Index: modules/simpletest/tests/session_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/session_test.info,v retrieving revision 1.1 diff -u -p -r1.1 session_test.info --- modules/simpletest/tests/session_test.info 16 Aug 2008 21:11:02 -0000 1.1 +++ modules/simpletest/tests/session_test.info 22 May 2009 23:43:37 -0000 @@ -6,3 +6,5 @@ version = VERSION core = 7.x files[] = session_test.module hidden = TRUE +files[] = session_test.registry.inc +files[] = session_test.user.inc Index: modules/simpletest/tests/session_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/session_test.module,v retrieving revision 1.6 diff -u -p -r1.6 session_test.module --- modules/simpletest/tests/session_test.module 26 Jan 2009 14:08:43 -0000 1.6 +++ modules/simpletest/tests/session_test.module 22 May 2009 23:43:37 -0000 @@ -2,52 +2,6 @@ // $Id: session_test.module,v 1.6 2009/01/26 14:08:43 dries Exp $ /** - * Implementation of hook_menu(). - */ -function session_test_menu() { - $items['session-test/get'] = array( - 'title' => t('Session value'), - 'page callback' => '_session_test_get', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['session-test/id'] = array( - 'title' => t('Session ID value'), - 'page callback' => '_session_test_id', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['session-test/set/%'] = array( - 'title' => t('Set Session value'), - 'page callback' => '_session_test_set', - 'page arguments' => array(2), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['session-test/no-set/%'] = array( - 'title' => t('Disabled session set value'), - 'page callback' => '_session_test_no_set', - 'page arguments' => array(2), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['session-test/set-message'] = array( - 'title' => t('Session value'), - 'page callback' => '_session_test_set_message', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['session-test/set-not-started'] = array( - 'title' => t('Session value'), - 'page callback' => '_session_test_set_not_started', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** * Implement hook_boot(). */ function session_test_boot() { @@ -124,14 +78,3 @@ function _session_test_set_not_started() } } -/** - * Implementation of hook_user(). - */ -function session_test_user_login($edit = array(), $user = NULL) { - if ($edit['name'] == 'session_test_user') { - // Exit so we can verify that the session was regenerated - // before hook_user() was called. - exit; - } -} - Index: modules/simpletest/tests/session_test.registry.inc =================================================================== RCS file: modules/simpletest/tests/session_test.registry.inc diff -N modules/simpletest/tests/session_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/session_test.registry.inc 22 May 2009 23:43:37 -0000 @@ -0,0 +1,54 @@ + t('Session value'), + 'page callback' => '_session_test_get', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['session-test/id'] = array( + 'title' => t('Session ID value'), + 'page callback' => '_session_test_id', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['session-test/set/%'] = array( + 'title' => t('Set Session value'), + 'page callback' => '_session_test_set', + 'page arguments' => array(2), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['session-test/no-set/%'] = array( + 'title' => t('Disabled session set value'), + 'page callback' => '_session_test_no_set', + 'page arguments' => array(2), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['session-test/set-message'] = array( + 'title' => t('Session value'), + 'page callback' => '_session_test_set_message', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['session-test/set-not-started'] = array( + 'title' => t('Session value'), + 'page callback' => '_session_test_set_not_started', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + Index: modules/simpletest/tests/session_test.user.inc =================================================================== RCS file: modules/simpletest/tests/session_test.user.inc diff -N modules/simpletest/tests/session_test.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/session_test.user.inc 22 May 2009 23:43:37 -0000 @@ -0,0 +1,19 @@ + 'system_test_basic_auth_page', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['system-test/redirect/%'] = array( - 'title' => 'Redirect', - 'page callback' => 'system_test_redirect', - 'page arguments' => array(2), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['system-test/set-header'] = array( - 'page callback' => 'system_test_set_header', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['system-test/redirect-noscheme'] = array( - 'page callback' => 'system_test_redirect_noscheme', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['system-test/redirect-noparse'] = array( - 'page callback' => 'system_test_redirect_noparse', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['system-test/redirect-invalid-scheme'] = array( - 'page callback' => 'system_test_redirect_invalid_scheme', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - $items['system-test/destination'] = array( - 'title' => 'Redirect', - 'page callback' => 'system_test_destination', - 'page arguments' => array(2), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - $items['system-test/variable-get'] = array( - 'title' => 'Variable Get', - 'page callback' => 'variable_get', - 'page arguments' => array('simpletest_bootstrap_variable_test', NULL), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - function system_test_basic_auth_page() { $output = t('$_SERVER[\'PHP_AUTH_USER\'] is @username.', array('@username' => $_SERVER['PHP_AUTH_USER'])); $output .= t('$_SERVER[\'PHP_AUTH_PW\'] is @password.', array('@password' => $_SERVER['PHP_AUTH_PW'])); @@ -96,42 +41,6 @@ function system_test_destination() { } /** - * Implementation of hook_modules_installed(). - */ -function system_test_modules_installed($modules) { - if (in_array('aggregator', $modules)) { - drupal_set_message(t('hook_modules_installed fired for aggregator')); - } -} - -/** - * Implementation of hook_modules_enabled(). - */ -function system_test_modules_enabled($modules) { - if (in_array('aggregator', $modules)) { - drupal_set_message(t('hook_modules_enabled fired for aggregator')); - } -} - -/** - * Implementation of hook_modules_disabled(). - */ -function system_test_modules_disabled($modules) { - if (in_array('aggregator', $modules)) { - drupal_set_message(t('hook_modules_disabled fired for aggregator')); - } -} - -/** - * Implementation of hook_modules_uninstalled(). - */ -function system_test_modules_uninstalled($modules) { - if (in_array('aggregator', $modules)) { - drupal_set_message(t('hook_modules_uninstalled fired for aggregator')); - } -} - -/** * Implementation of hook_boot(). */ function system_test_boot() { Index: modules/simpletest/tests/system_test.registry.inc =================================================================== RCS file: modules/simpletest/tests/system_test.registry.inc diff -N modules/simpletest/tests/system_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/system_test.registry.inc 22 May 2009 23:43:38 -0000 @@ -0,0 +1,99 @@ + 'system_test_basic_auth_page', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + $items['system-test/redirect/%'] = array( + 'title' => 'Redirect', + 'page callback' => 'system_test_redirect', + 'page arguments' => array(2), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['system-test/set-header'] = array( + 'page callback' => 'system_test_set_header', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['system-test/redirect-noscheme'] = array( + 'page callback' => 'system_test_redirect_noscheme', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['system-test/redirect-noparse'] = array( + 'page callback' => 'system_test_redirect_noparse', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['system-test/redirect-invalid-scheme'] = array( + 'page callback' => 'system_test_redirect_invalid_scheme', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + $items['system-test/destination'] = array( + 'title' => 'Redirect', + 'page callback' => 'system_test_destination', + 'page arguments' => array(2), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['system-test/variable-get'] = array( + 'title' => 'Variable Get', + 'page callback' => 'variable_get', + 'page arguments' => array('simpletest_bootstrap_variable_test', NULL), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implementation of hook_modules_installed(). + */ +function system_test_modules_installed($modules) { + if (in_array('aggregator', $modules)) { + drupal_set_message(t('hook_modules_installed fired for aggregator')); + } +} + +/** + * Implementation of hook_modules_enabled(). + */ +function system_test_modules_enabled($modules) { + if (in_array('aggregator', $modules)) { + drupal_set_message(t('hook_modules_enabled fired for aggregator')); + } +} + +/** + * Implementation of hook_modules_disabled(). + */ +function system_test_modules_disabled($modules) { + if (in_array('aggregator', $modules)) { + drupal_set_message(t('hook_modules_disabled fired for aggregator')); + } +} + +/** + * Implementation of hook_modules_uninstalled(). + */ +function system_test_modules_uninstalled($modules) { + if (in_array('aggregator', $modules)) { + drupal_set_message(t('hook_modules_uninstalled fired for aggregator')); + } +} + Index: modules/simpletest/tests/taxonomy_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/taxonomy_test.info,v retrieving revision 1.3 diff -u -p -r1.3 taxonomy_test.info --- modules/simpletest/tests/taxonomy_test.info 5 Apr 2009 12:21:12 -0000 1.3 +++ modules/simpletest/tests/taxonomy_test.info 22 May 2009 23:43:38 -0000 @@ -7,3 +7,4 @@ core = 7.x files[] = taxonomy_test.module hidden = TRUE dependencies[] = taxonomy +files[] = taxonomy_test.taxonomy.inc Index: modules/simpletest/tests/taxonomy_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/taxonomy_test.module,v retrieving revision 1.3 diff -u -p -r1.3 taxonomy_test.module --- modules/simpletest/tests/taxonomy_test.module 5 Dec 2008 22:18:45 -0000 1.3 +++ modules/simpletest/tests/taxonomy_test.module 22 May 2009 23:43:38 -0000 @@ -16,40 +16,6 @@ function taxonomy_test_taxonomy_term_loa } /** - * Implementation of hook_taxonomy_term_insert(). - */ -function taxonomy_test_taxonomy_term_insert($term) { - if (!empty($term->antonyms)) { - foreach (explode ("\n", str_replace("\r", '', $term->antonyms)) as $antonym) { - if ($antonym) { - db_insert('term_antonym')->fields(array('tid' => $term->tid, 'name' => rtrim($antonym)))->execute(); - } - } - } -} - -/** - * Implementation of hook_taxonomy_term_update(). - */ -function taxonomy_test_taxonomy_term_update($term) { - taxonomy_test_taxonomy_term_delete($term); - if (!empty($term->antonyms)) { - foreach (explode ("\n", str_replace("\r", '', $term->antonyms)) as $antonym) { - if ($antonym) { - db_insert('term_antonym')->fields(array('tid' => $term->tid, 'name' => rtrim($antonym)))->execute(); - } - } - } -} - -/** - * Implementation of hook_taxonomy_term_delete(). - */ -function taxonomy_test_taxonomy_term_delete($term) { - db_delete('term_antonym')->condition('tid', $term->tid)->execute(); -} - -/** * Implementation of hook_form_alter(). */ function taxonomy_test_form_alter(&$form, $form_state, $form_id) { Index: modules/simpletest/tests/taxonomy_test.taxonomy.inc =================================================================== RCS file: modules/simpletest/tests/taxonomy_test.taxonomy.inc diff -N modules/simpletest/tests/taxonomy_test.taxonomy.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/taxonomy_test.taxonomy.inc 22 May 2009 23:43:38 -0000 @@ -0,0 +1,42 @@ +antonyms)) { + foreach (explode ("\n", str_replace("\r", '', $term->antonyms)) as $antonym) { + if ($antonym) { + db_insert('term_antonym')->fields(array('tid' => $term->tid, 'name' => rtrim($antonym)))->execute(); + } + } + } +} + +/** + * Implementation of hook_taxonomy_term_update(). + */ +function taxonomy_test_taxonomy_term_update($term) { + taxonomy_test_taxonomy_term_delete($term); + if (!empty($term->antonyms)) { + foreach (explode ("\n", str_replace("\r", '', $term->antonyms)) as $antonym) { + if ($antonym) { + db_insert('term_antonym')->fields(array('tid' => $term->tid, 'name' => rtrim($antonym)))->execute(); + } + } + } +} + +/** + * Implementation of hook_taxonomy_term_delete(). + */ +function taxonomy_test_taxonomy_term_delete($term) { + db_delete('term_antonym')->condition('tid', $term->tid)->execute(); +} + Index: modules/simpletest/tests/xmlrpc_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/xmlrpc_test.info,v retrieving revision 1.1 diff -u -p -r1.1 xmlrpc_test.info --- modules/simpletest/tests/xmlrpc_test.info 9 Aug 2008 12:41:22 -0000 1.1 +++ modules/simpletest/tests/xmlrpc_test.info 22 May 2009 23:43:38 -0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = xmlrpc_test.module hidden = TRUE +files[] = xmlrpc_test.xmlrpc.inc Index: modules/simpletest/tests/xmlrpc_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/xmlrpc_test.module,v retrieving revision 1.3 diff -u -p -r1.3 xmlrpc_test.module --- modules/simpletest/tests/xmlrpc_test.module 15 Oct 2008 13:56:08 -0000 1.3 +++ modules/simpletest/tests/xmlrpc_test.module 22 May 2009 23:43:38 -0000 @@ -47,23 +47,6 @@ function xmlrpc_test_simpleStructReturnT } /** - * Implementation of hook_xmlrpc() - */ -function xmlrpc_test_xmlrpc() { - return array( - 'validator1.arrayOfStructsTest' => 'xmlrpc_test_arrayOfStructsTest', - 'validator1.countTheEntities' => 'xmlrpc_test_countTheEntities', - 'validator1.easyStructTest' => 'xmlrpc_test_easyStructTest', - 'validator1.echoStructTest' => 'xmlrpc_test_echoStructTest', - 'validator1.manyTypesTest' => 'xmlrpc_test_manyTypesTest', - 'validator1.moderateSizeArrayCheck' => 'xmlrpc_test_moderateSizeArrayCheck', - 'validator1.nestedStructTest' => 'xmlrpc_test_nestedStructTest', - 'validator1.simpleStructReturnTest' => 'xmlrpc_test_simpleStructReturnTest', - 'messages.messageSizedInKB' => 'xmlrpc_test_message_sized_in_kb', - ); -} - -/** * Created a message of the desired size in KB. * * @param $size Index: modules/simpletest/tests/xmlrpc_test.xmlrpc.inc =================================================================== RCS file: modules/simpletest/tests/xmlrpc_test.xmlrpc.inc diff -N modules/simpletest/tests/xmlrpc_test.xmlrpc.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/simpletest/tests/xmlrpc_test.xmlrpc.inc 22 May 2009 23:43:38 -0000 @@ -0,0 +1,25 @@ + 'xmlrpc_test_arrayOfStructsTest', + 'validator1.countTheEntities' => 'xmlrpc_test_countTheEntities', + 'validator1.easyStructTest' => 'xmlrpc_test_easyStructTest', + 'validator1.echoStructTest' => 'xmlrpc_test_echoStructTest', + 'validator1.manyTypesTest' => 'xmlrpc_test_manyTypesTest', + 'validator1.moderateSizeArrayCheck' => 'xmlrpc_test_moderateSizeArrayCheck', + 'validator1.nestedStructTest' => 'xmlrpc_test_nestedStructTest', + 'validator1.simpleStructReturnTest' => 'xmlrpc_test_simpleStructReturnTest', + 'messages.messageSizedInKB' => 'xmlrpc_test_message_sized_in_kb', + ); +} + Index: modules/statistics/statistics.block.inc =================================================================== RCS file: modules/statistics/statistics.block.inc diff -N modules/statistics/statistics.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/statistics/statistics.block.inc 22 May 2009 23:43:35 -0000 @@ -0,0 +1,41 @@ + t('Disabled')) + drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40)); + $form['statistics_block_top_day_num'] = array('#type' => 'select', '#title' => t("Number of day's top views to display"), '#default_value' => variable_get('statistics_block_top_day_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "day" list.')); + $form['statistics_block_top_all_num'] = array('#type' => 'select', '#title' => t('Number of all time views to display'), '#default_value' => variable_get('statistics_block_top_all_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "all time" list.')); + $form['statistics_block_top_last_num'] = array('#type' => 'select', '#title' => t('Number of most recent views to display'), '#default_value' => variable_get('statistics_block_top_last_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "recently viewed" list.')); + return $form; +} + +/** + * Implementation of hook_block_save(). + */ +function statistics_block_save($delta = '', $edit = array()) { + variable_set('statistics_block_top_day_num', $edit['statistics_block_top_day_num']); + variable_set('statistics_block_top_all_num', $edit['statistics_block_top_all_num']); + variable_set('statistics_block_top_last_num', $edit['statistics_block_top_last_num']); +} + Index: modules/statistics/statistics.cron.inc =================================================================== RCS file: modules/statistics/statistics.cron.inc diff -N modules/statistics/statistics.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/statistics/statistics.cron.inc 22 May 2009 23:43:35 -0000 @@ -0,0 +1,28 @@ += 86400) { + // Reset day counts. + db_update('node_counter') + ->fields(array('daycount' => 0)) + ->execute(); + variable_set('statistics_day_timestamp', REQUEST_TIME); + } + + // Clean up expired access logs. + db_delete('accesslog') + ->condition('timestamp', REQUEST_TIME - variable_get('statistics_flush_accesslog_timer', 259200), '<') + ->execute(); +} + Index: modules/statistics/statistics.help.inc =================================================================== RCS file: modules/statistics/statistics.help.inc diff -N modules/statistics/statistics.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/statistics/statistics.help.inc 22 May 2009 23:43:35 -0000 @@ -0,0 +1,39 @@ +' . t('The statistics module keeps track of numerous site usage statistics, including the number of times, and from where, each of your posts is viewed. These statistics are useful in determining how users are interacting with each other and with your site, and are required for the display of some Drupal blocks.') . ''; + $output .= '' . t('The statistics module provides:') . '
'; + $output .= '' . t('Configuring the statistics module') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Statistics module.', array('@statistics' => 'http://drupal.org/handbook/modules/statistics/')) . '
'; + return $output; + case 'admin/settings/statistics': + return '' . t('Settings for the statistical information that Drupal will keep about the site. See site statistics for the actual information.', array('@statistics' => url('admin/reports/hits'))) . '
'; + case 'admin/reports/hits': + return '' . t("This page displays the site's most recent hits.") . '
'; + case 'admin/reports/referrers': + return '' . t('This page displays all external referrers, or external references to your website.') . '
'; + case 'admin/reports/visitors': + return '' . t("When you ban a visitor, you prevent the visitor's IP address from accessing your site. Unlike blocking a user, banning a visitor works even for anonymous users. This is most commonly used to block resource-intensive bots or web crawlers.") . '
'; + } +} + Index: modules/statistics/statistics.info =================================================================== RCS file: /cvs/drupal/drupal/modules/statistics/statistics.info,v retrieving revision 1.8 diff -u -p -r1.8 statistics.info --- modules/statistics/statistics.info 11 Oct 2008 02:33:02 -0000 1.8 +++ modules/statistics/statistics.info 22 May 2009 23:43:35 -0000 @@ -8,3 +8,10 @@ files[] = statistics.module files[] = statistics.admin.inc files[] = statistics.pages.inc files[] = statistics.install +files[] = statistics.registry.inc +files[] = statistics.user.inc +files[] = statistics.block.inc +files[] = statistics.node.inc +files[] = statistics.search.inc +files[] = statistics.cron.inc +files[] = statistics.help.inc Index: modules/statistics/statistics.module =================================================================== RCS file: /cvs/drupal/drupal/modules/statistics/statistics.module,v retrieving revision 1.303 diff -u -p -r1.303 statistics.module --- modules/statistics/statistics.module 3 May 2009 10:11:35 -0000 1.303 +++ modules/statistics/statistics.module 22 May 2009 23:43:35 -0000 @@ -7,37 +7,6 @@ */ /** - * Implementation of hook_help(). - */ -function statistics_help($path, $arg) { - switch ($path) { - case 'admin/help#statistics': - $output = '' . t('The statistics module keeps track of numerous site usage statistics, including the number of times, and from where, each of your posts is viewed. These statistics are useful in determining how users are interacting with each other and with your site, and are required for the display of some Drupal blocks.') . '
'; - $output .= '' . t('The statistics module provides:') . '
'; - $output .= '' . t('Configuring the statistics module') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Statistics module.', array('@statistics' => 'http://drupal.org/handbook/modules/statistics/')) . '
'; - return $output; - case 'admin/settings/statistics': - return '' . t('Settings for the statistical information that Drupal will keep about the site. See site statistics for the actual information.', array('@statistics' => url('admin/reports/hits'))) . '
'; - case 'admin/reports/hits': - return '' . t("This page displays the site's most recent hits.") . '
'; - case 'admin/reports/referrers': - return '' . t('This page displays all external referrers, or external references to your website.') . '
'; - case 'admin/reports/visitors': - return '' . t("When you ban a visitor, you prevent the visitor's IP address from accessing your site. Unlike blocking a user, banning a visitor works even for anonymous users. This is most commonly used to block resource-intensive bots or web crawlers.") . '
'; - } -} - -/** * Implementation of hook_exit(). * * This is where statistics are gathered on page accesses. @@ -81,26 +50,6 @@ function statistics_exit() { } /** - * Implementation of hook_perm(). - */ -function statistics_perm() { - return array( - 'access statistics' => array( - 'title' => t('Access statistics'), - 'description' => t('View content access statistics.'), - ), - 'administer statistics' => array( - 'title' => t('Administer statistics'), - 'description' => t('Configure statistics settings.'), - ), - 'view post access counter' => array( - 'title' => t('View post access counter'), - 'description' => t('View the total number of times a piece of content has been accessed.'), - ), - ); -} - -/** * Implementation of hook_node_view(). */ function statistics_node_view($node, $teaser) { @@ -121,111 +70,6 @@ function statistics_node_view($node, $te } /** - * Implementation of hook_menu(). - */ -function statistics_menu() { - $items['admin/reports/hits'] = array( - 'title' => 'Recent hits', - 'description' => 'View pages that have recently been visited.', - 'page callback' => 'statistics_recent_hits', - 'access arguments' => array('access statistics'), - ); - $items['admin/reports/pages'] = array( - 'title' => 'Top pages', - 'description' => 'View pages that have been hit frequently.', - 'page callback' => 'statistics_top_pages', - 'access arguments' => array('access statistics'), - 'weight' => 1, - ); - $items['admin/reports/visitors'] = array( - 'title' => 'Top visitors', - 'description' => 'View visitors that hit many pages.', - 'page callback' => 'statistics_top_visitors', - 'access arguments' => array('access statistics'), - 'weight' => 2, - ); - $items['admin/reports/referrers'] = array( - 'title' => 'Top referrers', - 'description' => 'View top referrers.', - 'page callback' => 'statistics_top_referrers', - 'access arguments' => array('access statistics'), - ); - $items['admin/reports/access/%'] = array( - 'title' => 'Details', - 'description' => 'View access log.', - 'page callback' => 'statistics_access_log', - 'page arguments' => array(3), - 'access arguments' => array('access statistics'), - 'type' => MENU_CALLBACK, - ); - $items['admin/settings/statistics'] = array( - 'title' => 'Statistics', - 'description' => 'Control details about what and how your site logs access statistics.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('statistics_settings_form'), - 'access arguments' => array('administer statistics'), - ); - $items['user/%user/track/navigation'] = array( - 'title' => 'Track page visits', - 'page callback' => 'statistics_user_tracker', - 'access callback' => 'user_access', - 'access arguments' => array('access statistics'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 2, - ); - $items['node/%node/track'] = array( - 'title' => 'Track', - 'page callback' => 'statistics_node_tracker', - 'access callback' => 'user_access', - 'access arguments' => array('access statistics'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 2, - ); - - return $items; -} - -/** - * Implementation of hook_user_cancel(). - */ -function statistics_user_cancel($edit, $account, $method) { - switch ($method) { - case 'user_cancel_reassign': - db_update('accesslog') - ->fields(array('uid' => 0)) - ->condition('uid', $account->uid) - ->execute(); - break; - - case 'user_cancel_delete': - db_delete('accesslog') - ->condition('uid', $account->uid) - ->execute(); - break; - } -} - -/** - * Implementation of hook_cron(). - */ -function statistics_cron() { - $statistics_timestamp = variable_get('statistics_day_timestamp', ''); - - if ((REQUEST_TIME - $statistics_timestamp) >= 86400) { - // Reset day counts. - db_update('node_counter') - ->fields(array('daycount' => 0)) - ->execute(); - variable_set('statistics_day_timestamp', REQUEST_TIME); - } - - // Clean up expired access logs. - db_delete('accesslog') - ->condition('timestamp', REQUEST_TIME - variable_get('statistics_flush_accesslog_timer', 259200), '<') - ->execute(); -} - -/** * Returns all time or today top or last viewed node(s). * * @param $dbfield @@ -283,39 +127,6 @@ function statistics_get($nid) { } /** - * Implementation of hook_block_list(). - */ -function statistics_block_list() { - if (variable_get('statistics_count_content_views', 0)) { - $blocks['popular']['info'] = t('Popular content'); - // Too dynamic to cache. - $blocks['popular']['cache'] = BLOCK_NO_CACHE; - return $blocks; - } -} - -/** - * Implementation of hook_block_configure(). - */ -function statistics_block_configure($delta = '') { - // Popular content block settings - $numbers = array('0' => t('Disabled')) + drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40)); - $form['statistics_block_top_day_num'] = array('#type' => 'select', '#title' => t("Number of day's top views to display"), '#default_value' => variable_get('statistics_block_top_day_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "day" list.')); - $form['statistics_block_top_all_num'] = array('#type' => 'select', '#title' => t('Number of all time views to display'), '#default_value' => variable_get('statistics_block_top_all_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "all time" list.')); - $form['statistics_block_top_last_num'] = array('#type' => 'select', '#title' => t('Number of most recent views to display'), '#default_value' => variable_get('statistics_block_top_last_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "recently viewed" list.')); - return $form; -} - -/** - * Implementation of hook_block_save(). - */ -function statistics_block_save($delta = '', $edit = array()) { - variable_set('statistics_block_top_day_num', $edit['statistics_block_top_day_num']); - variable_set('statistics_block_top_all_num', $edit['statistics_block_top_all_num']); - variable_set('statistics_block_top_last_num', $edit['statistics_block_top_last_num']); -} - -/** * Implementation of hook_block_view(). */ function statistics_block_view($delta = '') { @@ -362,36 +173,3 @@ function _statistics_format_item($title, return $output; } -/** - * Implementation of hook_node_delete(). - */ -function statistics_node_delete($node) { - // clean up statistics table when node is deleted - db_delete('node_counter') - ->condition('nid', $node->nid) - ->execute(); -} - -/** - * Implementation of hook_ranking(). - */ -function statistics_ranking() { - if (variable_get('statistics_count_content_views', 0)) { - return array( - 'views' => array( - 'title' => t('Number of views'), - 'join' => 'LEFT JOIN {node_counter} node_counter ON node_counter.nid = i.sid', - // Inverse law that maps the highest view count on the site to 1 and 0 to 0. - 'score' => '2.0 - 2.0 / (1.0 + node_counter.totalcount * CAST(%f AS DECIMAL))', - 'arguments' => array(variable_get('node_cron_views_scale', 0)), - ), - ); - } -} - -/** - * Implementation of hook_update_index(). - */ -function statistics_update_index() { - variable_set('node_cron_views_scale', 1.0 / max(1, db_result(db_query('SELECT MAX(totalcount) FROM {node_counter}')))); -} Index: modules/statistics/statistics.node.inc =================================================================== RCS file: modules/statistics/statistics.node.inc diff -N modules/statistics/statistics.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/statistics/statistics.node.inc 22 May 2009 23:43:35 -0000 @@ -0,0 +1,18 @@ +condition('nid', $node->nid) + ->execute(); +} + Index: modules/statistics/statistics.registry.inc =================================================================== RCS file: modules/statistics/statistics.registry.inc diff -N modules/statistics/statistics.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/statistics/statistics.registry.inc 22 May 2009 23:43:34 -0000 @@ -0,0 +1,73 @@ + 'Recent hits', + 'description' => 'View pages that have recently been visited.', + 'page callback' => 'statistics_recent_hits', + 'access arguments' => array('access statistics'), + ); + $items['admin/reports/pages'] = array( + 'title' => 'Top pages', + 'description' => 'View pages that have been hit frequently.', + 'page callback' => 'statistics_top_pages', + 'access arguments' => array('access statistics'), + 'weight' => 1, + ); + $items['admin/reports/visitors'] = array( + 'title' => 'Top visitors', + 'description' => 'View visitors that hit many pages.', + 'page callback' => 'statistics_top_visitors', + 'access arguments' => array('access statistics'), + 'weight' => 2, + ); + $items['admin/reports/referrers'] = array( + 'title' => 'Top referrers', + 'description' => 'View top referrers.', + 'page callback' => 'statistics_top_referrers', + 'access arguments' => array('access statistics'), + ); + $items['admin/reports/access/%'] = array( + 'title' => 'Details', + 'description' => 'View access log.', + 'page callback' => 'statistics_access_log', + 'page arguments' => array(3), + 'access arguments' => array('access statistics'), + 'type' => MENU_CALLBACK, + ); + $items['admin/settings/statistics'] = array( + 'title' => 'Statistics', + 'description' => 'Control details about what and how your site logs access statistics.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('statistics_settings_form'), + 'access arguments' => array('administer statistics'), + ); + $items['user/%user/track/navigation'] = array( + 'title' => 'Track page visits', + 'page callback' => 'statistics_user_tracker', + 'access callback' => 'user_access', + 'access arguments' => array('access statistics'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 2, + ); + $items['node/%node/track'] = array( + 'title' => 'Track', + 'page callback' => 'statistics_node_tracker', + 'access callback' => 'user_access', + 'access arguments' => array('access statistics'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 2, + ); + + return $items; +} + Index: modules/statistics/statistics.search.inc =================================================================== RCS file: modules/statistics/statistics.search.inc diff -N modules/statistics/statistics.search.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/statistics/statistics.search.inc 22 May 2009 23:43:35 -0000 @@ -0,0 +1,31 @@ + array( + 'title' => t('Number of views'), + 'join' => 'LEFT JOIN {node_counter} node_counter ON node_counter.nid = i.sid', + // Inverse law that maps the highest view count on the site to 1 and 0 to 0. + 'score' => '2.0 - 2.0 / (1.0 + node_counter.totalcount * CAST(%f AS DECIMAL))', + 'arguments' => array(variable_get('node_cron_views_scale', 0)), + ), + ); + } +} + +/** + * Implementation of hook_update_index(). + */ +function statistics_update_index() { + variable_set('node_cron_views_scale', 1.0 / max(1, db_result(db_query('SELECT MAX(totalcount) FROM {node_counter}')))); +} Index: modules/statistics/statistics.user.inc =================================================================== RCS file: modules/statistics/statistics.user.inc diff -N modules/statistics/statistics.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/statistics/statistics.user.inc 22 May 2009 23:43:35 -0000 @@ -0,0 +1,48 @@ + array( + 'title' => t('Access statistics'), + 'description' => t('View content access statistics.'), + ), + 'administer statistics' => array( + 'title' => t('Administer statistics'), + 'description' => t('Configure statistics settings.'), + ), + 'view post access counter' => array( + 'title' => t('View post access counter'), + 'description' => t('View the total number of times a piece of content has been accessed.'), + ), + ); +} + +/** + * Implementation of hook_user_cancel(). + */ +function statistics_user_cancel($edit, $account, $method) { + switch ($method) { + case 'user_cancel_reassign': + db_update('accesslog') + ->fields(array('uid' => 0)) + ->condition('uid', $account->uid) + ->execute(); + break; + + case 'user_cancel_delete': + db_delete('accesslog') + ->condition('uid', $account->uid) + ->execute(); + break; + } +} + Index: modules/syslog/syslog.form.inc =================================================================== RCS file: modules/syslog/syslog.form.inc diff -N modules/syslog/syslog.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/syslog/syslog.form.inc 22 May 2009 23:43:34 -0000 @@ -0,0 +1,23 @@ + 'select', + '#title' => t('Send events to this syslog facility'), + '#default_value' => variable_get('syslog_facility', DEFAULT_SYSLOG_FACILITY), + '#options' => syslog_facility_list(), + '#description' => t('Select the syslog facility code under which Drupal\'s messages should be sent. On UNIX/Linux systems, Drupal can flag its messages with the code LOG_LOCAL0 through LOG_LOCAL7; for Microsoft Windows, all messages are flagged with the code LOG_USER. Depending on the system configuration, syslog and other logging tools use this code to identify or filter Drupal messages from within the entire system log. For more information on syslog, see Syslog help.', array( + '@syslog_help' => url('admin/help/syslog'))), + ); + $form['buttons']['#weight'] = 1; +} + Index: modules/syslog/syslog.help.inc =================================================================== RCS file: modules/syslog/syslog.help.inc diff -N modules/syslog/syslog.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/syslog/syslog.help.inc 22 May 2009 23:43:34 -0000 @@ -0,0 +1,21 @@ +' . t("The syslog module enables Drupal to send messages to the operating system's logging facility.") . ''; + $output .= '' . t('Syslog is an operating system administrative logging tool, and provides valuable information for use in system management and security auditing. Most suited to medium and large sites, syslog provides filtering tools that allow messages to be routed by type and severity. On UNIX/Linux systems, the file /etc/syslog.conf defines this routing configuration; on Microsoft Windows, all messages are sent to the Event Log. For more information on syslog facilities, severity levels, and how to set up a syslog.conf file, see UNIX/Linux syslog.conf and PHP\'s openlog and syslog functions.', array('@syslog_conf' => url('http://www.rt.com/man/syslog.5.html'), '@php_openlog' => url('http://www.php.net/manual/function.openlog.php'), '@php_syslog' => url('http://www.php.net/manual/function.syslog.php'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Syslog module.', array('@syslog' => 'http://drupal.org/handbook/modules/syslog')) . '
'; + return $output; + } +} + Index: modules/syslog/syslog.info =================================================================== RCS file: /cvs/drupal/drupal/modules/syslog/syslog.info,v retrieving revision 1.5 diff -u -p -r1.5 syslog.info --- modules/syslog/syslog.info 11 Oct 2008 02:33:03 -0000 1.5 +++ modules/syslog/syslog.info 22 May 2009 23:43:34 -0000 @@ -5,3 +5,7 @@ package = Core version = VERSION core = 7.x files[] = syslog.module +files[] = syslog.registry.inc +files[] = syslog.form.inc +files[] = syslog.help.inc +files[] = syslog.watchdog.inc Index: modules/syslog/syslog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/syslog/syslog.module,v retrieving revision 1.22 diff -u -p -r1.22 syslog.module --- modules/syslog/syslog.module 13 Apr 2009 08:49:01 -0000 1.22 +++ modules/syslog/syslog.module 22 May 2009 23:43:34 -0000 @@ -13,34 +13,6 @@ else { define('DEFAULT_SYSLOG_FACILITY', LOG_USER); } -/** - * Implementation of hook_help(). - */ -function syslog_help($path, $arg) { - switch ($path) { - case 'admin/help#syslog': - $output = '' . t("The syslog module enables Drupal to send messages to the operating system's logging facility.") . '
'; - $output .= '' . t('Syslog is an operating system administrative logging tool, and provides valuable information for use in system management and security auditing. Most suited to medium and large sites, syslog provides filtering tools that allow messages to be routed by type and severity. On UNIX/Linux systems, the file /etc/syslog.conf defines this routing configuration; on Microsoft Windows, all messages are sent to the Event Log. For more information on syslog facilities, severity levels, and how to set up a syslog.conf file, see UNIX/Linux syslog.conf and PHP\'s openlog and syslog functions.', array('@syslog_conf' => url('http://www.rt.com/man/syslog.5.html'), '@php_openlog' => url('http://www.php.net/manual/function.openlog.php'), '@php_syslog' => url('http://www.php.net/manual/function.syslog.php'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Syslog module.', array('@syslog' => 'http://drupal.org/handbook/modules/syslog')) . '
'; - return $output; - } -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function syslog_form_system_logging_settings_alter(&$form, &$form_state) { - $form['syslog_facility'] = array( - '#type' => 'select', - '#title' => t('Send events to this syslog facility'), - '#default_value' => variable_get('syslog_facility', DEFAULT_SYSLOG_FACILITY), - '#options' => syslog_facility_list(), - '#description' => t('Select the syslog facility code under which Drupal\'s messages should be sent. On UNIX/Linux systems, Drupal can flag its messages with the code LOG_LOCAL0 through LOG_LOCAL7; for Microsoft Windows, all messages are flagged with the code LOG_USER. Depending on the system configuration, syslog and other logging tools use this code to identify or filter Drupal messages from within the entire system log. For more information on syslog, see Syslog help.', array( - '@syslog_help' => url('admin/help/syslog'))), - ); - $form['buttons']['#weight'] = 1; -} - function syslog_facility_list() { $facility_list = array( LOG_USER => t('LOG_USER - User level messages. Use this for Windows.'), @@ -61,28 +33,6 @@ function syslog_facility_list() { } /** - * Implementation of hook_watchdog(). - */ -function syslog_watchdog(array $log_entry) { - static $log_init = FALSE; - - if (!$log_init) { - $log_init = TRUE; - openlog('drupal', LOG_NDELAY, variable_get('syslog_facility', DEFAULT_SYSLOG_FACILITY)); - } - - syslog($log_entry['severity'], theme('syslog_format', $log_entry)); -} - -function syslog_theme() { - return array( - 'syslog_format' => array( - 'arguments' => array('entry' => NULL), - ), - ); -} - -/** * Format a system log entry. * * @ingroup themeable Index: modules/syslog/syslog.registry.inc =================================================================== RCS file: modules/syslog/syslog.registry.inc diff -N modules/syslog/syslog.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/syslog/syslog.registry.inc 22 May 2009 23:43:34 -0000 @@ -0,0 +1,16 @@ + array( + 'arguments' => array('entry' => NULL), + ), + ); +} + Index: modules/syslog/syslog.watchdog.inc =================================================================== RCS file: modules/syslog/syslog.watchdog.inc diff -N modules/syslog/syslog.watchdog.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/syslog/syslog.watchdog.inc 22 May 2009 23:43:34 -0000 @@ -0,0 +1,22 @@ + $array) { + if ($array['configurable']) { + $options[$key] = $array['description'] . '...'; + } + else { + $unconfigurable[] = $array; + } + } + + $row = array(); + $instances_present = db_query("SELECT aid FROM {actions} WHERE parameters <> ''")->fetchField(); + $header = array( + array('data' => t('Action type'), 'field' => 'type'), + array('data' => t('Description'), 'field' => 'description'), + array('data' => $instances_present ? t('Operations') : '', 'colspan' => '2') + ); + $query = db_select('actions')->extend('PagerDefault')->extend('TableSort'); + $result = $query + ->fields('actions') + ->limit(50) + ->orderByHeader($header) + ->execute(); + + foreach ($result as $action) { + $row[] = array( + array('data' => $action->type), + array('data' => $action->description), + array('data' => $action->parameters ? l(t('configure'), "admin/settings/actions/configure/$action->aid") : ''), + array('data' => $action->parameters ? l(t('delete'), "admin/settings/actions/delete/$action->aid") : '') + ); + } + + if ($row) { + $pager = theme('pager', NULL); + if (!empty($pager)) { + $row[] = array(array('data' => $pager, 'colspan' => '3')); + } + $output .= '' . t('The system module provides:') . '
'; + $output .= '' . t('For more information, see the online handbook entry for System module.', array('@system' => 'http://drupal.org/handbook/modules/system/')) . '
'; + return $output; + case 'admin/by-module': + return '' . t('This page shows you all available administration tasks for each module.') . '
'; + case 'admin/build/themes': + $output = '' . t('Select which themes are available to your users and specify the default theme. To configure site-wide display settings, click the "configure" task above. Alternatively, to override these settings in a specific theme, click the "configure" link for that theme. Note that different themes may have different regions available for displaying content; for consistency in presentation, you may wish to enable only one theme.') . '
'; + $output .= '' . t('To change the appearance of your site, a number of contributed themes are available.', array('@themes' => 'http://drupal.org/project/themes')) . '
'; + return $output; + case 'admin/build/themes/settings/' . $arg[4]: + $reference = explode('.', $arg[4], 2); + $theme = array_pop($reference); + return '' . t('These options control the display settings for the %template theme. When your site is displayed using this theme, these settings will be used. By clicking "Reset to defaults," you can choose to use the global settings for this theme.', array('%template' => $theme, '@global' => url('admin/build/themes/settings'))) . '
' . t('These options control the default display settings for your entire site, across all themes. Unless they have been overridden by a specific theme, these settings will be used.') . '
'; + case 'admin/build/modules': + $output = '' . t('Modules are plugins that extend Drupal\'s core functionality. To enable modules, select the Enabled checkboxes below and click the Save configuration button. To further extend your site\'s functionality, a number of contributed modules are available for download.', array('@permissions' => url('admin/user/permissions'), '@modules' => 'http://drupal.org/project/modules')) . '
'; + $output .= '' . t('Module-related tasks can be located on the administration by module page. New module-related permissions may also become available as new modules are enabled.', array('@by-module' => url('admin/by-module'), '@permissions' => url('admin/user/permissions'))) . '
'; + $output .= '' . t('Each time a module is updated, it is important that update.php is run. To help manage the update process, the Update status module, if enabled, provides information on new versions of modules (and themes) as they are released. Regular review of the available updates page is essential to maintaining a secure and current site.', array('@update-php' => $base_url . '/update.php', '@updates' => url('admin/reports/updates'))) . '
'; + return $output; + case 'admin/build/modules/uninstall': + return '' . t('The uninstall process removes all data related to a module. To uninstall a module, you must first disable it. Not all modules support this feature.') . '
'; + case 'admin/build/block/configure': + if ($arg[4] == 'system' && $arg[5] == 'powered-by') { + return '' . t('The Powered by Drupal block is an optional link to the home page of the Drupal project. While there is absolutely no requirement that sites feature this link, it may be used to show support for Drupal.') . '
'; + } + break; + case 'admin/settings/actions': + case 'admin/settings/actions/manage': + $output = '' . t('Actions are individual tasks that the system can do, such as unpublishing a piece of content or banning a user. Modules, such as the trigger module, can fire these actions when certain system events happen; for example, when a new post is added or when a user logs in. Modules may also provide additional actions.') . '
'; + $output .= '' . t('There are two types of actions: simple and advanced. Simple actions do not require any additional configuration, and are listed here automatically. Advanced actions can do more than simple actions; for example, send an e-mail to a specified address, or check for certain words within a piece of content. These actions need to be created and configured first before they may be used. To create an advanced action, select the action from the drop-down below and click the Create button.') . '
'; + if (module_exists('trigger')) { + $output .= '' . t('You may proceed to the Triggers page to assign these actions to system events.', array('@url' => url('admin/build/trigger'))) . '
'; + } + return $output; + case 'admin/settings/actions/configure': + return t('An advanced action offers additional configuration options which may be filled out below. Changing the Description field is recommended, in order to better identify the precise action taking place. This description will be displayed in modules such as the trigger module when assigning actions to system events, so it is best if it is as descriptive as possible (for example, "Send e-mail to Moderation Team" rather than simply "Send e-mail").'); + case 'admin/settings/ip-blocking': + return '' . t('IP addresses listed here are blocked from your site before any modules are loaded. You may add IP addresses to the list, or delete existing entries.') . '
'; + case 'admin/reports/status': + return '' . t("Here you can find a short overview of your site's parameters as well as any problems detected with your installation. It may be useful to copy and paste this information into support requests filed on drupal.org's support forums and project issue queues.") . '
'; + } +} + Index: modules/system/system.info =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.info,v retrieving revision 1.12 diff -u -p -r1.12 system.info --- modules/system/system.info 6 May 2009 10:37:28 -0000 1.12 +++ modules/system/system.info 22 May 2009 23:44:32 -0000 @@ -10,3 +10,12 @@ files[] = system.queue.inc files[] = image.gd.inc files[] = system.install required = TRUE +files[] = system.registry.inc +files[] = system.actions.inc +files[] = system.mail.inc +files[] = system.user.inc +files[] = system.block.inc +files[] = system.cron.inc +files[] = system.help.inc +files[] = system.file.inc +files[] = system.form.inc Index: modules/system/system.mail.inc =================================================================== RCS file: modules/system/system.mail.inc diff -N modules/system/system.mail.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/system/system.mail.inc 22 May 2009 23:43:33 -0000 @@ -0,0 +1,49 @@ + variable_get('site_name', 'Drupal'), + '%username' => $account->name, + ); + if ($context['hook'] == 'taxonomy') { + $object = $params['object']; + $vocabulary = taxonomy_vocabulary_load($object->vid); + $variables += array( + '%term_name' => $object->name, + '%term_description' => $object->description, + '%term_id' => $object->tid, + '%vocabulary_name' => $vocabulary->name, + '%vocabulary_description' => $vocabulary->description, + '%vocabulary_id' => $vocabulary->vid, + ); + } + + // Node-based variable translation is only available if we have a node. + if (isset($params['node'])) { + $node = $params['node']; + $variables += array( + '%uid' => $node->uid, + '%node_url' => url('node/' . $node->nid, array('absolute' => TRUE)), + '%node_type' => node_get_types('name', $node), + '%title' => $node->title, + '%teaser' => $node->teaser, + '%body' => $node->body, + ); + } + $subject = strtr($context['subject'], $variables); + $body = strtr($context['message'], $variables); + $message['subject'] .= str_replace(array("\r", "\n"), '', $subject); + $message['body'][] = drupal_html_to_text($body); +} + Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.698 diff -u -p -r1.698 system.module --- modules/system/system.module 22 May 2009 11:33:18 -0000 1.698 +++ modules/system/system.module 22 May 2009 23:44:32 -0000 @@ -57,158 +57,6 @@ define('DRUPAL_USER_TIMEZONE_EMPTY', 1); define('DRUPAL_USER_TIMEZONE_SELECT', 2); /** - * Implementation of hook_help(). - */ -function system_help($path, $arg) { - global $base_url; - - switch ($path) { - case 'admin/help#system': - $output = '' . t('The system module is at the foundation of your Drupal website, and provides basic but extensible functionality for use by other modules and themes. Some integral elements of Drupal are contained in and managed by the system module, including caching, enabling or disabling of modules and themes, preparing and displaying the administrative page, and configuring fundamental site settings. A number of key system maintenance operations are also part of the system module.') . '
'; - $output .= '' . t('The system module provides:') . '
'; - $output .= '' . t('For more information, see the online handbook entry for System module.', array('@system' => 'http://drupal.org/handbook/modules/system/')) . '
'; - return $output; - case 'admin/by-module': - return '' . t('This page shows you all available administration tasks for each module.') . '
'; - case 'admin/build/themes': - $output = '' . t('Select which themes are available to your users and specify the default theme. To configure site-wide display settings, click the "configure" task above. Alternatively, to override these settings in a specific theme, click the "configure" link for that theme. Note that different themes may have different regions available for displaying content; for consistency in presentation, you may wish to enable only one theme.') . '
'; - $output .= '' . t('To change the appearance of your site, a number of contributed themes are available.', array('@themes' => 'http://drupal.org/project/themes')) . '
'; - return $output; - case 'admin/build/themes/settings/' . $arg[4]: - $reference = explode('.', $arg[4], 2); - $theme = array_pop($reference); - return '' . t('These options control the display settings for the %template theme. When your site is displayed using this theme, these settings will be used. By clicking "Reset to defaults," you can choose to use the global settings for this theme.', array('%template' => $theme, '@global' => url('admin/build/themes/settings'))) . '
' . t('These options control the default display settings for your entire site, across all themes. Unless they have been overridden by a specific theme, these settings will be used.') . '
'; - case 'admin/build/modules': - $output = '' . t('Modules are plugins that extend Drupal\'s core functionality. To enable modules, select the Enabled checkboxes below and click the Save configuration button. To further extend your site\'s functionality, a number of contributed modules are available for download.', array('@permissions' => url('admin/user/permissions'), '@modules' => 'http://drupal.org/project/modules')) . '
'; - $output .= '' . t('Module-related tasks can be located on the administration by module page. New module-related permissions may also become available as new modules are enabled.', array('@by-module' => url('admin/by-module'), '@permissions' => url('admin/user/permissions'))) . '
'; - $output .= '' . t('Each time a module is updated, it is important that update.php is run. To help manage the update process, the Update status module, if enabled, provides information on new versions of modules (and themes) as they are released. Regular review of the available updates page is essential to maintaining a secure and current site.', array('@update-php' => $base_url . '/update.php', '@updates' => url('admin/reports/updates'))) . '
'; - return $output; - case 'admin/build/modules/uninstall': - return '' . t('The uninstall process removes all data related to a module. To uninstall a module, you must first disable it. Not all modules support this feature.') . '
'; - case 'admin/build/block/configure': - if ($arg[4] == 'system' && $arg[5] == 'powered-by') { - return '' . t('The Powered by Drupal block is an optional link to the home page of the Drupal project. While there is absolutely no requirement that sites feature this link, it may be used to show support for Drupal.') . '
'; - } - break; - case 'admin/settings/actions': - case 'admin/settings/actions/manage': - $output = '' . t('Actions are individual tasks that the system can do, such as unpublishing a piece of content or banning a user. Modules, such as the trigger module, can fire these actions when certain system events happen; for example, when a new post is added or when a user logs in. Modules may also provide additional actions.') . '
'; - $output .= '' . t('There are two types of actions: simple and advanced. Simple actions do not require any additional configuration, and are listed here automatically. Advanced actions can do more than simple actions; for example, send an e-mail to a specified address, or check for certain words within a piece of content. These actions need to be created and configured first before they may be used. To create an advanced action, select the action from the drop-down below and click the Create button.') . '
'; - if (module_exists('trigger')) { - $output .= '' . t('You may proceed to the Triggers page to assign these actions to system events.', array('@url' => url('admin/build/trigger'))) . '
'; - } - return $output; - case 'admin/settings/actions/configure': - return t('An advanced action offers additional configuration options which may be filled out below. Changing the Description field is recommended, in order to better identify the precise action taking place. This description will be displayed in modules such as the trigger module when assigning actions to system events, so it is best if it is as descriptive as possible (for example, "Send e-mail to Moderation Team" rather than simply "Send e-mail").'); - case 'admin/settings/ip-blocking': - return '' . t('IP addresses listed here are blocked from your site before any modules are loaded. You may add IP addresses to the list, or delete existing entries.') . '
'; - case 'admin/reports/status': - return '' . t("Here you can find a short overview of your site's parameters as well as any problems detected with your installation. It may be useful to copy and paste this information into support requests filed on drupal.org's support forums and project issue queues.") . '
'; - } -} - -/** - * Implementation of hook_theme(). - */ -function system_theme() { - return array_merge(drupal_common_theme(), array( - 'system_theme_select_form' => array( - 'arguments' => array('form' => NULL), - 'file' => 'system.admin.inc', - ), - 'system_themes_form' => array( - 'arguments' => array('form' => NULL), - 'file' => 'system.admin.inc', - ), - 'system_modules_fieldset' => array( - 'arguments' => array('form' => NULL), - 'file' => 'system.admin.inc', - ), - 'system_modules_incompatible' => array( - 'arguments' => array('message' => NULL), - 'file' => 'system.admin.inc', - ), - 'system_modules_uninstall' => array( - 'arguments' => array('form' => NULL), - 'file' => 'system.admin.inc', - ), - 'status_report' => array( - 'arguments' => array('requirements' => NULL), - 'file' => 'system.admin.inc', - ), - 'admin_page' => array( - 'arguments' => array('blocks' => NULL), - 'file' => 'system.admin.inc', - ), - 'admin_block' => array( - 'arguments' => array('block' => NULL), - 'file' => 'system.admin.inc', - ), - 'admin_block_content' => array( - 'arguments' => array('content' => NULL), - 'file' => 'system.admin.inc', - ), - 'system_admin_by_module' => array( - 'arguments' => array('menu_items' => NULL), - 'file' => 'system.admin.inc', - ), - 'system_powered_by' => array( - 'arguments' => array('image_path' => NULL), - ), - 'meta_generator_html' => array( - 'arguments' => array('version' => NULL), - ), - 'meta_generator_header' => array( - 'arguments' => array('version' => NULL), - ), - 'system_compact_link' => array(), - )); -} - -/** - * Implementation of hook_perm(). - */ -function system_perm() { - return array( - 'administer site configuration' => array( - 'title' => t('Administer site configuration'), - 'description' => t('Configure site-wide settings such as module or theme administration settings.'), - ), - 'administer actions' => array( - 'title' => t('Administer actions'), - 'description' => t('Manage the actions defined for your site.'), - ), - 'administer files' => array( - 'title' => t('Administer files'), - 'description' => t('Manage user-uploaded files.'), - ), - 'access administration pages' => array( - 'title' => t('Access administration pages'), - 'description' => t('View the administration panel and browse the help system.'), - ), - 'access site reports' => array( - 'title' => t('Access site reports'), - 'description' => t('View reports from system logs and other status information.'), - ), - 'select different theme' => array( - 'title' => t('Select different theme'), - 'description' => t('Select a theme other than the default theme set by the site administrator.'), - ), - 'block IP addresses' => array( - 'title' => t('Block IP addresses'), - 'description' => t('Block IP addresses from accessing your site.'), - ), - ); -} - -/** * Implementation of hook_rdf_namespaces(). */ function system_rdf_namespaces() { @@ -228,537 +76,6 @@ function system_rdf_namespaces() { } /** - * Implementation of hook_elements(). - */ -function system_elements() { - // Top level form - $type['form'] = array( - '#method' => 'post', - '#action' => request_uri(), - '#theme_wrapper' => 'form', - ); - - $type['page'] = array( - '#show_messages' => TRUE, - '#show_blocks' => TRUE, - '#theme' => 'page', - ); - - $type['list'] = array( - '#title' => '', - '#list_type' => 'ul', - '#attributes' => array(), - '#items' => array(), - ); - - /** - * Input elements. - */ - $type['submit'] = array( - '#input' => TRUE, - '#name' => 'op', - '#button_type' => 'submit', - '#executes_submit_callback' => TRUE, - '#process' => array('form_process_ahah'), - '#theme_wrapper' => 'button', - ); - - $type['button'] = array( - '#input' => TRUE, - '#name' => 'op', - '#button_type' => 'submit', - '#executes_submit_callback' => FALSE, - '#process' => array('form_process_ahah'), - '#theme_wrapper' => 'button', - ); - - $type['image_button'] = array( - '#input' => TRUE, - '#button_type' => 'submit', - '#executes_submit_callback' => TRUE, - '#process' => array('form_process_ahah'), - '#return_value' => TRUE, - '#has_garbage_value' => TRUE, - '#src' => NULL, - '#theme_wrapper' => 'image_button', - ); - - $type['textfield'] = array( - '#input' => TRUE, - '#size' => 60, - '#maxlength' => 128, - '#autocomplete_path' => FALSE, - '#process' => array('form_process_text_format', 'form_process_ahah'), - '#theme' => 'textfield', - '#theme_wrapper' => 'form_element', - ); - - $type['password'] = array( - '#input' => TRUE, - '#size' => 60, - '#maxlength' => 128, - '#process' => array('form_process_ahah'), - '#theme' => 'password', - '#theme_wrapper' => 'form_element', - ); - - $type['password_confirm'] = array( - '#input' => TRUE, - '#process' => array('form_process_password_confirm'), - '#theme_wrapper' => 'form_element', - ); - - $type['textarea'] = array( - '#input' => TRUE, - '#cols' => 60, - '#rows' => 5, - '#resizable' => TRUE, - '#process' => array('form_process_text_format', 'form_process_ahah'), - '#theme' => 'textarea', - '#theme_wrapper' => 'form_element', - ); - - $type['radios'] = array( - '#input' => TRUE, - '#process' => array('form_process_radios'), - '#theme_wrapper' => 'radios', - '#pre_render' => array('form_pre_render_conditional_form_element'), - ); - - $type['radio'] = array( - '#input' => TRUE, - '#default_value' => NULL, - '#process' => array('form_process_ahah'), - '#theme' => 'radio', - '#theme_wrapper' => 'form_element', - '#form_element_skip_title' => TRUE, - ); - - $type['checkboxes'] = array( - '#input' => TRUE, - '#tree' => TRUE, - '#process' => array('form_process_checkboxes'), - '#theme_wrapper' => 'checkboxes', - '#pre_render' => array('form_pre_render_conditional_form_element'), - ); - - $type['checkbox'] = array( - '#input' => TRUE, - '#return_value' => 1, - '#process' => array('form_process_ahah'), - '#theme' => 'checkbox', - '#theme_wrapper' => 'form_element', - '#form_element_skip_title' => TRUE, - ); - - $type['select'] = array( - '#input' => TRUE, - '#size' => 0, - '#multiple' => FALSE, - '#process' => array('form_process_ahah'), - '#theme' => 'select', - '#theme_wrapper' => 'form_element', - ); - - $type['weight'] = array( - '#input' => TRUE, - '#delta' => 10, - '#default_value' => 0, - '#process' => array('form_process_weight', 'form_process_ahah'), - ); - - $type['date'] = array( - '#input' => TRUE, - '#element_validate' => array('date_validate'), - '#process' => array('form_process_date'), - '#theme' => 'date', - '#theme_wrapper' => 'form_element', - ); - - $type['file'] = array( - '#input' => TRUE, - '#size' => 60, - '#theme' => 'file', - '#theme_wrapper' => 'form_element', - ); - - $type['tableselect'] = array( - '#input' => TRUE, - '#js_select' => TRUE, - '#multiple' => TRUE, - '#process' => array('form_process_tableselect'), - '#options' => array(), - '#empty' => '', - '#theme' => 'tableselect' - ); - - /** - * Form structure. - */ - $type['item'] = array( - '#markup' => '', - '#theme' => 'markup', - '#theme_wrapper' => 'form_element', - ); - - $type['hidden'] = array( - '#input' => TRUE, - '#process' => array('form_process_ahah'), - '#theme' => 'hidden', - ); - - $type['value'] = array( - '#input' => TRUE, - ); - - $type['markup'] = array( - '#markup' => '', - '#theme' => 'markup', - ); - - $type['fieldset'] = array( - '#collapsible' => FALSE, - '#collapsed' => FALSE, - '#value' => NULL, - '#process' => array('form_process_fieldset', 'form_process_ahah'), - '#pre_render' => array('form_pre_render_fieldset'), - '#theme_wrapper' => 'fieldset', - ); - - $type['vertical_tabs'] = array( - '#theme_wrapper' => 'vertical_tabs', - '#default_tab' => '', - '#process' => array('form_process_vertical_tabs'), - ); - - $type['token'] = array( - '#input' => TRUE, - '#theme' => array('hidden'), - ); - - return $type; -} - -/** - * Implementation of hook_menu(). - */ -function system_menu() { - $items['system/files'] = array( - 'title' => 'File download', - 'page callback' => 'file_download', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['system/ahah'] = array( - 'title' => 'AHAH callback', - 'page callback' => 'form_ahah_callback', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['system/timezone'] = array( - 'title' => 'Time zone', - 'page callback' => 'system_timezone', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['admin'] = array( - 'title' => 'Administer', - 'access arguments' => array('access administration pages'), - 'page callback' => 'system_main_admin_page', - 'weight' => 9, - 'menu_name' => 'management', - ); - $items['admin/compact'] = array( - 'title' => 'Compact mode', - 'page callback' => 'system_admin_compact_page', - 'access arguments' => array('access administration pages'), - 'type' => MENU_CALLBACK, - ); - $items['admin/by-task'] = array( - 'title' => 'By task', - 'page callback' => 'system_main_admin_page', - 'access arguments' => array('access administration pages'), - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/by-module'] = array( - 'title' => 'By module', - 'page callback' => 'system_admin_by_module', - 'access arguments' => array('access administration pages'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 2, - ); - $items['admin/content'] = array( - 'title' => 'Content management', - 'description' => "Manage your site's content.", - 'position' => 'left', - 'weight' => -10, - 'page callback' => 'system_admin_menu_block_page', - 'access arguments' => array('access administration pages'), - ); - - // menu items that are basically just menu blocks - $items['admin/settings'] = array( - 'title' => 'Site configuration', - 'description' => 'Configure site settings.', - 'position' => 'right', - 'weight' => -5, - 'page callback' => 'system_settings_overview', - 'access arguments' => array('access administration pages'), - ); - $items['admin/build'] = array( - 'title' => 'Site building', - 'description' => 'Control how your site looks and feels.', - 'position' => 'right', - 'weight' => -10, - 'page callback' => 'system_admin_menu_block_page', - 'access arguments' => array('access administration pages'), - ); - // Themes: - $items['admin/build/themes'] = array( - 'title' => 'Themes', - 'description' => 'Change which theme your site uses or allows users to set.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_themes_form'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/build/themes/select'] = array( - 'title' => 'List', - 'description' => 'Select the default theme for your site.', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -1, - ); - $items['admin/build/themes/settings'] = array( - 'title' => 'Configure', - 'page arguments' => array('system_theme_settings'), - 'access arguments' => array('administer site configuration'), - 'type' => MENU_LOCAL_TASK, - ); - // Theme configuration subtabs - $items['admin/build/themes/settings/global'] = array( - 'title' => 'Global settings', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -1, - ); - - foreach (list_themes() as $theme) { - $items['admin/build/themes/settings/' . $theme->name] = array( - 'title' => $theme->info['name'], - 'page arguments' => array('system_theme_settings', $theme->name), - 'type' => MENU_LOCAL_TASK, - 'access callback' => '_system_themes_access', - 'access arguments' => array($theme), - ); - } - - // Modules: - $items['admin/build/modules'] = array( - 'title' => 'Modules', - 'description' => 'Enable or disable add-on modules for your site.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_modules'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/build/modules/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/build/modules/list/confirm'] = array( - 'title' => 'List', - 'access arguments' => array('administer site configuration'), - 'type' => MENU_CALLBACK, - ); - $items['admin/build/modules/uninstall'] = array( - 'title' => 'Uninstall', - 'page arguments' => array('system_modules_uninstall'), - 'access arguments' => array('administer site configuration'), - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/build/modules/uninstall/confirm'] = array( - 'title' => 'Uninstall', - 'access arguments' => array('administer site configuration'), - 'type' => MENU_CALLBACK, - ); - - // Actions: - $items['admin/settings/actions'] = array( - 'title' => 'Actions', - 'description' => 'Manage the actions defined for your site.', - 'access arguments' => array('administer actions'), - 'page callback' => 'system_actions_manage' - ); - $items['admin/settings/actions/manage'] = array( - 'title' => 'Manage actions', - 'description' => 'Manage the actions defined for your site.', - 'page callback' => 'system_actions_manage', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -2, - ); - $items['admin/settings/actions/configure'] = array( - 'title' => 'Configure an advanced action', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_actions_configure'), - 'access arguments' => array('administer actions'), - 'type' => MENU_CALLBACK, - ); - $items['admin/settings/actions/delete/%actions'] = array( - 'title' => 'Delete action', - 'description' => 'Delete an action.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_actions_delete_form', 4), - 'access arguments' => array('administer actions'), - 'type' => MENU_CALLBACK, - ); - $items['admin/settings/actions/orphan'] = array( - 'title' => 'Remove orphans', - 'page callback' => 'system_actions_remove_orphans', - 'access arguments' => array('administer actions'), - 'type' => MENU_CALLBACK, - ); - - // IP address blocking. - $items['admin/settings/ip-blocking'] = array( - 'title' => 'IP address blocking', - 'description' => 'Manage blocked IP addresses.', - 'page callback' => 'system_ip_blocking', - 'access arguments' => array('block IP addresses'), - ); - $items['admin/settings/ip-blocking/%'] = array( - 'title' => 'IP address blocking', - 'description' => 'Manage blocked IP addresses.', - 'page callback' => 'system_ip_blocking', - 'access arguments' => array('block IP addresses'), - 'type' => MENU_CALLBACK, - ); - $items['admin/settings/ip-blocking/delete/%blocked_ip'] = array( - 'title' => 'Delete IP address', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_ip_blocking_delete', 4), - 'access arguments' => array('block IP addresses'), - 'type' => MENU_CALLBACK, - ); - - // Settings: - $items['admin/settings/site-information'] = array( - 'title' => 'Site information', - 'description' => 'Change basic site information, such as the site name, slogan, e-mail address, mission, front page and more.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_site_information_settings'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/settings/logging'] = array( - 'title' => 'Logging and errors', - 'description' => "Settings for logging and alerts modules. Various modules can route Drupal's system events to different destinations, such as syslog, database, email, etc.", - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_logging_settings'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/settings/logging/settings'] = array( - 'title' => 'Settings', - 'access arguments' => array('administer site configuration'), - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -1, - ); - $items['admin/settings/performance'] = array( - 'title' => 'Performance', - 'description' => 'Enable or disable page caching for anonymous users and set CSS and JS bandwidth optimization options.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_performance_settings'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/settings/file-system'] = array( - 'title' => 'File system', - 'description' => 'Tell Drupal where to store uploaded files and how they are accessed.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_file_system_settings'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/settings/image-toolkit'] = array( - 'title' => 'Image toolkit', - 'description' => 'Choose which image toolkit to use if you have installed optional toolkits.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_image_toolkit_settings'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/content/rss-publishing'] = array( - 'title' => 'RSS publishing', - 'description' => 'Configure the site description, the number of items per feed and whether feeds should be titles/teasers/full-text.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_rss_feeds_settings'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/settings/regional-settings'] = array( - 'title' => 'Regional settings', - 'description' => "Settings for how Drupal displays date and time, as well as the system's default time zone.", - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_regional_settings'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/settings/regional-settings/lookup'] = array( - 'title' => 'Date and time lookup', - 'type' => MENU_CALLBACK, - 'page callback' => 'system_date_time_lookup', - 'access arguments' => array('administer site configuration'), - ); - $items['admin/settings/maintenance-mode'] = array( - 'title' => 'Maintenance mode', - 'description' => 'Take the site offline for maintenance or bring it back online.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_site_maintenance_mode'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/settings/clean-urls'] = array( - 'title' => 'Clean URLs', - 'description' => 'Enable or disable clean URLs for your site.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('system_clean_url_settings'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/settings/clean-urls/check'] = array( - 'title' => 'Clean URL check', - 'page callback' => 'drupal_json', - 'page arguments' => array(array('status' => TRUE)), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - - // Reports: - $items['admin/reports'] = array( - 'title' => 'Reports', - 'description' => 'View reports from system logs and other status information.', - 'page callback' => 'system_admin_menu_block_page', - 'access arguments' => array('access site reports'), - 'weight' => 5, - 'position' => 'left', - ); - $items['admin/reports/status'] = array( - 'title' => 'Status report', - 'description' => "Get a status report about your site's operation and any detected problems.", - 'page callback' => 'system_status', - 'weight' => 10, - 'access arguments' => array('administer site configuration'), - ); - $items['admin/reports/status/run-cron'] = array( - 'title' => 'Run cron', - 'page callback' => 'system_run_cron', - 'access arguments' => array('administer site configuration'), - 'type' => MENU_CALLBACK, - ); - $items['admin/reports/status/php'] = array( - 'title' => 'PHP', - 'page callback' => 'system_php', - 'access arguments' => array('administer site configuration'), - 'type' => MENU_CALLBACK, - ); - // Default page for batch operations - $items['batch'] = array( - 'page callback' => 'system_batch_page', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** * Retrieve a blocked IP address from the database. * * @param $iid integer @@ -812,141 +129,6 @@ function system_preprocess_page(&$variab } /** - * Implementation of hook_user_form(). - */ -function system_user_form(&$edit, &$user, $category = NULL) { - if ($category == 'account') { - $form['theme_select'] = system_theme_select_form(t('Selecting a different theme will change the look and feel of the site.'), isset($edit['theme']) ? $edit['theme'] : NULL, 2); - if (variable_get('configurable_timezones', 1)) { - system_user_timezone($edit, $form); - } - return $form; - } -} - -/** - * Implementation of hook_user_register(). - */ -function system_user_register(&$edit, &$user, $category = NULL) { - if (variable_get('configurable_timezones', 1)) { - $form = array(); - if (variable_get('user_default_timezone', DRUPAL_USER_TIMEZONE_DEFAULT) == DRUPAL_USER_TIMEZONE_SELECT) { - system_user_timezone($edit, $form); - } - else { - $form['timezone'] = array( - '#type' => 'hidden', - '#value' => variable_get('user_default_timezone', DRUPAL_USER_TIMEZONE_DEFAULT) ? '' : variable_get('date_default_timezone', ''), - ); - } - return $form; - } -} - -/** - * Implementation of hook_user_login(). - */ -function system_user_login(&$edit, &$user, $category = NULL) { - // If the user has a NULL time zone, notify them to set a time zone. - if (!$user->timezone && variable_get('configurable_timezones', 1) && variable_get('empty_timezone_message', 0)) { - drupal_set_message(t('Please configure your account time zone setting.', array('@user-edit' => url("user/$user->uid/edit", array('query' => drupal_get_destination(), 'fragment' => 'edit-timezone'))))); - } -} - -/** - * Add the time zone field to the user edit and register forms. - */ -function system_user_timezone(&$edit, &$form) { - global $user; - $form['timezone'] = array( - '#type' => 'fieldset', - '#title' => t('Locale settings'), - '#weight' => 6, - '#collapsible' => TRUE, - ); - $form['timezone']['timezone'] = array( - '#type' => 'select', - '#title' => t('Time zone'), - '#default_value' => $edit['timezone'] ? $edit['timezone'] : ($edit['uid'] == $user->uid ? variable_get('date_default_timezone', '') : ''), - '#options' => system_time_zones(($edit['uid'] != $user->uid)), - '#description' => t('Select the desired local time and time zone. Dates and times throughout this site will be displayed using this time zone.'), - ); - if (!$edit['timezone'] && $edit['uid'] == $user->uid) { - $form['timezone']['#description'] = t('Your time zone setting will be automatically detected if possible. Please confirm the selection and click save.'); - $form['timezone']['timezone']['#attributes'] = array('class' => 'timezone-detect'); - drupal_add_js('misc/timezone.js'); - } -} - -/** - * Implementation of hook_block_list(). - */ -function system_block_list() { - $blocks['main'] = array( - 'info' => t('Main page content'), - // Cached elsewhere. - 'cache' => BLOCK_NO_CACHE, - ); - $blocks['powered-by'] = array( - 'info' => t('Powered by Drupal'), - 'weight' => '10', - 'cache' => BLOCK_NO_CACHE, - ); - $blocks['help'] = array( - 'info' => t('System help'), - 'weight' => '5', - ); - // System-defined menu blocks. - foreach (menu_list_system_menus() as $menu_name => $title) { - $blocks[$menu_name]['info'] = t($title); - // Menu blocks can't be cached because each menu item can have - // a custom access callback. menu.inc manages its own caching. - $blocks[$menu_name]['cache'] = BLOCK_NO_CACHE; - } - return $blocks; -} - -/** - * Implementation of hook_block_configure(). - */ -function system_block_configure($delta = '') { - if ($delta == 'powered-by') { - $image_path = 'misc/' . variable_get('drupal_badge_color', 'powered-blue') . '-' . variable_get('drupal_badge_size', '80x15') . '.png'; - drupal_add_js(drupal_get_path('module', 'system') . '/system.js'); - // Compile a list of fields to show - $form['wrapper']['color'] = array( - '#type' => 'select', - '#title' => t('Badge color'), - '#default_value' => variable_get('drupal_badge_color', 'powered-blue'), - '#options' => array('powered-black' => t('Black'), 'powered-blue' => t('Blue'), 'powered-gray' => t('Gray')), - ); - $form['wrapper']['size'] = array( - '#type' => 'select', - '#title' => t('Badge size'), - '#default_value' => variable_get('drupal_badge_size', '80x15'), - '#options' => array('80x15' => t('Small'), '88x31' => t('Medium'), '135x42' => t('Large')), - ); - $form['wrapper']['preview'] = array( - '#type' => 'item', - '#title' => 'Preview', - '#markup' => theme('image', $image_path, t('Powered by Drupal, an open source content management system'), t('Powered by Drupal, an open source content management system'), array('class' => 'powered-by-preview'), FALSE), - ); - return $form; - } -} - -/** - * Implementation of hook_block_save(). - */ -function system_block_save($delta = '', $edit = NULL) { - if ($delta == 'powered-by') { - $image_path = 'misc/' . variable_get('drupal_badge_color', 'powered-blue') . '-' . variable_get('drupal_badge_size', '80x15') . '.png'; - variable_set('drupal_badge_color', $edit['color']); - variable_set('drupal_badge_size', $edit['size']); - } -} - -/** * Implementation of hook_block_view(). * * Generate a block with a promotional link to Drupal.org and @@ -1397,40 +579,6 @@ function system_settings_form($form, $au } /** - * Execute the system_settings_form. - * - * If you want node type configure style handling of your checkboxes, - * add an array_filter value to your form. - */ -function system_settings_form_submit($form, &$form_state) { - $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : ''; - - // Exclude unnecessary elements. - unset($form_state['values']['submit'], $form_state['values']['reset'], $form_state['values']['form_id'], $form_state['values']['op'], $form_state['values']['form_token'], $form_state['values']['form_build_id']); - - foreach ($form_state['values'] as $key => $value) { - if ($op == t('Reset to defaults')) { - variable_del($key); - } - else { - if (is_array($value) && isset($form_state['values']['array_filter'])) { - $value = array_keys(array_filter($value)); - } - variable_set($key, $value); - } - } - if ($op == t('Reset to defaults')) { - drupal_set_message(t('The configuration options have been reset to their default values.')); - } - else { - drupal_set_message(t('The configuration options have been saved.')); - } - - cache_clear_all(); - drupal_theme_rebuild(); -} - -/** * Helper function to sort requirements. */ function _system_sort_requirements($a, $b) { @@ -1573,675 +721,6 @@ function system_get_module_admin_tasks($ } /** - * Implementation of hook_cron(). - * - * Remove older rows from flood and batch table. Remove old temporary files. - */ -function system_cron() { - // Cleanup the flood. - db_delete('flood') - ->condition('timestamp', REQUEST_TIME - 3600, '<') - ->execute(); - // Cleanup the batch table. - db_delete('batch') - ->condition('timestamp', REQUEST_TIME - 864000, '<') - ->execute(); - - // Remove temporary files that are older than DRUPAL_MAXIMUM_TEMP_FILE_AGE. - // Use separate placeholders for the status to avoid a bug in some versions - // of PHP. See http://drupal.org/node/352956 - $result = db_query('SELECT fid FROM {files} WHERE status & :permanent1 <> :permanent2 AND timestamp < :timestamp', array( - ':permanent1' => FILE_STATUS_PERMANENT, - ':permanent2' => FILE_STATUS_PERMANENT, - ':timestamp' => REQUEST_TIME - DRUPAL_MAXIMUM_TEMP_FILE_AGE - )); - foreach ($result as $row) { - if ($file = file_load($row->fid)) { - if (!file_delete($file)) { - watchdog('file system', 'Could not delete temporary file "%path" during garbage collection', array('%path' => $file->filepath), WATCHDOG_ERROR); - } - } - } - - $core = array('cache', 'cache_filter', 'cache_page', 'cache_form', 'cache_menu'); - $cache_tables = array_merge(module_invoke_all('flush_caches'), $core); - foreach ($cache_tables as $table) { - cache_clear_all(NULL, $table); - } - - // Reset expired items in the default queue implementation table. If that's - // not used, this will simply be a no-op. - db_update('queue') - ->fields(array( - 'consumer_id' => 0, - 'expire' => 0, - )) - ->condition('expire', REQUEST_TIME, '<') - ->execute(); -} - -/** - * Implementation of hook_hook_info(). - */ -function system_hook_info() { - return array( - 'system' => array( - 'cron' => array( - 'run' => array( - 'runs when' => t('When cron runs'), - ), - ), - ), - ); -} - -/** - * Implementation of hook_action_info(). - */ -function system_action_info() { - return array( - 'system_message_action' => array( - 'type' => 'system', - 'description' => t('Display a message to the user'), - 'configurable' => TRUE, - 'hooks' => array( - 'node' => array('view', 'insert', 'update', 'delete'), - 'comment' => array('view', 'insert', 'update', 'delete'), - 'user' => array('view', 'insert', 'update', 'delete', 'login'), - 'taxonomy' => array('insert', 'update', 'delete'), - ), - ), - 'system_send_email_action' => array( - 'description' => t('Send e-mail'), - 'type' => 'system', - 'configurable' => TRUE, - 'hooks' => array( - 'node' => array('view', 'insert', 'update', 'delete'), - 'comment' => array('view', 'insert', 'update', 'delete'), - 'user' => array('view', 'insert', 'update', 'delete', 'login'), - 'taxonomy' => array('insert', 'update', 'delete'), - 'cron' => array('run'), - ) - ), - 'system_block_ip_action' => array( - 'description' => t('Ban IP address of current user'), - 'type' => 'user', - 'configurable' => FALSE, - 'hooks' => array(), - ), - 'system_goto_action' => array( - 'description' => t('Redirect to URL'), - 'type' => 'system', - 'configurable' => TRUE, - 'hooks' => array( - 'node' => array('view', 'insert', 'update', 'delete'), - 'comment' => array('view', 'insert', 'update', 'delete'), - 'user' => array('view', 'insert', 'update', 'delete', 'login'), - ) - ) - ); -} - -/** - * Menu callback. Display an overview of available and configured actions. - */ -function system_actions_manage() { - $output = ''; - actions_synchronize(); - $actions = actions_list(); - $actions_map = actions_actions_map($actions); - $options = array(t('Choose an advanced action')); - $unconfigurable = array(); - - foreach ($actions_map as $key => $array) { - if ($array['configurable']) { - $options[$key] = $array['description'] . '...'; - } - else { - $unconfigurable[] = $array; - } - } - - $row = array(); - $instances_present = db_query("SELECT aid FROM {actions} WHERE parameters <> ''")->fetchField(); - $header = array( - array('data' => t('Action type'), 'field' => 'type'), - array('data' => t('Description'), 'field' => 'description'), - array('data' => $instances_present ? t('Operations') : '', 'colspan' => '2') - ); - $query = db_select('actions')->extend('PagerDefault')->extend('TableSort'); - $result = $query - ->fields('actions') - ->limit(50) - ->orderByHeader($header) - ->execute(); - - foreach ($result as $action) { - $row[] = array( - array('data' => $action->type), - array('data' => $action->description), - array('data' => $action->parameters ? l(t('configure'), "admin/settings/actions/configure/$action->aid") : ''), - array('data' => $action->parameters ? l(t('delete'), "admin/settings/actions/delete/$action->aid") : '') - ); - } - - if ($row) { - $pager = theme('pager', NULL); - if (!empty($pager)) { - $row[] = array(array('data' => $pager, 'colspan' => '3')); - } - $output .= '' . t('For example, when creating a recipe site, you might want to classify posts by both the type of meal and preparation time. A vocabulary for each allows you to categorize using each criteria independently instead of creating a tag for every possible combination.') . '
'; + $output .= '' . t('Type of Meal: Appetizer, Main Course, Salad, Dessert') . '
'; + $output .= '' . t('Preparation Time: 0-30mins, 30-60mins, 1-2 hrs, 2hrs+') . '
'; + $output .= '' . t("Each taxonomy term (often called a 'category' or 'tag' in other systems) automatically provides lists of posts and a corresponding RSS feed. These taxonomy/term URLs can be manipulated to generate AND and OR lists of posts classified with terms. In our recipe site example, it then becomes easy to create pages displaying 'Main courses', '30 minute recipes', or '30 minute main courses and appetizers' by using terms on their own or in combination with others. There are a significant number of contributed modules which you to alter and extend the behavior of the core module for both display and organization of terms.") . '
'; + $output .= '' . t("Terms can also be organized in parent/child relationships from the admin interface. An example would be a vocabulary grouping countries under their parent geo-political regions. The taxonomy module also enables advanced implementations of hierarchy, for example placing Turkey in both the 'Middle East' and 'Europe'.") . '
'; + $output .= '' . t('The taxonomy module supports the use of both synonyms and related terms, but does not directly use this functionality. However, optional contributed or custom modules may make full use of these advanced features.') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Taxonomy module.', array('@taxonomy' => 'http://drupal.org/handbook/modules/taxonomy/')) . '
'; + return $output; + case 'admin/content/taxonomy': + $output = '' . t("The taxonomy module allows you to categorize your content using both tags and administrator defined terms. It is a flexible tool for classifying content with many advanced features. To begin, create a 'Vocabulary' to hold one set of terms or tags. You can create one free-tagging vocabulary for everything, or separate controlled vocabularies to define the various properties of your content, for example 'Countries' or 'Colors'.") . '
'; + $output .= '' . t('Use the list below to configure and review the vocabularies defined on your site, or to list and manage the terms (tags) they contain. A vocabulary may (optionally) be tied to specific content types as shown in the Type column and, if so, will be displayed when creating or editing posts of that type. Multiple vocabularies tied to the same content type will be displayed in the order shown below. To change the order of a vocabulary, grab a drag-and-drop handle under the Name column and drag it to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save button at the bottom of the page.') . '
'; + return $output; + case 'admin/content/taxonomy/%/list': + $vocabulary = taxonomy_vocabulary_load($arg[3]); + if ($vocabulary->tags) { + return '' . t('%capital_name is a free-tagging vocabulary. To change the name or description of a term, click the edit link next to the term.', array('%capital_name' => drupal_ucfirst($vocabulary->name))) . '
'; + } + switch ($vocabulary->hierarchy) { + case 0: + return '' . t('%capital_name is a flat vocabulary. You may organize the terms in the %name vocabulary by using the handles on the left side of the table. To change the name or description of a term, click the edit link next to the term.', array('%capital_name' => drupal_ucfirst($vocabulary->name), '%name' => $vocabulary->name)) . '
'; + case 1: + return '' . t('%capital_name is a single hierarchy vocabulary. You may organize the terms in the %name vocabulary by using the handles on the left side of the table. To change the name or description of a term, click the edit link next to the term.', array('%capital_name' => drupal_ucfirst($vocabulary->name), '%name' => $vocabulary->name)) . '
'; + case 2: + return '' . t('%capital_name is a multiple hierarchy vocabulary. To change the name or description of a term, click the edit link next to the term. Drag and drop of multiple hierarchies is not supported, but you can re-enable drag and drop support by editing each term to include only a single parent.', array('%capital_name' => drupal_ucfirst($vocabulary->name))) . '
'; + } + case 'admin/content/taxonomy/add': + return '' . t('Define how your vocabulary will be presented to administrators and users, and which content types to categorize with it. Tags allows users to create terms when submitting posts by typing a comma separated list. Otherwise terms are chosen from a select list and can only be created by users with the "administer taxonomy" permission.') . '
'; + } +} + Index: modules/taxonomy/taxonomy.info =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.info,v retrieving revision 1.8 diff -u -p -r1.8 taxonomy.info --- modules/taxonomy/taxonomy.info 11 Oct 2008 02:33:06 -0000 1.8 +++ modules/taxonomy/taxonomy.info 22 May 2009 23:43:29 -0000 @@ -8,3 +8,7 @@ files[] = taxonomy.module files[] = taxonomy.admin.inc files[] = taxonomy.pages.inc files[] = taxonomy.install +files[] = taxonomy.registry.inc +files[] = taxonomy.user.inc +files[] = taxonomy.node.inc +files[] = taxonomy.help.inc Index: modules/taxonomy/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v retrieving revision 1.473 diff -u -p -r1.473 taxonomy.module --- modules/taxonomy/taxonomy.module 19 May 2009 19:01:51 -0000 1.473 +++ modules/taxonomy/taxonomy.module 22 May 2009 23:44:33 -0000 @@ -7,35 +7,6 @@ */ /** - * Implementation of hook_perm(). - */ -function taxonomy_perm() { - return array( - 'administer taxonomy' => array( - 'title' => t('Administer taxonomy'), - 'description' => t('Manage taxonomy vocabularies and terms.'), - ), - ); -} - -/** - * Implementation of hook_theme(). - */ -function taxonomy_theme() { - return array( - 'taxonomy_term_select' => array( - 'arguments' => array('element' => NULL), - ), - 'taxonomy_overview_vocabularies' => array( - 'arguments' => array('form' => array()), - ), - 'taxonomy_overview_terms' => array( - 'arguments' => array('form' => array()), - ), - ); -} - -/** * An implementation of hook_node_view(). */ function taxonomy_node_view($node) { @@ -112,104 +83,6 @@ function taxonomy_term_path($term) { } /** - * Implementation of hook_menu(). - */ -function taxonomy_menu() { - $items['admin/content/taxonomy'] = array( - 'title' => 'Taxonomy', - 'description' => 'Manage tagging, categorization, and classification of your content.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('taxonomy_overview_vocabularies'), - 'access arguments' => array('administer taxonomy'), - ); - - $items['admin/content/taxonomy/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - - $items['admin/content/taxonomy/add'] = array( - 'title' => 'Add vocabulary', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('taxonomy_form_vocabulary'), - 'access arguments' => array('administer taxonomy'), - 'type' => MENU_LOCAL_TASK, - ); - - $items['taxonomy/term/%taxonomy_terms'] = array( - 'title' => 'Taxonomy term', - 'page callback' => 'taxonomy_term_page', - 'page arguments' => array(2), - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - $items['taxonomy/term/%taxonomy_terms/view'] = array( - 'title' => 'View', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - - $items['taxonomy/term/%taxonomy_term/edit'] = array( - 'title' => 'Edit term', - 'page callback' => 'taxonomy_term_edit', - 'page arguments' => array(2), - 'access arguments' => array('administer taxonomy'), - 'type' => MENU_LOCAL_TASK, - 'weight' => 10, - ); - - $items['taxonomy/autocomplete'] = array( - 'title' => 'Autocomplete taxonomy', - 'page callback' => 'taxonomy_autocomplete', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - - $items['admin/content/taxonomy/%taxonomy_vocabulary'] = array( - 'title' => 'Vocabulary', // this is replaced by callback - 'page callback' => 'drupal_get_form', - 'page arguments' => array('taxonomy_form_vocabulary', 3), - 'title callback' => 'taxonomy_admin_vocabulary_title_callback', - 'title arguments' => array(3), - 'access arguments' => array('administer taxonomy'), - 'type' => MENU_CALLBACK, - ); - - $items['admin/content/taxonomy/%taxonomy_vocabulary/edit'] = array( - 'title' => 'Edit vocabulary', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -20, - ); - - $items['admin/content/taxonomy/%taxonomy_vocabulary/list'] = array( - 'title' => 'List terms', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('taxonomy_overview_terms', 3), - 'access arguments' => array('administer taxonomy'), - 'type' => MENU_LOCAL_TASK, - 'weight' => -10, - ); - - $items['admin/content/taxonomy/%taxonomy_vocabulary/add'] = array( - 'title' => 'Add term', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('taxonomy_form_term', 3), - 'access arguments' => array('administer taxonomy'), - 'type' => MENU_LOCAL_TASK, - ); - - return $items; -} - -/** - * Return the vocabulary name given the vocabulary object. - */ -function taxonomy_admin_vocabulary_title_callback($vocabulary) { - return check_plain($vocabulary->name); -} - -/** * Save a vocabulary given a vocabulary object. */ function taxonomy_vocabulary_save($vocabulary) { @@ -774,111 +647,6 @@ function taxonomy_node_get_terms($node, } /** - * Save term associations for a given node. - */ -function taxonomy_node_save($node, $terms) { - - taxonomy_node_delete_revision($node); - - // Free tagging vocabularies do not send their tids in the form, - // so we'll detect them here and process them independently. - if (isset($terms['tags'])) { - $typed_input = $terms['tags']; - unset($terms['tags']); - - foreach ($typed_input as $vid => $vid_value) { - $typed_terms = drupal_explode_tags($vid_value); - - $inserted = array(); - foreach ($typed_terms as $typed_term) { - // See if the term exists in the chosen vocabulary - // and return the tid; otherwise, add a new record. - $possibilities = taxonomy_get_term_by_name($typed_term); - $typed_term_tid = NULL; // tid match, if any. - foreach ($possibilities as $possibility) { - if ($possibility->vid == $vid) { - $typed_term_tid = $possibility->tid; - } - } - - if (!$typed_term_tid) { - $edit = array('vid' => $vid, 'name' => $typed_term); - $term = (object)$edit; - $status = taxonomy_term_save($term); - $typed_term_tid = $term->tid; - } - - // Defend against duplicate, differently cased tags - if (!isset($inserted[$typed_term_tid])) { - db_insert('taxonomy_term_node') - ->fields(array( - 'nid' => $node->nid, - 'vid' => $node->vid, - 'tid' => $typed_term_tid - )) - ->execute(); - $inserted[$typed_term_tid] = TRUE; - } - } - } - } - - if (is_array($terms) && !empty($terms)) { - $query = db_insert('taxonomy_term_node') - ->fields(array('nid', 'vid', 'tid')); - - foreach ($terms as $term) { - if (is_array($term)) { - foreach ($term as $tid) { - if ($tid) { - $query->values(array( - 'nid' => $node->nid, - 'vid' => $node->vid, - 'tid' => $tid, - )); - } - } - } - elseif (is_object($term)) { - $query->values(array( - 'nid' => $node->nid, - 'vid' => $node->vid, - 'tid' => $term->tid, - )); - } - elseif ($term) { - $query->values(array( - 'nid' => $node->nid, - 'vid' => $node->vid, - 'tid' => $term, - )); - } - } - $query->execute(); - } -} - -/** - * Implementation of hook_node_type(). - */ -function taxonomy_node_type($op, $info) { - if ($op == 'update' && !empty($info->old_type) && $info->type != $info->old_type) { - db_update('taxonomy_vocabulary_node_type') - ->fields(array( - 'type' => $info->type, - )) - ->condition('type', $info->old_type) - ->execute(); - } - elseif ($op == 'delete') { - db_delete('taxonomy_vocabulary_node_type') - ->condition('type', $info->type) - ->execute(); - } - drupal_static_reset('taxonomy_term_count_nodes'); -} - -/** * Find all term objects related to a given term ID. */ function taxonomy_get_related($tid, $key = 'tid') { @@ -1585,82 +1353,6 @@ function taxonomy_node_load($nodes) { } /** - * Implementation of hook_node_insert(). - */ -function taxonomy_node_insert($node) { - if (!empty($node->taxonomy)) { - taxonomy_node_save($node, $node->taxonomy); - } -} - -/** - * Implementation of hook_node_update(). - */ -function taxonomy_node_update($node) { - if (!empty($node->taxonomy)) { - taxonomy_node_save($node, $node->taxonomy); - } -} - -/** - * Implementation of hook_node_delete(). - * - * Remove associations of a node to its terms. - */ -function taxonomy_node_delete($node) { - db_delete('taxonomy_term_node') - ->condition('nid', $node->nid) - ->execute(); - drupal_static_reset('taxonomy_term_count_nodes'); -} - -/** - * Implementation of hook_node_delete_revision(). - * - * Remove associations of a node to its terms. - */ -function taxonomy_node_delete_revision($node) { - db_delete('taxonomy_term_node') - ->condition('nid', $node->vid) - ->execute(); - drupal_static_reset('taxonomy_term_count_nodes'); -} - -/** - * Implementation of hook_node_validate(). - * - * Make sure incoming vids are free tagging enabled. - */ -function taxonomy_node_validate($node, $form) { - if (!empty($node->taxonomy)) { - $terms = $node->taxonomy; - if (!empty($terms['tags'])) { - foreach ($terms['tags'] as $vid => $vid_value) { - $vocabulary = taxonomy_vocabulary_load($vid); - if (empty($vocabulary->tags)) { - // see form_get_error $key = implode('][', $element['#parents']); - // on why this is the key - form_set_error("taxonomy][tags][$vid", t('The %name vocabulary can not be modified in this way.', array('%name' => $vocabulary->name))); - } - } - } - } -} - -/** - * Implementation of hook_node_update_index(). - */ -function taxonomy_node_update_index($node) { - $output = array(); - foreach ($node->taxonomy as $term) { - $output[] = $term->name; - } - if (count($output)) { - return '(' . implode(', ', $output) . ')'; - } -} - -/** * Parses a comma or plus separated string of term IDs. * * @param $str_tids @@ -1687,43 +1379,6 @@ function taxonomy_terms_parse_string($st } /** - * Implementation of hook_help(). - */ -function taxonomy_help($path, $arg) { - switch ($path) { - case 'admin/help#taxonomy': - $output = '' . t('The taxonomy module allows you to categorize content using various systems of classification. Free-tagging vocabularies are created by users on the fly when they submit posts (as commonly found in blogs and social bookmarking applications). Controlled vocabularies allow for administrator-defined short lists of terms as well as complex hierarchies with multiple relationships between different terms. These methods can be applied to different content types and combined together to create a powerful and flexible method of classifying and presenting your content.') . '
'; - $output .= '' . t('For example, when creating a recipe site, you might want to classify posts by both the type of meal and preparation time. A vocabulary for each allows you to categorize using each criteria independently instead of creating a tag for every possible combination.') . '
'; - $output .= '' . t('Type of Meal: Appetizer, Main Course, Salad, Dessert') . '
'; - $output .= '' . t('Preparation Time: 0-30mins, 30-60mins, 1-2 hrs, 2hrs+') . '
'; - $output .= '' . t("Each taxonomy term (often called a 'category' or 'tag' in other systems) automatically provides lists of posts and a corresponding RSS feed. These taxonomy/term URLs can be manipulated to generate AND and OR lists of posts classified with terms. In our recipe site example, it then becomes easy to create pages displaying 'Main courses', '30 minute recipes', or '30 minute main courses and appetizers' by using terms on their own or in combination with others. There are a significant number of contributed modules which you to alter and extend the behavior of the core module for both display and organization of terms.") . '
'; - $output .= '' . t("Terms can also be organized in parent/child relationships from the admin interface. An example would be a vocabulary grouping countries under their parent geo-political regions. The taxonomy module also enables advanced implementations of hierarchy, for example placing Turkey in both the 'Middle East' and 'Europe'.") . '
'; - $output .= '' . t('The taxonomy module supports the use of both synonyms and related terms, but does not directly use this functionality. However, optional contributed or custom modules may make full use of these advanced features.') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Taxonomy module.', array('@taxonomy' => 'http://drupal.org/handbook/modules/taxonomy/')) . '
'; - return $output; - case 'admin/content/taxonomy': - $output = '' . t("The taxonomy module allows you to categorize your content using both tags and administrator defined terms. It is a flexible tool for classifying content with many advanced features. To begin, create a 'Vocabulary' to hold one set of terms or tags. You can create one free-tagging vocabulary for everything, or separate controlled vocabularies to define the various properties of your content, for example 'Countries' or 'Colors'.") . '
'; - $output .= '' . t('Use the list below to configure and review the vocabularies defined on your site, or to list and manage the terms (tags) they contain. A vocabulary may (optionally) be tied to specific content types as shown in the Type column and, if so, will be displayed when creating or editing posts of that type. Multiple vocabularies tied to the same content type will be displayed in the order shown below. To change the order of a vocabulary, grab a drag-and-drop handle under the Name column and drag it to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the Save button at the bottom of the page.') . '
'; - return $output; - case 'admin/content/taxonomy/%/list': - $vocabulary = taxonomy_vocabulary_load($arg[3]); - if ($vocabulary->tags) { - return '' . t('%capital_name is a free-tagging vocabulary. To change the name or description of a term, click the edit link next to the term.', array('%capital_name' => drupal_ucfirst($vocabulary->name))) . '
'; - } - switch ($vocabulary->hierarchy) { - case 0: - return '' . t('%capital_name is a flat vocabulary. You may organize the terms in the %name vocabulary by using the handles on the left side of the table. To change the name or description of a term, click the edit link next to the term.', array('%capital_name' => drupal_ucfirst($vocabulary->name), '%name' => $vocabulary->name)) . '
'; - case 1: - return '' . t('%capital_name is a single hierarchy vocabulary. You may organize the terms in the %name vocabulary by using the handles on the left side of the table. To change the name or description of a term, click the edit link next to the term.', array('%capital_name' => drupal_ucfirst($vocabulary->name), '%name' => $vocabulary->name)) . '
'; - case 2: - return '' . t('%capital_name is a multiple hierarchy vocabulary. To change the name or description of a term, click the edit link next to the term. Drag and drop of multiple hierarchies is not supported, but you can re-enable drag and drop support by editing each term to include only a single parent.', array('%capital_name' => drupal_ucfirst($vocabulary->name))) . '
'; - } - case 'admin/content/taxonomy/add': - return '' . t('Define how your vocabulary will be presented to administrators and users, and which content types to categorize with it. Tags allows users to create terms when submitting posts by typing a comma separated list. Otherwise terms are chosen from a select list and can only be created by users with the "administer taxonomy" permission.') . '
'; - } -} - -/** * Helper function for array_map purposes. */ function _taxonomy_get_tid_from_term($term) { @@ -1750,23 +1405,3 @@ function taxonomy_implode_tags($tags, $v return implode(', ', $typed_tags); } -/** - * Implementation of hook_hook_info(). - */ -function taxonomy_hook_info() { - return array( - 'taxonomy' => array( - 'taxonomy' => array( - 'insert' => array( - 'runs when' => t('After saving a new term to the database'), - ), - 'update' => array( - 'runs when' => t('After saving an updated term to the database'), - ), - 'delete' => array( - 'runs when' => t('After deleting a term') - ), - ), - ), - ); -} Index: modules/taxonomy/taxonomy.node.inc =================================================================== RCS file: modules/taxonomy/taxonomy.node.inc diff -N modules/taxonomy/taxonomy.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/taxonomy/taxonomy.node.inc 22 May 2009 23:44:33 -0000 @@ -0,0 +1,189 @@ +old_type) && $info->type != $info->old_type) { + db_update('taxonomy_vocabulary_node_type') + ->fields(array( + 'type' => $info->type, + )) + ->condition('type', $info->old_type) + ->execute(); + } + elseif ($op == 'delete') { + db_delete('taxonomy_vocabulary_node_type') + ->condition('type', $info->type) + ->execute(); + } + drupal_static_reset('taxonomy_term_count_nodes'); +} + +/** + * Implementation of hook_node_insert(). + */ +function taxonomy_node_insert($node) { + if (!empty($node->taxonomy)) { + taxonomy_node_save($node, $node->taxonomy); + } +} + +/** + * Implementation of hook_node_update(). + */ +function taxonomy_node_update($node) { + if (!empty($node->taxonomy)) { + taxonomy_node_save($node, $node->taxonomy); + } +} + +/** + * Implementation of hook_node_delete(). + * + * Remove associations of a node to its terms. + */ +function taxonomy_node_delete($node) { + db_delete('taxonomy_term_node') + ->condition('nid', $node->nid) + ->execute(); + drupal_static_reset('taxonomy_term_count_nodes'); +} + +/** + * Implementation of hook_node_delete_revision(). + * + * Remove associations of a node to its terms. + */ +function taxonomy_node_delete_revision($node) { + db_delete('taxonomy_term_node') + ->condition('nid', $node->vid) + ->execute(); + drupal_static_reset('taxonomy_term_count_nodes'); +} + +/** + * Implementation of hook_node_validate(). + * + * Make sure incoming vids are free tagging enabled. + */ +function taxonomy_node_validate($node, $form) { + if (!empty($node->taxonomy)) { + $terms = $node->taxonomy; + if (!empty($terms['tags'])) { + foreach ($terms['tags'] as $vid => $vid_value) { + $vocabulary = taxonomy_vocabulary_load($vid); + if (empty($vocabulary->tags)) { + // see form_get_error $key = implode('][', $element['#parents']); + // on why this is the key + form_set_error("taxonomy][tags][$vid", t('The %name vocabulary can not be modified in this way.', array('%name' => $vocabulary->name))); + } + } + } + } +} + +/** + * Implementation of hook_node_update_index(). + */ +function taxonomy_node_update_index($node) { + $output = array(); + foreach ($node->taxonomy as $term) { + $output[] = $term->name; + } + if (count($output)) { + return '(' . implode(', ', $output) . ')'; + } +} + +/** + * Save term associations for a given node. + */ +function taxonomy_node_save($node, $terms) { + + taxonomy_node_delete_revision($node); + + // Free tagging vocabularies do not send their tids in the form, + // so we'll detect them here and process them independently. + if (isset($terms['tags'])) { + $typed_input = $terms['tags']; + unset($terms['tags']); + + foreach ($typed_input as $vid => $vid_value) { + $typed_terms = drupal_explode_tags($vid_value); + + $inserted = array(); + foreach ($typed_terms as $typed_term) { + // See if the term exists in the chosen vocabulary + // and return the tid; otherwise, add a new record. + $possibilities = taxonomy_get_term_by_name($typed_term); + $typed_term_tid = NULL; // tid match, if any. + foreach ($possibilities as $possibility) { + if ($possibility->vid == $vid) { + $typed_term_tid = $possibility->tid; + } + } + + if (!$typed_term_tid) { + $edit = array('vid' => $vid, 'name' => $typed_term); + $term = (object)$edit; + $status = taxonomy_term_save($term); + $typed_term_tid = $term->tid; + } + + // Defend against duplicate, differently cased tags + if (!isset($inserted[$typed_term_tid])) { + db_insert('taxonomy_term_node') + ->fields(array( + 'nid' => $node->nid, + 'vid' => $node->vid, + 'tid' => $typed_term_tid + )) + ->execute(); + $inserted[$typed_term_tid] = TRUE; + } + } + } + } + + if (is_array($terms) && !empty($terms)) { + $query = db_insert('taxonomy_term_node') + ->fields(array('nid', 'vid', 'tid')); + + foreach ($terms as $term) { + if (is_array($term)) { + foreach ($term as $tid) { + if ($tid) { + $query->values(array( + 'nid' => $node->nid, + 'vid' => $node->vid, + 'tid' => $tid, + )); + } + } + } + elseif (is_object($term)) { + $query->values(array( + 'nid' => $node->nid, + 'vid' => $node->vid, + 'tid' => $term->tid, + )); + } + elseif ($term) { + $query->values(array( + 'nid' => $node->nid, + 'vid' => $node->vid, + 'tid' => $term, + )); + } + } + $query->execute(); + } +} + Index: modules/taxonomy/taxonomy.registry.inc =================================================================== RCS file: modules/taxonomy/taxonomy.registry.inc diff -N modules/taxonomy/taxonomy.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/taxonomy/taxonomy.registry.inc 22 May 2009 23:43:27 -0000 @@ -0,0 +1,136 @@ + 'Taxonomy', + 'description' => 'Manage tagging, categorization, and classification of your content.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('taxonomy_overview_vocabularies'), + 'access arguments' => array('administer taxonomy'), + ); + + $items['admin/content/taxonomy/list'] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + + $items['admin/content/taxonomy/add'] = array( + 'title' => 'Add vocabulary', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('taxonomy_form_vocabulary'), + 'access arguments' => array('administer taxonomy'), + 'type' => MENU_LOCAL_TASK, + ); + + $items['taxonomy/term/%taxonomy_terms'] = array( + 'title' => 'Taxonomy term', + 'page callback' => 'taxonomy_term_page', + 'page arguments' => array(2), + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['taxonomy/term/%taxonomy_terms/view'] = array( + 'title' => 'View', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + + $items['taxonomy/term/%taxonomy_term/edit'] = array( + 'title' => 'Edit term', + 'page callback' => 'taxonomy_term_edit', + 'page arguments' => array(2), + 'access arguments' => array('administer taxonomy'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 10, + ); + + $items['taxonomy/autocomplete'] = array( + 'title' => 'Autocomplete taxonomy', + 'page callback' => 'taxonomy_autocomplete', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['admin/content/taxonomy/%taxonomy_vocabulary'] = array( + 'title' => 'Vocabulary', // this is replaced by callback + 'page callback' => 'drupal_get_form', + 'page arguments' => array('taxonomy_form_vocabulary', 3), + 'title callback' => 'taxonomy_admin_vocabulary_title_callback', + 'title arguments' => array(3), + 'access arguments' => array('administer taxonomy'), + 'type' => MENU_CALLBACK, + ); + + $items['admin/content/taxonomy/%taxonomy_vocabulary/edit'] = array( + 'title' => 'Edit vocabulary', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -20, + ); + + $items['admin/content/taxonomy/%taxonomy_vocabulary/list'] = array( + 'title' => 'List terms', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('taxonomy_overview_terms', 3), + 'access arguments' => array('administer taxonomy'), + 'type' => MENU_LOCAL_TASK, + 'weight' => -10, + ); + + $items['admin/content/taxonomy/%taxonomy_vocabulary/add'] = array( + 'title' => 'Add term', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('taxonomy_form_term', 3), + 'access arguments' => array('administer taxonomy'), + 'type' => MENU_LOCAL_TASK, + ); + + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function taxonomy_theme() { + return array( + 'taxonomy_term_select' => array( + 'arguments' => array('element' => NULL), + ), + 'taxonomy_overview_vocabularies' => array( + 'arguments' => array('form' => array()), + ), + 'taxonomy_overview_terms' => array( + 'arguments' => array('form' => array()), + ), + ); +} + +/** + * Implementation of hook_hook_info(). + */ +function taxonomy_hook_info() { + return array( + 'taxonomy' => array( + 'taxonomy' => array( + 'insert' => array( + 'runs when' => t('After saving a new term to the database'), + ), + 'update' => array( + 'runs when' => t('After saving an updated term to the database'), + ), + 'delete' => array( + 'runs when' => t('After deleting a term') + ), + ), + ), + ); +} Index: modules/taxonomy/taxonomy.user.inc =================================================================== RCS file: modules/taxonomy/taxonomy.user.inc diff -N modules/taxonomy/taxonomy.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/taxonomy/taxonomy.user.inc 22 May 2009 23:43:27 -0000 @@ -0,0 +1,20 @@ + array( + 'title' => t('Administer taxonomy'), + 'description' => t('Manage taxonomy vocabularies and terms.'), + ), + ); +} + Index: modules/tracker/tracker.help.inc =================================================================== RCS file: modules/tracker/tracker.help.inc diff -N modules/tracker/tracker.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/tracker/tracker.help.inc 22 May 2009 23:43:25 -0000 @@ -0,0 +1,21 @@ +' . t('The tracker module displays the most recently added or updated content on your site, and provides user-level tracking to follow the contributions of particular authors.') . ''; + $output .= '' . t("The Recent posts page is available via a link in the navigation menu block and displays new and recently-updated content (including the content type, the title, the author's name, number of comments, and time of last update) in reverse chronological order. Posts are marked updated when changes occur in the text, or when new comments are added. To use the tracker module to follow a specific user's contributions, select the Track tab from the user's profile page.") . '
'; + $output .= '' . t('For more information, see the online handbook entry for Tracker module.', array('@tracker' => 'http://drupal.org/handbook/modules/tracker/')) . '
'; + return $output; + } +} + Index: modules/tracker/tracker.info =================================================================== RCS file: /cvs/drupal/drupal/modules/tracker/tracker.info,v retrieving revision 1.8 diff -u -p -r1.8 tracker.info --- modules/tracker/tracker.info 11 Oct 2008 02:33:07 -0000 1.8 +++ modules/tracker/tracker.info 22 May 2009 23:43:25 -0000 @@ -7,3 +7,5 @@ version = VERSION core = 7.x files[] = tracker.module files[] = tracker.pages.inc +files[] = tracker.registry.inc +files[] = tracker.help.inc Index: modules/tracker/tracker.module =================================================================== RCS file: /cvs/drupal/drupal/modules/tracker/tracker.module,v retrieving revision 1.157 diff -u -p -r1.157 tracker.module --- modules/tracker/tracker.module 6 May 2008 12:18:51 -0000 1.157 +++ modules/tracker/tracker.module 22 May 2009 23:43:25 -0000 @@ -7,56 +7,6 @@ */ /** - * Implementation of hook_help(). - */ -function tracker_help($path, $arg) { - switch ($path) { - case 'admin/help#tracker': - $output = '' . t('The tracker module displays the most recently added or updated content on your site, and provides user-level tracking to follow the contributions of particular authors.') . '
'; - $output .= '' . t("The Recent posts page is available via a link in the navigation menu block and displays new and recently-updated content (including the content type, the title, the author's name, number of comments, and time of last update) in reverse chronological order. Posts are marked updated when changes occur in the text, or when new comments are added. To use the tracker module to follow a specific user's contributions, select the Track tab from the user's profile page.") . '
'; - $output .= '' . t('For more information, see the online handbook entry for Tracker module.', array('@tracker' => 'http://drupal.org/handbook/modules/tracker/')) . '
'; - return $output; - } -} - -/** - * Implementation of hook_menu(). - */ -function tracker_menu() { - $items['tracker'] = array( - 'title' => 'Recent posts', - 'page callback' => 'tracker_page', - 'access arguments' => array('access content'), - 'weight' => 1, - ); - $items['tracker/all'] = array( - 'title' => 'All recent posts', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['tracker/%user_uid_optional'] = array( - 'title' => 'My recent posts', - 'access callback' => '_tracker_myrecent_access', - 'access arguments' => array(1), - 'page arguments' => array(1), - 'type' => MENU_LOCAL_TASK, - ); - - $items['user/%user/track'] = array( - 'title' => 'Track', - 'page callback' => 'tracker_page', - 'page arguments' => array(1, TRUE), - 'access callback' => '_tracker_user_access', - 'access arguments' => array(1), - 'type' => MENU_LOCAL_TASK, - ); - $items['user/%user/track/posts'] = array( - 'title' => 'Track posts', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - return $items; -} - -/** * Access callback for tracker/%user_uid_optional */ function _tracker_myrecent_access($account) { Index: modules/tracker/tracker.registry.inc =================================================================== RCS file: modules/tracker/tracker.registry.inc diff -N modules/tracker/tracker.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/tracker/tracker.registry.inc 22 May 2009 23:43:25 -0000 @@ -0,0 +1,45 @@ + 'Recent posts', + 'page callback' => 'tracker_page', + 'access arguments' => array('access content'), + 'weight' => 1, + ); + $items['tracker/all'] = array( + 'title' => 'All recent posts', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['tracker/%user_uid_optional'] = array( + 'title' => 'My recent posts', + 'access callback' => '_tracker_myrecent_access', + 'access arguments' => array(1), + 'page arguments' => array(1), + 'type' => MENU_LOCAL_TASK, + ); + + $items['user/%user/track'] = array( + 'title' => 'Track', + 'page callback' => 'tracker_page', + 'page arguments' => array(1, TRUE), + 'access callback' => '_tracker_user_access', + 'access arguments' => array(1), + 'type' => MENU_LOCAL_TASK, + ); + $items['user/%user/track/posts'] = array( + 'title' => 'Track posts', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + return $items; +} + Index: modules/translation/translation.form.inc =================================================================== RCS file: modules/translation/translation.form.inc diff -N modules/translation/translation.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/translation/translation.form.inc 22 May 2009 23:43:25 -0000 @@ -0,0 +1,18 @@ +enabled languages. You can also turn on translation for this content type, which lets you have content translated to any of the enabled languages. If disabled, new posts are saved with the default language. Existing content will not be affected by changing this option.', array('!languages' => url('admin/settings/language'))); +} + Index: modules/translation/translation.help.inc =================================================================== RCS file: modules/translation/translation.help.inc diff -N modules/translation/translation.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/translation/translation.help.inc 22 May 2009 23:43:25 -0000 @@ -0,0 +1,33 @@ +' . t('The content translation module allows content to be translated into different languages. Working with the locale module (which manages enabled languages and provides translation for the site interface), the content translation module is key to creating and maintaining translated site content.', array('@locale' => url('admin/help/locale'))) . ''; + $output .= '' . t('Configuring content translation and translation-enabled content types:') . '
'; + $output .= '' . t('Working with translation-enabled content types:') . '
'; + $output .= '' . t('Use the language switcher block provided by locale module to allow users to select a language. If available, both the site interface and site content are presented in the language selected.', array('@blocks' => url('admin/build/block'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Translation module.', array('@translation' => 'http://drupal.org/handbook/modules/translation/')) . '
'; + return $output; + case 'node/%/translate': + $output = '' . t('Translations of a piece of content are managed with translation sets. Each translation set has one source post and any number of translations in any of the enabled languages. All translations are tracked to be up to date or outdated based on whether the source post was modified significantly.', array('!languages' => url('admin/settings/language'))) . '
'; + return $output; + } +} + Index: modules/translation/translation.info =================================================================== RCS file: /cvs/drupal/drupal/modules/translation/translation.info,v retrieving revision 1.4 diff -u -p -r1.4 translation.info --- modules/translation/translation.info 11 Oct 2008 02:33:09 -0000 1.4 +++ modules/translation/translation.info 22 May 2009 23:43:25 -0000 @@ -7,3 +7,8 @@ version = VERSION core = 7.x files[] = translation.module files[] = translation.pages.inc +files[] = translation.registry.inc +files[] = translation.user.inc +files[] = translation.node.inc +files[] = translation.form.inc +files[] = translation.help.inc Index: modules/translation/translation.module =================================================================== RCS file: /cvs/drupal/drupal/modules/translation/translation.module,v retrieving revision 1.45 diff -u -p -r1.45 translation.module --- modules/translation/translation.module 18 May 2009 09:45:01 -0000 1.45 +++ modules/translation/translation.module 22 May 2009 23:43:25 -0000 @@ -26,48 +26,6 @@ define('TRANSLATION_ENABLED', 2); /** - * Implementation of hook_help(). - */ -function translation_help($path, $arg) { - switch ($path) { - case 'admin/help#translation': - $output = '' . t('The content translation module allows content to be translated into different languages. Working with the locale module (which manages enabled languages and provides translation for the site interface), the content translation module is key to creating and maintaining translated site content.', array('@locale' => url('admin/help/locale'))) . '
'; - $output .= '' . t('Configuring content translation and translation-enabled content types:') . '
'; - $output .= '' . t('Working with translation-enabled content types:') . '
'; - $output .= '' . t('Use the language switcher block provided by locale module to allow users to select a language. If available, both the site interface and site content are presented in the language selected.', array('@blocks' => url('admin/build/block'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Translation module.', array('@translation' => 'http://drupal.org/handbook/modules/translation/')) . '
'; - return $output; - case 'node/%/translate': - $output = '' . t('Translations of a piece of content are managed with translation sets. Each translation set has one source post and any number of translations in any of the enabled languages. All translations are tracked to be up to date or outdated based on whether the source post was modified significantly.', array('!languages' => url('admin/settings/language'))) . '
'; - return $output; - } -} - -/** - * Implementation of hook_menu(). - */ -function translation_menu() { - $items = array(); - $items['node/%node/translate'] = array( - 'title' => 'Translate', - 'page callback' => 'translation_node_overview', - 'page arguments' => array(1), - 'access callback' => '_translation_tab_access', - 'access arguments' => array(1), - 'type' => MENU_LOCAL_TASK, - 'weight' => 2, - ); - return $items; -} - -/** * Menu access callback. * * Only display translation tab for node types, which have translation enabled @@ -82,28 +40,6 @@ function _translation_tab_access($node) } /** - * Implementation of hook_perm(). - */ -function translation_perm() { - return array( - 'translate content' => array( - 'title' => t('Translate content'), - 'description' => t('Translate website content.'), - ), - ); -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - */ -function translation_form_node_type_form_alter(&$form, &$form_state) { - // Add translation option to content type form. - $form['workflow']['language_content_type']['#options'][TRANSLATION_ENABLED] = t('Enabled, with translation'); - // Description based on text from locale.module. - $form['workflow']['language_content_type']['#description'] = t('Enable multilingual support for this content type. If enabled, a language selection field will be added to the editing form, allowing you to select from one of the enabled languages. You can also turn on translation for this content type, which lets you have content translated to any of the enabled languages. If disabled, new posts are saved with the default language. Existing content will not be affected by changing this option.', array('!languages' => url('admin/settings/language'))); -} - -/** * Implementation of hook_form_alter(). * * - Add translation option to content type form. @@ -190,123 +126,6 @@ function translation_node_view($node, $t } /** - * Implementation of hook_node_prepare(). - */ -function translation_node_prepare($node) { - // Only act if we are dealing with a content type supporting translations. - if (translation_supported_type($node->type)) { - if (empty($node->nid) && isset($_GET['translation']) && isset($_GET['language']) && - ($source_nid = $_GET['translation']) && ($language = $_GET['language']) && - (user_access('translate content'))) { - // We are translating a node from a source node, so - // load the node to be translated and populate fields. - $source_node = node_load($source_nid); - // Ensure we don't have an existing translation in this language. - if (!empty($source_node->tnid)) { - $translations = translation_node_get_translations($source_node->tnid); - if (isset($translations[$language])) { - $languages = language_list(); - drupal_set_message(t('A translation of %title in %language already exists, a new %type will be created instead of a translation.', array('%title' => $source_node->title, '%language' => $languages[$language]->name, '%type' => $node->type)), 'error'); - return; - } - } - $node->language = $language; - $node->translation_source = $source_node; - $node->title = $node->translation_source->title; - $node->body = $node->translation_source->body; - // Let every module add custom translated fields. - module_invoke_all('node_prepare_translation', $node); - } - } -} - -/** - * Implementation of hook_node_insert(). - */ -function translation_node_insert($node) { - // Only act if we are dealing with a content type supporting translations. - if (translation_supported_type($node->type)) { - if (!empty($node->translation_source)) { - if ($node->translation_source->tnid) { - // Add node to existing translation set. - $tnid = $node->translation_source->tnid; - } - else { - // Create new translation set, using nid from the source node. - $tnid = $node->translation_source->nid; - db_update('node') - ->fields(array( - 'tnid' => $tnid, - 'translate' => 0, - )) - ->condition('nid', $node->translation_source->nid) - ->execute(); - } - db_update('node') - ->fields(array( - 'tnid' => $tnid, - 'translate' => 0, - )) - ->condition('nid', $node->nid) - ->execute(); - } - } -} - -/** - * Implementation of hook_node_update(). - */ -function translation_node_update($node) { - // Only act if we are dealing with a content type supporting translations. - if (translation_supported_type($node->type)) { - if (isset($node->translation) && $node->translation && !empty($node->language) && $node->tnid) { - // Update translation information. - db_update('node') - ->fields(array( - 'tnid' => $node->tnid, - 'translate' => $node->translation['status'], - )) - ->condition('nid', $node->nid) - ->execute(); - if (!empty($node->translation['retranslate'])) { - // This is the source node, asking to mark all translations outdated. - db_update('node') - ->fields(array('translate' => 1)) - ->condition('nid', $node->nid, '<>') - ->condition('tnid', $node->tnid) - ->execute(); - } - } - } -} - -/** - * Implementation of hook_node_validate(). - * - * Ensure that duplicate translations can not be created for the same source. - */ -function translation_node_validate($node, $form) { - // Only act on translatable nodes with a tnid or translation_source. - if (translation_supported_type($node->type) && (!empty($node->tnid) || !empty($form['#node']->translation_source->nid))) { - $tnid = !empty($node->tnid) ? $node->tnid : $form['#node']->translation_source->nid; - $translations = translation_node_get_translations($tnid); - if (isset($translations[$node->language]) && $translations[$node->language]->nid != $node->nid ) { - form_set_error('language', t('There is already a translation in this language.')); - } - } -} - -/** - * Implementation of hook_node_delete(). - */ -function translation_node_delete($node) { - // Only act if we are dealing with a content type supporting translations. - if (translation_supported_type($node->type)) { - translation_remove_from_set($node); - } -} - -/** * Remove a node from its translation set (if any) * and update the set accordingly. */ Index: modules/translation/translation.node.inc =================================================================== RCS file: modules/translation/translation.node.inc diff -N modules/translation/translation.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/translation/translation.node.inc 22 May 2009 23:43:25 -0000 @@ -0,0 +1,125 @@ +type)) { + if (empty($node->nid) && isset($_GET['translation']) && isset($_GET['language']) && + ($source_nid = $_GET['translation']) && ($language = $_GET['language']) && + (user_access('translate content'))) { + // We are translating a node from a source node, so + // load the node to be translated and populate fields. + $source_node = node_load($source_nid); + // Ensure we don't have an existing translation in this language. + if (!empty($source_node->tnid)) { + $translations = translation_node_get_translations($source_node->tnid); + if (isset($translations[$language])) { + $languages = language_list(); + drupal_set_message(t('A translation of %title in %language already exists, a new %type will be created instead of a translation.', array('%title' => $source_node->title, '%language' => $languages[$language]->name, '%type' => $node->type)), 'error'); + return; + } + } + $node->language = $language; + $node->translation_source = $source_node; + $node->title = $node->translation_source->title; + $node->body = $node->translation_source->body; + // Let every module add custom translated fields. + module_invoke_all('node_prepare_translation', $node); + } + } +} + +/** + * Implementation of hook_node_insert(). + */ +function translation_node_insert($node) { + // Only act if we are dealing with a content type supporting translations. + if (translation_supported_type($node->type)) { + if (!empty($node->translation_source)) { + if ($node->translation_source->tnid) { + // Add node to existing translation set. + $tnid = $node->translation_source->tnid; + } + else { + // Create new translation set, using nid from the source node. + $tnid = $node->translation_source->nid; + db_update('node') + ->fields(array( + 'tnid' => $tnid, + 'translate' => 0, + )) + ->condition('nid', $node->translation_source->nid) + ->execute(); + } + db_update('node') + ->fields(array( + 'tnid' => $tnid, + 'translate' => 0, + )) + ->condition('nid', $node->nid) + ->execute(); + } + } +} + +/** + * Implementation of hook_node_update(). + */ +function translation_node_update($node) { + // Only act if we are dealing with a content type supporting translations. + if (translation_supported_type($node->type)) { + if (isset($node->translation) && $node->translation && !empty($node->language) && $node->tnid) { + // Update translation information. + db_update('node') + ->fields(array( + 'tnid' => $node->tnid, + 'translate' => $node->translation['status'], + )) + ->condition('nid', $node->nid) + ->execute(); + if (!empty($node->translation['retranslate'])) { + // This is the source node, asking to mark all translations outdated. + db_update('node') + ->fields(array('translate' => 1)) + ->condition('nid', $node->nid, '<>') + ->condition('tnid', $node->tnid) + ->execute(); + } + } + } +} + +/** + * Implementation of hook_node_validate(). + * + * Ensure that duplicate translations can not be created for the same source. + */ +function translation_node_validate($node, $form) { + // Only act on translatable nodes with a tnid or translation_source. + if (translation_supported_type($node->type) && (!empty($node->tnid) || !empty($form['#node']->translation_source->nid))) { + $tnid = !empty($node->tnid) ? $node->tnid : $form['#node']->translation_source->nid; + $translations = translation_node_get_translations($tnid); + if (isset($translations[$node->language]) && $translations[$node->language]->nid != $node->nid ) { + form_set_error('language', t('There is already a translation in this language.')); + } + } +} + +/** + * Implementation of hook_node_delete(). + */ +function translation_node_delete($node) { + // Only act if we are dealing with a content type supporting translations. + if (translation_supported_type($node->type)) { + translation_remove_from_set($node); + } +} + Index: modules/translation/translation.registry.inc =================================================================== RCS file: modules/translation/translation.registry.inc diff -N modules/translation/translation.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/translation/translation.registry.inc 22 May 2009 23:43:25 -0000 @@ -0,0 +1,25 @@ + 'Translate', + 'page callback' => 'translation_node_overview', + 'page arguments' => array(1), + 'access callback' => '_translation_tab_access', + 'access arguments' => array(1), + 'type' => MENU_LOCAL_TASK, + 'weight' => 2, + ); + return $items; +} + Index: modules/translation/translation.user.inc =================================================================== RCS file: modules/translation/translation.user.inc diff -N modules/translation/translation.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/translation/translation.user.inc 22 May 2009 23:43:25 -0000 @@ -0,0 +1,20 @@ + array( + 'title' => t('Translate content'), + 'description' => t('Translate website content.'), + ), + ); +} + Index: modules/trigger/trigger.actions.inc =================================================================== RCS file: modules/trigger/trigger.actions.inc diff -N modules/trigger/trigger.actions.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/trigger.actions.inc 22 May 2009 23:43:24 -0000 @@ -0,0 +1,16 @@ + 'cron', + 'op' => '', + ); + // Cron does not act on any specific object. + $object = NULL; + actions_do(array_keys($aids), $object, $context); +} + Index: modules/trigger/trigger.help.inc =================================================================== RCS file: modules/trigger/trigger.help.inc diff -N modules/trigger/trigger.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/trigger.help.inc 22 May 2009 23:43:24 -0000 @@ -0,0 +1,32 @@ +' . t('Triggers are system events, such as when new content is added or when a user logs in. Trigger module combines these triggers with actions (functional tasks), such as unpublishing content or e-mailing an administrator. The Actions settings page contains a list of existing actions and provides the ability to create and configure additional actions.', array('@url' => url('admin/settings/actions'))) . ''; + switch ($path) { + case 'admin/build/trigger/comment': + return $explanation . '' . t('Below you can assign actions to run when certain comment-related triggers happen. For example, you could promote a post to the front page when a comment is added.') . '
'; + case 'admin/build/trigger/node': + return $explanation . '' . t('Below you can assign actions to run when certain content-related triggers happen. For example, you could send an e-mail to an administrator when a post is created or updated.') . '
'; + case 'admin/build/trigger/cron': + return $explanation . '' . t('Below you can assign actions to run during each pass of a cron maintenance task.', array('@cron' => url('admin/reports/status'))) . '
'; + case 'admin/build/trigger/taxonomy': + return $explanation . '' . t('Below you can assign actions to run when certain taxonomy-related triggers happen. For example, you could send an e-mail to an administrator when a term is deleted.') . '
'; + case 'admin/build/trigger/user': + return $explanation . '' . t("Below you can assign actions to run when certain user-related triggers happen. For example, you could send an e-mail to an administrator when a user account is deleted.") . '
'; + case 'admin/help#trigger': + $output = '' . t('The Trigger module provides the ability to trigger actions upon system events, such as when new content is added or when a user logs in.', array('@actions' => url('admin/settings/actions'))) . '
'; + $output .= '' . t('The combination of actions and triggers can perform many useful tasks, such as e-mailing an administrator if a user account is deleted, or automatically unpublishing comments that contain certain words. By default, there are five "contexts" of events (Comments, Content, Cron, Taxonomy, and Users), but more may be added by additional modules.') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Trigger module.', array('@trigger' => 'http://drupal.org/handbook/modules/trigger/')) . '
'; + return $output; + } +} + Index: modules/trigger/trigger.info =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/trigger.info,v retrieving revision 1.5 diff -u -p -r1.5 trigger.info --- modules/trigger/trigger.info 11 Oct 2008 02:33:10 -0000 1.5 +++ modules/trigger/trigger.info 22 May 2009 23:43:24 -0000 @@ -7,3 +7,11 @@ core = 7.x files[] = trigger.module files[] = trigger.admin.inc files[] = trigger.install +files[] = trigger.registry.inc +files[] = trigger.actions.inc +files[] = trigger.user.inc +files[] = trigger.node.inc +files[] = trigger.comment.inc +files[] = trigger.taxonomy.inc +files[] = trigger.cron.inc +files[] = trigger.help.inc Index: modules/trigger/trigger.module =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/trigger.module,v retrieving revision 1.34 diff -u -p -r1.34 trigger.module --- modules/trigger/trigger.module 21 May 2009 23:07:16 -0000 1.34 +++ modules/trigger/trigger.module 22 May 2009 23:43:24 -0000 @@ -8,114 +8,6 @@ */ /** - * Implementation of hook_help(). - */ -function trigger_help($path, $arg) { - $explanation = '' . t('Triggers are system events, such as when new content is added or when a user logs in. Trigger module combines these triggers with actions (functional tasks), such as unpublishing content or e-mailing an administrator. The Actions settings page contains a list of existing actions and provides the ability to create and configure additional actions.', array('@url' => url('admin/settings/actions'))) . '
'; - switch ($path) { - case 'admin/build/trigger/comment': - return $explanation . '' . t('Below you can assign actions to run when certain comment-related triggers happen. For example, you could promote a post to the front page when a comment is added.') . '
'; - case 'admin/build/trigger/node': - return $explanation . '' . t('Below you can assign actions to run when certain content-related triggers happen. For example, you could send an e-mail to an administrator when a post is created or updated.') . '
'; - case 'admin/build/trigger/cron': - return $explanation . '' . t('Below you can assign actions to run during each pass of a cron maintenance task.', array('@cron' => url('admin/reports/status'))) . '
'; - case 'admin/build/trigger/taxonomy': - return $explanation . '' . t('Below you can assign actions to run when certain taxonomy-related triggers happen. For example, you could send an e-mail to an administrator when a term is deleted.') . '
'; - case 'admin/build/trigger/user': - return $explanation . '' . t("Below you can assign actions to run when certain user-related triggers happen. For example, you could send an e-mail to an administrator when a user account is deleted.") . '
'; - case 'admin/help#trigger': - $output = '' . t('The Trigger module provides the ability to trigger actions upon system events, such as when new content is added or when a user logs in.', array('@actions' => url('admin/settings/actions'))) . '
'; - $output .= '' . t('The combination of actions and triggers can perform many useful tasks, such as e-mailing an administrator if a user account is deleted, or automatically unpublishing comments that contain certain words. By default, there are five "contexts" of events (Comments, Content, Cron, Taxonomy, and Users), but more may be added by additional modules.') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Trigger module.', array('@trigger' => 'http://drupal.org/handbook/modules/trigger/')) . '
'; - return $output; - } -} - -/** - * Implementation of hook_menu(). - */ -function trigger_menu() { - $items['admin/build/trigger'] = array( - 'title' => 'Triggers', - 'description' => 'Tell Drupal when to execute actions.', - 'page callback' => 'trigger_assign', - 'access callback' => 'trigger_access_check', - 'access arguments' => array('node'), - ); - // We don't use a menu wildcard here because these are tabs, - // not invisible items. - $items['admin/build/trigger/node'] = array( - 'title' => 'Content', - 'page callback' => 'trigger_assign', - 'page arguments' => array('node'), - 'access callback' => 'trigger_access_check', - 'access arguments' => array('node'), - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/build/trigger/user'] = array( - 'title' => 'Users', - 'page callback' => 'trigger_assign', - 'page arguments' => array('user'), - 'access callback' => 'trigger_access_check', - 'access arguments' => array('user'), - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/build/trigger/comment'] = array( - 'title' => 'Comments', - 'page callback' => 'trigger_assign', - 'page arguments' => array('comment'), - 'access callback' => 'trigger_access_check', - 'access arguments' => array('comment'), - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/build/trigger/taxonomy'] = array( - 'title' => 'Taxonomy', - 'page callback' => 'trigger_assign', - 'page arguments' => array('taxonomy'), - 'access callback' => 'trigger_access_check', - 'access arguments' => array('taxonomy'), - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/build/trigger/cron'] = array( - 'title' => 'Cron', - 'page callback' => 'trigger_assign', - 'page arguments' => array('cron'), - 'access arguments' => array('administer actions'), - 'type' => MENU_LOCAL_TASK, - ); - - // We want contributed modules to be able to describe - // their hooks and have actions assignable to them. - $hooks = module_invoke_all('hook_info'); - foreach ($hooks as $module => $hook) { - // We've already done these. - if (in_array($module, array('node', 'comment', 'user', 'system', 'taxonomy'))) { - continue; - } - $info = db_result(db_query("SELECT info FROM {system} WHERE name = '%s'", $module)); - $info = unserialize($info); - $nice_name = $info['name']; - $items["admin/build/trigger/$module"] = array( - 'title' => $nice_name, - 'page callback' => 'trigger_assign', - 'page arguments' => array($module), - 'access arguments' => array($module), - 'type' => MENU_LOCAL_TASK, - ); - } - $items['admin/build/trigger/unassign'] = array( - 'title' => 'Unassign', - 'description' => 'Unassign an action from a trigger.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('trigger_unassign'), - 'access arguments' => array('administer actions'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** * Access callback for menu system. */ function trigger_access_check($module) { @@ -143,18 +35,6 @@ function _trigger_get_hook_aids($hook, $ } /** - * Implementation of hook_theme(). - */ -function trigger_theme() { - return array( - 'trigger_display' => array( - 'arguments' => array('element'), - 'file' => 'trigger.admin.inc', - ), - ); -} - -/** * Implementation of hook_forms(). We reuse code by using the * same assignment form definition for each node-op combination. */ @@ -249,34 +129,6 @@ function trigger_node_view($node, $tease } /** - * Implementation of hook_node_update(). - */ -function trigger_node_update($node) { - _trigger_node($node, 'update'); -} - -/** - * Implementation of hook_node_presave(). - */ -function trigger_node_presave($node) { - _trigger_node($node, 'presave'); -} - -/** - * Implementation of hook_node_insert(). - */ -function trigger_node_insert($node) { - _trigger_node($node, 'insert'); -} - -/** - * Implementation of hook_node_delete(). - */ -function trigger_node_delete($node) { - _trigger_node($node, 'delete'); -} - -/** * When an action is called in a context that does not match its type, * the object that the action expects must be retrieved. For example, when * an action that works on nodes is called during the comment hook, the @@ -303,27 +155,6 @@ function _trigger_normalize_comment_cont } /** - * Implementation of hook_comment_insert(). - */ -function trigger_comment_insert($form_values) { - _trigger_comment($form_values, 'insert'); -} - -/** - * Implementation of hook_comment_update(). - */ -function trigger_comment_update($form_values) { - _trigger_comment($form_values, 'update'); -} - -/** - * Implementation of hook_comment_delete(). - */ -function trigger_comment_delete($comment) { - _trigger_comment($comment, 'delete'); -} - -/** * Implementation of hook_comment_view(). */ function trigger_comment_view($comment) { @@ -368,20 +199,6 @@ function _trigger_comment($a1, $op) { } /** - * Implementation of hook_cron(). - */ -function trigger_cron() { - $aids = _trigger_get_hook_aids('cron'); - $context = array( - 'hook' => 'cron', - 'op' => '', - ); - // Cron does not act on any specific object. - $object = NULL; - actions_do(array_keys($aids), $object, $context); -} - -/** * When an action is called in a context that does not match its type, * the object that the action expects must be retrieved. For example, when * an action that works on nodes is called during the user hook, the @@ -413,46 +230,6 @@ function _trigger_normalize_user_context } /** - * trigger_user_login - */ -function trigger_user_login(&$edit, &$account, $category) { - _trigger_user('login', $edit, $account, $category); -} - -/** - * Implementation of hook_user_logout(). - */ -function trigger_user_logout($edit, $account) { - _trigger_user('logout', $edit, $account); -} - -/** - * Implementation of hook_user_insert(). - */ -function trigger_user_insert(&$edit, &$account, $category) { - _trigger_user('insert', $edit, $account, $category); -} - -/** - * Implementation of hook_user_update(). - */ -function trigger_user_update(&$edit, &$account, $category) { - _trigger_user('update', $edit, $account, $category); -} - -/** - * Implementation of hook_user_cancel(). - */ -function trigger_user_cancel($edit, $account, $method) { - switch ($method) { - case 'user_cancel_reassign': - case 'user_cancel_delete': - _trigger_user('delete', $edit, $account, $method); - break; - } -} - -/** * Implementation of hook_user_view(). */ function trigger_user_view(&$edit, &$account, $category) { @@ -488,24 +265,6 @@ function _trigger_user($op, &$edit, &$ac } /** - * Implementation of hook_taxonomy(). - */ -function trigger_taxonomy($op, $type, $array) { - if ($type != 'term') { - return; - } - $aids = _trigger_get_hook_aids('taxonomy', $op); - $context = array( - 'hook' => 'taxonomy', - 'op' => $op - ); - $_array = (object) $array; - foreach ($aids as $aid => $action_info) { - actions_do($aid, $_array, $context); - } -} - -/** * Often we generate a select field of all actions. This function * generates the options for that select. * @@ -528,11 +287,3 @@ function trigger_options($type = 'all') } } -/** - * Implementation of hook_actions_delete(). - * - * Remove all trigger entries for the given action, when deleted. - */ -function trigger_actions_delete($aid) { - db_query("DELETE FROM {trigger_assignments} WHERE aid = '%s'", $aid); -} Index: modules/trigger/trigger.node.inc =================================================================== RCS file: modules/trigger/trigger.node.inc diff -N modules/trigger/trigger.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/trigger.node.inc 22 May 2009 23:43:24 -0000 @@ -0,0 +1,36 @@ + 'Triggers', + 'description' => 'Tell Drupal when to execute actions.', + 'page callback' => 'trigger_assign', + 'access callback' => 'trigger_access_check', + 'access arguments' => array('node'), + ); + // We don't use a menu wildcard here because these are tabs, + // not invisible items. + $items['admin/build/trigger/node'] = array( + 'title' => 'Content', + 'page callback' => 'trigger_assign', + 'page arguments' => array('node'), + 'access callback' => 'trigger_access_check', + 'access arguments' => array('node'), + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/build/trigger/user'] = array( + 'title' => 'Users', + 'page callback' => 'trigger_assign', + 'page arguments' => array('user'), + 'access callback' => 'trigger_access_check', + 'access arguments' => array('user'), + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/build/trigger/comment'] = array( + 'title' => 'Comments', + 'page callback' => 'trigger_assign', + 'page arguments' => array('comment'), + 'access callback' => 'trigger_access_check', + 'access arguments' => array('comment'), + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/build/trigger/taxonomy'] = array( + 'title' => 'Taxonomy', + 'page callback' => 'trigger_assign', + 'page arguments' => array('taxonomy'), + 'access callback' => 'trigger_access_check', + 'access arguments' => array('taxonomy'), + 'type' => MENU_LOCAL_TASK, + ); + $items['admin/build/trigger/cron'] = array( + 'title' => 'Cron', + 'page callback' => 'trigger_assign', + 'page arguments' => array('cron'), + 'access arguments' => array('administer actions'), + 'type' => MENU_LOCAL_TASK, + ); + + // We want contributed modules to be able to describe + // their hooks and have actions assignable to them. + $hooks = module_invoke_all('hook_info'); + foreach ($hooks as $module => $hook) { + // We've already done these. + if (in_array($module, array('node', 'comment', 'user', 'system', 'taxonomy'))) { + continue; + } + $info = db_result(db_query("SELECT info FROM {system} WHERE name = '%s'", $module)); + $info = unserialize($info); + $nice_name = $info['name']; + $items["admin/build/trigger/$module"] = array( + 'title' => $nice_name, + 'page callback' => 'trigger_assign', + 'page arguments' => array($module), + 'access arguments' => array($module), + 'type' => MENU_LOCAL_TASK, + ); + } + $items['admin/build/trigger/unassign'] = array( + 'title' => 'Unassign', + 'description' => 'Unassign an action from a trigger.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('trigger_unassign'), + 'access arguments' => array('administer actions'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function trigger_theme() { + return array( + 'trigger_display' => array( + 'arguments' => array('element'), + 'file' => 'trigger.admin.inc', + ), + ); +} + Index: modules/trigger/trigger.taxonomy.inc =================================================================== RCS file: modules/trigger/trigger.taxonomy.inc diff -N modules/trigger/trigger.taxonomy.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/trigger.taxonomy.inc 22 May 2009 23:43:24 -0000 @@ -0,0 +1,26 @@ + 'taxonomy', + 'op' => $op + ); + $_array = (object) $array; + foreach ($aids as $aid => $action_info) { + actions_do($aid, $_array, $context); + } +} + Index: modules/trigger/trigger.user.inc =================================================================== RCS file: modules/trigger/trigger.user.inc diff -N modules/trigger/trigger.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/trigger.user.inc 22 May 2009 23:43:24 -0000 @@ -0,0 +1,48 @@ + $interval)) { + update_refresh(); + _update_cron_notify(); + } +} + Index: modules/update/update.form.inc =================================================================== RCS file: modules/update/update.form.inc diff -N modules/update/update.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/update/update.form.inc 22 May 2009 23:43:23 -0000 @@ -0,0 +1,32 @@ +' . t('Here you can find information about available updates for your installed modules and themes. Note that each module or theme is part of a "project", which may or may not have the same name, and might include multiple modules or themes within it.') . ''; + $output .= '' . t('To extend the functionality or to change the look of your site, a number of contributed modules and themes are available.', array('@modules' => 'http://drupal.org/project/modules', '@themes' => 'http://drupal.org/project/themes')) . '
'; + $output .= '' . t('Each time Drupal core or a contributed module or theme is updated, it is important that update.php is run.', array('@update-php' => url($base_url . '/update.php', array('external' => TRUE)))) . '
'; + return $output; + case 'admin/build/themes': + case 'admin/build/modules': + include_once DRUPAL_ROOT . '/includes/install.inc'; + $status = module_invoke('update', 'requirements', 'runtime'); + foreach (array('core', 'contrib') as $report_type) { + $type = 'update_' . $report_type; + if (isset($status[$type]['severity'])) { + if ($status[$type]['severity'] == REQUIREMENT_ERROR) { + drupal_set_message($status[$type]['description'], 'error'); + } + elseif ($status[$type]['severity'] == REQUIREMENT_WARNING) { + drupal_set_message($status[$type]['description'], 'warning'); + } + } + } + + case 'admin/reports/updates/settings': + case 'admin/reports/status': + // These two pages don't need additional nagging. + break; + + case 'admin/help#update': + $output = '' . t("The Update status module periodically checks for new versions of your site's software (including contributed modules and themes), and alerts you to available updates.") . '
'; + $output .= '' . t('The report of available updates will alert you when new releases are available for download. You may configure options for update checking frequency and notifications at the Update status module settings page.', array('@update-report' => url('admin/reports/updates'), '@update-settings' => url('admin/settings/updates'))) . '
'; + $output .= '' . t('Please note that in order to provide this information, anonymous usage statistics are sent to drupal.org. If desired, you may disable the Update status module from the module administration page.', array('@modules' => url('admin/build/modules'))) . '
'; + $output .= '' . t('For more information, see the online handbook entry for Update status module.', array('@update' => 'http://drupal.org/handbook/modules/update')) . '
'; + return $output; + + default: + // Otherwise, if we're on *any* admin page and there's a security + // update missing, print an error message about it. + if (arg(0) == 'admin' && strpos($path, '#') === FALSE + && user_access('administer site configuration')) { + include_once DRUPAL_ROOT . '/includes/install.inc'; + $status = module_invoke('update', 'requirements', 'runtime'); + foreach (array('core', 'contrib') as $report_type) { + $type = 'update_' . $report_type; + if (isset($status[$type]) + && isset($status[$type]['reason']) + && $status[$type]['reason'] === UPDATE_NOT_SECURE) { + drupal_set_message($status[$type]['description'], 'error'); + } + } + } + + } +} + Index: modules/update/update.info =================================================================== RCS file: /cvs/drupal/drupal/modules/update/update.info,v retrieving revision 1.5 diff -u -p -r1.5 update.info --- modules/update/update.info 11 Oct 2008 02:33:12 -0000 1.5 +++ modules/update/update.info 22 May 2009 23:43:23 -0000 @@ -10,3 +10,8 @@ files[] = update.fetch.inc files[] = update.report.inc files[] = update.settings.inc files[] = update.install +files[] = update.registry.inc +files[] = update.mail.inc +files[] = update.cron.inc +files[] = update.form.inc +files[] = update.help.inc Index: modules/update/update.install =================================================================== RCS file: /cvs/drupal/drupal/modules/update/update.install,v retrieving revision 1.7 diff -u -p -r1.7 update.install --- modules/update/update.install 13 May 2009 19:42:17 -0000 1.7 +++ modules/update/update.install 22 May 2009 23:43:22 -0000 @@ -67,3 +67,54 @@ function update_update_6000() { _update_remove_update_status_variables(); return array(); } +/** + * Implementation of hook_requirements(). + * + * @return + * An array describing the status of the site regarding available updates. + * If there is no update data, only one record will be returned, indicating + * that the status of core can't be determined. If data is available, there + * will be two records: one for core, and another for all of contrib + * (assuming there are any contributed modules or themes enabled on the + * site). In addition to the fields expected by hook_requirements ('value', + * 'severity', and optionally 'description'), this array will contain a + * 'reason' attribute, which is an integer constant to indicate why the + * given status is being returned (UPDATE_NOT_SECURE, UPDATE_NOT_CURRENT, or + * UPDATE_UNKNOWN). This is used for generating the appropriate e-mail + * notification messages during update_cron(), and might be useful for other + * modules that invoke update_requirements() to find out if the site is up + * to date or not. + * + * @see _update_message_text() + * @see _update_cron_notify() + */ +function update_requirements($phase) { + if ($phase == 'runtime') { + if ($available = update_get_available(FALSE)) { + module_load_include('inc', 'update', 'update.compare'); + $data = update_calculate_project_data($available); + // First, populate the requirements for core: + $requirements['update_core'] = _update_requirement_check($data['drupal'], 'core'); + // We don't want to check drupal a second time. + unset($data['drupal']); + if (!empty($data)) { + // Now, sort our $data array based on each project's status. The + // status constants are numbered in the right order of precedence, so + // we just need to make sure the projects are sorted in ascending + // order of status, and we can look at the first project we find. + uasort($data, '_update_project_status_sort'); + $first_project = reset($data); + $requirements['update_contrib'] = _update_requirement_check($first_project, 'contrib'); + } + } + else { + $requirements['update_core']['title'] = t('Drupal core update status'); + $requirements['update_core']['value'] = t('No update data available'); + $requirements['update_core']['severity'] = REQUIREMENT_WARNING; + $requirements['update_core']['reason'] = UPDATE_UNKNOWN; + $requirements['update_core']['description'] = _update_no_data(); + } + return $requirements; + } +} + Index: modules/update/update.mail.inc =================================================================== RCS file: modules/update/update.mail.inc diff -N modules/update/update.mail.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/update/update.mail.inc 22 May 2009 23:43:23 -0000 @@ -0,0 +1,37 @@ +language; + $message['subject'] .= t('New release(s) available for !site_name', array('!site_name' => variable_get('site_name', 'Drupal')), $langcode); + foreach ($params as $msg_type => $msg_reason) { + $message['body'][] = _update_message_text($msg_type, $msg_reason, FALSE, $language); + } + $message['body'][] = t('See the available updates page for more information:', array(), $langcode) . "\n" . url('admin/reports/updates', array('absolute' => TRUE, 'language' => $language)); +} + Index: modules/update/update.module =================================================================== RCS file: /cvs/drupal/drupal/modules/update/update.module,v retrieving revision 1.33 diff -u -p -r1.33 update.module --- modules/update/update.module 13 May 2009 18:21:42 -0000 1.33 +++ modules/update/update.module 22 May 2009 23:43:23 -0000 @@ -53,163 +53,6 @@ define('UPDATE_UNKNOWN', -2); /** - * Implementation of hook_help(). - */ -function update_help($path, $arg) { - switch ($path) { - case 'admin/reports/updates': - global $base_url; - $output = '' . t('Here you can find information about available updates for your installed modules and themes. Note that each module or theme is part of a "project", which may or may not have the same name, and might include multiple modules or themes within it.') . '
'; - $output .= '' . t('To extend the functionality or to change the look of your site, a number of contributed modules and themes are available.', array('@modules' => 'http://drupal.org/project/modules', '@themes' => 'http://drupal.org/project/themes')) . '
'; - $output .= '' . t('Each time Drupal core or a contributed module or theme is updated, it is important that update.php is run.', array('@update-php' => url($base_url . '/update.php', array('external' => TRUE)))) . '
'; - return $output; - case 'admin/build/themes': - case 'admin/build/modules': - include_once DRUPAL_ROOT . '/includes/install.inc'; - $status = update_requirements('runtime'); - foreach (array('core', 'contrib') as $report_type) { - $type = 'update_' . $report_type; - if (isset($status[$type]['severity'])) { - if ($status[$type]['severity'] == REQUIREMENT_ERROR) { - drupal_set_message($status[$type]['description'], 'error'); - } - elseif ($status[$type]['severity'] == REQUIREMENT_WARNING) { - drupal_set_message($status[$type]['description'], 'warning'); - } - } - } - - case 'admin/reports/updates/settings': - case 'admin/reports/status': - // These two pages don't need additional nagging. - break; - - case 'admin/help#update': - $output = '' . t("The Update status module periodically checks for new versions of your site's software (including contributed modules and themes), and alerts you to available updates.") . '
'; - $output .= '' . t('The report of available updates will alert you when new releases are available for download. You may configure options for update checking frequency and notifications at the Update status module settings page.', array('@update-report' => url('admin/reports/updates'), '@update-settings' => url('admin/settings/updates'))) . '
'; - $output .= '' . t('Please note that in order to provide this information, anonymous usage statistics are sent to drupal.org. If desired, you may disable the Update status module from the module administration page.', array('@modules' => url('admin/build/modules'))) . '
'; - $output .= '' . t('For more information, see the online handbook entry for Update status module.', array('@update' => 'http://drupal.org/handbook/modules/update')) . '
'; - return $output; - - default: - // Otherwise, if we're on *any* admin page and there's a security - // update missing, print an error message about it. - if (arg(0) == 'admin' && strpos($path, '#') === FALSE - && user_access('administer site configuration')) { - include_once DRUPAL_ROOT . '/includes/install.inc'; - $status = update_requirements('runtime'); - foreach (array('core', 'contrib') as $report_type) { - $type = 'update_' . $report_type; - if (isset($status[$type]) - && isset($status[$type]['reason']) - && $status[$type]['reason'] === UPDATE_NOT_SECURE) { - drupal_set_message($status[$type]['description'], 'error'); - } - } - } - - } -} - -/** - * Implementation of hook_menu(). - */ -function update_menu() { - $items = array(); - - $items['admin/reports/updates'] = array( - 'title' => 'Available updates', - 'description' => 'Get a status report about available updates for your installed modules and themes.', - 'page callback' => 'update_status', - 'access arguments' => array('administer site configuration'), - 'weight' => 10, - ); - $items['admin/settings/updates'] = array( - 'title' => 'Updates', - 'description' => 'Change frequency of checks for available updates to your installed modules and themes, and how you would like to be notified.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('update_settings'), - 'access arguments' => array('administer site configuration'), - ); - $items['admin/reports/updates/check'] = array( - 'title' => 'Manual update check', - 'page callback' => 'update_manual_status', - 'access arguments' => array('administer site configuration'), - 'type' => MENU_CALLBACK, - ); - - return $items; -} - -/** - * Implementation of the hook_theme() registry. - */ -function update_theme() { - return array( - 'update_settings' => array( - 'arguments' => array('form' => NULL), - ), - 'update_report' => array( - 'arguments' => array('data' => NULL), - ), - 'update_version' => array( - 'arguments' => array('version' => NULL, 'tag' => NULL, 'class' => NULL), - ), - ); -} - -/** - * Implementation of hook_requirements(). - * - * @return - * An array describing the status of the site regarding available updates. - * If there is no update data, only one record will be returned, indicating - * that the status of core can't be determined. If data is available, there - * will be two records: one for core, and another for all of contrib - * (assuming there are any contributed modules or themes enabled on the - * site). In addition to the fields expected by hook_requirements ('value', - * 'severity', and optionally 'description'), this array will contain a - * 'reason' attribute, which is an integer constant to indicate why the - * given status is being returned (UPDATE_NOT_SECURE, UPDATE_NOT_CURRENT, or - * UPDATE_UNKNOWN). This is used for generating the appropriate e-mail - * notification messages during update_cron(), and might be useful for other - * modules that invoke update_requirements() to find out if the site is up - * to date or not. - * - * @see _update_message_text() - * @see _update_cron_notify() - */ -function update_requirements($phase) { - if ($phase == 'runtime') { - if ($available = update_get_available(FALSE)) { - module_load_include('inc', 'update', 'update.compare'); - $data = update_calculate_project_data($available); - // First, populate the requirements for core: - $requirements['update_core'] = _update_requirement_check($data['drupal'], 'core'); - // We don't want to check drupal a second time. - unset($data['drupal']); - if (!empty($data)) { - // Now, sort our $data array based on each project's status. The - // status constants are numbered in the right order of precedence, so - // we just need to make sure the projects are sorted in ascending - // order of status, and we can look at the first project we find. - uasort($data, '_update_project_status_sort'); - $first_project = reset($data); - $requirements['update_contrib'] = _update_requirement_check($first_project, 'contrib'); - } - } - else { - $requirements['update_core']['title'] = t('Drupal core update status'); - $requirements['update_core']['value'] = t('No update data available'); - $requirements['update_core']['severity'] = REQUIREMENT_WARNING; - $requirements['update_core']['reason'] = UPDATE_UNKNOWN; - $requirements['update_core']['description'] = _update_no_data(); - } - return $requirements; - } -} - -/** * Private helper method to fill in the requirements array. * * This is shared for both core and contrib to generate the right elements in @@ -272,44 +115,6 @@ function _update_requirement_check($proj } /** - * Implementation of hook_cron(). - */ -function update_cron() { - $frequency = variable_get('update_check_frequency', 1); - $interval = 60 * 60 * 24 * $frequency; - // Cron should check for updates if there is no update data cached or if the - // configured update interval has elapsed. - if (!_update_cache_get('update_available_releases') || ((REQUEST_TIME - variable_get('update_last_check', 0)) > $interval)) { - update_refresh(); - _update_cron_notify(); - } -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - * - * Adds a submit handler to the system modules and themes forms, so that if a - * site admin saves either form, we invalidate the cache of available updates. - * - * @see _update_cache_clear() - */ -function update_form_system_themes_form_alter(&$form, $form_state) { - $form['#submit'][] = 'update_cache_clear_submit'; -} - -/** - * Implementation of hook_form_FORM_ID_alter(). - * - * Adds a submit handler to the system modules and themes forms, so that if a - * site admin saves either form, we invalidate the cache of available updates. - * - * @see _update_cache_clear() - */ -function update_form_system_modules_alter(&$form, $form_state) { - $form['#submit'][] = 'update_cache_clear_submit'; -} - -/** * Helper function for use as a form submit callback. */ function update_cache_clear_submit($form, &$form_state) { @@ -383,35 +188,6 @@ function update_refresh() { } /** - * Implementation of hook_mail(). - * - * Constructs the email notification message when the site is out of date. - * - * @param $key - * Unique key to indicate what message to build, always 'status_notify'. - * @param $message - * Reference to the message array being built. - * @param $params - * Array of parameters to indicate what kind of text to include in the - * message body. This is a keyed array of message type ('core' or 'contrib') - * as the keys, and the status reason constant (UPDATE_NOT_SECURE, etc) for - * the values. - * - * @see drupal_mail() - * @see _update_cron_notify() - * @see _update_message_text() - */ -function update_mail($key, &$message, $params) { - $language = $message['language']; - $langcode = $language->language; - $message['subject'] .= t('New release(s) available for !site_name', array('!site_name' => variable_get('site_name', 'Drupal')), $langcode); - foreach ($params as $msg_type => $msg_reason) { - $message['body'][] = _update_message_text($msg_type, $msg_reason, FALSE, $language); - } - $message['body'][] = t('See the available updates page for more information:', array(), $langcode) . "\n" . url('admin/reports/updates', array('absolute' => TRUE, 'language' => $language)); -} - -/** * Helper function to return the appropriate message text when the site is out * of date or missing a security update. * @@ -596,28 +372,5 @@ function _update_cache_clear($cid = NULL } /** - * Implementation of hook_flush_caches(). - * - * Called from update.php (among others) to flush the caches. - * Since we're running update.php, we are likely to install a new version of - * something, in which case, we want to check for available update data again. - * However, because we have our own caching system, we need to directly clear - * the database table ourselves at this point and return nothing, for example, - * on sites that use memcache where cache_clear_all() won't know how to purge - * this data. - * - * However, we only want to do this from update.php, since otherwise, we'd - * lose all the available update data on every cron run. So, we specifically - * check if the site is in MAINTENANCE_MODE == 'update' (which indicates - * update.php is running, not update module... alas for overloaded names). - */ -function update_flush_caches() { - if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') { - _update_cache_clear(); - } - return array(); -} - -/** * @} End of "defgroup update_status_cache". */ Index: modules/update/update.registry.inc =================================================================== RCS file: modules/update/update.registry.inc diff -N modules/update/update.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/update/update.registry.inc 22 May 2009 23:43:23 -0000 @@ -0,0 +1,78 @@ + 'Available updates', + 'description' => 'Get a status report about available updates for your installed modules and themes.', + 'page callback' => 'update_status', + 'access arguments' => array('administer site configuration'), + 'weight' => 10, + ); + $items['admin/settings/updates'] = array( + 'title' => 'Updates', + 'description' => 'Change frequency of checks for available updates to your installed modules and themes, and how you would like to be notified.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('update_settings'), + 'access arguments' => array('administer site configuration'), + ); + $items['admin/reports/updates/check'] = array( + 'title' => 'Manual update check', + 'page callback' => 'update_manual_status', + 'access arguments' => array('administer site configuration'), + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implementation of the hook_theme() registry. + */ +function update_theme() { + return array( + 'update_settings' => array( + 'arguments' => array('form' => NULL), + ), + 'update_report' => array( + 'arguments' => array('data' => NULL), + ), + 'update_version' => array( + 'arguments' => array('version' => NULL, 'tag' => NULL, 'class' => NULL), + ), + ); +} + +/** + * Implementation of hook_flush_caches(). + * + * Called from update.php (among others) to flush the caches. + * Since we're running update.php, we are likely to install a new version of + * something, in which case, we want to check for available update data again. + * However, because we have our own caching system, we need to directly clear + * the database table ourselves at this point and return nothing, for example, + * on sites that use memcache where cache_clear_all() won't know how to purge + * this data. + * + * However, we only want to do this from update.php, since otherwise, we'd + * lose all the available update data on every cron run. So, we specifically + * check if the site is in MAINTENANCE_MODE == 'update' (which indicates + * update.php is running, not update module... alas for overloaded names). + */ +function update_flush_caches() { + if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') { + _update_cache_clear(); + } + return array(); +} + Index: modules/upload/upload.file.inc =================================================================== RCS file: modules/upload/upload.file.inc diff -N modules/upload/upload.file.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/upload/upload.file.inc 22 May 2009 23:43:22 -0000 @@ -0,0 +1,46 @@ + $filepath))->fetchObject(); + + if ($file && user_access('view uploaded files') && ($node = node_load($file->nid)) && node_access('view', $node)) { + return array( + 'Content-Type' => $file->filemime, + 'Content-Length' => $file->filesize, + ); + } + else { + return -1; + } +} + +/** + * Implementation of hook_file_references(). + */ +function upload_file_references($file) { + // If upload.module is still using a file, do not let other modules delete it. + $file_used = (bool) db_query_range('SELECT 1 FROM {upload} WHERE fid = :fid', array(':fid' => $file->fid), 0, 1)->fetchField(); + if ($file_used) { + // Return the name of the module and how many references it has to the file. + return array('upload' => $count); + } +} + +/** + * Implementation of hook_file_delete(). + */ +function upload_file_delete($file) { + // Delete all information associated with the file. + db_delete('upload')->condition('fid', $file->fid)->execute(); +} + Index: modules/upload/upload.form.inc =================================================================== RCS file: modules/upload/upload.form.inc diff -N modules/upload/upload.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/upload/upload.form.inc 22 May 2009 23:44:34 -0000 @@ -0,0 +1,54 @@ + array($limits['extensions']), + 'file_validate_image_resolution' => array($limits['resolution']), + 'file_validate_size' => array($limits['file_size'], $limits['user_size']), + ); + + // Save new file uploads. + if (user_access('upload files') && ($file = file_save_upload('upload', $validators, file_directory_path()))) { + $file->list = variable_get('upload_list_default', 1); + $file->description = $file->filename; + $file->weight = 0; + $file->new = TRUE; + $form['#node']->files[$file->fid] = $file; + $form_state['values']['files'][$file->fid] = (array)$file; + } + + if (isset($form_state['values']['files'])) { + foreach ($form_state['values']['files'] as $fid => $file) { + $form_state['values']['files'][$fid]['new'] = !empty($form['#node']->files[$fid]->new); + } + } + + // Order the form according to the set file weight values. + if (!empty($form_state['values']['files'])) { + $microweight = 0.001; + foreach ($form_state['values']['files'] as $fid => $file) { + if (is_numeric($fid)) { + $form_state['values']['files'][$fid]['#weight'] = $file['weight'] + $microweight; + $microweight += 0.001; + } + } + uasort($form_state['values']['files'], 'element_sort'); + } +} + Index: modules/upload/upload.help.inc =================================================================== RCS file: modules/upload/upload.help.inc diff -N modules/upload/upload.help.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/upload/upload.help.inc 22 May 2009 23:43:22 -0000 @@ -0,0 +1,23 @@ +' . t('The upload module allows users to upload files to the site. The ability to upload files is important for members of a community who want to share work. It is also useful to administrators who want to keep uploaded files connected to posts.') . ''; + $output .= '' . t('Users with the upload files permission can upload attachments to posts. Uploads may be enabled for specific content types on the content types settings page. Each user role can be customized to limit or control the file size of uploads, or the maximum dimension of image files.') . '
'; + $output .= '' . t('For more information, see the online handbook entry for Upload module.', array('@upload' => 'http://drupal.org/handbook/modules/upload/')) . '
'; + return $output; + case 'admin/settings/upload': + return '' . t('Users with the upload files permission can upload attachments. Users with the view uploaded files permission can view uploaded attachments. You can choose which post types can take attachments on the content types settings page.', array('@permissions' => url('admin/user/permissions'), '@types' => url('admin/settings/types'))) . '
'; + } +} + Index: modules/upload/upload.info =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.info,v retrieving revision 1.8 diff -u -p -r1.8 upload.info --- modules/upload/upload.info 11 Oct 2008 02:33:13 -0000 1.8 +++ modules/upload/upload.info 22 May 2009 23:44:34 -0000 @@ -7,3 +7,10 @@ core = 7.x files[] = upload.module files[] = upload.admin.inc files[] = upload.install +files[] = upload.registry.inc +files[] = upload.user.inc +files[] = upload.node.inc +files[] = upload.help.inc +files[] = upload.file.inc +files[] = upload.form.inc +files[] = upload.pages.inc Index: modules/upload/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v retrieving revision 1.239 diff -u -p -r1.239 upload.module --- modules/upload/upload.module 21 May 2009 12:00:06 -0000 1.239 +++ modules/upload/upload.module 22 May 2009 23:44:34 -0000 @@ -8,54 +8,6 @@ */ /** - * Implementation of hook_help(). - */ -function upload_help($path, $arg) { - switch ($path) { - case 'admin/help#upload': - $output = '' . t('The upload module allows users to upload files to the site. The ability to upload files is important for members of a community who want to share work. It is also useful to administrators who want to keep uploaded files connected to posts.') . '
'; - $output .= '' . t('Users with the upload files permission can upload attachments to posts. Uploads may be enabled for specific content types on the content types settings page. Each user role can be customized to limit or control the file size of uploads, or the maximum dimension of image files.') . '
'; - $output .= '' . t('For more information, see the online handbook entry for Upload module.', array('@upload' => 'http://drupal.org/handbook/modules/upload/')) . '
'; - return $output; - case 'admin/settings/upload': - return '' . t('Users with the upload files permission can upload attachments. Users with the view uploaded files permission can view uploaded attachments. You can choose which post types can take attachments on the content types settings page.', array('@permissions' => url('admin/user/permissions'), '@types' => url('admin/settings/types'))) . '
'; - } -} - -/** - * Implementation of hook_theme(). - */ -function upload_theme() { - return array( - 'upload_attachments' => array( - 'arguments' => array('elements' => NULL), - ), - 'upload_form_current' => array( - 'arguments' => array('form' => NULL), - ), - 'upload_form_new' => array( - 'arguments' => array('form' => NULL), - ), - ); -} - -/** - * Implementation of hook_perm(). - */ -function upload_perm() { - return array( - 'upload files' => array( - 'title' => t('Upload files'), - 'description' => t('Attach images and other files to content.'), - ), - 'view uploaded files' => array( - 'title' => t('View uploaded files'), - 'description' => t('View and download files attached to content.'), - ), - ); -} - -/** * Inject links into $node for attachments. */ function upload_node_links($node, $teaser) { @@ -83,26 +35,6 @@ function upload_node_links($node, $tease } /** - * Implementation of hook_menu(). - */ -function upload_menu() { - $items['upload/js'] = array( - 'page callback' => 'upload_js', - 'access arguments' => array('upload files'), - 'type' => MENU_CALLBACK, - ); - $items['admin/settings/uploads'] = array( - 'title' => 'File uploads', - 'description' => 'Control how files may be attached to content.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('upload_admin_settings'), - 'access arguments' => array('administer site configuration'), - 'type' => MENU_NORMAL_ITEM, - ); - return $items; -} - -/** * Determine the limitations on files that a given user may upload. The user * may be in multiple roles so we select the most permissive limitations from * all of their roles. @@ -145,70 +77,6 @@ function _upload_file_limits($user) { ); } -/** - * Implementation of hook_file_download(). - */ -function upload_file_download($filepath) { - $filepath = file_create_path($filepath); - $file = db_query("SELECT f.*, u.nid FROM {files} f INNER JOIN {upload} u ON f.fid = u.fid WHERE filepath = :path", array(':path' => $filepath))->fetchObject(); - - if ($file && user_access('view uploaded files') && ($node = node_load($file->nid)) && node_access('view', $node)) { - return array( - 'Content-Type' => $file->filemime, - 'Content-Length' => $file->filesize, - ); - } - else { - return -1; - } -} - -/** - * Save new uploads and store them in the session to be associated to the node - * on upload_save. - * - * @param $node - * A node object to associate with uploaded files. - */ -function upload_node_form_submit(&$form, &$form_state) { - global $user; - - $limits = _upload_file_limits($user); - $validators = array( - 'file_validate_extensions' => array($limits['extensions']), - 'file_validate_image_resolution' => array($limits['resolution']), - 'file_validate_size' => array($limits['file_size'], $limits['user_size']), - ); - - // Save new file uploads. - if (user_access('upload files') && ($file = file_save_upload('upload', $validators, file_directory_path()))) { - $file->list = variable_get('upload_list_default', 1); - $file->description = $file->filename; - $file->weight = 0; - $file->new = TRUE; - $form['#node']->files[$file->fid] = $file; - $form_state['values']['files'][$file->fid] = (array)$file; - } - - if (isset($form_state['values']['files'])) { - foreach ($form_state['values']['files'] as $fid => $file) { - $form_state['values']['files'][$fid]['new'] = !empty($form['#node']->files[$fid]->new); - } - } - - // Order the form according to the set file weight values. - if (!empty($form_state['values']['files'])) { - $microweight = 0.001; - foreach ($form_state['values']['files'] as $fid => $file) { - if (is_numeric($fid)) { - $form_state['values']['files'][$fid]['#weight'] = $file['weight'] + $microweight; - $microweight += 0.001; - } - } - uasort($form_state['values']['files'], 'element_sort'); - } -} - function upload_form_alter(&$form, $form_state, $form_id) { if ($form_id == 'node_type_form' && isset($form['identity']['type'])) { $form['workflow']['upload'] = array( @@ -278,26 +146,6 @@ function upload_file_load($files) { } /** - * Implementation of hook_file_references(). - */ -function upload_file_references($file) { - // If upload.module is still using a file, do not let other modules delete it. - $file_used = (bool) db_query_range('SELECT 1 FROM {upload} WHERE fid = :fid', array(':fid' => $file->fid), 0, 1)->fetchField(); - if ($file_used) { - // Return the name of the module and how many references it has to the file. - return array('upload' => $count); - } -} - -/** - * Implementation of hook_file_delete(). - */ -function upload_file_delete($file) { - // Delete all information associated with the file. - db_delete('upload')->condition('fid', $file->fid)->execute(); -} - -/** * Implementation of hook_node_load(). */ function upload_node_load($nodes, $types) { @@ -382,50 +230,6 @@ function upload_node_view($node, $teaser } /** - * Implementation of hook_node_insert(). - */ -function upload_node_insert($node) { - if (user_access('upload files')) { - upload_save($node); - } -} - -/** - * Implementation of hook_node_update(). - */ -function upload_node_update($node) { - if (user_access('upload files')) { - upload_save($node); - } -} - -/** - * Implementation of hook_node_delete(). - */ -function upload_node_delete($node) { - db_delete('upload')->condition('nid', $node->nid)->execute(); - if (!is_array($node->files)) { - return; - } - foreach ($node->files as $file) { - file_delete($file); - } -} - -/** - * Implementation of hook_node_delete_revision(). - */ -function upload_node_delete_revision($node) { - db_delete('upload')->condition('vid', $node->vid)->execute(); - if (!is_array($node->files)) { - return; - } - foreach ($node->files as $file) { - file_delete($file); - } -} - -/** * Implementation of hook_node_search_result(). */ function upload_node_search_result($node) { @@ -632,69 +436,3 @@ function theme_upload_form_new($form) { return $output; } -/** - * Menu-callback for JavaScript-based uploads. - */ -function upload_js() { - $cached_form_state = array(); - $files = array(); - - // Load the form from the Form API cache. - if (!($cached_form = form_get_cache($_POST['form_build_id'], $cached_form_state)) || !isset($cached_form['#node']) || !isset($cached_form['attachments'])) { - form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.')); - $output = theme('status_messages'); - print drupal_to_js(array('status' => TRUE, 'data' => $output)); - exit(); - } - - $form_state = array('values' => $_POST); - - // Handle new uploads, and merge tmp files into node-files. - upload_node_form_submit($cached_form, $form_state); - - if (!empty($form_state['values']['files'])) { - foreach ($form_state['values']['files'] as $fid => $file) { - if (isset($cached_form['#node']->files[$fid])) { - $files[$fid] = $cached_form['#node']->files[$fid]; - } - } - } - - $node = $cached_form['#node']; - - $node->files = $files; - - $form = _upload_form($node); - - unset($cached_form['attachments']['wrapper']['new']); - $cached_form['attachments']['wrapper'] = array_merge($cached_form['attachments']['wrapper'], $form); - - $cached_form['attachments']['#collapsed'] = FALSE; - - form_set_cache($_POST['form_build_id'], $cached_form, $cached_form_state); - - foreach ($files as $fid => $file) { - if (is_numeric($fid)) { - $form['files'][$fid]['description']['#default_value'] = $form_state['values']['files'][$fid]['description']; - $form['files'][$fid]['list']['#default_value'] = !empty($form_state['values']['files'][$fid]['list']); - $form['files'][$fid]['remove']['#default_value'] = !empty($form_state['values']['files'][$fid]['remove']); - $form['files'][$fid]['weight']['#default_value'] = $form_state['values']['files'][$fid]['weight']; - } - } - - // Render the form for output. - $form += array( - '#tree' => FALSE, - '#parents' => array(), - ); - drupal_alter('form', $form, array(), 'upload_js'); - $form_state = array('submitted' => FALSE, 'programmed' => FALSE); - $form = form_builder('upload_js', $form, $form_state); - $output = theme('status_messages') . drupal_render($form); - - // We send the updated file attachments form. - // Don't call drupal_json(). ahah.js uses an iframe and - // the header output by drupal_json() causes problems in some browsers. - print drupal_to_js(array('status' => TRUE, 'data' => $output)); - exit; -} Index: modules/upload/upload.node.inc =================================================================== RCS file: modules/upload/upload.node.inc diff -N modules/upload/upload.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/upload/upload.node.inc 22 May 2009 23:43:21 -0000 @@ -0,0 +1,52 @@ +condition('nid', $node->nid)->execute(); + if (!is_array($node->files)) { + return; + } + foreach ($node->files as $file) { + file_delete($file); + } +} + +/** + * Implementation of hook_node_delete_revision(). + */ +function upload_node_delete_revision($node) { + db_delete('upload')->condition('vid', $node->vid)->execute(); + if (!is_array($node->files)) { + return; + } + foreach ($node->files as $file) { + file_delete($file); + } +} + Index: modules/upload/upload.pages.inc =================================================================== RCS file: modules/upload/upload.pages.inc diff -N modules/upload/upload.pages.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/upload/upload.pages.inc 22 May 2009 23:44:34 -0000 @@ -0,0 +1,74 @@ + TRUE, 'data' => $output)); + exit(); + } + + $form_state = array('values' => $_POST); + + // Handle new uploads, and merge tmp files into node-files. + upload_node_form_submit($cached_form, $form_state); + + if (!empty($form_state['values']['files'])) { + foreach ($form_state['values']['files'] as $fid => $file) { + if (isset($cached_form['#node']->files[$fid])) { + $files[$fid] = $cached_form['#node']->files[$fid]; + } + } + } + + $node = $cached_form['#node']; + + $node->files = $files; + + $form = _upload_form($node); + + unset($cached_form['attachments']['wrapper']['new']); + $cached_form['attachments']['wrapper'] = array_merge($cached_form['attachments']['wrapper'], $form); + + $cached_form['attachments']['#collapsed'] = FALSE; + + form_set_cache($_POST['form_build_id'], $cached_form, $cached_form_state); + + foreach ($files as $fid => $file) { + if (is_numeric($fid)) { + $form['files'][$fid]['description']['#default_value'] = $form_state['values']['files'][$fid]['description']; + $form['files'][$fid]['list']['#default_value'] = !empty($form_state['values']['files'][$fid]['list']); + $form['files'][$fid]['remove']['#default_value'] = !empty($form_state['values']['files'][$fid]['remove']); + $form['files'][$fid]['weight']['#default_value'] = $form_state['values']['files'][$fid]['weight']; + } + } + + // Render the form for output. + $form += array( + '#tree' => FALSE, + '#parents' => array(), + ); + drupal_alter('form', $form, array(), 'upload_js'); + $form_state = array('submitted' => FALSE, 'programmed' => FALSE); + $form = form_builder('upload_js', $form, $form_state); + $output = theme('status_messages') . drupal_render($form); + + // We send the updated file attachments form. + // Don't call drupal_json(). ahah.js uses an iframe and + // the header output by drupal_json() causes problems in some browsers. + print drupal_to_js(array('status' => TRUE, 'data' => $output)); + exit; +} Index: modules/upload/upload.registry.inc =================================================================== RCS file: modules/upload/upload.registry.inc diff -N modules/upload/upload.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/upload/upload.registry.inc 22 May 2009 23:43:21 -0000 @@ -0,0 +1,45 @@ + 'upload_js', + 'access arguments' => array('upload files'), + 'type' => MENU_CALLBACK, + ); + $items['admin/settings/uploads'] = array( + 'title' => 'File uploads', + 'description' => 'Control how files may be attached to content.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('upload_admin_settings'), + 'access arguments' => array('administer site configuration'), + 'type' => MENU_NORMAL_ITEM, + ); + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function upload_theme() { + return array( + 'upload_attachments' => array( + 'arguments' => array('elements' => NULL), + ), + 'upload_form_current' => array( + 'arguments' => array('form' => NULL), + ), + 'upload_form_new' => array( + 'arguments' => array('form' => NULL), + ), + ); +} + Index: modules/upload/upload.user.inc =================================================================== RCS file: modules/upload/upload.user.inc diff -N modules/upload/upload.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/upload/upload.user.inc 22 May 2009 23:43:21 -0000 @@ -0,0 +1,24 @@ + array( + 'title' => t('Upload files'), + 'description' => t('Attach images and other files to content.'), + ), + 'view uploaded files' => array( + 'title' => t('View uploaded files'), + 'description' => t('View and download files attached to content.'), + ), + ); +} + Index: modules/user/user.actions.inc =================================================================== RCS file: modules/user/user.actions.inc diff -N modules/user/user.actions.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/user/user.actions.inc 22 May 2009 23:43:17 -0000 @@ -0,0 +1,31 @@ +uid)) { + $uid = $object->uid; + } + elseif (isset($context['uid'])) { + $uid = $context['uid']; + } + else { + global $user; + $uid = $user->uid; + } + db_update('users') + ->fields(array('status' => 0)) + ->condition('uid', $uid) + ->execute(); + drupal_session_destroy_uid($uid); + watchdog('action', 'Blocked user %name.', array('%name' => $user->name)); +} + Index: modules/user/user.block.inc =================================================================== RCS file: modules/user/user.block.inc diff -N modules/user/user.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/user/user.block.inc 22 May 2009 23:43:19 -0000 @@ -0,0 +1,69 @@ + 'select', + '#title' => t('Number of users to display'), + '#default_value' => variable_get('user_block_whois_new_count', 5), + '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), + ); + return $form; + + case 'online': + $period = drupal_map_assoc(array(30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600, 5400, 7200, 10800, 21600, 43200, 86400), 'format_interval'); + $form['user_block_seconds_online'] = array('#type' => 'select', '#title' => t('User activity'), '#default_value' => variable_get('user_block_seconds_online', 900), '#options' => $period, '#description' => t('A user is considered online for this long after they have last viewed a page.')); + $form['user_block_max_list_count'] = array('#type' => 'select', '#title' => t('User list length'), '#default_value' => variable_get('user_block_max_list_count', 10), '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#description' => t('Maximum number of currently online users to display.')); + $form['user_block_cache'] = array('#markup' => 'If page caching is disabled, the block shows the number of anonymous and authenticated users, respectively. If page caching is enabled, only the number of authenticated users is displayed.
'); + return $form; + } +} + +/** + * Implementation of hook_block_save(). + */ +function user_block_save($delta = '', $edit = array()) { + global $user; + + switch ($delta) { + case 'new': + variable_set('user_block_whois_new_count', $edit['user_block_whois_new_count']); + break; + + case 'online': + variable_set('user_block_seconds_online', $edit['user_block_seconds_online']); + variable_set('user_block_max_list_count', $edit['user_block_max_list_count']); + break; + } +} + Index: modules/user/user.file.inc =================================================================== RCS file: modules/user/user.file.inc diff -N modules/user/user.file.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/user/user.file.inc 22 May 2009 23:43:20 -0000 @@ -0,0 +1,43 @@ + $info['mime_type']); + } +} + +/** + * Implementation of hook_file_references(). + */ +function user_file_references($file) { + // Determine if the file is used by this module. + $file_used = (bool) db_query_range('SELECT 1 FROM {users} WHERE picture = :fid', array(':fid' => $file->fid), 0, 1)->fetchField(); + if ($file_used) { + // Return the name of the module and how many references it has to the file. + return array('user' => $count); + } +} + +/** + * Implementation of hook_file_delete(). + */ +function user_file_delete($file) { + // Remove any references to the file. + db_update('users') + ->fields(array('picture' => 0)) + ->condition('picture', $file->fid) + ->execute(); +} + Index: modules/user/user.form.inc =================================================================== RCS file: modules/user/user.form.inc diff -N modules/user/user.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/user/user.form.inc 22 May 2009 23:44:36 -0000 @@ -0,0 +1,404 @@ +uid) { + drupal_goto('user/' . $user->uid); + } + + // Display login form: + $form['name'] = array('#type' => 'textfield', + '#title' => t('Username'), + '#size' => 60, + '#maxlength' => USERNAME_MAX_LENGTH, + '#required' => TRUE, + ); + + $form['name']['#description'] = t('Enter your @s username.', array('@s' => variable_get('site_name', 'Drupal'))); + $form['pass'] = array('#type' => 'password', + '#title' => t('Password'), + '#description' => t('Enter the password that accompanies your username.'), + '#required' => TRUE, + ); + $form['#validate'] = user_login_default_validators(); + $form['submit'] = array('#type' => 'submit', '#value' => t('Log in'), '#weight' => 2); + + return $form; +} + +/** + * A FAPI validate handler. Sets an error if supplied username has been blocked. + */ +function user_login_name_validate($form, &$form_state) { + if (isset($form_state['values']['name']) && user_is_blocked($form_state['values']['name'])) { + // Blocked in user administration. + form_set_error('name', t('The username %name has not been activated or is blocked.', array('%name' => $form_state['values']['name']))); + } +} + +/** + * A validate handler on the login form. Check supplied username/password + * against local users table. If successful, sets the global $user object. + */ +function user_login_authenticate_validate($form, &$form_state) { + user_authenticate($form_state['values']); +} + +/** + * A validate handler on the login form. Should be the last validator. Sets an + * error if user has not been authenticated yet. + */ +function user_login_final_validate($form, &$form_state) { + global $user; + if (!$user->uid) { + form_set_error('name', t('Sorry, unrecognized username or password. Have you forgotten your password?', array('@password' => url('user/password')))); + watchdog('user', 'Login attempt failed for %user.', array('%user' => $form_state['values']['name'])); + } +} + +/** + * Submit handler for the login form. Redirects the user to a page. + * + * The user is redirected to the My Account page. Setting the destination in + * the query string (as done by the user login block) overrides the redirect. + */ +function user_login_submit($form, &$form_state) { + global $user; + if ($user->uid) { + $form_state['redirect'] = 'user/' . $user->uid; + return; + } +} + +function user_login_block() { + $form = array( + '#action' => url($_GET['q'], array('query' => drupal_get_destination())), + '#id' => 'user-login-form', + '#validate' => user_login_default_validators(), + '#submit' => array('user_login_submit'), + ); + $form['name'] = array('#type' => 'textfield', + '#title' => t('Username'), + '#maxlength' => USERNAME_MAX_LENGTH, + '#size' => 15, + '#required' => TRUE, + ); + $form['pass'] = array('#type' => 'password', + '#title' => t('Password'), + '#maxlength' => 60, + '#size' => 15, + '#required' => TRUE, + ); + $form['submit'] = array('#type' => 'submit', + '#value' => t('Log in'), + ); + $items = array(); + if (variable_get('user_register', 1)) { + $items[] = l(t('Create new account'), 'user/register', array('attributes' => array('title' => t('Create a new user account.')))); + } + $items[] = l(t('Request new password'), 'user/password', array('attributes' => array('title' => t('Request new password via e-mail.')))); + $form['links'] = array('#markup' => theme('item_list', $items)); + return $form; +} + +function user_edit_form(&$form_state, $uid, $edit, $register = FALSE) { + _user_password_dynamic_validation(); + $admin = user_access('administer users'); + + $form = array(); + + // Account information: + $form['account'] = array('#type' => 'fieldset', + '#title' => t('Account information'), + '#weight' => -10, + ); + // Only show name field when: registration page; or user is editing own account and can change username; or an admin user. + if ($register || ($GLOBALS['user']->uid == $uid && user_access('change own username')) || $admin) { + $form['account']['name'] = array('#type' => 'textfield', + '#title' => t('Username'), + '#default_value' => $edit['name'], + '#maxlength' => USERNAME_MAX_LENGTH, + '#description' => t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, apostrophes, and underscores.'), + '#required' => TRUE, + '#attributes' => array('class' => 'username'), + ); + } + $form['account']['mail'] = array('#type' => 'textfield', + '#title' => t('E-mail address'), + '#default_value' => $edit['mail'], + '#maxlength' => EMAIL_MAX_LENGTH, + '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'), + '#required' => TRUE, + ); + if (!$register) { + $form['account']['pass'] = array('#type' => 'password_confirm', + '#description' => t('To change the current user password, enter the new password in both fields.'), + '#size' => 25, + ); + } + elseif (!variable_get('user_email_verification', TRUE) || $admin) { + $form['account']['pass'] = array( + '#type' => 'password_confirm', + '#description' => t('Provide a password for the new account in both fields.'), + '#required' => TRUE, + '#size' => 25, + ); + } + if ($admin) { + $form['account']['status'] = array( + '#type' => 'radios', + '#title' => t('Status'), + '#default_value' => isset($edit['status']) ? $edit['status'] : 1, + '#options' => array(t('Blocked'), t('Active')) + ); + } + if (user_access('administer permissions')) { + $roles = user_roles(TRUE); + + // The disabled checkbox subelement for the 'authenticated user' role + // must be generated separately and added to the checkboxes element, + // because of a limitation in D6 FormAPI not supporting a single disabled + // checkbox within a set of checkboxes. + // TODO: This should be solved more elegantly. See issue #119038. + $checkbox_authenticated = array( + '#type' => 'checkbox', + '#title' => $roles[DRUPAL_AUTHENTICATED_RID], + '#default_value' => TRUE, + '#disabled' => TRUE, + ); + + unset($roles[DRUPAL_AUTHENTICATED_RID]); + if ($roles) { + $default = empty($edit['roles']) ? array() : array_keys($edit['roles']); + $form['account']['roles'] = array( + '#type' => 'checkboxes', + '#title' => t('Roles'), + '#default_value' => $default, + '#options' => $roles, + DRUPAL_AUTHENTICATED_RID => $checkbox_authenticated, + ); + } + } + + // Signature: + if (variable_get('user_signatures', 0) && module_exists('comment') && !$register) { + $form['signature_settings'] = array( + '#type' => 'fieldset', + '#title' => t('Signature settings'), + '#weight' => 1, + ); + $form['signature_settings']['signature'] = array( + '#type' => 'textarea', + '#title' => t('Signature'), + '#default_value' => $edit['signature'], + '#description' => t('Your signature will be publicly displayed at the end of your comments.'), + ); + } + + // Picture/avatar: + if (variable_get('user_pictures', 0) && !$register) { + $form['picture'] = array( + '#type' => 'fieldset', + '#title' => t('Picture'), + '#weight' => 1, + ); + $form['picture']['picture'] = array( + '#type' => 'value', + '#value' => $edit['picture'], + ); + $form['picture']['picture_current'] = array( + '#markup' => theme('user_picture', (object)$edit), + ); + $form['picture']['picture_delete'] = array( + '#type' => 'checkbox', + '#title' => t('Delete picture'), + '#access' => !empty($edit['picture']->fid), + '#description' => t('Check this box to delete your current picture.'), + ); + $form['picture']['picture_upload'] = array( + '#type' => 'file', + '#title' => t('Upload picture'), + '#size' => 48, + '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions pixels and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'), '%size' => variable_get('user_picture_file_size', '30'))) . ' ' . variable_get('user_picture_guidelines', ''), + ); + $form['#validate'][] = 'user_validate_picture'; + } + $form['#uid'] = $uid; + + return $form; +} + +/** + * Form builder; The user registration form. + * + * @ingroup forms + * @see user_register_validate() + * @see user_register_submit() + */ +function user_register() { + global $user; + + $admin = user_access('administer users'); + + // If we aren't admin but already logged on, go to the user page instead. + if (!$admin && $user->uid) { + drupal_goto('user/' . $user->uid); + } + + // Start with the default user edit fields. + $form = user_edit_form($form_state, NULL, NULL, TRUE); + if ($admin) { + $form['account']['notify'] = array( + '#type' => 'checkbox', + '#title' => t('Notify user of new account') + ); + // Redirect back to page which initiated the create request; + // usually admin/user/user/create. + $form['destination'] = array('#type' => 'hidden', '#value' => $_GET['q']); + } + + // Create a dummy variable for pass-by-reference parameters. + $null = NULL; + $extra = _user_forms($null, NULL, NULL, 'register'); + + // Remove form_group around default fields if there are no other groups. + if (!$extra) { + foreach (array('name', 'mail', 'pass', 'status', 'roles', 'notify') as $key) { + if (isset($form['account'][$key])) { + $form[$key] = $form['account'][$key]; + } + } + unset($form['account']); + } + else { + $form = array_merge($form, $extra); + } + + $form['submit'] = array('#type' => 'submit', '#value' => t('Create new account'), '#weight' => 30); + $form['#validate'][] = 'user_register_validate'; + + return $form; +} + +function user_register_validate($form, &$form_state) { + user_module_invoke('validate', $form_state['values'], $form_state['values'], 'account'); +} + +/** + * Submit handler for the user registration form. + * + * This function is shared by the installation form and the normal registration form, + * which is why it can't be in the user.pages.inc file. + */ +function user_register_submit($form, &$form_state) { + global $base_url; + $admin = user_access('administer users'); + + $mail = $form_state['values']['mail']; + $name = $form_state['values']['name']; + if (!variable_get('user_email_verification', TRUE) || $admin) { + $pass = $form_state['values']['pass']; + } + else { + $pass = user_password(); + }; + $notify = isset($form_state['values']['notify']) ? $form_state['values']['notify'] : NULL; + $from = variable_get('site_mail', ini_get('sendmail_from')); + if (isset($form_state['values']['roles'])) { + // Remove unset roles. + $roles = array_filter($form_state['values']['roles']); + } + else { + $roles = array(); + } + + if (!$admin && array_intersect(array_keys($form_state['values']), array('uid', 'roles', 'init', 'session', 'status'))) { + watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING); + $form_state['redirect'] = 'user/register'; + return; + } + // The unset below is needed to prevent these form values from being saved as + // user data. + unset($form_state['values']['form_token'], $form_state['values']['submit'], $form_state['values']['op'], $form_state['values']['notify'], $form_state['values']['form_id'], $form_state['values']['affiliates'], $form_state['values']['destination'], $form_state['values']['form_build_id']); + + $merge_data = array('pass' => $pass, 'init' => $mail, 'roles' => $roles); + if (!$admin) { + // Set the user's status because it was not displayed in the form. + $merge_data['status'] = variable_get('user_register', 1) == 1; + } + $account = user_save('', array_merge($form_state['values'], $merge_data)); + // Terminate if an error occurred during user_save(). + if (!$account) { + drupal_set_message(t("Error saving user account."), 'error'); + $form_state['redirect'] = ''; + return; + } + $form_state['user'] = $account; + + watchdog('user', 'New user: %name (%email).', array('%name' => $name, '%email' => $mail), WATCHDOG_NOTICE, l(t('edit'), 'user/' . $account->uid . '/edit')); + + // The first user may login immediately, and receives a customized welcome e-mail. + if ($account->uid == 1) { + drupal_set_message(t('Welcome to Drupal. You are now logged in as user #1, which gives you full control over your website.')); + if (variable_get('user_email_verification', TRUE)) { + drupal_set_message(t('Your password is %pass. You may change your password below.
', array('%pass' => $pass))); + } + + user_authenticate(array_merge($form_state['values'], $merge_data)); + + $form_state['redirect'] = 'user/1/edit'; + return; + } + else { + // Add plain text password into user account to generate mail tokens. + $account->password = $pass; + if ($admin && !$notify) { + drupal_set_message(t('Created a new user account for %name. No e-mail has been sent.', array('@url' => url("user/$account->uid"), '%name' => $account->name))); + } + elseif (!variable_get('user_email_verification', TRUE) && $account->status && !$admin) { + // No e-mail verification is required, create new user account, and login + // user immediately. + _user_mail_notify('register_no_approval_required', $account); + if (user_authenticate(array_merge($form_state['values'], $merge_data))) { + drupal_set_message(t('Registration successful. You are now logged in.')); + } + $form_state['redirect'] = ''; + return; + } + elseif ($account->status || $notify) { + // Create new user account, no administrator approval required. + $op = $notify ? 'register_admin_created' : 'register_no_approval_required'; + _user_mail_notify($op, $account); + if ($notify) { + drupal_set_message(t('Password and further instructions have been e-mailed to the new user %name.', array('@url' => url("user/$account->uid"), '%name' => $account->name))); + } + else { + drupal_set_message(t('Your password and further instructions have been sent to your e-mail address.')); + $form_state['redirect'] = ''; + return; + } + } + else { + // Create new user account, administrator approval required. + _user_mail_notify('register_pending_approval', $account); + drupal_set_message(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.' . t("Users can use their own name or handle and can specify personal configuration settings through their individual My account page. Users must authenticate by supplying a local username and password or through their OpenID, an optional and secure method for logging into many websites with a single username and password. In some configurations, users may authenticate using a username and password from another Drupal site, or through some other site-specific mechanism.") . '
'; + $output .= '' . t('A visitor accessing your website is assigned a unique ID, or session ID, which is stored in a cookie. The cookie does not contain personal information, but acts as a key to retrieve information from your site. Users should have cookies enabled in their web browser when using your site.') . '
'; + $output .= '' . t('For more information, see the online handbook entry for User module.', array('@user' => 'http://drupal.org/handbook/modules/user/')) . '
'; + return $output; + case 'admin/user/user/create': + case 'admin/user/user/account/create': + return '' . t("This web page allows administrators to register new users. Users' e-mail addresses and usernames must be unique.") . '
'; + case 'admin/user/permissions': + return '' . t('Permissions let you control what users can do on your site. Each user role (defined on the user roles page) has its own set of permissions. For example, you could give users classified as "Administrators" permission to "administer nodes" but deny this power to ordinary, "authenticated" users. You can use permissions to reveal new features to privileged users (those with subscriptions, for example). Permissions also allow trusted users to share the administrative burden of running a busy site.', array('@role' => url('admin/user/roles'))) . '
'; + case 'admin/user/roles': + return t('Roles allow you to fine tune the security and administration of Drupal. A role defines a group of users that have certain privileges as defined in user permissions. Examples of roles include: anonymous user, authenticated user, moderator, administrator and so on. In this area you will define the role names of the various roles. To delete a role choose "edit".
By default, Drupal comes with two user roles:
+' . t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username or e-mail address. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda@example.com".') . '
'; + } +} + Index: modules/user/user.info =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.info,v retrieving revision 1.10 diff -u -p -r1.10 user.info --- modules/user/user.info 12 Oct 2008 01:23:07 -0000 1.10 +++ modules/user/user.info 22 May 2009 23:44:36 -0000 @@ -9,3 +9,12 @@ files[] = user.admin.inc files[] = user.pages.inc files[] = user.install required = TRUE +files[] = user.registry.inc +files[] = user.actions.inc +files[] = user.mail.inc +files[] = user.user.inc +files[] = user.block.inc +files[] = user.search.inc +files[] = user.help.inc +files[] = user.file.inc +files[] = user.form.inc Index: modules/user/user.mail.inc =================================================================== RCS file: modules/user/user.mail.inc diff -N modules/user/user.mail.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/user/user.mail.inc 22 May 2009 23:43:18 -0000 @@ -0,0 +1,18 @@ + array( - 'arguments' => array('account' => NULL), - 'template' => 'user-picture', - ), - 'user_profile' => array( - 'arguments' => array('elements' => NULL), - 'template' => 'user-profile', - 'file' => 'user.pages.inc', - ), - 'user_profile_category' => array( - 'arguments' => array('element' => NULL), - 'template' => 'user-profile-category', - 'file' => 'user.pages.inc', - ), - 'user_profile_item' => array( - 'arguments' => array('element' => NULL), - 'template' => 'user-profile-item', - 'file' => 'user.pages.inc', - ), - 'user_list' => array( - 'arguments' => array('users' => NULL, 'title' => NULL), - ), - 'user_admin_perm' => array( - 'arguments' => array('form' => NULL), - 'file' => 'user.admin.inc', - ), - 'user_admin_new_role' => array( - 'arguments' => array('form' => NULL), - 'file' => 'user.admin.inc', - ), - 'user_admin_account' => array( - 'arguments' => array('form' => NULL), - 'file' => 'user.admin.inc', - ), - 'user_filter_form' => array( - 'arguments' => array('form' => NULL), - 'file' => 'user.admin.inc', - ), - 'user_filters' => array( - 'arguments' => array('form' => NULL), - 'file' => 'user.admin.inc', - ), - 'user_signature' => array( - 'arguments' => array('signature' => NULL), - ), - ); -} - -/** - * Implementation of hook_fieldable_info(). - */ -function user_fieldable_info() { - $return = array( - 'user' => array( - 'name' => t('User'), - 'id key' => 'uid', - ), - ); - return $return; -} - -/** - * Implementation of hook_field_build_modes(). - */ -function user_field_build_modes($obj_type) { - $modes = array(); - if ($obj_type == 'user') { - $modes = array( - 'full' => t('User account'), - ); - } - return $modes; -} - function user_external_load($authname) { $uid = db_query("SELECT uid FROM {authmap} WHERE authname = :authname", array(':authname' => $authname))->fetchField(); @@ -784,123 +705,6 @@ function user_is_blocked($name) { } /** - * Implementation of hook_perm(). - */ -function user_perm() { - return array( - 'administer permissions' => array( - 'title' => t('Administer permissions'), - 'description' => t('Manage the permissions assigned to user roles. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), - ), - 'administer users' => array( - 'title' => t('Administer users'), - 'description' => t('Manage or block users, and manage their role assignments.'), - ), - 'access user profiles' => array( - 'title' => t('Access user profiles'), - 'description' => t('View profiles of users on the site, which may contain personal information.'), - ), - 'change own username' => array( - 'title' => t('Change own username'), - 'description' => t('Select a different username.'), - ), - 'cancel account' => array( - 'title' => t('Cancel account'), - 'description' => t('Remove or disable own user account and unpublish, anonymize, or remove own submissions depending on the configured user settings.', array('@user-settings-url' => url('admin/user/settings'))), - ), - 'select account cancellation method' => array( - 'title' => t('Select method for cancelling own account'), - 'description' => t('Select the method for cancelling own user account. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), - ), - ); -} - -/** - * Implementation of hook_file_download(). - * - * Ensure that user pictures (avatars) are always downloadable. - */ -function user_file_download($filepath) { - if (strpos($filepath, variable_get('user_picture_path', 'pictures') . '/picture-') === 0) { - $info = image_get_info(file_create_path($filepath)); - return array('Content-Type' => $info['mime_type']); - } -} - -/** - * Implementation of hook_file_references(). - */ -function user_file_references($file) { - // Determine if the file is used by this module. - $file_used = (bool) db_query_range('SELECT 1 FROM {users} WHERE picture = :fid', array(':fid' => $file->fid), 0, 1)->fetchField(); - if ($file_used) { - // Return the name of the module and how many references it has to the file. - return array('user' => $count); - } -} - -/** - * Implementation of hook_file_delete(). - */ -function user_file_delete($file) { - // Remove any references to the file. - db_update('users') - ->fields(array('picture' => 0)) - ->condition('picture', $file->fid) - ->execute(); -} - -/** - * Implementation of hook_search(). - */ -function user_search($op = 'search', $keys = NULL, $skip_access_check = FALSE) { - switch ($op) { - case 'name': - if ($skip_access_check || user_access('access user profiles')) { - return t('Users'); - } - case 'search': - if (user_access('access user profiles')) { - $find = array(); - // Replace wildcards with MySQL/PostgreSQL wildcards. - $keys = preg_replace('!\*+!', '%', $keys); - $query = db_select('users')->extend('PagerDefault'); - $query->fields('users', array('name', 'uid', 'mail')); - if (user_access('administer users')) { - // Administrators can also search in the otherwise private email field. - $query->condition(db_or()-> - where('LOWER(name) LIKE LOWER(:name)', array(':name' => "%$keys%"))-> - where('LOWER(mail) LIKE LOWER(:mail)', array(':mail' => "%$keys%"))); - } - else { - $query->where('LOWER(name) LIKE LOWER(:name)', array(':name' => "%$keys%")); - } - $result = $query - ->limit(15) - ->execute(); - foreach ($result as $account) { - $find[] = array('title' => $account->name . ' (' . $account->mail . ')', 'link' => url('user/' . $account->uid, array('absolute' => TRUE))); - } - return $find; - } - } -} - -/** - * Implementation of hook_elements(). - */ -function user_elements() { - return array( - 'user_profile_category' => array( - '#theme_wrapper' => 'user_profile_category' - ), - 'user_profile_item' => array( - '#theme' => 'user_profile_item' - ), - ); -} - -/** * Implementation of hook_user_view(). */ function user_user_view(&$edit, &$account, $category = NULL) { @@ -925,178 +729,6 @@ function user_user_view(&$edit, &$accoun } /** - * Implementation of hook_user_form. - */ -function user_user_form(&$edit, &$account, $category = NULL) { - if ($category == 'account') { - $form_state = array(); - return user_edit_form($form_state, (isset($account->uid) ? $account->uid : FALSE), $edit); - } -} - -/** - * Implementation of hook_user_validate(). - */ -function user_user_validate(&$edit, &$account, $category = NULL) { - if ($category == 'account') { - $uid = isset($account->uid) ? $account->uid : FALSE; - // Validate the username when: new user account; or user is editing own account and can change username; or an admin user. - if (!$uid || ($GLOBALS['user']->uid == $uid && user_access('change own username')) || user_access('administer users')) { - if ($error = user_validate_name($edit['name'])) { - form_set_error('name', $error); - } - elseif ((bool) db_query_range("SELECT 1 FROM {users} WHERE uid != :uid AND LOWER(name) = LOWER(:name)", array(':uid' => $uid, ':name' => $edit['name']), 0, 1)->fetchField()) { - form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name']))); - } - } - - // Validate the e-mail address, and check if it is taken by an existing user. - if ($error = user_validate_mail($edit['mail'])) { - form_set_error('mail', $error); - } - elseif ((bool) db_query_range("SELECT 1 FROM {users} WHERE uid != :uid AND LOWER(mail) = LOWER(:mail)", array(':uid' => $uid, ':mail' => $edit['mail']), 0, 1)->fetchField()) { - // Format error message dependent on whether the user is logged in or not. - if ($GLOBALS['user']->uid) { - form_set_error('mail', t('The e-mail address %email is already taken.', array('%email' => $edit['mail']))); - } - else { - form_set_error('mail', t('The e-mail address %email is already registered. Have you forgotten your password?', array('%email' => $edit['mail'], '@password' => url('user/password')))); - } - } - - // Make sure the signature isn't longer than the size of the database field. - // Signatures are disabled by default, so make sure it exists first. - if (isset($edit['signature'])) { - $user_schema = drupal_get_schema('users'); - if (strlen($edit['signature']) > $user_schema['fields']['signature']['length']) { - form_set_error('signature', t('The signature is too long: it must be %max characters or less.', array('%max' => $user_schema['fields']['signature']['length']))); - } - } - } -} - -/** - * Implementation of hook_user_submit(). - */ -function user_user_submit(&$edit, &$account, $category = NULL) { - if ($category == 'account') { - if (!empty($edit['picture_upload'])) { - $edit['picture'] = $edit['picture_upload']; - } - // Delete picture if requested, and if no replacement picture was given. - elseif (!empty($edit['picture_delete'])) { - $edit['picture'] = NULL; - } - // Remove these values so they don't end up serialized in the data field. - $edit['picture_upload'] = NULL; - $edit['picture_delete'] = NULL; - - if (isset($edit['roles'])) { - $edit['roles'] = array_filter($edit['roles']); - } - } -} - -/** - * Implementation of hook_user_categories. - */ -function user_user_categories($edit, $account, $category = NULL) { - return array(array('name' => 'account', 'title' => t('Account settings'), 'weight' => 1)); -} - -function user_login_block() { - $form = array( - '#action' => url($_GET['q'], array('query' => drupal_get_destination())), - '#id' => 'user-login-form', - '#validate' => user_login_default_validators(), - '#submit' => array('user_login_submit'), - ); - $form['name'] = array('#type' => 'textfield', - '#title' => t('Username'), - '#maxlength' => USERNAME_MAX_LENGTH, - '#size' => 15, - '#required' => TRUE, - ); - $form['pass'] = array('#type' => 'password', - '#title' => t('Password'), - '#maxlength' => 60, - '#size' => 15, - '#required' => TRUE, - ); - $form['submit'] = array('#type' => 'submit', - '#value' => t('Log in'), - ); - $items = array(); - if (variable_get('user_register', 1)) { - $items[] = l(t('Create new account'), 'user/register', array('attributes' => array('title' => t('Create a new user account.')))); - } - $items[] = l(t('Request new password'), 'user/password', array('attributes' => array('title' => t('Request new password via e-mail.')))); - $form['links'] = array('#markup' => theme('item_list', $items)); - return $form; -} - -/** - * Implementation of hook_block_list(). - */ -function user_block_list() { - global $user; - - $blocks['login']['info'] = t('User login'); - // Not worth caching. - $blocks['login']['cache'] = BLOCK_NO_CACHE; - - $blocks['new']['info'] = t('Who\'s new'); - - // Too dynamic to cache. - $blocks['online']['info'] = t('Who\'s online'); - $blocks['online']['cache'] = BLOCK_NO_CACHE; - return $blocks; -} - -/** - * Implementation of hook_block_configure(). - */ -function user_block_configure($delta = '') { - global $user; - - switch($delta) { - case 'new': - $form['user_block_whois_new_count'] = array( - '#type' => 'select', - '#title' => t('Number of users to display'), - '#default_value' => variable_get('user_block_whois_new_count', 5), - '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), - ); - return $form; - - case 'online': - $period = drupal_map_assoc(array(30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600, 5400, 7200, 10800, 21600, 43200, 86400), 'format_interval'); - $form['user_block_seconds_online'] = array('#type' => 'select', '#title' => t('User activity'), '#default_value' => variable_get('user_block_seconds_online', 900), '#options' => $period, '#description' => t('A user is considered online for this long after they have last viewed a page.')); - $form['user_block_max_list_count'] = array('#type' => 'select', '#title' => t('User list length'), '#default_value' => variable_get('user_block_max_list_count', 10), '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#description' => t('Maximum number of currently online users to display.')); - $form['user_block_cache'] = array('#markup' => 'If page caching is disabled, the block shows the number of anonymous and authenticated users, respectively. If page caching is enabled, only the number of authenticated users is displayed.
'); - return $form; - } -} - -/** - * Implementation of hook_block_save(). - */ -function user_block_save($delta = '', $edit = array()) { - global $user; - - switch ($delta) { - case 'new': - variable_set('user_block_whois_new_count', $edit['user_block_whois_new_count']); - break; - - case 'online': - variable_set('user_block_seconds_online', $edit['user_block_seconds_online']); - variable_set('user_block_max_list_count', $edit['user_block_max_list_count']); - break; - } -} - -/** * Implementation of hook_block_view(). */ function user_block_view($delta = '') { @@ -1272,193 +904,6 @@ function user_load_self($arg) { return $arg; } -/** - * Implementation of hook_menu(). - */ -function user_menu() { - $items['user/autocomplete'] = array( - 'title' => 'User autocomplete', - 'page callback' => 'user_autocomplete', - 'access callback' => 'user_access', - 'access arguments' => array('access user profiles'), - 'type' => MENU_CALLBACK, - ); - - // Registration and login pages. - $items['user'] = array( - 'title' => 'User account', - 'page callback' => 'user_page', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - - $items['user/login'] = array( - 'title' => 'Log in', - 'access callback' => 'user_is_anonymous', - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - - $items['user/register'] = array( - 'title' => 'Create new account', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_register'), - 'access callback' => 'user_register_access', - 'type' => MENU_LOCAL_TASK, - ); - - $items['user/password'] = array( - 'title' => 'Request new password', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_pass'), - 'access callback' => 'user_is_anonymous', - 'type' => MENU_LOCAL_TASK, - ); - $items['user/reset/%/%/%'] = array( - 'title' => 'Reset password', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_pass_reset', 2, 3, 4), - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - - $items['user/logout'] = array( - 'title' => 'Log out', - 'access callback' => 'user_is_logged_in', - 'page callback' => 'user_logout', - 'weight' => 10, - 'menu_name' => 'user-menu', - ); - - // User administration pages. - $items['admin/user'] = array( - 'title' => 'User management', - 'description' => "Manage your site's users, groups and access to site features.", - 'position' => 'left', - 'page callback' => 'system_admin_menu_block_page', - 'access arguments' => array('access administration pages'), - ); - $items['admin/user/user'] = array( - 'title' => 'Users', - 'description' => 'List, add, and edit users.', - 'page callback' => 'user_admin', - 'page arguments' => array('list'), - 'access arguments' => array('administer users'), - ); - $items['admin/user/user/list'] = array( - 'title' => 'List', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['admin/user/user/create'] = array( - 'title' => 'Add user', - 'page arguments' => array('create'), - 'access arguments' => array('administer users'), - 'type' => MENU_LOCAL_TASK, - ); - $items['admin/user/settings'] = array( - 'title' => 'User settings', - 'description' => 'Configure default behavior of users, including registration requirements, e-mails, and user pictures.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_admin_settings'), - 'access arguments' => array('administer users'), - ); - - // Permission administration pages. - $items['admin/user/permissions'] = array( - 'title' => 'Permissions', - 'description' => 'Determine access to features by selecting permissions for roles.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_admin_perm'), - 'access arguments' => array('administer permissions'), - ); - $items['admin/user/roles'] = array( - 'title' => 'Roles', - 'description' => 'List, edit, or add user roles.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_admin_new_role'), - 'access arguments' => array('administer permissions'), - ); - $items['admin/user/roles/edit'] = array( - 'title' => 'Edit role', - 'page arguments' => array('user_admin_role'), - 'access arguments' => array('administer permissions'), - 'type' => MENU_CALLBACK, - ); - - $items['user/%user_uid_optional'] = array( - 'title' => 'My account', - 'title callback' => 'user_page_title', - 'title arguments' => array(1), - 'page callback' => 'user_view', - 'page arguments' => array(1), - 'access callback' => 'user_view_access', - 'access arguments' => array(1), - 'weight' => -10, - 'menu_name' => 'user-menu', - ); - - $items['user/%user/view'] = array( - 'title' => 'View', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - - $items['user/%user/cancel'] = array( - 'title' => 'Cancel account', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_cancel_confirm_form', 1), - 'access callback' => 'user_cancel_access', - 'access arguments' => array(1), - 'type' => MENU_CALLBACK, - ); - - $items['user/%user/cancel/confirm/%/%'] = array( - 'title' => 'Confirm account cancellation', - 'page callback' => 'user_cancel_confirm', - 'page arguments' => array(1, 4, 5), - 'access callback' => 'user_cancel_access', - 'access arguments' => array(1), - 'type' => MENU_CALLBACK, - ); - - $items['user/%user/edit'] = array( - 'title' => 'Edit', - 'page callback' => 'user_edit', - 'page arguments' => array(1), - 'access callback' => 'user_edit_access', - 'access arguments' => array(1), - 'type' => MENU_LOCAL_TASK, - ); - - $items['user/%user_category/edit/account'] = array( - 'title' => 'Account', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'load arguments' => array('%map', '%index'), - ); - - $empty_account = new stdClass(); - if (($categories = _user_categories($empty_account)) && (count($categories) > 1)) { - foreach ($categories as $key => $category) { - // 'account' is already handled by the MENU_DEFAULT_LOCAL_TASK. - if ($category['name'] != 'account') { - $items['user/%user_category/edit/' . $category['name']] = array( - 'title callback' => 'check_plain', - 'title arguments' => array($category['title']), - 'page callback' => 'user_edit', - 'page arguments' => array(1, 3), - 'access callback' => isset($category['access callback']) ? $category['access callback'] : 'user_edit_access', - 'access arguments' => isset($category['access arguments']) ? $category['access arguments'] : array(1), - 'type' => MENU_LOCAL_TASK, - 'weight' => $category['weight'], - 'load arguments' => array('%map', '%index'), - 'tab_parent' => 'user/%/edit', - ); - } - } - } - return $items; -} - function user_init() { drupal_add_css(drupal_get_path('module', 'user') . '/user.css'); } @@ -1573,39 +1018,6 @@ function user_set_authmaps($account, $au } /** - * Form builder; the main user login form. - * - * @ingroup forms - */ -function user_login(&$form_state) { - global $user; - - // If we are already logged on, go to the user page instead. - if ($user->uid) { - drupal_goto('user/' . $user->uid); - } - - // Display login form: - $form['name'] = array('#type' => 'textfield', - '#title' => t('Username'), - '#size' => 60, - '#maxlength' => USERNAME_MAX_LENGTH, - '#required' => TRUE, - ); - - $form['name']['#description'] = t('Enter your @s username.', array('@s' => variable_get('site_name', 'Drupal'))); - $form['pass'] = array('#type' => 'password', - '#title' => t('Password'), - '#description' => t('Enter the password that accompanies your username.'), - '#required' => TRUE, - ); - $form['#validate'] = user_login_default_validators(); - $form['submit'] = array('#type' => 'submit', '#value' => t('Log in'), '#weight' => 2); - - return $form; -} - -/** * Set up a series for validators which check for blocked users, * then authenticate against local database, then return an error if * authentication fails. Distributed authentication modules are welcome @@ -1627,36 +1039,6 @@ function user_login_default_validators() } /** - * A FAPI validate handler. Sets an error if supplied username has been blocked. - */ -function user_login_name_validate($form, &$form_state) { - if (isset($form_state['values']['name']) && user_is_blocked($form_state['values']['name'])) { - // Blocked in user administration. - form_set_error('name', t('The username %name has not been activated or is blocked.', array('%name' => $form_state['values']['name']))); - } -} - -/** - * A validate handler on the login form. Check supplied username/password - * against local users table. If successful, sets the global $user object. - */ -function user_login_authenticate_validate($form, &$form_state) { - user_authenticate($form_state['values']); -} - -/** - * A validate handler on the login form. Should be the last validator. Sets an - * error if user has not been authenticated yet. - */ -function user_login_final_validate($form, &$form_state) { - global $user; - if (!$user->uid) { - form_set_error('name', t('Sorry, unrecognized username or password. Have you forgotten your password?', array('@password' => url('user/password')))); - watchdog('user', 'Login attempt failed for %user.', array('%user' => $form_state['values']['name'])); - } -} - -/** * Try to log in the user locally. * * @param $form_values @@ -1722,20 +1104,6 @@ function user_authenticate_finalize(&$ed } /** - * Submit handler for the login form. Redirects the user to a page. - * - * The user is redirected to the My Account page. Setting the destination in - * the query string (as done by the user login block) overrides the redirect. - */ -function user_login_submit($form, &$form_state) { - global $user; - if ($user->uid) { - $form_state['redirect'] = 'user/' . $user->uid; - return; - } -} - -/** * Helper function for authentication modules. Either login in or registers * the current user, based on username. Either way, the global $user object is * populated based on $name. @@ -1788,133 +1156,6 @@ function user_pass_rehash($password, $ti return md5($timestamp . $password . $login); } -function user_edit_form(&$form_state, $uid, $edit, $register = FALSE) { - _user_password_dynamic_validation(); - $admin = user_access('administer users'); - - $form = array(); - - // Account information: - $form['account'] = array('#type' => 'fieldset', - '#title' => t('Account information'), - '#weight' => -10, - ); - // Only show name field when: registration page; or user is editing own account and can change username; or an admin user. - if ($register || ($GLOBALS['user']->uid == $uid && user_access('change own username')) || $admin) { - $form['account']['name'] = array('#type' => 'textfield', - '#title' => t('Username'), - '#default_value' => $edit['name'], - '#maxlength' => USERNAME_MAX_LENGTH, - '#description' => t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, apostrophes, and underscores.'), - '#required' => TRUE, - '#attributes' => array('class' => 'username'), - ); - } - $form['account']['mail'] = array('#type' => 'textfield', - '#title' => t('E-mail address'), - '#default_value' => $edit['mail'], - '#maxlength' => EMAIL_MAX_LENGTH, - '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'), - '#required' => TRUE, - ); - if (!$register) { - $form['account']['pass'] = array('#type' => 'password_confirm', - '#description' => t('To change the current user password, enter the new password in both fields.'), - '#size' => 25, - ); - } - elseif (!variable_get('user_email_verification', TRUE) || $admin) { - $form['account']['pass'] = array( - '#type' => 'password_confirm', - '#description' => t('Provide a password for the new account in both fields.'), - '#required' => TRUE, - '#size' => 25, - ); - } - if ($admin) { - $form['account']['status'] = array( - '#type' => 'radios', - '#title' => t('Status'), - '#default_value' => isset($edit['status']) ? $edit['status'] : 1, - '#options' => array(t('Blocked'), t('Active')) - ); - } - if (user_access('administer permissions')) { - $roles = user_roles(TRUE); - - // The disabled checkbox subelement for the 'authenticated user' role - // must be generated separately and added to the checkboxes element, - // because of a limitation in D6 FormAPI not supporting a single disabled - // checkbox within a set of checkboxes. - // TODO: This should be solved more elegantly. See issue #119038. - $checkbox_authenticated = array( - '#type' => 'checkbox', - '#title' => $roles[DRUPAL_AUTHENTICATED_RID], - '#default_value' => TRUE, - '#disabled' => TRUE, - ); - - unset($roles[DRUPAL_AUTHENTICATED_RID]); - if ($roles) { - $default = empty($edit['roles']) ? array() : array_keys($edit['roles']); - $form['account']['roles'] = array( - '#type' => 'checkboxes', - '#title' => t('Roles'), - '#default_value' => $default, - '#options' => $roles, - DRUPAL_AUTHENTICATED_RID => $checkbox_authenticated, - ); - } - } - - // Signature: - if (variable_get('user_signatures', 0) && module_exists('comment') && !$register) { - $form['signature_settings'] = array( - '#type' => 'fieldset', - '#title' => t('Signature settings'), - '#weight' => 1, - ); - $form['signature_settings']['signature'] = array( - '#type' => 'textarea', - '#title' => t('Signature'), - '#default_value' => $edit['signature'], - '#description' => t('Your signature will be publicly displayed at the end of your comments.'), - ); - } - - // Picture/avatar: - if (variable_get('user_pictures', 0) && !$register) { - $form['picture'] = array( - '#type' => 'fieldset', - '#title' => t('Picture'), - '#weight' => 1, - ); - $form['picture']['picture'] = array( - '#type' => 'value', - '#value' => $edit['picture'], - ); - $form['picture']['picture_current'] = array( - '#markup' => theme('user_picture', (object)$edit), - ); - $form['picture']['picture_delete'] = array( - '#type' => 'checkbox', - '#title' => t('Delete picture'), - '#access' => !empty($edit['picture']->fid), - '#description' => t('Check this box to delete your current picture.'), - ); - $form['picture']['picture_upload'] = array( - '#type' => 'file', - '#title' => t('Upload picture'), - '#size' => 48, - '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions pixels and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'), '%size' => variable_get('user_picture_file_size', '30'))) . ' ' . variable_get('user_picture_guidelines', ''), - ); - $form['#validate'][] = 'user_validate_picture'; - } - $form['#uid'] = $uid; - - return $form; -} - /** * Cancel a user account. * @@ -2054,16 +1295,6 @@ function user_build_content(&$account) { } /** - * Implementation of hook_mail(). - */ -function user_mail($key, &$message, $params) { - $language = $message['language']; - $variables = user_mail_tokens($params['account'], $language); - $message['subject'] .= _user_mail_text($key . '_subject', $language, $variables); - $message['body'][] = _user_mail_text($key . '_body', $language, $variables); -} - -/** * Returns a mail string for a variable name. * * Used by user_mail() and the settings forms to retrieve strings. @@ -2181,234 +1412,6 @@ function user_roles($membersonly = FALSE } /** - * Implementation of hook_user_operations(). - */ -function user_user_operations($form_state = array()) { - $operations = array( - 'unblock' => array( - 'label' => t('Unblock the selected users'), - 'callback' => 'user_user_operations_unblock', - ), - 'block' => array( - 'label' => t('Block the selected users'), - 'callback' => 'user_user_operations_block', - ), - 'cancel' => array( - 'label' => t('Cancel the selected user accounts'), - ), - ); - - if (user_access('administer permissions')) { - $roles = user_roles(TRUE); - unset($roles[DRUPAL_AUTHENTICATED_RID]); // Can't edit authenticated role. - - $add_roles = array(); - foreach ($roles as $key => $value) { - $add_roles['add_role-' . $key] = $value; - } - - $remove_roles = array(); - foreach ($roles as $key => $value) { - $remove_roles['remove_role-' . $key] = $value; - } - - if (count($roles)) { - $role_operations = array( - t('Add a role to the selected users') => array( - 'label' => $add_roles, - ), - t('Remove a role from the selected users') => array( - 'label' => $remove_roles, - ), - ); - - $operations += $role_operations; - } - } - - // If the form has been posted, we need to insert the proper data for - // role editing if necessary. - if (!empty($form_state['submitted'])) { - $operation_rid = explode('-', $form_state['values']['operation']); - $operation = $operation_rid[0]; - if ($operation == 'add_role' || $operation == 'remove_role') { - $rid = $operation_rid[1]; - if (user_access('administer permissions')) { - $operations[$form_state['values']['operation']] = array( - 'callback' => 'user_multiple_role_edit', - 'callback arguments' => array($operation, $rid), - ); - } - else { - watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING); - return; - } - } - } - - return $operations; -} - -/** - * Callback function for admin mass unblocking users. - */ -function user_user_operations_unblock($accounts) { - foreach ($accounts as $uid) { - $account = user_load($uid); - // Skip unblocking user if they are already unblocked. - if ($account !== FALSE && $account->status == 0) { - user_save($account, array('status' => 1)); - } - } -} - -/** - * Callback function for admin mass blocking users. - */ -function user_user_operations_block($accounts) { - foreach ($accounts as $uid) { - $account = user_load($uid); - // Skip blocking user if they are already blocked. - if ($account !== FALSE && $account->status == 1) { - user_save($account, array('status' => 0)); - } - } -} - -/** - * Callback function for admin mass adding/deleting a user role. - */ -function user_multiple_role_edit($accounts, $operation, $rid) { - // The role name is not necessary as user_save() will reload the user - // object, but some modules' hook_user() may look at this first. - $role_name = db_query('SELECT name FROM {role} WHERE rid = :rid', array(':rid' => $rid))->fetchField(); - - switch ($operation) { - case 'add_role': - foreach ($accounts as $uid) { - $account = user_load($uid); - // Skip adding the role to the user if they already have it. - if ($account !== FALSE && !isset($account->roles[$rid])) { - $roles = $account->roles + array($rid => $role_name); - user_save($account, array('roles' => $roles)); - } - } - break; - case 'remove_role': - foreach ($accounts as $uid) { - $account = user_load($uid); - // Skip removing the role from the user if they already don't have it. - if ($account !== FALSE && isset($account->roles[$rid])) { - $roles = array_diff($account->roles, array($rid => $role_name)); - user_save($account, array('roles' => $roles)); - } - } - break; - } -} - -function user_multiple_cancel_confirm(&$form_state) { - $edit = $form_state['input']; - - $form['accounts'] = array('#prefix' => '' . t('The user module allows users to register, login, and log out. Users benefit from being able to sign on because it associates content they create with their account and allows various permissions to be set for their roles. The user module supports user roles which establish fine grained permissions allowing each role to do only what the administrator wants them to. Each user is assigned to one or more roles. By default there are two roles anonymous - a user who has not logged in, and authenticated a user who has signed up and who has been authorized.') . '
'; - $output .= '' . t("Users can use their own name or handle and can specify personal configuration settings through their individual My account page. Users must authenticate by supplying a local username and password or through their OpenID, an optional and secure method for logging into many websites with a single username and password. In some configurations, users may authenticate using a username and password from another Drupal site, or through some other site-specific mechanism.") . '
'; - $output .= '' . t('A visitor accessing your website is assigned a unique ID, or session ID, which is stored in a cookie. The cookie does not contain personal information, but acts as a key to retrieve information from your site. Users should have cookies enabled in their web browser when using your site.') . '
'; - $output .= '' . t('For more information, see the online handbook entry for User module.', array('@user' => 'http://drupal.org/handbook/modules/user/')) . '
'; - return $output; - case 'admin/user/user/create': - case 'admin/user/user/account/create': - return '' . t("This web page allows administrators to register new users. Users' e-mail addresses and usernames must be unique.") . '
'; - case 'admin/user/permissions': - return '' . t('Permissions let you control what users can do on your site. Each user role (defined on the user roles page) has its own set of permissions. For example, you could give users classified as "Administrators" permission to "administer nodes" but deny this power to ordinary, "authenticated" users. You can use permissions to reveal new features to privileged users (those with subscriptions, for example). Permissions also allow trusted users to share the administrative burden of running a busy site.', array('@role' => url('admin/user/roles'))) . '
'; - case 'admin/user/roles': - return t('Roles allow you to fine tune the security and administration of Drupal. A role defines a group of users that have certain privileges as defined in user permissions. Examples of roles include: anonymous user, authenticated user, moderator, administrator and so on. In this area you will define the role names of the various roles. To delete a role choose "edit".
By default, Drupal comes with two user roles:
-' . t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username or e-mail address. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda@example.com".') . '
'; - } -} - -/** * Retrieve a list of all user setting/information categories and sort them by weight. */ function _user_categories($account) { @@ -2672,234 +1675,6 @@ function _user_password_dynamic_validati } /** - * Implementation of hook_hook_info(). - */ -function user_hook_info() { - return array( - 'user' => array( - 'user' => array( - 'insert' => array( - 'runs when' => t('After a user account has been created'), - ), - 'update' => array( - 'runs when' => t("After a user's profile has been updated"), - ), - 'delete' => array( - 'runs when' => t('After a user has been deleted') - ), - 'login' => array( - 'runs when' => t('After a user has logged in') - ), - 'logout' => array( - 'runs when' => t('After a user has logged out') - ), - 'view' => array( - 'runs when' => t("When a user's profile is being viewed") - ), - ), - ), - ); -} - -/** - * Implementation of hook_action_info(). - */ -function user_action_info() { - return array( - 'user_block_user_action' => array( - 'description' => t('Block current user'), - 'type' => 'user', - 'configurable' => FALSE, - 'hooks' => array(), - ), - ); -} - -/** - * Implementation of a Drupal action. - * Blocks the current user. - */ -function user_block_user_action(&$object, $context = array()) { - if (isset($object->uid)) { - $uid = $object->uid; - } - elseif (isset($context['uid'])) { - $uid = $context['uid']; - } - else { - global $user; - $uid = $user->uid; - } - db_update('users') - ->fields(array('status' => 0)) - ->condition('uid', $uid) - ->execute(); - drupal_session_destroy_uid($uid); - watchdog('action', 'Blocked user %name.', array('%name' => $user->name)); -} - -/** - * Submit handler for the user registration form. - * - * This function is shared by the installation form and the normal registration form, - * which is why it can't be in the user.pages.inc file. - */ -function user_register_submit($form, &$form_state) { - global $base_url; - $admin = user_access('administer users'); - - $mail = $form_state['values']['mail']; - $name = $form_state['values']['name']; - if (!variable_get('user_email_verification', TRUE) || $admin) { - $pass = $form_state['values']['pass']; - } - else { - $pass = user_password(); - }; - $notify = isset($form_state['values']['notify']) ? $form_state['values']['notify'] : NULL; - $from = variable_get('site_mail', ini_get('sendmail_from')); - if (isset($form_state['values']['roles'])) { - // Remove unset roles. - $roles = array_filter($form_state['values']['roles']); - } - else { - $roles = array(); - } - - if (!$admin && array_intersect(array_keys($form_state['values']), array('uid', 'roles', 'init', 'session', 'status'))) { - watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING); - $form_state['redirect'] = 'user/register'; - return; - } - // The unset below is needed to prevent these form values from being saved as - // user data. - unset($form_state['values']['form_token'], $form_state['values']['submit'], $form_state['values']['op'], $form_state['values']['notify'], $form_state['values']['form_id'], $form_state['values']['affiliates'], $form_state['values']['destination'], $form_state['values']['form_build_id']); - - $merge_data = array('pass' => $pass, 'init' => $mail, 'roles' => $roles); - if (!$admin) { - // Set the user's status because it was not displayed in the form. - $merge_data['status'] = variable_get('user_register', 1) == 1; - } - $account = user_save('', array_merge($form_state['values'], $merge_data)); - // Terminate if an error occurred during user_save(). - if (!$account) { - drupal_set_message(t("Error saving user account."), 'error'); - $form_state['redirect'] = ''; - return; - } - $form_state['user'] = $account; - - watchdog('user', 'New user: %name (%email).', array('%name' => $name, '%email' => $mail), WATCHDOG_NOTICE, l(t('edit'), 'user/' . $account->uid . '/edit')); - - // The first user may login immediately, and receives a customized welcome e-mail. - if ($account->uid == 1) { - drupal_set_message(t('Welcome to Drupal. You are now logged in as user #1, which gives you full control over your website.')); - if (variable_get('user_email_verification', TRUE)) { - drupal_set_message(t('Your password is %pass. You may change your password below.
', array('%pass' => $pass))); - } - - user_authenticate(array_merge($form_state['values'], $merge_data)); - - $form_state['redirect'] = 'user/1/edit'; - return; - } - else { - // Add plain text password into user account to generate mail tokens. - $account->password = $pass; - if ($admin && !$notify) { - drupal_set_message(t('Created a new user account for %name. No e-mail has been sent.', array('@url' => url("user/$account->uid"), '%name' => $account->name))); - } - elseif (!variable_get('user_email_verification', TRUE) && $account->status && !$admin) { - // No e-mail verification is required, create new user account, and login - // user immediately. - _user_mail_notify('register_no_approval_required', $account); - if (user_authenticate(array_merge($form_state['values'], $merge_data))) { - drupal_set_message(t('Registration successful. You are now logged in.')); - } - $form_state['redirect'] = ''; - return; - } - elseif ($account->status || $notify) { - // Create new user account, no administrator approval required. - $op = $notify ? 'register_admin_created' : 'register_no_approval_required'; - _user_mail_notify($op, $account); - if ($notify) { - drupal_set_message(t('Password and further instructions have been e-mailed to the new user %name.', array('@url' => url("user/$account->uid"), '%name' => $account->name))); - } - else { - drupal_set_message(t('Your password and further instructions have been sent to your e-mail address.')); - $form_state['redirect'] = ''; - return; - } - } - else { - // Create new user account, administrator approval required. - _user_mail_notify('register_pending_approval', $account); - drupal_set_message(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.