Index: install.php =================================================================== RCS file: /cvs/drupal/drupal/install.php,v retrieving revision 1.176 diff -u -p -r1.176 install.php --- install.php 2 Jun 2009 06:58:15 -0000 1.176 +++ install.php 5 Jun 2009 21:27:53 -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/actions.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/actions.inc,v retrieving revision 1.27 diff -u -p -r1.27 actions.inc --- includes/actions.inc 31 May 2009 03:12:18 -0000 1.27 +++ includes/actions.inc 5 Jun 2009 21:26:47 -0000 @@ -81,12 +81,16 @@ function actions_do($action_ids, $object // Configurable actions need parameters. if (is_numeric($action_id)) { $function = $params['callback']; - $context = array_merge($context, $params); - $actions_result[$action_id] = $function($object, $context, $a1, $a2); + if (drupal_function_exists($function)) { + $context = array_merge($context, $params); + $actions_result[$action_id] = $function($object, $context, $a1, $a2); + } } // Singleton action; $action_id is the function name. else { - $actions_result[$action_id] = $action_id($object, $context, $a1, $a2); + if (drupal_function_exists($action_id)) { + $actions_result[$action_id] = $action_id($object, $context, $a1, $a2); + } } } } @@ -96,12 +100,16 @@ function actions_do($action_ids, $object if (is_numeric($action_ids)) { $action = db_query("SELECT callback, parameters FROM {actions} WHERE aid = :aid", array(':aid' => $action_ids))->fetchObject(); $function = $action->callback; - $context = array_merge($context, unserialize($action->parameters)); - $actions_result[$action_ids] = $function($object, $context, $a1, $a2); + if (drupal_function_exists($function)) { + $context = array_merge($context, unserialize($action->parameters)); + $actions_result[$action_ids] = $function($object, $context, $a1, $a2); + } } // Singleton action; $action_ids is the function name. else { - $actions_result[$action_ids] = $action_ids($object, $context, $a1, $a2); + if (drupal_function_exists($action_ids)) { + $actions_result[$action_ids] = $action_ids($object, $context, $a1, $a2); + } } } $stack--; Index: includes/theme.maintenance.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.maintenance.inc,v retrieving revision 1.29 diff -u -p -r1.29 theme.maintenance.inc --- includes/theme.maintenance.inc 28 May 2009 16:44:05 -0000 1.29 +++ includes/theme.maintenance.inc 5 Jun 2009 21:27:53 -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 5 Jun 2009 21:45:43 -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; +} + +/** + * Implement 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; + } +} + +/** + * Implement 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 5 Jun 2009 21:45:43 -0000 @@ -0,0 +1,23 @@ + REQUEST_TIME, + ':never' => AGGREGATOR_CLEAR_NEVER + )); + foreach ($result as $feed) { + aggregator_refresh($feed); + } +} + 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 5 Jun 2009 21:45:43 -0000 @@ -11,3 +11,7 @@ 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 Index: modules/aggregator/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v retrieving revision 1.412 diff -u -p -r1.412 aggregator.module --- modules/aggregator/aggregator.module 28 May 2009 09:30:58 -0000 1.412 +++ modules/aggregator/aggregator.module 5 Jun 2009 21:45:43 -0000 @@ -35,214 +35,6 @@ function aggregator_help($path, $arg) { } /** - * Implement 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', - ), - ); -} - -/** - * Implement 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 @@ -270,83 +62,6 @@ function _aggregator_has_categories() { } /** - * Implement 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.'), - ), - ); -} - -/** - * Implement 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 != :never', array( - ':time' => REQUEST_TIME, - ':never' => AGGREGATOR_CLEAR_NEVER - )); - foreach ($result as $feed) { - aggregator_refresh($feed); - } -} - -/** - * Implement 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; -} - -/** - * Implement 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; - } -} - -/** - * Implement 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(); - } -} - -/** * Implement 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 5 Jun 2009 21:45:43 -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; +} + +/** + * Implement 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 5 Jun 2009 21:45:43 -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 5 Jun 2009 21:45:42 -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.3 diff -u -p -r1.3 aggregator_test.module --- modules/aggregator/tests/aggregator_test.module 27 May 2009 18:33:54 -0000 1.3 +++ modules/aggregator/tests/aggregator_test.module 5 Jun 2009 21:45:42 -0000 @@ -2,20 +2,6 @@ // $Id: aggregator_test.module,v 1.3 2009/05/27 18:33:54 dries Exp $ /** - * Implement 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 5 Jun 2009 21:45:42 -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 5 Jun 2009 21:45:44 -0000 @@ -0,0 +1,90 @@ +bid]['info'] = $block->info; + // Not worth caching. + $blocks[$block->bid]['cache'] = BLOCK_NO_CACHE; + } + return $blocks; +} + +/** + * Implement hook_block_configure(). + */ +function block_block_configure($delta = 0, $edit = array()) { + $box = array('format' => FILTER_FORMAT_DEFAULT); + if ($delta) { + $box = block_box_get($delta); + } + return block_box_form($box); +} + +/** + * Implement hook_block_save(). + */ +function block_block_save($delta = 0, $edit = array()) { + block_box_save($edit, $delta); +} + +function block_box_get($bid) { + return db_query("SELECT * FROM {box} WHERE bid = :bid", array(':bid' => $bid))->fetchAssoc(); +} + +/** + * 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, + '#access' => filter_access($edit['format']), + ); + + return $form; +} + +function block_box_save($edit, $delta) { + db_update('box') + ->fields(array( + 'body' => $edit['body'], + 'info' => $edit['info'], + 'format' => $edit['body_format'], + )) + ->condition('bid', $delta) + ->execute(); + 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 5 Jun 2009 21:45:44 -0000 @@ -0,0 +1,73 @@ + '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_query_range("SELECT 1 FROM {block} b WHERE module = 'user' AND delta = 'online' AND status = 1", array(), 0, 1)->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.') . '

'; + } + +} + +/** + * Implement hook_form_FORM_ID_alter(). + */ +function block_form_system_themes_form_alter(&$form, &$form_state) { + // This function needs to fire before the theme changes are recorded in the + // database, otherwise it will populate the default list of blocks from the + // new theme, which is empty. + array_unshift($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.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 5 Jun 2009 21:45:42 -0000 @@ -8,3 +8,7 @@ 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 Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.341 diff -u -p -r1.341 block.module --- modules/block/block.module 31 May 2009 07:46:54 -0000 1.341 +++ modules/block/block.module 5 Jun 2009 21:45:44 -0000 @@ -88,91 +88,6 @@ function block_help($path, $arg) { } /** - * Implement 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), - ), - ); -} - -/** - * Implement 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.'), - ), - ); -} - -/** - * Implement 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) { @@ -181,39 +96,6 @@ function _block_themes_access($theme) { } /** - * Implement hook_block_list(). - */ -function block_block_list() { - $blocks = array(); - - $result = db_query('SELECT bid, info FROM {box} ORDER BY info'); - foreach ($result as $block) { - $blocks[$block->bid]['info'] = $block->info; - // Not worth caching. - $blocks[$block->bid]['cache'] = BLOCK_NO_CACHE; - } - return $blocks; -} - -/** - * Implement hook_block_configure(). - */ -function block_block_configure($delta = 0, $edit = array()) { - $box = array('format' => FILTER_FORMAT_DEFAULT); - if ($delta) { - $box = block_box_get($delta); - } - return block_box_form($box); -} - -/** - * Implement hook_block_save(). - */ -function block_block_save($delta = 0, $edit = array()) { - block_box_save($edit, $delta); -} - -/** * Implement hook_block_view(). * * Generates the administrator-defined blocks for display. @@ -361,156 +243,6 @@ function _block_rehash() { return $blocks; } -function block_box_get($bid) { - return db_query("SELECT * FROM {box} WHERE bid = :bid", array(':bid' => $bid))->fetchAssoc(); -} - -/** - * 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, - '#access' => filter_access($edit['format']), - ); - - return $form; -} - -function block_box_save($edit, $delta) { - db_update('box') - ->fields(array( - 'body' => $edit['body'], - 'info' => $edit['info'], - 'format' => $edit['body_format'], - )) - ->condition('bid', $delta) - ->execute(); - return TRUE; -} - -/** - * Implement 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); - foreach ($result as $block) { - $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; - } - } -} - -/** - * Implement hook_user_validate(). - */ -function block_user_validate(&$edit, &$account, $category = NULL) { - if (empty($edit['block'])) { - $edit['block'] = array(); - } - return $edit; -} - -/** - * Implement 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_query_range("SELECT 1 FROM {block} b WHERE module = 'user' AND delta = 'online' AND status = 1", array(), 0, 1)->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.') . '

'; - } - -} - -/** - * Implement hook_form_FORM_ID_alter(). - */ -function block_form_system_themes_form_alter(&$form, &$form_state) { - // This function needs to fire before the theme changes are recorded in the - // database, otherwise it will populate the default list of blocks from the - // new theme, which is empty. - array_unshift($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. * @@ -752,13 +484,6 @@ function _block_get_cache_id($block) { } /** - * Implement 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 5 Jun 2009 21:45:41 -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; +} + +/** + * Implement 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), + ), + ); +} + +/** + * Implement 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 5 Jun 2009 21:45:42 -0000 @@ -0,0 +1,56 @@ + array( + 'title' => t('Administer blocks'), + 'description' => t('Select which blocks are displayed, and arrange them on the page.'), + ), + ); +} + +/** + * Implement 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); + foreach ($result as $block) { + $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; + } + } +} + +/** + * Implement 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 5 Jun 2009 21:45:40 -0000 @@ -0,0 +1,16 @@ + array( - 'name' => t('Blog entry'), - 'base' => 'blog', - 'description' => t('A blog entry is a single post to an online journal, or blog.'), - ) - ); -} - -/** - * Implement hook_perm(). - */ -function blog_perm() { - return node_list_permissions('blog'); -} - -/** * Implement hook_access(). */ function blog_access($op, $node, $account) { @@ -70,30 +50,6 @@ function blog_help($path, $arg) { } /** - * Implement hook_form(). - */ -function blog_form($node, $form_state) { - global $nid; - $type = node_type_get_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; -} - -/** - * Implement 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); -} - -/** * Implement hook_node_view. */ function blog_node_view($node, $teaser = FALSE) { @@ -113,41 +69,6 @@ function blog_node_view($node, $teaser = } /** - * Implement 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 +94,6 @@ function _blog_post_exists($account) { } /** - * Implement hook_block_list(). - */ -function blog_block_list() { - $block['recent']['info'] = t('Recent blog posts'); - return $block; -} - -/** * Implement 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 5 Jun 2009 21:45:45 -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; +} + +/** + * Implement 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 5 Jun 2009 21:45:40 -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; +} + +/** + * Implement 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 5 Jun 2009 21:45:40 -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.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 5 Jun 2009 21:45:45 -0000 @@ -7,3 +7,7 @@ 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.admin.inc Index: modules/blogapi/blogapi.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.module,v retrieving revision 1.154 diff -u -p -r1.154 blogapi.module --- modules/blogapi/blogapi.module 4 Jun 2009 03:33:27 -0000 1.154 +++ modules/blogapi/blogapi.module 5 Jun 2009 21:45:45 -0000 @@ -21,307 +21,6 @@ function blogapi_help($path, $arg) { } /** - * Implement 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.'), - ), - ); -} - -/** - * Implement 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 +48,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 +84,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('/(.*?)<\/title>/i', $contents, $title)) { - $title = strip_tags($title[0]); - $contents = preg_replace('/<title>.*?<\/title>/i', '', $contents); - } - else { - list($title, $contents) = explode("\n", $contents, 2); - } - - return $title; -} - -/** - * Add some settings to the admin_settings form. - */ -function blogapi_admin_settings() { - $node_types = array_map('check_plain', node_type_get_names()); - $defaults = isset($node_types['blog']) ? array('blog' => 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' => '<p>' . t('Your PHP settings limit the maximum file size per upload to %size.', array('%size' => format_size(file_upload_max_size()))) . '</p>'); - - $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); -} - -/** - * Implement 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; -} - -/** * Implement 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 5 Jun 2009 21:45:39 -0000 @@ -0,0 +1,30 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Blogapi module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:40 -0000 @@ -0,0 +1,20 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Blogapi module. + */ + +/** + * Implement 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.'), + ), + ); +} + 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 5 Jun 2009 21:45:40 -0000 @@ -0,0 +1,628 @@ +<?php +// $Id$ + +/** + * @file + * XML-RPC hooks for Blogapi module. + */ + +/** + * Implement 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); +} + +/** + * 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 + * <a href="http://movabletype.org/docs/mtmanual_programmatic.html#item_mt%2EgetRecentPostTitles"> + * returns a bandwidth-friendly list</a>. + */ +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('/<title>(.*?)<\/title>/i', $contents, $title)) { + $title = strip_tags($title[0]); + $contents = preg_replace('/<title>.*?<\/title>/i', '', $contents); + } + else { + list($title, $contents) = explode("\n", $contents, 2); + } + + return $title; +} + Index: modules/book/book.block.inc =================================================================== RCS file: modules/book/book.block.inc diff -N modules/book/book.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/book/book.block.inc 5 Jun 2009 21:45:38 -0000 @@ -0,0 +1,47 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Book module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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 <em>Show block on all pages</em> is selected, the block will contain the automatically generated menus for all of the site's books. If <em>Show block only on book pages</em> 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 <em>Page specific visibility settings</em> or other visibility settings can be used in addition to selectively display this block."), + ); + + return $form; +} + +/** + * Implement hook_block_save(). + */ +function book_block_save($delta = '', $edit = array()) { + $block = array(); + variable_set('book_block_mode', $edit['book_block_mode']); +} + Index: modules/book/book.form.inc =================================================================== RCS file: modules/book/book.form.inc diff -N modules/book/book.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/book/book.form.inc 5 Jun 2009 21:45:38 -0000 @@ -0,0 +1,22 @@ +<?php +// $Id$ + +/** + * @file + * Form alter hooks for specific forms for Book module. + */ + +/** + * 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' => '<p>' . 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)) . '</p>', + '#weight' => -10, + ); + } +} + 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 5 Jun 2009 21:45:38 -0000 @@ -9,3 +9,8 @@ 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 Index: modules/book/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.module,v retrieving revision 1.494 diff -u -p -r1.494 book.module --- modules/book/book.module 27 May 2009 18:33:55 -0000 1.494 +++ modules/book/book.module 5 Jun 2009 21:45:38 -0000 @@ -7,60 +7,6 @@ */ /** - * Implement 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', - ), - ); -} - -/** - * Implement 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 } /** - * Implement 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() { } /** - * Implement 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; -} - -/** * Implement 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 = '') { } /** - * Implement 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 <em>Show block on all pages</em> is selected, the block will contain the automatically generated menus for all of the site's books. If <em>Show block only on book pages</em> 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 <em>Page specific visibility settings</em> or other visibility settings can be used in addition to selectively display this block."), - ); - - return $form; -} - -/** - * Implement 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) { } /** - * Implement 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; - } -} - -/** - * Implement 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); - } -} - -/** - * Implement 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); - } -} - -/** - * Implement 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(); - } -} - -/** - * Implement 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' => '<p>' . 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)) . '</p>', - '#weight' => -10, - ); - } -} - -/** * Return an array with default values for a book link. */ function _book_link_defaults($nid) { @@ -1065,35 +787,6 @@ function book_type_is_allowed($type) { } /** - * Implement 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; - } -} - -/** * Implement hook_help(). */ function book_help($path, $arg) { 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 5 Jun 2009 21:45:38 -0000 @@ -0,0 +1,140 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Book module. + */ + +/** + * Implement 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; + } +} + +/** + * Implement 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); + } +} + +/** + * Implement 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); + } +} + +/** + * Implement 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(); + } +} + +/** + * Implement 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); + } +} + +/** + * Implement 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 5 Jun 2009 21:45:37 -0000 @@ -0,0 +1,106 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Book module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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 5 Jun 2009 21:45:37 -0000 @@ -0,0 +1,32 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Book module. + */ + +/** + * Implement 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.'), + ), + ); +} + 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 5 Jun 2009 21:45:46 -0000 @@ -0,0 +1,229 @@ +<?php +// $Id$ + +/** + * @file + * Form alter hooks for specific forms for Color module. + */ + +/** + * Implement 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 <a href="@url">download method</a> 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'; + } + } +} + +/** + * Implement hook_form_FORM_ID_alter(). + */ +function color_form_system_themes_alter(&$form, &$form_state) { + _color_theme_select_form_alter($form, $form_state); +} + +/** + * Implement 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 <a href="@url">PHP documentation</a> 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.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 5 Jun 2009 21:45:36 -0000 @@ -7,3 +7,5 @@ version = VERSION core = 7.x files[] = color.module files[] = color.install +files[] = color.registry.inc +files[] = color.form.inc Index: modules/color/color.module =================================================================== RCS file: /cvs/drupal/drupal/modules/color/color.module,v retrieving revision 1.59 diff -u -p -r1.59 color.module --- modules/color/color.module 27 May 2009 18:33:55 -0000 1.59 +++ modules/color/color.module 5 Jun 2009 21:45:46 -0000 @@ -17,55 +17,6 @@ function color_help($path, $arg) { } /** - * Implement hook_theme(). - */ -function color_theme() { - return array( - 'color_scheme_form' => array( - 'arguments' => array('form' => NULL), - ), - ); -} - -/** - * Implement 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 <a href="@url">download method</a> 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'; - } - } -} - -/** - * Implement hook_form_FORM_ID_alter(). - */ -function color_form_system_themes_alter(&$form, &$form_state) { - _color_theme_select_form_alter($form, $form_state); -} - -/** - * Implement 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 +113,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 +144,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 <a href="@url">PHP documentation</a> 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 5 Jun 2009 21:45:36 -0000 @@ -0,0 +1,19 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Color module. + */ + +/** + * Implement hook_theme(). + */ +function color_theme() { + return array( + 'color_scheme_form' => 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 5 Jun 2009 21:45:33 -0000 @@ -0,0 +1,80 @@ +<?php +// $Id$ + +/** + * @file + * Action hooks for Comment module. + */ + +/** + * Drupal action to unpublish a comment. + * + * @param $context + * Keyed array. Must contain the id of the comment if $comment is not passed. + * @param $comment + * An optional comment object. + */ +function comment_unpublish_action($comment, $context = array()) { + if (isset($comment->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'])); +} + +/** + * Implement 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 5 Jun 2009 21:45:34 -0000 @@ -0,0 +1,39 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Comment module. + */ + +/** + * Implement hook_block_list(). + */ +function comment_block_list() { + $blocks['recent']['info'] = t('Recent comments'); + + return $blocks; +} + +/** + * Implement 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 <em>Recent comments</em> block.'), + ); + + return $form; +} + +/** + * Implement 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 5 Jun 2009 21:45:47 -0000 @@ -0,0 +1,490 @@ +<?php +// $Id$ + +/** + * @file + * Form alter hooks for specific forms for Comment module. + */ + +/** + * Implement 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 <em>administer comments</em> 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 <a href="@url">permissions page</a>.', 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 form <code>http://example.com/directory</code>.')); + } + } + } + } + + 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' => '<div class="preview">', + '#suffix' => '</div>', + ); + + $output = ''; // Isn't this line a duplication of the first $output above? + + if ($edit['pid']) { + $comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array( + ':cid' => $edit['pid'], + ':status' => COMMENT_PUBLISHED, + ))->fetchObject(); + $comment = drupal_unpack($comment); + $comment->name = $comment->uid ? $comment->registered_name : $comment->name; + $output .= theme('comment_view', $comment, $node); + } + else { + $suffix = empty($form['#suffix']) ? '' : $form['#suffix']; + $form['#suffix'] = $suffix . drupal_render(node_build($node)); + $edit['pid'] = 0; + } + + $form['comment_preview_below'] = array( + '#markup' => $output, + '#weight' => 100, + ); + + return $form; +} + +/** + * Process comment form submissions; prepare the comment, store it, and set a redirection target. + */ +function comment_form_submit($form, &$form_state) { + _comment_form_submit($form_state['values']); + if ($cid = comment_save($form_state['values'])) { + $node = node_load($form_state['values']['nid']); + // Add 1 to existing $node->comment count to include new comment. + $comment_count = $node->comment_count + 1; + $page = comment_new_page_count($comment_count, 1, $node); + $form_state['redirect'] = array('node/' . $node->nid, $page, "comment-$cid"); + return; + } +} + 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 5 Jun 2009 21:45:34 -0000 @@ -9,3 +9,10 @@ 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 Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.719 diff -u -p -r1.719 comment.module --- modules/comment/comment.module 3 Jun 2009 06:52:29 -0000 1.719 +++ modules/comment/comment.module 5 Jun 2009 21:45:47 -0000 @@ -106,187 +106,6 @@ function comment_help($path, $arg) { } /** - * Implement 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, 'node' => 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), - ), - ); -} - -/** - * Implement 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; -} - -/** - * Implement 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; - } -} - -/** - * Implement 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).'), - ), - ); -} - -/** - * Implement hook_block_list(). - */ -function comment_block_list() { - $blocks['recent']['info'] = t('Recent comments'); - - return $blocks; -} - -/** - * Implement 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 <em>Recent comments</em> block.'), - ); - - return $form; -} - -/** - * Implement hook_block_save(). - */ -function comment_block_save($delta = '', $edit = array()) { - variable_set('comment_block_count', (int)$edit['comment_block_count']); -} - -/** * Implement hook_block_view(). * * Generates a block with the most recent comments. @@ -511,76 +330,6 @@ function comment_node_view($node, $tease } /** - * Implement 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 <em>administer comments</em> 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 <a href="@url">permissions page</a>.', 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')), - ); - } -} - -/** * Implement hook_form_alter(). */ function comment_form_alter(&$form, $form_state, $form_id) { @@ -677,59 +426,6 @@ function comment_node_load($nodes, $type } /** - * Implement hook_node_prepare(). - */ -function comment_node_prepare($node) { - if (!isset($node->comment)) { - $node->comment = variable_get("comment_$node->type", COMMENT_NODE_OPEN); - } -} - -/** - * Implement 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(); -} - -/** - * Implement 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(); -} - -/** - * Implement hook_node_update_index(). - */ -function comment_node_update_index($node) { - $text = ''; - if ($node->comment != COMMENT_NODE_HIDDEN) { - $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 .= '<h2>' . check_plain($comment->subject) . '</h2>' . check_markup($comment->comment, $comment->format, '', FALSE); - } - } - return $text; -} - -/** * Implement hook_update_index(). */ function comment_update_index() { @@ -749,46 +445,6 @@ function comment_node_search_result($nod } /** - * Implement hook_user_cancel(). - */ -function comment_user_cancel($edit, $account, $method) { - switch ($method) { - case 'user_cancel_block_unpublish': - db_update('comment') - ->fields(array('status' => 0)) - ->condition('uid', $account->uid) - ->execute(); - db_update('node_comment_statistics') - ->fields(array('last_comment_uid' => 0)) - ->condition('last_comment_uid', $account->uid) - ->execute(); - break; - - case 'user_cancel_reassign': - db_update('comment') - ->fields(array('uid' => 0)) - ->condition('uid', $account->uid) - ->execute(); - db_update('node_comment_statistics') - ->fields(array('last_comment_uid' => 0)) - ->condition('last_comment_uid', $account->uid) - ->execute(); - break; - - case 'user_cancel_delete': - module_load_include('inc', 'comment', 'comment.admin'); - $result = db_query('SELECT c.cid FROM {comment} c WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol(); - foreach ($result as $cid) { - $comment = comment_load($cid); - // Delete the comment and its replies. - _comment_delete_thread($comment); - _comment_update_node_statistics($comment->nid); - } - break; - } -} - -/** * This is *not* a hook_access() implementation. This function is called * to determine whether the current user has access to a particular comment. * @@ -1348,313 +1004,6 @@ function comment_num_new($nid, $timestam } /** - * 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 form <code>http://example.com/directory</code>.')); - } - } - } - } - - 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 @@ -1671,96 +1020,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' => '<div class="preview">', - '#suffix' => '</div>', - ); - - $output = ''; // Isn't this line a duplication of the first $output above? - - if ($edit['pid']) { - $comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array( - ':cid' => $edit['pid'], - ':status' => COMMENT_PUBLISHED, - ))->fetchObject(); - $comment = drupal_unpack($comment); - $comment->name = $comment->uid ? $comment->registered_name : $comment->name; - $output .= theme('comment_view', $comment, $node); - } - else { - $suffix = empty($form['#suffix']) ? '' : $form['#suffix']; - $form['#suffix'] = $suffix . drupal_render(node_build($node)); - $edit['pid'] = 0; - } - - $form['comment_preview_below'] = array( - '#markup' => $output, - '#weight' => 100, - ); - - 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']); -} - -/** * Prepare a comment for submission. * * @param $comment_values @@ -1796,21 +1055,6 @@ function _comment_form_submit(&$comment_ } /** - * Process comment form submissions; prepare the comment, store it, and set a redirection target. - */ -function comment_form_submit($form, &$form_state) { - _comment_form_submit($form_state['values']); - if ($cid = comment_save($form_state['values'])) { - $node = node_load($form_state['values']['nid']); - // Add 1 to existing $node->comment count to include new comment. - $comment_count = $node->comment_count + 1; - $page = comment_new_page_count($comment_count, 1, $node); - $form_state['redirect'] = array('node/' . $node->nid, $page, "comment-$cid"); - return; - } -} - -/** * Theme a single comment block. * * @param $comment @@ -2194,137 +1438,3 @@ function vancode2int($c = '00') { return base_convert(substr($c, 1), 36, 10); } -/** - * Implement hook_hook_info(). - */ -function comment_hook_info() { - return array( - 'comment' => array( - 'comment' => array( - 'insert' => array( - 'runs when' => t('After saving a new comment'), - ), - 'update' => array( - 'runs when' => t('After saving an updated comment'), - ), - 'delete' => array( - 'runs when' => t('After deleting a comment') - ), - 'view' => array( - 'runs when' => t('When a comment is being viewed by an authenticated user') - ), - ), - ), - ); -} - -/** - * Implement hook_action_info(). - */ -function comment_action_info() { - return array( - 'comment_unpublish_action' => array( - 'description' => t('Unpublish comment'), - 'type' => 'comment', - 'configurable' => FALSE, - 'hooks' => array( - 'comment' => array('insert', 'update'), - ) - ), - 'comment_unpublish_by_keyword_action' => array( - 'description' => t('Unpublish comment containing keyword(s)'), - 'type' => 'comment', - 'configurable' => TRUE, - 'hooks' => array( - 'comment' => array('insert', 'update'), - ) - ) - ); -} - -/** - * Drupal action to unpublish a comment. - * - * @param $context - * Keyed array. Must contain the id of the comment if $comment is not passed. - * @param $comment - * An optional comment object. - */ -function comment_unpublish_action($comment, $context = array()) { - if (isset($comment->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'])); -} - -/** - * Implement 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; - } - } -} - -/** - * Implement hook_ranking(). - */ -function comment_ranking() { - return array( - 'comments' => array( - 'title' => t('Number of comments'), - 'join' => 'LEFT JOIN {node_comment_statistics} node_comment_statistics ON node_comment_statistics.nid = i.sid', - // Inverse law that maps the highest reply count on the site to 1 and 0 to 0. - 'score' => '2.0 - 2.0 / (1.0 + node_comment_statistics.comment_count * CAST(%f AS DECIMAL))', - 'arguments' => array(variable_get('node_cron_comments_scale', 0)), - ), - ); -} Index: modules/comment/comment.node.inc =================================================================== RCS file: modules/comment/comment.node.inc diff -N modules/comment/comment.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/comment/comment.node.inc 5 Jun 2009 21:45:34 -0000 @@ -0,0 +1,84 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Comment module. + */ + +/** + * Implement 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; + } +} + +/** + * Implement hook_node_prepare(). + */ +function comment_node_prepare($node) { + if (!isset($node->comment)) { + $node->comment = variable_get("comment_$node->type", COMMENT_NODE_OPEN); + } +} + +/** + * Implement 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(); +} + +/** + * Implement 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(); +} + +/** + * Implement hook_node_update_index(). + */ +function comment_node_update_index($node) { + $text = ''; + if ($node->comment != COMMENT_NODE_HIDDEN) { + $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 .= '<h2>' . check_plain($comment->subject) . '</h2>' . check_markup($comment->comment, $comment->format, '', FALSE); + } + } + return $text; +} + Index: modules/comment/comment.registry.inc =================================================================== RCS file: modules/comment/comment.registry.inc diff -N modules/comment/comment.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/comment/comment.registry.inc 5 Jun 2009 21:45:32 -0000 @@ -0,0 +1,159 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Comment module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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, 'node' => 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), + ), + ); +} + +/** + * Implement hook_hook_info(). + */ +function comment_hook_info() { + return array( + 'comment' => array( + 'comment' => array( + 'insert' => array( + 'runs when' => t('After saving a new comment'), + ), + 'update' => array( + 'runs when' => t('After saving an updated comment'), + ), + 'delete' => array( + 'runs when' => t('After deleting a comment') + ), + 'view' => array( + 'runs when' => t('When a comment is being viewed by an authenticated user') + ), + ), + ), + ); +} + +/** + * Implement hook_action_info(). + */ +function comment_action_info() { + return array( + 'comment_unpublish_action' => array( + 'description' => t('Unpublish comment'), + 'type' => 'comment', + 'configurable' => FALSE, + 'hooks' => array( + 'comment' => array('insert', 'update'), + ) + ), + 'comment_unpublish_by_keyword_action' => array( + 'description' => t('Unpublish comment containing keyword(s)'), + 'type' => 'comment', + 'configurable' => TRUE, + 'hooks' => array( + 'comment' => array('insert', 'update'), + ) + ) + ); +} + Index: modules/comment/comment.search.inc =================================================================== RCS file: modules/comment/comment.search.inc diff -N modules/comment/comment.search.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/comment/comment.search.inc 5 Jun 2009 21:45:34 -0000 @@ -0,0 +1,22 @@ +<?php +// $Id$ + +/** + * @file + * Search hooks for Comment module. + */ + +/** + * Implement hook_ranking(). + */ +function comment_ranking() { + return array( + 'comments' => array( + 'title' => t('Number of comments'), + 'join' => 'LEFT JOIN {node_comment_statistics} node_comment_statistics ON node_comment_statistics.nid = i.sid', + // Inverse law that maps the highest reply count on the site to 1 and 0 to 0. + 'score' => '2.0 - 2.0 / (1.0 + node_comment_statistics.comment_count * CAST(%f AS DECIMAL))', + 'arguments' => array(variable_get('node_cron_comments_scale', 0)), + ), + ); +} Index: modules/comment/comment.user.inc =================================================================== RCS file: modules/comment/comment.user.inc diff -N modules/comment/comment.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/comment/comment.user.inc 5 Jun 2009 21:45:33 -0000 @@ -0,0 +1,72 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Comment module. + */ + +/** + * Implement 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).'), + ), + ); +} + +/** + * Implement hook_user_cancel(). + */ +function comment_user_cancel($edit, $account, $method) { + switch ($method) { + case 'user_cancel_block_unpublish': + db_update('comment') + ->fields(array('status' => 0)) + ->condition('uid', $account->uid) + ->execute(); + db_update('node_comment_statistics') + ->fields(array('last_comment_uid' => 0)) + ->condition('last_comment_uid', $account->uid) + ->execute(); + break; + + case 'user_cancel_reassign': + db_update('comment') + ->fields(array('uid' => 0)) + ->condition('uid', $account->uid) + ->execute(); + db_update('node_comment_statistics') + ->fields(array('last_comment_uid' => 0)) + ->condition('last_comment_uid', $account->uid) + ->execute(); + break; + + case 'user_cancel_delete': + module_load_include('inc', 'comment', 'comment.admin'); + $result = db_query('SELECT c.cid FROM {comment} c WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol(); + foreach ($result as $cid) { + $comment = comment_load($cid); + // Delete the comment and its replies. + _comment_delete_thread($comment); + _comment_update_node_statistics($comment->nid); + } + break; + } +} + 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 5 Jun 2009 21:45:30 -0000 @@ -8,3 +8,6 @@ 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 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 5 Jun 2009 21:45:30 -0000 @@ -0,0 +1,39 @@ +<?php +// $Id$ + +/** + * @file + * Mail hooks for Contact module. + */ + +/** + * Implement 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.module =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.module,v retrieving revision 1.115 diff -u -p -r1.115 contact.module --- modules/contact/contact.module 27 May 2009 18:33:56 -0000 1.115 +++ modules/contact/contact.module 5 Jun 2009 21:45:30 -0000 @@ -33,85 +33,6 @@ function contact_help($path, $arg) { } /** - * Implement 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.'), - ), - ); -} - -/** - * Implement 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 +57,3 @@ function contact_load($cid) { return empty($contact) ? FALSE : $contact; } -/** - * Implement 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 <a href="@url">personal contact form</a> 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; - } -} - -/** - * Implement hook_user_insert(). - */ -function contact_user_insert(&$edit, &$user, $category = NULL) { - $edit['contact'] = variable_get('contact_default_status', 1); -} - -/** - * Implement hook_user_validate(). - */ -function contact_user_validate(&$edit, &$user, $category = NULL) { - return array('contact' => isset($edit['contact']) ? $edit['contact'] : FALSE); -} - -/** - * Implement 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 5 Jun 2009 21:45:30 -0000 @@ -0,0 +1,71 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Contact module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:30 -0000 @@ -0,0 +1,57 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Contact module. + */ + +/** + * Implement 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.'), + ), + ); +} + +/** + * Implement 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 <a href="@url">personal contact form</a> 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; + } +} + +/** + * Implement hook_user_insert(). + */ +function contact_user_insert(&$edit, &$user, $category = NULL) { + $edit['contact'] = variable_get('contact_default_status', 1); +} + +/** + * Implement 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 5 Jun 2009 21:45:29 -0000 @@ -0,0 +1,21 @@ +<?php +// $Id$ + +/** + * @file + * Cron functionality for Dblog module. + */ + +/** + * Implement 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(); +} + 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 5 Jun 2009 21:45:29 -0000 @@ -7,3 +7,7 @@ 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.watchdog.inc Index: modules/dblog/dblog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/dblog/dblog.module,v retrieving revision 1.38 diff -u -p -r1.38 dblog.module --- modules/dblog/dblog.module 27 May 2009 18:33:56 -0000 1.38 +++ modules/dblog/dblog.module 5 Jun 2009 21:45:29 -0000 @@ -27,52 +27,6 @@ function dblog_help($path, $arg) { } } -/** - * Implement hook_theme(). - */ -function dblog_theme() { - return array( - 'dblog_filters' => array( - 'arguments' => array('form' => NULL), - ), - ); -} - -/** - * Implement 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 +36,6 @@ function dblog_init() { -/** - * Implement 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(); -} - -/** - * Implement 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 +48,6 @@ function _dblog_get_message_types() { } /** - * Implement 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 5 Jun 2009 21:45:29 -0000 @@ -0,0 +1,54 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Dblog module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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 5 Jun 2009 21:45:29 -0000 @@ -0,0 +1,28 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Dblog module. + */ + +/** + * Implement 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; + } +} + 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 5 Jun 2009 21:45:29 -0000 @@ -0,0 +1,30 @@ +<?php +// $Id$ + +/** + * @file + * Watchdog functionality for Dblog module. + */ + +/** + * Implement 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(); +} + Index: modules/field/field.info =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.info,v retrieving revision 1.3 diff -u -p -r1.3 field.info --- modules/field/field.info 5 Jun 2009 18:25:41 -0000 1.3 +++ modules/field/field.info 5 Jun 2009 21:45:29 -0000 @@ -13,3 +13,4 @@ files[] = field.attach.inc files[] = field.form.inc dependencies[] = field_sql_storage required = TRUE +files[] = field.registry.inc Index: modules/field/field.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.module,v retrieving revision 1.12 diff -u -p -r1.12 field.module --- modules/field/field.module 5 Jun 2009 18:25:41 -0000 1.12 +++ modules/field/field.module 5 Jun 2009 21:45:29 -0000 @@ -97,13 +97,6 @@ define('FIELD_LOAD_REVISION', 'FIELD_LOA class FieldException extends Exception {} /** - * Implement hook_flush_caches. - */ -function field_flush_caches() { - return array('cache_field'); -} - -/** * Implement hook_help(). */ function field_help($path, $arg) { @@ -123,92 +116,6 @@ function field_init() { } /** - * Implement 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; -} - -/** - * Implement 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), - ), - ); -} - -/** - * Implement hook_modules_installed(). - */ -function field_modules_installed($modules) { - field_cache_clear(); -} - -/** - * Implement 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); - } -} - -/** - * Implement hook_modules_enabled(). - */ -function field_modules_enabled($modules) { - foreach ($modules as $module) { - field_associate_fields($module); - } - field_cache_clear(); -} - -/** - * Implement 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 5 Jun 2009 21:45:29 -0000 @@ -0,0 +1,101 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Field module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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), + ), + ); +} + +/** + * Implement hook_flush_caches. + */ +function field_flush_caches() { + return array('cache_field'); +} + +/** + * Implement hook_modules_installed(). + */ +function field_modules_installed($modules) { + field_cache_clear(); +} + +/** + * Implement 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); + } +} + +/** + * Implement hook_modules_enabled(). + */ +function field_modules_enabled($modules) { + foreach ($modules as $module) { + field_associate_fields($module); + } + field_cache_clear(); +} + +/** + * Implement 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 5 Jun 2009 21:45:28 -0000 @@ -0,0 +1,174 @@ +<?php +// $Id$ + +/** + * @file + * Field storage hooks for Field_sql_storage module. + */ + +/** + * Implement 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); + } +} + +/** + * Implement hook_field_storage_delete_field(). + */ +function field_sql_storage_field_storage_delete_field($field_name) { + // Mark all data associated with the field for deletion. + $field = field_info_field($field_name); + $table = _field_sql_storage_tablename($field); + db_update($table) + ->fields(array('deleted' => 1)) + ->execute(); +} + +/** + * Implement 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; + } + + $field = field_info_field($field_name); + $table_name = _field_sql_storage_tablename($field); + $revision_name = _field_sql_storage_revision_tablename($field); + + // 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(); + } + } + } + } +} + +/** + * Implement 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']; + $field = field_read_field($field_name); + $table_name = _field_sql_storage_tablename($field); + $revision_name = _field_sql_storage_revision_tablename($field); + db_delete($table_name) + ->condition('etid', $etid) + ->condition('entity_id', $id) + ->execute(); + db_delete($revision_name) + ->condition('etid', $etid) + ->condition('entity_id', $id) + ->execute(); + } +} + +/** + * Implement 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']; + $field = field_read_field($field_name); + $revision_name = _field_sql_storage_revision_tablename($field); + db_delete($revision_name) + ->condition('etid', $etid) + ->condition('entity_id', $id) + ->condition('revision_id', $vid) + ->execute(); + } + } +} + +/** + * Implement 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) { + $field = field_read_field($field_name); + $table_name = _field_sql_storage_tablename($field); + $revision_name = _field_sql_storage_revision_tablename($field); + 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.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 5 Jun 2009 21:45:28 -0000 @@ -7,3 +7,4 @@ core = 7.x files[] = field_sql_storage.module files[] = field_sql_storage.install required = TRUE +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.11 diff -u -p -r1.11 field_sql_storage.module --- modules/field/modules/field_sql_storage/field_sql_storage.module 28 May 2009 10:05:32 -0000 1.11 +++ modules/field/modules/field_sql_storage/field_sql_storage.module 5 Jun 2009 21:45:28 -0000 @@ -178,28 +178,6 @@ function _field_sql_storage_schema($fiel } /** - * Implement 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); - } -} - -/** - * Implement hook_field_storage_delete_field(). - */ -function field_sql_storage_field_storage_delete_field($field_name) { - // Mark all data associated with the field for deletion. - $field = field_info_field($field_name); - $table = _field_sql_storage_tablename($field); - db_update($table) - ->fields(array('deleted' => 1)) - ->execute(); -} - -/** * Implement hook_field_storage_load(). */ function field_sql_storage_field_storage_load($obj_type, &$objects, $age, $skip_fields = array()) { @@ -250,150 +228,6 @@ function field_sql_storage_field_storage } /** - * Implement 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; - } - - $field = field_info_field($field_name); - $table_name = _field_sql_storage_tablename($field); - $revision_name = _field_sql_storage_revision_tablename($field); - - // 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(); - } - } - } - } -} - -/** - * Implement 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']; - $field = field_read_field($field_name); - $table_name = _field_sql_storage_tablename($field); - $revision_name = _field_sql_storage_revision_tablename($field); - db_delete($table_name) - ->condition('etid', $etid) - ->condition('entity_id', $id) - ->execute(); - db_delete($revision_name) - ->condition('etid', $etid) - ->condition('entity_id', $id) - ->execute(); - } -} - -/** - * Implement 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']; - $field = field_read_field($field_name); - $revision_name = _field_sql_storage_revision_tablename($field); - db_delete($revision_name) - ->condition('etid', $etid) - ->condition('entity_id', $id) - ->condition('revision_id', $vid) - ->execute(); - } - } -} - -/** - * Implement 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) { - $field = field_read_field($field_name); - $table_name = _field_sql_storage_tablename($field); - $revision_name = _field_sql_storage_revision_tablename($field); - db_update($table_name) - ->fields(array('deleted' => 1)) - ->condition('bundle', $bundle) - ->execute(); - db_update($revision_name) - ->fields(array('deleted' => 1)) - ->condition('bundle', $bundle) - ->execute(); -} - -/** * Implement 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 5 Jun 2009 21:45:27 -0000 @@ -0,0 +1,69 @@ +<?php +// $Id$ + +/** + * @file + * Field hooks for List module. + */ + +/** + * Implement 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'), + ), + ); +} + +/** + * Implement 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']))), + ); + } + } + } +} + 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 5 Jun 2009 21:45:27 -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.6 diff -u -p -r1.6 list.module --- modules/field/modules/list/list.module 27 May 2009 18:33:56 -0000 1.6 +++ modules/field/modules/list/list.module 5 Jun 2009 21:45:27 -0000 @@ -7,117 +7,6 @@ */ /** - * Implement 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), - ), - ); -} - -/** - * Implement 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', - ), - ); -} - -/** - * Implement 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'), - ), - ); -} - -/** - * Implement 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']))), - ); - } - } - } -} - -/** * Implement hook_field_is_empty(). */ function list_field_is_empty($item, $field) { @@ -128,28 +17,6 @@ function list_field_is_empty($item, $fie } /** - * Implement 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 5 Jun 2009 21:45:27 -0000 @@ -0,0 +1,80 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for List module. + */ + +/** + * Implement 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), + ), + ); +} + +/** + * Implement 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', + ), + ); +} + +/** + * Implement 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 5 Jun 2009 21:45:48 -0000 @@ -0,0 +1,251 @@ +<?php +// $Id$ + +/** + * @file + * Field hooks for Number module. + */ + +/** + * Implement 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, + ); +} + +/** + * Implement 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'])), + ); + } + } + } +} + +/** + * Implement 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; +} + +/** + * Implement 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_elements_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 5 Jun 2009 21:45:27 -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.10 diff -u -p -r1.10 number.module --- modules/field/modules/number/number.module 28 May 2009 16:44:06 -0000 1.10 +++ modules/field/modules/number/number.module 5 Jun 2009 21:45:48 -0000 @@ -7,113 +7,6 @@ */ /** - * Implement 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)), - ); -} - -/** - * Implement 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', - ), - ); -} - -/** - * Implement 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, - ); -} - -/** - * Implement 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'])), - ); - } - } - } -} - -/** * Implement hook_content_is_empty(). */ function number_field_is_empty($item, $field) { @@ -124,47 +17,6 @@ function number_field_is_empty($item, $f } /** - * Implement 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 +51,6 @@ function theme_field_formatter_number($e } /** - * Implement 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, - ), - ), - ); -} - -/** - * Implement 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_elements_process'), - ), - ); -} - -/** - * Implement 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; -} - -/** - * Implement 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_elements_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 5 Jun 2009 21:45:27 -0000 @@ -0,0 +1,137 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Number module. + */ + +/** + * Implement 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)), + ); +} + +/** + * Implement 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_elements_process'), + ), + ); +} + +/** + * Implement 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', + ), + ); +} + +/** + * Implement 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, + ), + ), + ); +} + +/** + * Implement 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 5 Jun 2009 21:45:48 -0000 @@ -0,0 +1,193 @@ +<?php +// $Id$ + +/** + * @file + * Field hooks for Options module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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_elements_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_elements_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_elements_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 5 Jun 2009 21:45:26 -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.7 diff -u -p -r1.7 options.module --- modules/field/modules/options/options.module 28 May 2009 16:44:06 -0000 1.7 +++ modules/field/modules/options/options.module 5 Jun 2009 21:45:48 -0000 @@ -7,283 +7,6 @@ */ /** - * Implement 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), - ), - ); -} - -/** - * Implement 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, - ), - ), - ); -} - -/** - * Implement 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_elements_process'), - ), - 'options_buttons' => array( - '#input' => TRUE, - '#columns' => array('value'), '#delta' => 0, - '#process' => array('options_buttons_elements_process'), - ), - 'options_onoff' => array( - '#input' => TRUE, - '#columns' => array('value'), '#delta' => 0, - '#process' => array('options_onoff_elements_process'), - ), - ); -} - -/** - * Implement 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; -} - -/** - * Implement 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_elements_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_elements_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_elements_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 5 Jun 2009 21:45:26 -0000 @@ -0,0 +1,100 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Options module. + */ + +/** + * Implement 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), + ), + ); +} + +/** + * Implement 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_elements_process'), + ), + 'options_buttons' => array( + '#input' => TRUE, + '#columns' => array('value'), '#delta' => 0, + '#process' => array('options_buttons_elements_process'), + ), + 'options_onoff' => array( + '#input' => TRUE, + '#columns' => array('value'), '#delta' => 0, + '#process' => array('options_onoff_elements_process'), + ), + ); +} + +/** + * Implement 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 5 Jun 2009 21:45:48 -0000 @@ -0,0 +1,198 @@ +<?php +// $Id$ + +/** + * @file + * Field hooks for Text module. + */ + +/** + * Implement 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'), + ), + ); +} + +/** + * Implement 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'])), + ); + } + } + } +} + +/** + * Implement 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; +} + +/** + * Implement 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_elements_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_elements_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 5 Jun 2009 21:45:26 -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.11 diff -u -p -r1.11 text.module --- modules/field/modules/text/text.module 3 Jun 2009 02:38:47 -0000 1.11 +++ modules/field/modules/text/text.module 5 Jun 2009 21:45:48 -0000 @@ -7,110 +7,6 @@ */ /** - * Implement 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), - ), - ); -} - -/** - * Implement 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', - ), - ); -} - -/** - * Implement 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'), - ), - ); -} - -/** - * Implement 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'])), - ); - } - } - } -} - -/** * Implement hook_field_load(). * * Where possible, generate the sanitized version of each field early so that @@ -178,35 +74,6 @@ function text_field_is_empty($item, $fie } /** - * Implement 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) { @@ -230,203 +97,6 @@ function theme_field_formatter_text_trim } /** - * Implement 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, - ), - ), - ); -} - -/** - * Implement 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_elements_process'), - '#autocomplete_path' => FALSE, - ), - 'text_textarea' => array( - '#input' => TRUE, - '#columns' => array('value', 'format'), '#delta' => 0, - '#process' => array('text_textarea_elements_process'), - '#filter_value' => FILTER_FORMAT_DEFAULT, - ), - ); -} - -/** - * Implement 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; -} - -/** - * Implement 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_elements_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_elements_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 5 Jun 2009 21:45:25 -0000 @@ -0,0 +1,148 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Text module. + */ + +/** + * Implement 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), + ), + ); +} + +/** + * Implement 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_elements_process'), + '#autocomplete_path' => FALSE, + ), + 'text_textarea' => array( + '#input' => TRUE, + '#columns' => array('value', 'format'), '#delta' => 0, + '#process' => array('text_textarea_elements_process'), + '#filter_value' => FILTER_FORMAT_DEFAULT, + ), + ); +} + +/** + * Implement 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', + ), + ); +} + +/** + * Implement 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, + ), + ), + ); +} + +/** + * Implement 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.28 diff -u -p -r1.28 filter.admin.inc --- modules/filter/filter.admin.inc 30 May 2009 07:11:08 -0000 1.28 +++ modules/filter/filter.admin.inc 5 Jun 2009 21:45:49 -0000 @@ -451,3 +451,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 5 Jun 2009 21:45:25 -0000 @@ -0,0 +1,17 @@ +<?php +// $Id$ + +/** + * @file + * Cron functionality for Filter module. + */ + +/** + * Implement hook_cron(). + * + * Expire outdated filter cache entries + */ +function filter_cron() { + cache_clear_all(NULL, 'cache_filter'); +} + 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 5 Jun 2009 21:45:25 -0000 @@ -9,3 +9,6 @@ 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 Index: modules/filter/filter.module =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v retrieving revision 1.259 diff -u -p -r1.259 filter.module --- modules/filter/filter.module 29 May 2009 20:06:44 -0000 1.259 +++ modules/filter/filter.module 5 Jun 2009 21:45:49 -0000 @@ -40,132 +40,11 @@ function filter_help($path, $arg) { } } -/** - * Implement 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), - ), - ); -} - -/** - * Implement 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; -} - -/** - * Implement 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.'))), - ), - ); -} - -/** - * Implement hook_cron(). - * - * Expire outdated filter cache entries - */ -function filter_cron() { - cache_clear_all(NULL, 'cache_filter'); -} - -/** * Implement 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 5 Jun 2009 21:45:24 -0000 @@ -0,0 +1,101 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Filter module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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 5 Jun 2009 21:45:24 -0000 @@ -0,0 +1,20 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Filter module. + */ + +/** + * Implement 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.'))), + ), + ); +} + 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 5 Jun 2009 21:45:22 -0000 @@ -0,0 +1,32 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Forum module. + */ + +/** + * Implement hook_block_list(). + */ +function forum_block_list() { + $blocks['active']['info'] = t('Active forum topics'); + $blocks['new']['info'] = t('New forum topics'); + return $blocks; +} + +/** + * Implement 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; +} + +/** + * Implement 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.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 5 Jun 2009 21:45:23 -0000 @@ -10,3 +10,8 @@ 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 Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.498 diff -u -p -r1.498 forum.module --- modules/forum/forum.module 4 Jun 2009 03:33:27 -0000 1.498 +++ modules/forum/forum.module 5 Jun 2009 21:45:49 -0000 @@ -33,38 +33,6 @@ function forum_help($path, $arg) { } /** - * Implement 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,75 +47,6 @@ function forum_term_load($tid) { } /** - * Implement hook_menu(). - */ -function forum_menu() { - $items['forum'] = array( - 'title' => 'Forums', - 'page callback' => 'forum_page', - 'access arguments' => array('access content'), - ); - $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; -} - - -/** * Implement hook_init(). */ function forum_init() { @@ -218,128 +117,6 @@ function forum_node_view($node, $teaser) } /** - * Implement 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), - ); - } - } -} - -/** - * Implement 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))); - } - } - } - } - } -} - -/** - * Implement 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; - } - } - } -} - -/** - * Implement 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); - } - } - } -} - -/** - * Implement 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); - } - } -} - -/** - * Implement 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); - } -} - -/** * Implement hook_node_load(). */ function forum_node_load($nodes, $types) { @@ -365,20 +142,6 @@ function forum_node_load($nodes, $types) } /** - * Implement hook_node_info(). - */ -function forum_node_info() { - return array( - 'forum' => array( - 'name' => t('Forum topic'), - 'base' => 'forum', - 'description' => t('A <em>forum topic</em> is the initial post to a new discussion thread within a forum.'), - 'title_label' => t('Subject'), - ) - ); -} - -/** * Implement hook_access(). */ function forum_access($op, $node, $account) { @@ -393,47 +156,6 @@ function forum_access($op, $node, $accou } /** - * Implement 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; -} - -/** - * Implement 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'); - } - } -} - -/** * Implement hook_form_alter(). */ function forum_form_alter(&$form, $form_state, $form_id) { @@ -467,30 +189,6 @@ function forum_form_alter(&$form, $form_ } /** - * Implement hook_block_list(). - */ -function forum_block_list() { - $blocks['active']['info'] = t('Active forum topics'); - $blocks['new']['info'] = t('New forum topics'); - return $blocks; -} - -/** - * Implement 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; -} - -/** - * Implement hook_block_save(). - */ -function forum_block_save($delta = '', $edit = array()) { - variable_set('forum_block_num_' . $delta, $edit['forum_block_num_' . $delta]); -} - -/** * Implement hook_block_view(). * * Generates a block containing the currently active forum topics and the @@ -535,29 +233,6 @@ function forum_block_view($delta = '') { } /** - * Implement hook_form(). - */ -function forum_form($node, $form_state) { - $type = node_type_get_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; -} - -/** * Implement 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 5 Jun 2009 21:45:49 -0000 @@ -0,0 +1,153 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Forum module. + */ + +/** + * Implement 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), + ); + } + } +} + +/** + * Implement 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))); + } + } + } + } + } +} + +/** + * Implement 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; + } + } + } +} + +/** + * Implement 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); + } + } + } +} + +/** + * Implement 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); + } + } +} + +/** + * Implement 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); + } +} + +/** + * Implement hook_form(). + */ +function forum_form($node, $form_state) { + $type = node_type_get_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 5 Jun 2009 21:45:22 -0000 @@ -0,0 +1,123 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Forum module. + */ + +/** + * Implement hook_menu(). + */ +function forum_menu() { + $items['forum'] = array( + 'title' => 'Forums', + 'page callback' => 'forum_page', + 'access arguments' => array('access content'), + ); + $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; +} + + +/** + * Implement 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), + ), + ); +} + +/** + * Implement hook_node_info(). + */ +function forum_node_info() { + return array( + 'forum' => array( + 'name' => t('Forum topic'), + 'base' => 'forum', + 'description' => t('A <em>forum topic</em> 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 5 Jun 2009 21:45:23 -0000 @@ -0,0 +1,35 @@ +<?php +// $Id$ + +/** + * @file + * Taxonomy hooks for Forum module. + */ + +/** + * Implement 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'); + } + } +} + 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 5 Jun 2009 21:45:22 -0000 @@ -0,0 +1,22 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Forum module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:21 -0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = help.module files[] = help.admin.inc +files[] = help.registry.inc Index: modules/help/help.module =================================================================== RCS file: /cvs/drupal/drupal/modules/help/help.module,v retrieving revision 1.84 diff -u -p -r1.84 help.module --- modules/help/help.module 4 Jun 2009 09:38:25 -0000 1.84 +++ modules/help/help.module 5 Jun 2009 21:45:21 -0000 @@ -7,30 +7,6 @@ */ /** - * Implement 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; -} - -/** * Implement hook_help(). */ function help_help($path, $arg) { 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 5 Jun 2009 21:45:21 -0000 @@ -0,0 +1,32 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Help module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:20 -0000 @@ -0,0 +1,18 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Locale module. + */ + +/** + * Implement 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; +} + Index: modules/locale/locale.form.inc =================================================================== RCS file: modules/locale/locale.form.inc diff -N modules/locale/locale.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/locale/locale.form.inc 5 Jun 2009 21:45:21 -0000 @@ -0,0 +1,37 @@ +<?php +// $Id$ + +/** + * @file + * Form alter hooks for specific forms for Locale module. + */ + +/** + * Implement 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 <em>All languages</em>.'), + ); +} + +/** + * Implement 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 <a href="!languages">enabled languages</a>. 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.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 5 Jun 2009 21:45:21 -0000 @@ -6,3 +6,7 @@ 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 Index: modules/locale/locale.module =================================================================== RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v retrieving revision 1.241 diff -u -p -r1.241 locale.module --- modules/locale/locale.module 27 May 2009 18:33:58 -0000 1.241 +++ modules/locale/locale.module 5 Jun 2009 21:45:21 -0000 @@ -66,114 +66,6 @@ function locale_help($path, $arg) { } /** - * Implement 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 callback' => 'system_admin_menu_block_access', - 'access arguments' => array('admin/international', '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() { @@ -184,22 +76,6 @@ function locale_inc_callback() { } /** - * Implement 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.'), - ), - ); -} - -/** * Implement hook_locale(). */ function locale_locale($op = 'groups') { @@ -209,28 +85,6 @@ function locale_locale($op = 'groups') { } } -/** - * Implement 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); - } -} - -/** - * Implement 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'); @@ -263,35 +117,6 @@ function locale_language_selector_form($ } /** - * Implement 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 <em>All languages</em>.'), - ); -} - -/** - * Implement 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 <a href="!languages">enabled languages</a>. 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'))), - ); - } -} - -/** * Implement hook_form_alter(). Adds language fields to forms. */ function locale_form_alter(&$form, &$form_state, $form_id) { @@ -315,20 +140,6 @@ function locale_form_alter(&$form, &$for } } -/** - * Implement 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 @@ -583,16 +394,6 @@ function locale_js_alter(&$javascript) { // Language switcher block /** - * Implement 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; -} - -/** * Implement 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 5 Jun 2009 21:45:20 -0000 @@ -0,0 +1,130 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Locale module. + */ + +/** + * Implement 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 callback' => 'system_admin_menu_block_access', + 'access arguments' => array('admin/international', '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; +} + +/** + * Implement 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 5 Jun 2009 21:45:20 -0000 @@ -0,0 +1,46 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Locale module. + */ + +/** + * Implement 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.'), + ), + ); +} + +/** + * Implement 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); + } +} + +/** + * Implement 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 5 Jun 2009 21:45:19 -0000 @@ -0,0 +1,25 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Menu module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:50 -0000 @@ -0,0 +1,15 @@ +<?php +// $Id$ + +/** + * @file + * + */ + +/** + * 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']); +} + 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 5 Jun 2009 21:45:50 -0000 @@ -7,3 +7,8 @@ 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.form.inc Index: modules/menu/menu.install =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.install,v retrieving revision 1.18 diff -u -p -r1.18 menu.install --- modules/menu/menu.install 27 May 2009 18:33:58 -0000 1.18 +++ modules/menu/menu.install 5 Jun 2009 21:45:18 -0000 @@ -69,3 +69,32 @@ function menu_schema() { return $schema; } +/** + * Implement 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.192 diff -u -p -r1.192 menu.module --- modules/menu/menu.module 27 May 2009 18:33:58 -0000 1.192 +++ modules/menu/menu.module 5 Jun 2009 21:45:50 -0000 @@ -35,153 +35,6 @@ function menu_help($path, $arg) { } /** - * Implement hook_perm(). - */ -function menu_perm() { - return array( - 'administer menu' => array( - 'title' => t('Administer menu'), - 'description' => t('Manage menus and menu items.'), - ), - ); -} - -/** - * Implement 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; -} - -/** - * Implement 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), - ), - ); -} - -/** - * Implement 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 +119,6 @@ function menu_reset_item($item) { } /** - * Implement 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; -} - -/** * Implement hook_block_view(). */ function menu_block_view($delta = '') { @@ -293,96 +129,6 @@ function menu_block_view($delta = '') { } /** - * Implement 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'); - } - } - } -} - -/** - * Implement 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'); - } - } - } -} - -/** - * Implement 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']); - } -} - -/** - * Implement 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 +206,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 5 Jun 2009 21:45:19 -0000 @@ -0,0 +1,98 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Menu module. + */ + +/** + * Implement 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'); + } + } + } +} + +/** + * Implement 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'); + } + } + } +} + +/** + * Implement 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']); + } +} + +/** + * Implement 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 5 Jun 2009 21:45:19 -0000 @@ -0,0 +1,114 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Menu module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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 5 Jun 2009 21:45:19 -0000 @@ -0,0 +1,20 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Menu module. + */ + +/** + * Implement hook_perm(). + */ +function menu_perm() { + return array( + 'administer menu' => 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 5 Jun 2009 21:45:15 -0000 @@ -0,0 +1,165 @@ +<?php +// $Id$ + +/** + * @file + * Action hooks for Node module. + */ + +/** + * Implement a Drupal action. + * Sets the status of a node to 1, meaning published. + */ +function node_publish_action($node, $context = array()) { + $node->status = 1; + watchdog('action', 'Set @type %title to published.', array('@type' => node_type_get_name($node), '%title' => $node->title)); +} + +/** + * Implement 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_type_get_name($node), '%title' => $node->title)); +} + +/** + * Implement 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_type_get_name($node), '%title' => $node->title)); +} + +/** + * Implement 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_type_get_name($node), '%title' => $node->title)); +} + +/** + * Implement 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_type_get_name($node), '%title' => $node->title)); +} + +/** + * Implement 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_type_get_name($node), '%title' => $node->title)); +} + +/** + * Implement a Drupal action. + * Saves a node. + */ +function node_save_action($node) { + node_save($node); + watchdog('action', 'Saved @type %title', array('@type' => node_type_get_name($node), '%title' => $node->title)); +} + +/** + * Implement 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_type_get_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'])); +} + +/** + * Implement 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_type_get_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 5 Jun 2009 21:45:16 -0000 @@ -0,0 +1,18 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Node module. + */ + +/** + * Implement hook_block_list(). + */ +function node_block_list() { + $blocks['syndicate']['info'] = t('Syndicate'); + // Not worth caching. + $blocks['syndicate']['cache'] = BLOCK_NO_CACHE; + return $blocks; +} + Index: modules/node/node.cron.inc =================================================================== RCS file: modules/node/node.cron.inc diff -N modules/node/node.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/node/node.cron.inc 5 Jun 2009 21:45:17 -0000 @@ -0,0 +1,17 @@ +<?php +// $Id$ + +/** + * @file + * Cron functionality for Node module. + */ + +/** + * Implement hook_cron(). + */ +function node_cron() { + db_delete('history') + ->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 5 Jun 2009 21:45:51 -0000 @@ -0,0 +1,158 @@ +<?php +// $Id$ + +/** + * @file + * Form alter hooks for specific forms for Node module. + */ + +/** + * Implement hook_form_FORM_ID_alter(). + */ +function node_form_search_form_alter(&$form, $form_state) { + if ($form['module']['#value'] == 'node' && user_access('use advanced search')) { + // Keyword boxes: + $form['advanced'] = array( + '#type' => 'fieldset', + '#title' => t('Advanced search'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#attributes' => array('class' => 'search-advanced'), + ); + $form['advanced']['keywords'] = array( + '#prefix' => '<div class="criterion">', + '#suffix' => '</div>', + ); + $form['advanced']['keywords']['or'] = array( + '#type' => 'textfield', + '#title' => t('Containing any of the words'), + '#size' => 30, + '#maxlength' => 255, + ); + $form['advanced']['keywords']['phrase'] = array( + '#type' => 'textfield', + '#title' => t('Containing the phrase'), + '#size' => 30, + '#maxlength' => 255, + ); + $form['advanced']['keywords']['negative'] = array( + '#type' => 'textfield', + '#title' => t('Containing none of the words'), + '#size' => 30, + '#maxlength' => 255, + ); + + // Taxonomy box: + if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) { + $form['advanced']['term'] = array( + '#type' => 'select', + '#title' => t('Only in the term(s)'), + '#prefix' => '<div class="criterion">', + '#size' => 10, + '#suffix' => '</div>', + '#options' => $taxonomy, + '#multiple' => TRUE, + ); + } + + // Node types: + $types = array_map('check_plain', node_type_get_names()); + $form['advanced']['type'] = array( + '#type' => 'checkboxes', + '#title' => t('Only of the type(s)'), + '#prefix' => '<div class="criterion">', + '#suffix' => '</div>', + '#options' => $types, + ); + $form['advanced']['submit'] = array( + '#type' => 'submit', + '#value' => t('Advanced search'), + '#prefix' => '<div class="action">', + '#suffix' => '</div>', + ); + + // Languages: + $language_options = array(); + foreach (language_list('language') as $key => $object) { + $language_options[$key] = $object->name; + } + if (count($language_options) > 1) { + $form['advanced']['language'] = array( + '#type' => 'checkboxes', + '#title' => t('Languages'), + '#prefix' => '<div class="criterion">', + '#suffix' => '</div>', + '#options' => $language_options, + ); + } + + $form['#validate'][] = 'node_search_validate'; + } +} + +/** + * Form API callback for the search form. Registered in node_form_alter(). + */ +function node_search_validate($form, &$form_state) { + // Initialize using any existing basic search keywords. + $keys = $form_state['values']['processed_keys']; + + // Insert extra restrictions into the search keywords string. + if (isset($form_state['values']['type']) && is_array($form_state['values']['type'])) { + // Retrieve selected types - Forms API sets the value of unselected + // checkboxes to 0. + $form_state['values']['type'] = array_filter($form_state['values']['type']); + if (count($form_state['values']['type'])) { + $keys = search_query_insert($keys, 'type', implode(',', array_keys($form_state['values']['type']))); + } + } + + if (isset($form_state['values']['term']) && is_array($form_state['values']['term'])) { + $keys = search_query_insert($keys, 'term', implode(',', $form_state['values']['term'])); + } + if (isset($form_state['values']['language']) && is_array($form_state['values']['language'])) { + $keys = search_query_insert($keys, 'language', implode(',', array_filter($form_state['values']['language']))); + } + if ($form_state['values']['or'] != '') { + if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' ' . $form_state['values']['or'], $matches)) { + $keys .= ' ' . implode(' OR ', $matches[1]); + } + } + if ($form_state['values']['negative'] != '') { + if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' ' . $form_state['values']['negative'], $matches)) { + $keys .= ' -' . implode(' -', $matches[1]); + } + } + if ($form_state['values']['phrase'] != '') { + $keys .= ' "' . str_replace('"', ' ', $form_state['values']['phrase']) . '"'; + } + if (!empty($keys)) { + form_set_value($form['basic']['inline']['processed_keys'], trim($keys), $form_state); + } +} + +/** + * Implement hook_form(). + */ +function node_content_form($node, $form_state) { + + $type = node_type_get_type($node); + + $form = array(); + + if ($type->has_title) { + $form['title'] = array( + '#type' => 'textfield', + '#title' => check_plain($type->title_label), + '#required' => TRUE, + '#default_value' => $node->title, + '#maxlength' => 255, + '#weight' => -5, + ); + } + + $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count); + + return $form; +} + 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 5 Jun 2009 21:45:17 -0000 @@ -10,3 +10,10 @@ 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 Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1068 diff -u -p -r1.1068 node.module --- modules/node/node.module 5 Jun 2009 19:22:58 -0000 1.1068 +++ modules/node/node.module 5 Jun 2009 21:45:51 -0000 @@ -89,112 +89,6 @@ function node_help($path, $arg) { } /** - * Implement 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), - ), - ); -} - -/** - * Implement hook_cron(). - */ -function node_cron() { - db_delete('history') - ->condition('timestamp', NODE_NEW_LIMIT, '<') - ->execute(); -} - -/** - * Implement 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_type_get_names(), - ), - ); - return $return; -} - - -/** - * Implement 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 @@ -1468,50 +1362,6 @@ function theme_node_log_message($log) { } /** - * Implement 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_type_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() { @@ -1545,234 +1395,6 @@ function _node_rankings() { /** - * Implement 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' => '<em>' . 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.') . '</em>' - ); - - // 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_type_get_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; - } -} - -/** - * Implement 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; -} - -/** - * Implement 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 @@ -1853,170 +1475,6 @@ function _node_add_access() { } /** - * Implement 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/reports/status/rebuild'] = array( - 'title' => 'Rebuild permissions', - 'page callback' => 'drupal_get_form', - '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' => 'Add new 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, - ); - // Reset internal static cache of _node_types_build, forces to rebuild the node type information. - node_type_clear(); - foreach (node_type_get_types() 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) { @@ -2048,16 +1506,6 @@ function node_revision_list($node) { } /** - * Implement hook_block_list(). - */ -function node_block_list() { - $blocks['syndicate']['info'] = t('Syndicate'); - // Not worth caching. - $blocks['syndicate']['cache'] = BLOCK_NO_CACHE; - return $blocks; -} - -/** * Implement hook_block_view(). */ function node_block_view($delta = '') { @@ -2171,56 +1619,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, - ); - drupal_set_title(''); - } - else { - drupal_set_title(t('Welcome to @site-name', array('@site-name' => variable_get('site_name', 'Drupal')))); - - $default_message = '<p>' . t('No front page content has been created yet.') . '</p>'; - - if (user_access('access administration pages')) { - $default_links = array ( - l(t('Create content'), 'node/add'), - l(t('Change the default front page'), 'admin/settings/site-information'), - ); - $default_message .= theme('item_list', $default_links); - } - - $build['default_message'] = array( - '#markup' => $default_message, - '#prefix' => '<div id="first-time">', - '#suffix' => '</div>', - ); - } - return $build; -} - -/** * Menu callback; view a single node. */ function node_page_view($node) { @@ -2272,131 +1670,6 @@ function _node_index_node($node) { } /** - * Implement hook_form_FORM_ID_alter(). - */ -function node_form_search_form_alter(&$form, $form_state) { - if ($form['module']['#value'] == 'node' && user_access('use advanced search')) { - // Keyword boxes: - $form['advanced'] = array( - '#type' => 'fieldset', - '#title' => t('Advanced search'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#attributes' => array('class' => 'search-advanced'), - ); - $form['advanced']['keywords'] = array( - '#prefix' => '<div class="criterion">', - '#suffix' => '</div>', - ); - $form['advanced']['keywords']['or'] = array( - '#type' => 'textfield', - '#title' => t('Containing any of the words'), - '#size' => 30, - '#maxlength' => 255, - ); - $form['advanced']['keywords']['phrase'] = array( - '#type' => 'textfield', - '#title' => t('Containing the phrase'), - '#size' => 30, - '#maxlength' => 255, - ); - $form['advanced']['keywords']['negative'] = array( - '#type' => 'textfield', - '#title' => t('Containing none of the words'), - '#size' => 30, - '#maxlength' => 255, - ); - - // Taxonomy box: - if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) { - $form['advanced']['term'] = array( - '#type' => 'select', - '#title' => t('Only in the term(s)'), - '#prefix' => '<div class="criterion">', - '#size' => 10, - '#suffix' => '</div>', - '#options' => $taxonomy, - '#multiple' => TRUE, - ); - } - - // Node types: - $types = array_map('check_plain', node_type_get_names()); - $form['advanced']['type'] = array( - '#type' => 'checkboxes', - '#title' => t('Only of the type(s)'), - '#prefix' => '<div class="criterion">', - '#suffix' => '</div>', - '#options' => $types, - ); - $form['advanced']['submit'] = array( - '#type' => 'submit', - '#value' => t('Advanced search'), - '#prefix' => '<div class="action">', - '#suffix' => '</div>', - ); - - // Languages: - $language_options = array(); - foreach (language_list('language') as $key => $object) { - $language_options[$key] = $object->name; - } - if (count($language_options) > 1) { - $form['advanced']['language'] = array( - '#type' => 'checkboxes', - '#title' => t('Languages'), - '#prefix' => '<div class="criterion">', - '#suffix' => '</div>', - '#options' => $language_options, - ); - } - - $form['#validate'][] = 'node_search_validate'; - } -} - -/** - * Form API callback for the search form. Registered in node_form_alter(). - */ -function node_search_validate($form, &$form_state) { - // Initialize using any existing basic search keywords. - $keys = $form_state['values']['processed_keys']; - - // Insert extra restrictions into the search keywords string. - if (isset($form_state['values']['type']) && is_array($form_state['values']['type'])) { - // Retrieve selected types - Forms API sets the value of unselected - // checkboxes to 0. - $form_state['values']['type'] = array_filter($form_state['values']['type']); - if (count($form_state['values']['type'])) { - $keys = search_query_insert($keys, 'type', implode(',', array_keys($form_state['values']['type']))); - } - } - - if (isset($form_state['values']['term']) && is_array($form_state['values']['term'])) { - $keys = search_query_insert($keys, 'term', implode(',', $form_state['values']['term'])); - } - if (isset($form_state['values']['language']) && is_array($form_state['values']['language'])) { - $keys = search_query_insert($keys, 'language', implode(',', array_filter($form_state['values']['language']))); - } - if ($form_state['values']['or'] != '') { - if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' ' . $form_state['values']['or'], $matches)) { - $keys .= ' ' . implode(' OR ', $matches[1]); - } - } - if ($form_state['values']['negative'] != '') { - if (preg_match_all('/ ("[^"]+"|[^" ]+)/i', ' ' . $form_state['values']['negative'], $matches)) { - $keys .= ' -' . implode(' -', $matches[1]); - } - } - if ($form_state['values']['phrase'] != '') { - $keys .= ' "' . str_replace('"', ' ', $form_state['values']['phrase']) . '"'; - } - if (!empty($keys)) { - form_set_value($form['basic']['inline']['processed_keys'], trim($keys), $form_state); - } -} - -/** * @defgroup node_access Node access rights * @{ * The node access system determines who can do what to which nodes. @@ -2974,31 +2247,6 @@ function node_content_access($op, $node, } /** - * Implement hook_form(). - */ -function node_content_form($node, $form_state) { - - $type = node_type_get_type($node); - - $form = array(); - - if ($type->has_title) { - $form['title'] = array( - '#type' => 'textfield', - '#title' => check_plain($type->title_label), - '#required' => TRUE, - '#default_value' => $node->title, - '#maxlength' => 255, - '#weight' => -5, - ); - } - - $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count); - - return $form; -} - -/** * @} End of "defgroup node_content". */ @@ -3030,285 +2278,6 @@ function theme_node_submitted($node) { } /** - * Implement hook_hook_info(). - */ -function node_hook_info() { - return array( - 'node' => array( - 'node' => array( - 'presave' => array( - 'runs when' => t('When either saving a new post or updating an existing post'), - ), - 'insert' => array( - 'runs when' => t('After saving a new post'), - ), - 'update' => array( - 'runs when' => t('After saving an updated post'), - ), - 'delete' => array( - 'runs when' => t('After deleting a post') - ), - 'view' => array( - 'runs when' => t('When content is viewed by an authenticated user') - ), - ), - ), - ); -} - -/** - * Implement hook_action_info(). - */ -function node_action_info() { - return array( - 'node_publish_action' => array( - 'type' => 'node', - 'description' => t('Publish post'), - 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'hooks' => array( - 'node' => array('presave'), - 'comment' => array('insert', 'update'), - ), - ), - 'node_unpublish_action' => array( - 'type' => 'node', - 'description' => t('Unpublish post'), - 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'hooks' => array( - 'node' => array('presave'), - 'comment' => array('delete', 'insert', 'update'), - ), - ), - 'node_make_sticky_action' => array( - 'type' => 'node', - 'description' => t('Make post sticky'), - 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'hooks' => array( - 'node' => array('presave'), - 'comment' => array('insert', 'update'), - ), - ), - 'node_make_unsticky_action' => array( - 'type' => 'node', - 'description' => t('Make post unsticky'), - 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'hooks' => array( - 'node' => array('presave'), - 'comment' => array('delete', 'insert', 'update'), - ), - ), - 'node_promote_action' => array( - 'type' => 'node', - 'description' => t('Promote post to front page'), - 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'hooks' => array( - 'node' => array('presave'), - 'comment' => array('insert', 'update'), - ), - ), - 'node_unpromote_action' => array( - 'type' => 'node', - 'description' => t('Remove post from front page'), - 'configurable' => FALSE, - 'behavior' => array('changes_node_property'), - 'hooks' => array( - 'node' => array('presave'), - 'comment' => array('delete', 'insert', 'update'), - ), - ), - 'node_assign_owner_action' => array( - 'type' => 'node', - 'description' => t('Change the author of a post'), - 'configurable' => TRUE, - 'behavior' => array('changes_node_property'), - 'hooks' => array( - 'any' => TRUE, - 'node' => array('presave'), - 'comment' => array('delete', 'insert', 'update'), - ), - ), - 'node_save_action' => array( - 'type' => 'node', - 'description' => t('Save post'), - 'configurable' => FALSE, - 'hooks' => array( - 'comment' => array('delete', 'insert', 'update'), - ), - ), - 'node_unpublish_by_keyword_action' => array( - 'type' => 'node', - 'description' => t('Unpublish post containing keyword(s)'), - 'configurable' => TRUE, - 'hooks' => array( - 'node' => array('presave', 'insert', 'update'), - ), - ), - ); -} - -/** - * Implement a Drupal action. - * Sets the status of a node to 1, meaning published. - */ -function node_publish_action($node, $context = array()) { - $node->status = 1; - watchdog('action', 'Set @type %title to published.', array('@type' => node_type_get_name($node), '%title' => $node->title)); -} - -/** - * Implement 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_type_get_name($node), '%title' => $node->title)); -} - -/** - * Implement 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_type_get_name($node), '%title' => $node->title)); -} - -/** - * Implement 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_type_get_name($node), '%title' => $node->title)); -} - -/** - * Implement 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_type_get_name($node), '%title' => $node->title)); -} - -/** - * Implement 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_type_get_name($node), '%title' => $node->title)); -} - -/** - * Implement a Drupal action. - * Saves a node. - */ -function node_save_action($node) { - node_save($node); - watchdog('action', 'Saved @type %title', array('@type' => node_type_get_name($node), '%title' => $node->title)); -} - -/** - * Implement 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_type_get_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'])); -} - -/** - * Implement 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_type_get_name($node), '%title' => $node->title)); - break; - } - } -} - -/** * Helper function to generate standard node permission list for a given type. * * @param $type @@ -3348,15 +2317,6 @@ function node_list_permissions($type) { } /** - * Implement hook_elements(). - */ -function node_elements() { - $type['node_links'] = array('#theme' => 'node_links'); - - return $type; -} - -/** * Format a set of node links. * * @param $element Index: modules/node/node.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v retrieving revision 1.68 diff -u -p -r1.68 node.pages.inc --- modules/node/node.pages.inc 5 Jun 2009 05:28:28 -0000 1.68 +++ modules/node/node.pages.inc 5 Jun 2009 21:45:51 -0000 @@ -622,3 +622,53 @@ function node_revision_delete_confirm_su $form_state['redirect'] .= '/revisions'; } } +/** + * 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, + ); + drupal_set_title(''); + } + else { + drupal_set_title(t('Welcome to @site-name', array('@site-name' => variable_get('site_name', 'Drupal')))); + + $default_message = '<p>' . t('No front page content has been created yet.') . '</p>'; + + if (user_access('access administration pages')) { + $default_links = array ( + l(t('Create content'), 'node/add'), + l(t('Change the default front page'), 'admin/settings/site-information'), + ); + $default_message .= theme('item_list', $default_links); + } + + $build['default_message'] = array( + '#markup' => $default_message, + '#prefix' => '<div id="first-time">', + '#suffix' => '</div>', + ); + } + return $build; +} + Index: modules/node/node.registry.inc =================================================================== RCS file: modules/node/node.registry.inc diff -N modules/node/node.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/node/node.registry.inc 5 Jun 2009 21:45:14 -0000 @@ -0,0 +1,400 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Node module. + */ + +/** + * Implement 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/reports/status/rebuild'] = array( + 'title' => 'Rebuild permissions', + 'page callback' => 'drupal_get_form', + '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' => 'Add new 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, + ); + // Reset internal static cache of _node_types_build, forces to rebuild the node type information. + node_type_clear(); + foreach (node_type_get_types() 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; +} + +/** + * Implement 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), + ), + ); +} + +/** + * Implement hook_elements(). + */ +function node_elements() { + $type['node_links'] = array('#theme' => 'node_links'); + + return $type; +} + +/** + * Implement 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_type_get_names(), + ), + ); + return $return; +} + + +/** + * Implement 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; +} + +/** + * Implement hook_hook_info(). + */ +function node_hook_info() { + return array( + 'node' => array( + 'node' => array( + 'presave' => array( + 'runs when' => t('When either saving a new post or updating an existing post'), + ), + 'insert' => array( + 'runs when' => t('After saving a new post'), + ), + 'update' => array( + 'runs when' => t('After saving an updated post'), + ), + 'delete' => array( + 'runs when' => t('After deleting a post') + ), + 'view' => array( + 'runs when' => t('When content is viewed by an authenticated user') + ), + ), + ), + ); +} + +/** + * Implement hook_action_info(). + */ +function node_action_info() { + return array( + 'node_publish_action' => array( + 'type' => 'node', + 'description' => t('Publish post'), + 'configurable' => FALSE, + 'behavior' => array('changes_node_property'), + 'hooks' => array( + 'node' => array('presave'), + 'comment' => array('insert', 'update'), + ), + ), + 'node_unpublish_action' => array( + 'type' => 'node', + 'description' => t('Unpublish post'), + 'configurable' => FALSE, + 'behavior' => array('changes_node_property'), + 'hooks' => array( + 'node' => array('presave'), + 'comment' => array('delete', 'insert', 'update'), + ), + ), + 'node_make_sticky_action' => array( + 'type' => 'node', + 'description' => t('Make post sticky'), + 'configurable' => FALSE, + 'behavior' => array('changes_node_property'), + 'hooks' => array( + 'node' => array('presave'), + 'comment' => array('insert', 'update'), + ), + ), + 'node_make_unsticky_action' => array( + 'type' => 'node', + 'description' => t('Make post unsticky'), + 'configurable' => FALSE, + 'behavior' => array('changes_node_property'), + 'hooks' => array( + 'node' => array('presave'), + 'comment' => array('delete', 'insert', 'update'), + ), + ), + 'node_promote_action' => array( + 'type' => 'node', + 'description' => t('Promote post to front page'), + 'configurable' => FALSE, + 'behavior' => array('changes_node_property'), + 'hooks' => array( + 'node' => array('presave'), + 'comment' => array('insert', 'update'), + ), + ), + 'node_unpromote_action' => array( + 'type' => 'node', + 'description' => t('Remove post from front page'), + 'configurable' => FALSE, + 'behavior' => array('changes_node_property'), + 'hooks' => array( + 'node' => array('presave'), + 'comment' => array('delete', 'insert', 'update'), + ), + ), + 'node_assign_owner_action' => array( + 'type' => 'node', + 'description' => t('Change the author of a post'), + 'configurable' => TRUE, + 'behavior' => array('changes_node_property'), + 'hooks' => array( + 'any' => TRUE, + 'node' => array('presave'), + 'comment' => array('delete', 'insert', 'update'), + ), + ), + 'node_save_action' => array( + 'type' => 'node', + 'description' => t('Save post'), + 'configurable' => FALSE, + 'hooks' => array( + 'comment' => array('delete', 'insert', 'update'), + ), + ), + 'node_unpublish_by_keyword_action' => array( + 'type' => 'node', + 'description' => t('Unpublish post containing keyword(s)'), + 'configurable' => TRUE, + 'hooks' => array( + 'node' => array('presave', 'insert', 'update'), + ), + ), + ); +} + Index: modules/node/node.search.inc =================================================================== RCS file: modules/node/node.search.inc diff -N modules/node/node.search.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/node/node.search.inc 5 Jun 2009 21:45:17 -0000 @@ -0,0 +1,177 @@ +<?php +// $Id$ + +/** + * @file + * Search hooks for Node module. + */ + +/** + * Implement 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' => '<em>' . 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.') . '</em>' + ); + + // 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_type_get_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; + } +} + +/** + * Implement 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; +} + Index: modules/node/node.user.inc =================================================================== RCS file: modules/node/node.user.inc diff -N modules/node/node.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/node/node.user.inc 5 Jun 2009 21:45:16 -0000 @@ -0,0 +1,111 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Node module. + */ + +/** + * Implement 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_type_get_types() as $type) { + if ($type->base == 'node_content') { + $perms += node_list_permissions($type); + } + } + + return $perms; +} + +/** + * Implement 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; + } +} + Index: modules/node/tests/node_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/node/tests/node_test.info,v retrieving revision 1.1 diff -u -p -r1.1 node_test.info --- modules/node/tests/node_test.info 2 Apr 2009 20:47:54 -0000 1.1 +++ modules/node/tests/node_test.info 5 Jun 2009 21:45:10 -0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = node_test.module hidden = TRUE +files[] = node_test.node.inc Index: modules/node/tests/node_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/tests/node_test.module,v retrieving revision 1.4 diff -u -p -r1.4 node_test.module --- modules/node/tests/node_test.module 27 May 2009 18:33:58 -0000 1.4 +++ modules/node/tests/node_test.module 5 Jun 2009 21:45:10 -0000 @@ -49,36 +49,6 @@ function node_test_node_grants($account, } /** - * Implement hook_node_access_records(). - */ -function node_test_node_access_records($node) { - $grants = array(); - if ($node->type == 'article') { - // Create grant in arbitrary article_realm for article nodes. - $grants[] = array( - 'realm' => 'test_article_realm', - 'gid' => 1, - 'grant_view' => 1, - 'grant_update' => 0, - 'grant_delete' => 0, - 'priority' => 0, - ); - } - elseif ($node->type == 'page') { - // Create grant in arbitrary page_realm for page nodes. - $grants[] = array( - 'realm' => 'test_page_realm', - 'gid' => 1, - 'grant_view' => 1, - 'grant_update' => 0, - 'grant_delete' => 0, - 'priority' => 0, - ); - } - return $grants; -} - -/** * Implement hook_node_access_records_alter(). */ function node_test_node_access_records_alter(&$grants, $node) { Index: modules/node/tests/node_test.node.inc =================================================================== RCS file: modules/node/tests/node_test.node.inc diff -N modules/node/tests/node_test.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/node/tests/node_test.node.inc 5 Jun 2009 21:45:10 -0000 @@ -0,0 +1,38 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Node_test module. + */ + +/** + * Implement hook_node_access_records(). + */ +function node_test_node_access_records($node) { + $grants = array(); + if ($node->type == 'article') { + // Create grant in arbitrary article_realm for article nodes. + $grants[] = array( + 'realm' => 'test_article_realm', + 'gid' => 1, + 'grant_view' => 1, + 'grant_update' => 0, + 'grant_delete' => 0, + 'priority' => 0, + ); + } + elseif ($node->type == 'page') { + // Create grant in arbitrary page_realm for page nodes. + $grants[] = array( + 'realm' => 'test_page_realm', + 'gid' => 1, + 'grant_view' => 1, + 'grant_update' => 0, + 'grant_delete' => 0, + 'priority' => 0, + ); + } + return $grants; +} + Index: modules/openid/openid.form.inc =================================================================== RCS file: modules/openid/openid.form.inc diff -N modules/openid/openid.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/openid/openid.form.inc 5 Jun 2009 21:45:52 -0000 @@ -0,0 +1,53 @@ +<?php +// $Id$ + +/** + * @file + * Form alter hooks for specific forms for Openid module. + */ + +/** + * Implement hook_form_FORM_ID_alter(). + */ +function openid_form_user_login_block_alter(&$form, &$form_state) { + _openid_user_login_form_alter($form, $form_state); +} + +/** + * Implement hook_form_FORM_ID_alter(). + */ +function openid_form_user_login_alter(&$form, &$form_state) { + _openid_user_login_form_alter($form, $form_state); +} + +/** + * Implement 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']); +} + 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 5 Jun 2009 21:45:10 -0000 @@ -9,3 +9,6 @@ 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 Index: modules/openid/openid.module =================================================================== RCS file: /cvs/drupal/drupal/modules/openid/openid.module,v retrieving revision 1.48 diff -u -p -r1.48 openid.module --- modules/openid/openid.module 2 Jun 2009 06:58:17 -0000 1.48 +++ modules/openid/openid.module 5 Jun 2009 21:45:52 -0000 @@ -7,35 +7,6 @@ */ /** - * Implement 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; -} - -/** * Implement hook_help(). */ function openid_help($path, $arg) { @@ -56,33 +27,6 @@ function openid_help($path, $arg) { } } -/** - * Implement 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']); - } -} - -/** - * Implement hook_form_FORM_ID_alter(). - */ -function openid_form_user_login_block_alter(&$form, &$form_state) { - _openid_user_login_form_alter($form, $form_state); -} - -/** - * Implement 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 +66,6 @@ function _openid_user_login_form_alter(& } /** - * Implement 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 5 Jun 2009 21:45:09 -0000 @@ -0,0 +1,37 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Openid module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:09 -0000 @@ -0,0 +1,21 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Openid module. + */ + +/** + * Implement 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']); + } +} + Index: modules/openid/tests/openid_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/openid/tests/openid_test.info,v retrieving revision 1.1 diff -u -p -r1.1 openid_test.info --- modules/openid/tests/openid_test.info 8 May 2009 21:44:48 -0000 1.1 +++ modules/openid/tests/openid_test.info 5 Jun 2009 21:45:08 -0000 @@ -8,3 +8,4 @@ files[] = openid_test.install files[] = openid_test.module dependencies[] = openid hidden = TRUE +files[] = openid_test.registry.inc Index: modules/openid/tests/openid_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/openid/tests/openid_test.module,v retrieving revision 1.2 diff -u -p -r1.2 openid_test.module --- modules/openid/tests/openid_test.module 27 May 2009 18:33:58 -0000 1.2 +++ modules/openid/tests/openid_test.module 5 Jun 2009 21:45:08 -0000 @@ -22,49 +22,6 @@ */ /** - * Implement hook_menu(). - */ -function openid_test_menu() { - $items['openid-test/yadis/xrds'] = array( - 'title' => '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 <meta http-equiv="X-XRDS-Location" ...>', - 'page callback' => 'openid_test_yadis_http_equiv', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['openid-test/html/openid1'] = array( - 'title' => 'HTML-based discovery using <link rel="openid.server" ...>', - 'page callback' => 'openid_test_html_openid1', - 'access callback' => TRUE, - 'type' => MENU_CALLBACK, - ); - $items['openid-test/html/openid2'] = array( - 'title' => 'HTML-based discovery using <link rel="openid2.provider" ...>', - '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 5 Jun 2009 21:45:08 -0000 @@ -0,0 +1,51 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Openid_test module. + */ + +/** + * Implement hook_menu(). + */ +function openid_test_menu() { + $items['openid-test/yadis/xrds'] = array( + 'title' => '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 <meta http-equiv="X-XRDS-Location" ...>', + 'page callback' => 'openid_test_yadis_http_equiv', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + $items['openid-test/html/openid1'] = array( + 'title' => 'HTML-based discovery using <link rel="openid.server" ...>', + 'page callback' => 'openid_test_html_openid1', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + $items['openid-test/html/openid2'] = array( + 'title' => 'HTML-based discovery using <link rel="openid2.provider" ...>', + '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 5 Jun 2009 21:45:52 -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.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 5 Jun 2009 21:45:08 -0000 @@ -6,3 +6,6 @@ version = VERSION core = 7.x files[] = path.module files[] = path.admin.inc +files[] = path.registry.inc +files[] = path.user.inc +files[] = path.node.inc Index: modules/path/path.module =================================================================== RCS file: /cvs/drupal/drupal/modules/path/path.module,v retrieving revision 1.158 diff -u -p -r1.158 path.module --- modules/path/path.module 27 May 2009 18:33:58 -0000 1.158 +++ modules/path/path.module 5 Jun 2009 21:45:52 -0000 @@ -30,54 +30,6 @@ function path_help($path, $arg) { } /** - * Implement 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 +97,6 @@ function path_set_alias($path = NULL, $a } /** - * Implement 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.')); - } - } - } -} - -/** * Implement hook_node_load(). */ function path_node_load($nodes, $types) { @@ -181,43 +111,6 @@ function path_node_load($nodes, $types) } /** - * Implement 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); - } - } -} - -/** - * Implement 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); - } -} - -/** - * Implement 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); - } - } -} - -/** * Implement hook_form_alter(). */ function path_form_alter(&$form, $form_state, $form_id) { @@ -256,22 +149,6 @@ function path_form_alter(&$form, $form_s } /** - * Implement 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 5 Jun 2009 21:45:08 -0000 @@ -0,0 +1,67 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Path module. + */ + +/** + * Implement 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.')); + } + } + } +} + +/** + * Implement 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); + } + } +} + +/** + * Implement 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); + } +} + +/** + * Implement 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 5 Jun 2009 21:45:08 -0000 @@ -0,0 +1,46 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Path module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:08 -0000 @@ -0,0 +1,24 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Path module. + */ + +/** + * Implement 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.'), + ), + ); +} + 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 5 Jun 2009 21:45:07 -0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = php.module files[] = php.install +files[] = php.user.inc Index: modules/php/php.module =================================================================== RCS file: /cvs/drupal/drupal/modules/php/php.module,v retrieving revision 1.14 diff -u -p -r1.14 php.module --- modules/php/php.module 27 May 2009 18:34:00 -0000 1.14 +++ modules/php/php.module 5 Jun 2009 21:45:07 -0000 @@ -22,18 +22,6 @@ function php_help($path, $arg) { } /** - * Implement 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 5 Jun 2009 21:45:07 -0000 @@ -0,0 +1,20 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Php module. + */ + +/** + * Implement 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.'))), + ), + ); +} + 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 5 Jun 2009 21:45:07 -0000 @@ -0,0 +1,18 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Poll module. + */ + +/** + * Implement hook_block_list(). + */ +function poll_block_list() { + if (user_access('access content')) { + $blocks['recent']['info'] = t('Most recent poll'); + return $blocks; + } +} + Index: modules/poll/poll.cron.inc =================================================================== RCS file: modules/poll/poll.cron.inc diff -N modules/poll/poll.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/poll/poll.cron.inc 5 Jun 2009 21:45:07 -0000 @@ -0,0 +1,23 @@ +<?php +// $Id$ + +/** + * @file + * Cron functionality for Poll module. + */ + +/** + * Implement 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(); + } +} + 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 5 Jun 2009 21:45:53 -0000 @@ -0,0 +1,127 @@ +<?php +// $Id$ + +/** + * @file + * + */ + +/** + * Generates the voting form for a poll. + * + * @ingroup forms + * @see poll_vote() + * @see phptemplate_preprocess_poll_vote() + */ +function poll_view_voting(&$form_state, $node, $block = FALSE) { + if ($node->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(); + + drupal_set_message(t('Your vote was cancelled.')); +} + 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 5 Jun 2009 21:45:53 -0000 @@ -7,3 +7,9 @@ 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.form.inc Index: modules/poll/poll.module =================================================================== RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v retrieving revision 1.299 diff -u -p -r1.299 poll.module --- modules/poll/poll.module 4 Jun 2009 03:33:28 -0000 1.299 +++ modules/poll/poll.module 5 Jun 2009 21:45:53 -0000 @@ -28,52 +28,6 @@ function poll_init() { } /** - * Implement 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), - ), - ); -} - -/** - * Implement 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; -} - -/** * Implement hook_access(). */ function poll_access($op, $node, $account) { @@ -88,40 +42,6 @@ function poll_access($op, $node, $accoun } /** - * Implement 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 +49,6 @@ function _poll_menu_access($node, $perm, } /** - * Implement hook_block_list(). - */ -function poll_block_list() { - if (user_access('access content')) { - $blocks['recent']['info'] = t('Most recent poll'); - return $blocks; - } -} - -/** * Implement hook_block_view(). * * Generates a block containing the latest poll. @@ -168,163 +78,6 @@ function poll_block_view($delta = '') { } } -/** - * Implement 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(); - } -} - -/** - * Implement hook_node_info(). - */ -function poll_node_info() { - return array( - 'poll' => array( - 'name' => t('Poll'), - 'base' => 'poll', - 'description' => t('A <em>poll</em> is a question with a set of possible responses. A <em>poll</em>, once created, automatically provides a simple running count of the number of votes received for each response.'), - 'title_label' => t('Question'), - 'has_body' => FALSE, - ) - ); -} - -/** - * Implement 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_type_get_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' => '<div class="clearfix" id="poll-choice-wrapper">', - '#suffix' => '</div>', - ); - - // Container for just the poll choices. - $form['choice_wrapper']['choice'] = array( - '#prefix' => '<div id="poll-choices">', - '#suffix' => '</div>', - '#theme' => 'poll_choices', - ); - - // Add the current choices to the form. - $delta = 0; - $weight = 0; - if (isset($node->choice)) { - $delta = count($node->choice); - $weight = -$delta; - foreach ($node->choice as $chid => $choice) { - $key = 'chid:' . $chid; - $form['choice_wrapper']['choice'][$key] = _poll_choice_form($key, $choice['chid'], $choice['chtext'], $choice['chvotes'], $choice['weight'], $choice_count); - $weight = ($choice['weight'] > $weight) ? $choice['weight'] : $weight; - } - } - - // Add initial or additional choices. - $existing_delta = $delta; - for ($delta; $delta < $choice_count; $delta++) { - $key = 'new:' . ($delta - $existing_delta); - $form['choice_wrapper']['choice'][$key] = _poll_choice_form($key, NULL, '', 0, $weight, $choice_count); - } - - // We name our button 'poll_more' to avoid conflicts with other modules using - // AHAH-enabled buttons with the id 'more'. - $form['choice_wrapper']['poll_more'] = array( - '#type' => 'submit', - '#value' => t('More choices'), - '#description' => t("If the amount of boxes above isn't enough, click here to add more choices."), - '#weight' => 1, - '#submit' => array('poll_more_choices_submit'), // If no javascript action. - '#ahah' => array( - 'callback' => 'poll_choice_js', - 'wrapper' => 'poll-choices', - 'method' => 'replace', - 'effect' => 'fade', - ), - ); - - // Poll attributes - $duration = array(0 => t('Unlimited')) + drupal_map_assoc(array(86400, 172800, 345600, 604800, 1209600, 2419200, 4838400, 9676800, 31536000), "format_interval"); - $active = array(0 => t('Closed'), 1 => t('Active')); - - $form['settings'] = array( - '#type' => 'fieldset', - '#collapsible' => TRUE, - '#title' => t('Poll settings'), - '#weight' => -3, - '#access' => $admin, - ); - - $form['settings']['active'] = array( - '#type' => 'radios', - '#title' => t('Poll status'), - '#default_value' => isset($node->active) ? $node->active : 1, - '#options' => $active, - '#description' => t('When a poll is closed, visitors can no longer vote for it.'), - '#access' => $admin, - ); - $form['settings']['runtime'] = array( - '#type' => 'select', - '#title' => t('Poll duration'), - '#default_value' => isset($node->runtime) ? $node->runtime : 0, - '#options' => $duration, - '#description' => t('After this period, the poll will be closed automatically.'), - ); - - return $form; -} - -/** - * Submit handler to add more choices to a poll form. This handler is used when - * javascript is not available. It makes changes to the form state and the - * entire form is rebuilt during the page reload. - */ -function poll_more_choices_submit($form, &$form_state) { - // Set the form to rebuild and run submit handlers. - node_form_submit_build_node($form, $form_state); - - // Make the changes we want to the form state. - if ($form_state['values']['poll_more']) { - $n = $_GET['q'] == 'system/ahah' ? 1 : 5; - $form_state['choice_count'] = count($form_state['values']['choice']) + $n; - } -} - function _poll_choice_form($key, $chid = NULL, $value = '', $votes = 0, $weight = 0, $size = 10) { $admin = user_access('administer nodes'); @@ -379,48 +132,6 @@ function poll_choice_js($form, $form_sta } /** - * Implement hook_submit(). - */ -function poll_node_form_submit(&$form, &$form_state) { - // Renumber fields - $form_state['values']['choice'] = array_values($form_state['values']['choice']); - $form_state['values']['teaser'] = poll_teaser((object)$form_state['values']); -} - -/** - * Implement hook_validate(). - */ -function poll_validate($node, $form) { - if (isset($node->title)) { - // Check for at least two options and validate amount of votes: - $realchoices = 0; - // Renumber fields - $node->choice = array_values($node->choice); - foreach ($node->choice as $i => $choice) { - if ($choice['chtext'] != '') { - $realchoices++; - } - if (isset($choice['chvotes']) && $choice['chvotes'] < 0) { - form_set_error("choice][$i][chvotes", t('Negative values are not allowed.')); - } - } - - if ($realchoices < 2) { - form_set_error("choice][$realchoices][chtext", t('You must fill in at least two choices.')); - } - } -} - -/** - * Implement hook_node_prepare_translation(). - */ -function poll_node_prepare_translation($node) { - if ($node->type == 'poll') { - $node->choice = $node->translation_source->choice; - } -} - -/** * Implement hook_load(). */ function poll_load($nodes) { @@ -455,92 +166,6 @@ function poll_load($nodes) { } /** - * Implement hook_insert(). - */ -function poll_insert($node) { - if (!user_access('administer nodes')) { - // Make sure all votes are 0 initially - foreach ($node->choice as $i => $choice) { - $node->choice[$i]['chvotes'] = 0; - } - $node->active = 1; - } - - db_insert('poll') - ->fields(array( - 'nid' => $node->nid, - 'runtime' => $node->runtime, - 'active' => $node->active, - )) - ->execute(); - - foreach ($node->choice as $choice) { - if ($choice['chtext'] != '') { - db_insert('poll_choice') - ->fields(array( - 'nid' => $node->nid, - 'chtext' => $choice['chtext'], - 'chvotes' => $choice['chvotes'], - 'weight' => $choice['weight'], - )) - ->execute(); - } - } -} - -/** - * Implement hook_update(). - */ -function poll_update($node) { - // Update poll settings. - db_update('poll') - ->fields(array( - 'runtime' => $node->runtime, - 'active' => $node->active, - )) - ->condition('nid', $node->nid) - ->execute(); - - // Poll choices with empty titles signifies removal. We remove all votes to - // the removed options, so people who voted on them can vote again. - foreach ($node->choice as $key => $choice) { - if (!empty($choice['chtext'])) { - db_merge('poll_choice') - ->key(array('chid' => $choice['chid'])) - ->fields(array( - 'nid' => $node->nid, - 'chtext' => $choice['chtext'], - 'chvotes' => (int) $choice['chvotes'], - 'weight' => $choice['weight'], - )) - ->updateExcept('nid') - ->execute(); - } - else { - db_delete('poll_vote') - ->condition('nid', $node->nid) - ->condition('chid', $key) - ->execute(); - } - } -} - -/** - * Implement hook_delete(). - */ -function poll_delete($node) { - db_delete('poll') - ->condition('nid', $node->nid) - ->execute(); - db_delete('poll_choice') - ->condition('nid', $node->nid) - ->execute(); - db_delete('poll_vote') - ->condition('nid', $node->nid) - ->execute(); -} - -/** * Return content for 'latest poll' block. * * @param $node @@ -582,22 +207,6 @@ function poll_block_latest_poll_view($no /** - * Implement hook_view(). - */ -function poll_view($node, $teaser = FALSE) { - global $user; - $output = ''; - - if (!empty($node->allowvotes) && empty($node->show_results)) { - $node->content['poll_view_voting'] = drupal_get_form('poll_view_voting', $node); - } - else { - $node->content['poll_view_results'] = array('#markup' => poll_view_results($node, $teaser)); - } - return $node; -} - -/** * Creates a simple teaser that lists all the choices. * * This is primarily used for RSS. @@ -615,83 +224,6 @@ function poll_teaser($node) { } /** - * Generates the voting form for a poll. - * - * @ingroup forms - * @see poll_vote() - * @see phptemplate_preprocess_poll_vote() - */ -function poll_view_voting(&$form_state, $node, $block = FALSE) { - if ($node->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. -} - -/** * Themes the voting form for a poll. * * Inputs: $form @@ -822,65 +354,3 @@ function template_preprocess_poll_bar(&$ $variables['percentage'] = round($variables['votes'] * 100 / max($variables['total_votes'], 1)); } -/** - * 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(); - - drupal_set_message(t('Your vote was cancelled.')); -} - -/** - * Implement hook_user_cancel(). - */ -function poll_user_cancel($edit, $account, $method) { - switch ($method) { - case 'user_cancel_reassign': - db_update('poll_vote') - ->fields(array('uid' => 0)) - ->condition('uid', $account->uid) - ->execute(); - break; - - case 'user_cancel_delete': - db_delete('poll_vote') - ->condition('uid', $account->uid) - ->execute(); - break; - } -} - Index: modules/poll/poll.node.inc =================================================================== RCS file: modules/poll/poll.node.inc diff -N modules/poll/poll.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/poll/poll.node.inc 5 Jun 2009 21:45:53 -0000 @@ -0,0 +1,279 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Poll module. + */ + +/** + * Implement hook_node_prepare_translation(). + */ +function poll_node_prepare_translation($node) { + if ($node->type == 'poll') { + $node->choice = $node->translation_source->choice; + } +} + +/** + * Implement 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_type_get_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' => '<div class="clearfix" id="poll-choice-wrapper">', + '#suffix' => '</div>', + ); + + // Container for just the poll choices. + $form['choice_wrapper']['choice'] = array( + '#prefix' => '<div id="poll-choices">', + '#suffix' => '</div>', + '#theme' => 'poll_choices', + ); + + // Add the current choices to the form. + $delta = 0; + $weight = 0; + if (isset($node->choice)) { + $delta = count($node->choice); + $weight = -$delta; + foreach ($node->choice as $chid => $choice) { + $key = 'chid:' . $chid; + $form['choice_wrapper']['choice'][$key] = _poll_choice_form($key, $choice['chid'], $choice['chtext'], $choice['chvotes'], $choice['weight'], $choice_count); + $weight = ($choice['weight'] > $weight) ? $choice['weight'] : $weight; + } + } + + // Add initial or additional choices. + $existing_delta = $delta; + for ($delta; $delta < $choice_count; $delta++) { + $key = 'new:' . ($delta - $existing_delta); + $form['choice_wrapper']['choice'][$key] = _poll_choice_form($key, NULL, '', 0, $weight, $choice_count); + } + + // We name our button 'poll_more' to avoid conflicts with other modules using + // AHAH-enabled buttons with the id 'more'. + $form['choice_wrapper']['poll_more'] = array( + '#type' => 'submit', + '#value' => t('More choices'), + '#description' => t("If the amount of boxes above isn't enough, click here to add more choices."), + '#weight' => 1, + '#submit' => array('poll_more_choices_submit'), // If no javascript action. + '#ahah' => array( + 'callback' => 'poll_choice_js', + 'wrapper' => 'poll-choices', + 'method' => 'replace', + 'effect' => 'fade', + ), + ); + + // Poll attributes + $duration = array(0 => t('Unlimited')) + drupal_map_assoc(array(86400, 172800, 345600, 604800, 1209600, 2419200, 4838400, 9676800, 31536000), "format_interval"); + $active = array(0 => t('Closed'), 1 => t('Active')); + + $form['settings'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#title' => t('Poll settings'), + '#weight' => -3, + '#access' => $admin, + ); + + $form['settings']['active'] = array( + '#type' => 'radios', + '#title' => t('Poll status'), + '#default_value' => isset($node->active) ? $node->active : 1, + '#options' => $active, + '#description' => t('When a poll is closed, visitors can no longer vote for it.'), + '#access' => $admin, + ); + $form['settings']['runtime'] = array( + '#type' => 'select', + '#title' => t('Poll duration'), + '#default_value' => isset($node->runtime) ? $node->runtime : 0, + '#options' => $duration, + '#description' => t('After this period, the poll will be closed automatically.'), + ); + + return $form; +} + +/** + * Submit handler to add more choices to a poll form. This handler is used when + * javascript is not available. It makes changes to the form state and the + * entire form is rebuilt during the page reload. + */ +function poll_more_choices_submit($form, &$form_state) { + // Set the form to rebuild and run submit handlers. + node_form_submit_build_node($form, $form_state); + + // Make the changes we want to the form state. + if ($form_state['values']['poll_more']) { + $n = $_GET['q'] == 'system/ahah' ? 1 : 5; + $form_state['choice_count'] = count($form_state['values']['choice']) + $n; + } +} + +/** + * Implement hook_submit(). + */ +function poll_node_form_submit(&$form, &$form_state) { + // Renumber fields + $form_state['values']['choice'] = array_values($form_state['values']['choice']); + $form_state['values']['teaser'] = poll_teaser((object)$form_state['values']); +} + +/** + * Implement hook_validate(). + */ +function poll_validate($node, $form) { + if (isset($node->title)) { + // Check for at least two options and validate amount of votes: + $realchoices = 0; + // Renumber fields + $node->choice = array_values($node->choice); + foreach ($node->choice as $i => $choice) { + if ($choice['chtext'] != '') { + $realchoices++; + } + if (isset($choice['chvotes']) && $choice['chvotes'] < 0) { + form_set_error("choice][$i][chvotes", t('Negative values are not allowed.')); + } + } + + if ($realchoices < 2) { + form_set_error("choice][$realchoices][chtext", t('You must fill in at least two choices.')); + } + } +} + +/** + * Implement hook_insert(). + */ +function poll_insert($node) { + if (!user_access('administer nodes')) { + // Make sure all votes are 0 initially + foreach ($node->choice as $i => $choice) { + $node->choice[$i]['chvotes'] = 0; + } + $node->active = 1; + } + + db_insert('poll') + ->fields(array( + 'nid' => $node->nid, + 'runtime' => $node->runtime, + 'active' => $node->active, + )) + ->execute(); + + foreach ($node->choice as $choice) { + if ($choice['chtext'] != '') { + db_insert('poll_choice') + ->fields(array( + 'nid' => $node->nid, + 'chtext' => $choice['chtext'], + 'chvotes' => $choice['chvotes'], + 'weight' => $choice['weight'], + )) + ->execute(); + } + } +} + +/** + * Implement hook_update(). + */ +function poll_update($node) { + // Update poll settings. + db_update('poll') + ->fields(array( + 'runtime' => $node->runtime, + 'active' => $node->active, + )) + ->condition('nid', $node->nid) + ->execute(); + + // Poll choices with empty titles signifies removal. We remove all votes to + // the removed options, so people who voted on them can vote again. + foreach ($node->choice as $key => $choice) { + if (!empty($choice['chtext'])) { + db_merge('poll_choice') + ->key(array('chid' => $choice['chid'])) + ->fields(array( + 'nid' => $node->nid, + 'chtext' => $choice['chtext'], + 'chvotes' => (int) $choice['chvotes'], + 'weight' => $choice['weight'], + )) + ->updateExcept('nid') + ->execute(); + } + else { + db_delete('poll_vote') + ->condition('nid', $node->nid) + ->condition('chid', $key) + ->execute(); + } + } +} + +/** + * Implement hook_delete(). + */ +function poll_delete($node) { + db_delete('poll') + ->condition('nid', $node->nid) + ->execute(); + db_delete('poll_choice') + ->condition('nid', $node->nid) + ->execute(); + db_delete('poll_vote') + ->condition('nid', $node->nid) + ->execute(); +} + +/** + * Implement hook_view(). + */ +function poll_view($node, $teaser = FALSE) { + global $user; + $output = ''; + + if (!empty($node->allowvotes) && empty($node->show_results)) { + $node->content['poll_view_voting'] = drupal_get_form('poll_view_voting', $node); + } + else { + $node->content['poll_view_results'] = array('#markup' => poll_view_results($node, $teaser)); + } + return $node; +} + Index: modules/poll/poll.registry.inc =================================================================== RCS file: modules/poll/poll.registry.inc diff -N modules/poll/poll.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/poll/poll.registry.inc 5 Jun 2009 21:45:06 -0000 @@ -0,0 +1,80 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Poll module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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), + ), + ); +} + +/** + * Implement hook_node_info(). + */ +function poll_node_info() { + return array( + 'poll' => array( + 'name' => t('Poll'), + 'base' => 'poll', + 'description' => t('A <em>poll</em> is a question with a set of possible responses. A <em>poll</em>, once created, automatically provides a simple running count of the number of votes received for each response.'), + 'title_label' => t('Question'), + 'has_body' => FALSE, + ) + ); +} + Index: modules/poll/poll.user.inc =================================================================== RCS file: modules/poll/poll.user.inc diff -N modules/poll/poll.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/poll/poll.user.inc 5 Jun 2009 21:45:07 -0000 @@ -0,0 +1,51 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Poll module. + */ + +/** + * Implement 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; +} + +/** + * Implement hook_user_cancel(). + */ +function poll_user_cancel($edit, $account, $method) { + switch ($method) { + case 'user_cancel_reassign': + db_update('poll_vote') + ->fields(array('uid' => 0)) + ->condition('uid', $account->uid) + ->execute(); + break; + + case 'user_cancel_delete': + db_delete('poll_vote') + ->condition('uid', $account->uid) + ->execute(); + break; + } +} + Index: modules/profile/profile.block.inc =================================================================== RCS file: modules/profile/profile.block.inc diff -N modules/profile/profile.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/profile/profile.block.inc 5 Jun 2009 21:45:05 -0000 @@ -0,0 +1,45 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Profile module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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 (:visibility) ORDER BY weight', array(':visibility' => array(PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS))); + foreach ($result as $record) { + $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 <a href="@profile-admin">profile field configuration</a> are available.', array('@profile-admin' => url('admin/user/profile'))), + ); + return $form; +} + +/** + * Implement hook_block_save(). + */ +function profile_block_save($delta = '', $edit = array()) { + variable_set('profile_block_author_fields', $edit['profile_block_author_fields']); +} + 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 5 Jun 2009 21:45:05 -0000 @@ -8,3 +8,6 @@ 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 Index: modules/profile/profile.module =================================================================== RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v retrieving revision 1.261 diff -u -p -r1.261 profile.module --- modules/profile/profile.module 3 Jun 2009 07:28:28 -0000 1.261 +++ modules/profile/profile.module 5 Jun 2009 21:45:54 -0000 @@ -49,120 +49,6 @@ function profile_help($path, $arg) { } /** - * Implement 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', - ) - ); -} - -/** - * Implement 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; -} - -/** - * Implement 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; -} - -/** - * Implement 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 (:visibility) ORDER BY weight', array(':visibility' => array(PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS))); - foreach ($result as $record) { - $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 <a href="@profile-admin">profile field configuration</a> are available.', array('@profile-admin' => url('admin/user/profile'))), - ); - return $form; -} - -/** - * Implement hook_block_save(). - */ -function profile_block_save($delta = '', $edit = array()) { - variable_set('profile_block_author_fields', $edit['profile_block_author_fields']); -} - -/** * Implement hook_block_view(). */ function profile_block_view($delta = '') { @@ -203,27 +89,6 @@ function profile_block_view($delta = '') } /** - * Implement hook_user_register(). - */ -function profile_user_register(&$edit, &$user, $category = NULL) { - return profile_form_profile($edit, $user, $category, TRUE); -} - -/** - * Implement hook_user_update(). - */ -function profile_user_update(&$edit, &$user, $category = NULL) { - return profile_save_profile($edit, $user, $category); -} - -/** - * Implement hook_user_insert(). - */ -function profile_user_insert(&$edit, &$user, $category = NULL) { - return profile_save_profile($edit, $user, $category, TRUE); -} - -/** * Implement hook_user_view(). */ function profile_user_view(&$edit, &$user, $category = NULL) { @@ -231,34 +96,6 @@ function profile_user_view(&$edit, &$use } /** - * Implement hook_user_form(). - */ -function profile_user_form(&$edit, &$user, $category = NULL) { - return profile_form_profile($edit, $user, $category); -} - -/** - * Implement hook_user_validate(). - */ -function profile_user_validate(&$edit, &$user, $category = NULL) { - return profile_validate_profile($edit, $category); -} - -/** - * Implement 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; - } -} - -/** * Implement hook_user_load(). */ function profile_user_load($users) { @@ -270,24 +107,6 @@ function profile_user_load($users) { } } -function profile_save_profile(&$edit, &$user, $category, $register = FALSE) { - $result = _profile_get_fields($category, $register); - foreach ($result as $field) { - if (_profile_field_serialize($field->type)) { - $edit[$field->name] = serialize($edit[$field->name]); - } - db_merge('profile_value') - ->key(array( - 'fid' => $field->fid, - 'uid' => $user->uid, - )) - ->fields(array('value' => $edit[$field->name])) - ->execute(); - // 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 +204,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(); - foreach ($result as $field) { - $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,41 +214,6 @@ function _profile_update_user_fields($fi return $fields; } -function profile_validate_profile($edit, $category) { - $result = _profile_get_fields($category); - foreach ($result as $field) { - 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; -} -/** - * Implement hook_user_categories(). - */ -function profile_user_categories() { - $result = db_query("SELECT DISTINCT(category) FROM {profile_field}"); - $data = array(); - foreach ($result as $category) { - $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 5 Jun 2009 21:45:05 -0000 @@ -0,0 +1,85 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Profile module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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 5 Jun 2009 21:45:54 -0000 @@ -0,0 +1,186 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Profile module. + */ + +/** + * Implement hook_user_register(). + */ +function profile_user_register(&$edit, &$user, $category = NULL) { + return profile_form_profile($edit, $user, $category, TRUE); +} + +/** + * Implement hook_user_update(). + */ +function profile_user_update(&$edit, &$user, $category = NULL) { + return profile_save_profile($edit, $user, $category); +} + +/** + * Implement hook_user_insert(). + */ +function profile_user_insert(&$edit, &$user, $category = NULL) { + return profile_save_profile($edit, $user, $category, TRUE); +} + +/** + * Implement hook_user_form(). + */ +function profile_user_form(&$edit, &$user, $category = NULL) { + return profile_form_profile($edit, $user, $category); +} + +/** + * Implement hook_user_validate(). + */ +function profile_user_validate(&$edit, &$user, $category = NULL) { + return profile_validate_profile($edit, $category); +} + +/** + * Implement 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; + } +} + +/** + * Implement hook_user_categories(). + */ +function profile_user_categories() { + $result = db_query("SELECT DISTINCT(category) FROM {profile_field}"); + $data = array(); + foreach ($result as $category) { + $data[] = array( + 'name' => $category->category, + 'title' => $category->category, + 'weight' => 3, + 'access callback' => 'profile_category_access', + 'access arguments' => array(1, $category->category) + ); + } + return $data; +} + +function profile_form_profile($edit, $user, $category, $register = FALSE) { + $result = _profile_get_fields($category, $register); + $weight = 1; + $fields = array(); + foreach ($result as $field) { + $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); + foreach ($result as $field) { + 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); + foreach ($result as $field) { + if (_profile_field_serialize($field->type)) { + $edit[$field->name] = serialize($edit[$field->name]); + } + db_merge('profile_value') + ->key(array( + 'fid' => $field->fid, + 'uid' => $user->uid, + )) + ->fields(array('value' => $edit[$field->name])) + ->execute(); + // Mark field as handled (prevents saving to user->data). + $edit[$field->name] = NULL; + } +} + 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 5 Jun 2009 21:45:04 -0000 @@ -0,0 +1,18 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Search module. + */ + +/** + * Implement hook_block_list(). + */ +function search_block_list() { + $blocks['form']['info'] = t('Search form'); + // Not worth caching. + $blocks['form']['cache'] = BLOCK_NO_CACHE; + return $blocks; +} + Index: modules/search/search.comment.inc =================================================================== RCS file: modules/search/search.comment.inc diff -N modules/search/search.comment.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/search/search.comment.inc 5 Jun 2009 21:45:04 -0000 @@ -0,0 +1,48 @@ +<?php +// $Id$ + +/** + * @file + * Comment hooks for Search module. + */ + +/** + * Implement hook_comment_insert(). + */ +function search_comment_insert($form_values) { + // Reindex the node when comments are added. + search_touch_node($form_values['nid']); +} + +/** + * Implement hook_comment_update(). + */ +function search_comment_update($form_values) { + // Reindex the node when comments are changed. + search_touch_node($form_values['nid']); +} + +/** + * Implement hook_comment_delete(). + */ +function search_comment_delete($comment) { + // Reindex the node when comments are deleted. + search_touch_node($comment->nid); +} + +/** + * Implement hook_comment_publish(). + */ +function search_comment_publish($comment) { + // Reindex the node when comments are published. + search_touch_node($comment->nid); +} + +/** + * Implement 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 5 Jun 2009 21:45:04 -0000 @@ -0,0 +1,23 @@ +<?php +// $Id$ + +/** + * @file + * Cron functionality for Search module. + */ + +/** + * Implement hook_cron(). + * + * Fires hook_update_index() in all modules and cleans up dirty words (see + * search_dirty). + */ +function search_cron() { + // We register a shutdown function to ensure that search_total is always up + // to date. + register_shutdown_function('search_update_totals'); + + // Update word index + module_invoke_all('update_index'); +} + Index: modules/search/search.form.inc =================================================================== RCS file: modules/search/search.form.inc diff -N modules/search/search.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/search/search.form.inc 5 Jun 2009 21:45:55 -0000 @@ -0,0 +1,57 @@ +<?php +// $Id$ + +/** + * @file + * + */ + +/** + * Render a search form. + * + * @param $action + * Form action. Defaults to "search". + * @param $keys + * The search string entered by the user, containing keywords for the search. + * @param $type + * The type of search to render the node for. Must be the name of module + * which implements hook_search(). Defaults to 'node'. + * @param $prompt + * A piece of text to put before the form (e.g. "Enter your keywords") + * @return + * An HTML string containing the search form. + */ +function search_form(&$form_state, $action = '', $keys = '', $type = NULL, $prompt = NULL) { + + // Add CSS + drupal_add_css(drupal_get_path('module', 'search') . '/search.css', array('preprocess' => 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' => '<div class="container-inline">', '#suffix' => '</div>'); + $form['basic']['inline']['keys'] = array( + '#type' => 'textfield', + '#title' => '', + '#default_value' => $keys, + '#size' => $prompt ? 40 : 20, + '#maxlength' => 255, + ); + // processed_keys is used to coordinate keyword passing between other forms + // that hook into the basic search form. + $form['basic']['inline']['processed_keys'] = array('#type' => 'value', '#value' => array()); + $form['basic']['inline']['submit'] = array('#type' => 'submit', '#value' => t('Search')); + + return $form; +} + Index: modules/search/search.info =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.info,v retrieving revision 1.8 diff -u -p -r1.8 search.info --- modules/search/search.info 11 Oct 2008 02:33:00 -0000 1.8 +++ modules/search/search.info 5 Jun 2009 21:45:55 -0000 @@ -8,3 +8,10 @@ files[] = search.module files[] = search.admin.inc files[] = search.pages.inc files[] = search.install +files[] = search.registry.inc +files[] = search.user.inc +files[] = search.block.inc +files[] = search.node.inc +files[] = search.comment.inc +files[] = search.cron.inc +files[] = search.form.inc Index: modules/search/search.module =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.module,v retrieving revision 1.298 diff -u -p -r1.298 search.module --- modules/search/search.module 3 Jun 2009 06:52:29 -0000 1.298 +++ modules/search/search.module 5 Jun 2009 21:45:55 -0000 @@ -112,65 +112,6 @@ function search_help($path, $arg) { } /** - * Implement hook_theme(). - */ -function search_theme() { - return array( - 'search_theme_form' => array( - 'arguments' => array('form' => NULL), - 'template' => 'search-theme-form', - ), - 'search_block_form' => array( - 'arguments' => array('form' => NULL), - 'template' => 'search-block-form', - ), - 'search_result' => array( - 'arguments' => array('result' => NULL, 'type' => NULL), - 'file' => 'search.pages.inc', - 'template' => 'search-result', - ), - 'search_results' => array( - 'arguments' => array('results' => NULL, 'type' => NULL), - 'file' => 'search.pages.inc', - 'template' => 'search-results', - ), - 'search_results_listing' => array( - 'arguments' => array('title' => NULL, 'content' => NULL), - ), - ); -} - -/** - * Implement hook_perm(). - */ -function search_perm() { - return array( - 'administer search' => array( - 'title' => t('Administer search'), - 'description' => t('Configure search administration settings.'), - ), - 'search content' => array( - 'title' => t('Search content'), - 'description' => t('Search website content.'), - ), - 'use advanced search' => array( - 'title' => t('Use advanced search'), - 'description' => t('Limit search results with additional criteria, such as specific content types. Could have performance implications.'), - ), - ); -} - -/** - * Implement hook_block_list(). - */ -function search_block_list() { - $blocks['form']['info'] = t('Search form'); - // Not worth caching. - $blocks['form']['cache'] = BLOCK_NO_CACHE; - return $blocks; -} - -/** * Implement hook_block_view(). */ function search_block_view($delta = '') { @@ -181,55 +122,6 @@ function search_block_view($delta = '') } } -/** - * Implement hook_menu(). - */ -function search_menu() { - $items['search'] = array( - 'title' => 'Search', - 'page callback' => 'search_view', - 'access arguments' => array('search content'), - 'type' => MENU_SUGGESTED_ITEM, - ); - $items['admin/settings/search'] = array( - 'title' => 'Search settings', - 'description' => 'Configure relevance settings for search and other indexing options', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('search_admin_settings'), - 'access arguments' => array('administer search'), - 'type' => MENU_NORMAL_ITEM, - ); - $items['admin/settings/search/wipe'] = array( - 'title' => 'Clear index', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('search_wipe_confirm'), - 'access arguments' => array('administer search'), - 'type' => MENU_CALLBACK, - ); - $items['admin/reports/search'] = array( - 'title' => 'Top search phrases', - 'description' => 'View most popular search phrases.', - 'page callback' => 'dblog_top', - 'page arguments' => array('search'), - 'access arguments' => array('access site reports'), - 'file path' => drupal_get_path('module', 'dblog'), - ); - - foreach (module_implements('search') as $module) { - $items['search/' . $module . '/%menu_tail'] = array( - 'title callback' => 'module_invoke', - 'title arguments' => array($module, 'search', 'name', TRUE), - 'page callback' => 'search_view', - 'page arguments' => array($module), - 'access callback' => '_search_menu', - 'access arguments' => array($module), - 'type' => MENU_LOCAL_TASK, - 'parent' => 'search', - ); - } - return $items; -} - function _search_menu($name) { return user_access('search content') && module_invoke($name, 'search', 'name'); } @@ -273,21 +165,6 @@ function search_dirty($word = NULL) { } /** - * Implement hook_cron(). - * - * Fires hook_update_index() in all modules and cleans up dirty words (see - * search_dirty). - */ -function search_cron() { - // We register a shutdown function to ensure that search_total is always up - // to date. - register_shutdown_function('search_update_totals'); - - // Update word index - module_invoke_all('update_index'); -} - -/** * This function is called on shutdown to ensure that search_total is always * up to date (even if cron times out or otherwise fails). */ @@ -640,70 +517,6 @@ function search_touch_node($nid) { } /** - * Implement hook_node_update_index(). - */ -function search_node_update_index($node) { - // Transplant links to a node into the target node. - $result = db_query("SELECT caption FROM {search_node_links} WHERE nid = %d", $node->nid); - $output = array(); - while ($link = db_fetch_object($result)) { - $output[] = $link->caption; - } - if (count($output)) { - return '<a>(' . implode(', ', $output) . ')</a>'; - } -} - -/** - * Implement hook_node_update(). - */ -function search_node_update($node) { - // Reindex the node when it is updated. The node is automatically indexed - // when it is added, simply by being added to the node table. - search_touch_node($node->nid); -} - -/** - * Implement hook_comment_insert(). - */ -function search_comment_insert($form_values) { - // Reindex the node when comments are added. - search_touch_node($form_values['nid']); -} - -/** - * Implement hook_comment_update(). - */ -function search_comment_update($form_values) { - // Reindex the node when comments are changed. - search_touch_node($form_values['nid']); -} - -/** - * Implement hook_comment_delete(). - */ -function search_comment_delete($comment) { - // Reindex the node when comments are deleted. - search_touch_node($comment->nid); -} - -/** - * Implement hook_comment_publish(). - */ -function search_comment_publish($comment) { - // Reindex the node when comments are published. - search_touch_node($comment->nid); -} - -/** - * Implement hook_comment_unpublish(). - */ -function search_comment_unpublish($comment) { - // Reindex the node when comments are unpublished. - search_touch_node($comment->nid); -} - -/** * Extract a module-specific search option from a search query. e.g. 'type:book' */ function search_query_extract($keys, $option) { @@ -1044,55 +857,6 @@ function search_get_keys() { */ /** - * Render a search form. - * - * @param $action - * Form action. Defaults to "search". - * @param $keys - * The search string entered by the user, containing keywords for the search. - * @param $type - * The type of search to render the node for. Must be the name of module - * which implements hook_search(). Defaults to 'node'. - * @param $prompt - * A piece of text to put before the form (e.g. "Enter your keywords") - * @return - * An HTML string containing the search form. - */ -function search_form(&$form_state, $action = '', $keys = '', $type = NULL, $prompt = NULL) { - - // Add CSS - drupal_add_css(drupal_get_path('module', 'search') . '/search.css', array('preprocess' => 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' => '<div class="container-inline">', '#suffix' => '</div>'); - $form['basic']['inline']['keys'] = array( - '#type' => 'textfield', - '#title' => '', - '#default_value' => $keys, - '#size' => $prompt ? 40 : 20, - '#maxlength' => 255, - ); - // processed_keys is used to coordinate keyword passing between other forms - // that hook into the basic search form. - $form['basic']['inline']['processed_keys'] = array('#type' => 'value', '#value' => array()); - $form['basic']['inline']['submit'] = array('#type' => 'submit', '#value' => t('Search')); - - return $form; -} - -/** * Form builder; Output a search form for the search block and the theme's search box. * * @ingroup forms Index: modules/search/search.node.inc =================================================================== RCS file: modules/search/search.node.inc diff -N modules/search/search.node.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/search/search.node.inc 5 Jun 2009 21:45:04 -0000 @@ -0,0 +1,32 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Search module. + */ + +/** + * Implement hook_node_update_index(). + */ +function search_node_update_index($node) { + // Transplant links to a node into the target node. + $result = db_query("SELECT caption FROM {search_node_links} WHERE nid = %d", $node->nid); + $output = array(); + while ($link = db_fetch_object($result)) { + $output[] = $link->caption; + } + if (count($output)) { + return '<a>(' . implode(', ', $output) . ')</a>'; + } +} + +/** + * Implement hook_node_update(). + */ +function search_node_update($node) { + // Reindex the node when it is updated. The node is automatically indexed + // when it is added, simply by being added to the node table. + search_touch_node($node->nid); +} + Index: modules/search/search.registry.inc =================================================================== RCS file: modules/search/search.registry.inc diff -N modules/search/search.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/search/search.registry.inc 5 Jun 2009 21:45:03 -0000 @@ -0,0 +1,86 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Search module. + */ + +/** + * Implement hook_menu(). + */ +function search_menu() { + $items['search'] = array( + 'title' => 'Search', + 'page callback' => 'search_view', + 'access arguments' => array('search content'), + 'type' => MENU_SUGGESTED_ITEM, + ); + $items['admin/settings/search'] = array( + 'title' => 'Search settings', + 'description' => 'Configure relevance settings for search and other indexing options', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('search_admin_settings'), + 'access arguments' => array('administer search'), + 'type' => MENU_NORMAL_ITEM, + ); + $items['admin/settings/search/wipe'] = array( + 'title' => 'Clear index', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('search_wipe_confirm'), + 'access arguments' => array('administer search'), + 'type' => MENU_CALLBACK, + ); + $items['admin/reports/search'] = array( + 'title' => 'Top search phrases', + 'description' => 'View most popular search phrases.', + 'page callback' => 'dblog_top', + 'page arguments' => array('search'), + 'access arguments' => array('access site reports'), + 'file path' => drupal_get_path('module', 'dblog'), + ); + + foreach (module_implements('search') as $module) { + $items['search/' . $module . '/%menu_tail'] = array( + 'title callback' => 'module_invoke', + 'title arguments' => array($module, 'search', 'name', TRUE), + 'page callback' => 'search_view', + 'page arguments' => array($module), + 'access callback' => '_search_menu', + 'access arguments' => array($module), + 'type' => MENU_LOCAL_TASK, + 'parent' => 'search', + ); + } + return $items; +} + +/** + * Implement hook_theme(). + */ +function search_theme() { + return array( + 'search_theme_form' => array( + 'arguments' => array('form' => NULL), + 'template' => 'search-theme-form', + ), + 'search_block_form' => array( + 'arguments' => array('form' => NULL), + 'template' => 'search-block-form', + ), + 'search_result' => array( + 'arguments' => array('result' => NULL, 'type' => NULL), + 'file' => 'search.pages.inc', + 'template' => 'search-result', + ), + 'search_results' => array( + 'arguments' => array('results' => NULL, 'type' => NULL), + 'file' => 'search.pages.inc', + 'template' => 'search-results', + ), + 'search_results_listing' => array( + 'arguments' => array('title' => NULL, 'content' => NULL), + ), + ); +} + Index: modules/search/search.user.inc =================================================================== RCS file: modules/search/search.user.inc diff -N modules/search/search.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/search/search.user.inc 5 Jun 2009 21:45:03 -0000 @@ -0,0 +1,28 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Search module. + */ + +/** + * Implement hook_perm(). + */ +function search_perm() { + return array( + 'administer search' => array( + 'title' => t('Administer search'), + 'description' => t('Configure search administration settings.'), + ), + 'search content' => array( + 'title' => t('Search content'), + 'description' => t('Search website content.'), + ), + 'use advanced search' => array( + 'title' => t('Use advanced search'), + 'description' => t('Limit search results with additional criteria, such as specific content types. Could have performance implications.'), + ), + ); +} + 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 5 Jun 2009 21:45:02 -0000 @@ -7,3 +7,5 @@ core = 7.x files[] = simpletest.module files[] = simpletest.pages.inc files[] = simpletest.install +files[] = simpletest.registry.inc +files[] = simpletest.user.inc Index: modules/simpletest/simpletest.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.module,v retrieving revision 1.52 diff -u -p -r1.52 simpletest.module --- modules/simpletest/simpletest.module 30 May 2009 11:17:32 -0000 1.52 +++ modules/simpletest/simpletest.module 5 Jun 2009 21:45:02 -0000 @@ -22,56 +22,6 @@ function simpletest_help($path, $arg) { } /** - * Implement hook_menu(). - */ -function simpletest_menu() { - $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; -} - -/** - * Implement 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.'))), - ), - ); -} - -/** - * Implement 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', - ), - ); -} - -/** * Implement 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 5 Jun 2009 21:45:02 -0000 @@ -0,0 +1,46 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Simpletest module. + */ + +/** + * Implement hook_menu(). + */ +function simpletest_menu() { + $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; +} + +/** + * Implement 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 5 Jun 2009 21:45:02 -0000 @@ -0,0 +1,20 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Simpletest module. + */ + +/** + * Implement 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.'))), + ), + ); +} + 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 5 Jun 2009 21:44:59 -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.9 diff -u -p -r1.9 database_test.module --- modules/simpletest/tests/database_test.module 27 May 2009 18:34:00 -0000 1.9 +++ modules/simpletest/tests/database_test.module 5 Jun 2009 21:44:59 -0000 @@ -41,34 +41,6 @@ function database_test_query_database_te } /** - * Implement 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 5 Jun 2009 21:44:59 -0000 @@ -0,0 +1,36 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Database_test module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:00 -0000 @@ -0,0 +1,95 @@ +<?php +// $Id$ + +/** + * @file + * Field hooks for Field_test module. + */ + +/** + * Implement 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'), + ), + ); +} + +/** + * Implement 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'])), + ); + } + } +} + +/** + * Implement 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; +} + +/** + * Implement 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 5 Jun 2009 21:45:00 -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.9 diff -u -p -r1.9 field_test.module --- modules/simpletest/tests/field_test.module 27 May 2009 18:34:00 -0000 1.9 +++ modules/simpletest/tests/field_test.module 5 Jun 2009 21:45:00 -0000 @@ -5,52 +5,6 @@ define('FIELD_TEST_ELEMENT_ID', 1); define('FIELD_TEST_BUNDLE', 'test_bundle'); /** - * Implement 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; -} - -/** - * Implement 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 } /** - * Implement 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,63 +240,6 @@ function field_test_entity_form_submit_b */ /** - * Implement 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', - ), - ); -} - -/** - * Implement 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'), - ), - ); -} - -/** - * Implement 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'])), - ); - } - } -} - -/** * Implement hook_field_sanitize(). */ function field_test_field_sanitize($obj_type, $object, $field, $instance, &$items) { @@ -400,120 +257,6 @@ function field_test_field_is_empty($item } /** - * Implement 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, - ), - ), - ); -} - -/** - * Implement 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; -} - -/** - * Implement hook_field_widget_error(). - */ -function field_test_field_widget_error($element, $error) { - form_error($element['value'], $error['message']); -} - -/** - * Implement 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, - ), - ), - ); -} - -/** * Implement hook_field_load(). */ function field_test_field_load($obj_type, $objects, $field, $instances, &$items, $age) { @@ -532,20 +275,6 @@ function field_test_field_load($obj_type } /** - * Implement 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 5 Jun 2009 21:44:59 -0000 @@ -0,0 +1,175 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Field_test module. + */ + +/** + * Implement 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; +} + + +/** + * Implement 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, + ), + ); +} + +/** + * Implement 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; +} + +/** + * Implement 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', + ), + ); +} + +/** + * Implement 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, + ), + ), + ); +} + +/** + * Implement 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 5 Jun 2009 21:44:59 -0000 @@ -0,0 +1,25 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Field_test module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:00 -0000 @@ -0,0 +1,66 @@ +<?php +// $Id$ + +/** + * @file + * File hooks for File_test module. + */ + +/** + * Implement hook_file_validate(). + */ +function file_test_file_validate($file) { + _file_test_log_call('validate', array($file)); + return _file_test_get_return('validate'); +} + +/** + * Implement hook_file_download(). + */ +function file_test_file_download($file) { + _file_test_log_call('download', array($file)); + return _file_test_get_return('download'); +} + +/** + * Implement hook_file_references(). + */ +function file_test_file_references($file) { + _file_test_log_call('references', array($file)); + return _file_test_get_return('references'); +} + +/** + * Implement hook_file_insert(). + */ +function file_test_file_insert($file) { + _file_test_log_call('insert', array($file)); +} + +/** + * Implement hook_file_update(). + */ +function file_test_file_update($file) { + _file_test_log_call('update', array($file)); +} + +/** + * Implement hook_file_copy(). + */ +function file_test_file_copy($file, $source) { + _file_test_log_call('copy', array($file, $source)); +} + +/** + * Implement hook_file_move(). + */ +function file_test_file_move($file, $source) { + _file_test_log_call('move', array($file, $source)); +} + +/** + * Implement hook_file_delete(). + */ +function file_test_file_delete($file) { + _file_test_log_call('delete', array($file)); +} Index: modules/simpletest/tests/file_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/file_test.info,v retrieving revision 1.1 diff -u -p -r1.1 file_test.info --- modules/simpletest/tests/file_test.info 20 Sep 2008 07:35:53 -0000 1.1 +++ modules/simpletest/tests/file_test.info 5 Jun 2009 21:45:00 -0000 @@ -6,3 +6,5 @@ version = VERSION core = 7.x files[] = file_test.module hidden = TRUE +files[] = file_test.registry.inc +files[] = file_test.file.inc Index: modules/simpletest/tests/file_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/file_test.module,v retrieving revision 1.10 diff -u -p -r1.10 file_test.module --- modules/simpletest/tests/file_test.module 27 May 2009 18:34:00 -0000 1.10 +++ modules/simpletest/tests/file_test.module 5 Jun 2009 21:45:00 -0000 @@ -10,20 +10,6 @@ */ /** - * Implement hook_menu(). - */ -function file_test_menu() { - $items['file-test/upload'] = array( - 'title' => 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) { @@ -180,61 +166,3 @@ function file_test_file_load($files) { } } -/** - * Implement hook_file_validate(). - */ -function file_test_file_validate($file) { - _file_test_log_call('validate', array($file)); - return _file_test_get_return('validate'); -} - -/** - * Implement hook_file_download(). - */ -function file_test_file_download($file) { - _file_test_log_call('download', array($file)); - return _file_test_get_return('download'); -} - -/** - * Implement hook_file_references(). - */ -function file_test_file_references($file) { - _file_test_log_call('references', array($file)); - return _file_test_get_return('references'); -} - -/** - * Implement hook_file_insert(). - */ -function file_test_file_insert($file) { - _file_test_log_call('insert', array($file)); -} - -/** - * Implement hook_file_update(). - */ -function file_test_file_update($file) { - _file_test_log_call('update', array($file)); -} - -/** - * Implement hook_file_copy(). - */ -function file_test_file_copy($file, $source) { - _file_test_log_call('copy', array($file, $source)); -} - -/** - * Implement hook_file_move(). - */ -function file_test_file_move($file, $source) { - _file_test_log_call('move', array($file, $source)); -} - -/** - * Implement 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 5 Jun 2009 21:45:00 -0000 @@ -0,0 +1,22 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for File_test module. + */ + +/** + * Implement hook_menu(). + */ +function file_test_menu() { + $items['file-test/upload'] = array( + 'title' => 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 5 Jun 2009 21:45:00 -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.7 diff -u -p -r1.7 form_test.module --- modules/simpletest/tests/form_test.module 27 May 2009 18:34:00 -0000 1.7 +++ modules/simpletest/tests/form_test.module 5 Jun 2009 21:45:00 -0000 @@ -7,69 +7,6 @@ */ /** - * Implement 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 5 Jun 2009 21:45:00 -0000 @@ -0,0 +1,71 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Form_test module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:01 -0000 @@ -0,0 +1,24 @@ +<?php +// $Id$ + +/** + * @file + * File hooks for Image_test module. + */ + +/** + * Implement 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, + ), + ); +} + 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 5 Jun 2009 21:45:01 -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.3 diff -u -p -r1.3 image_test.module --- modules/simpletest/tests/image_test.module 27 May 2009 18:34:00 -0000 1.3 +++ modules/simpletest/tests/image_test.module 5 Jun 2009 21:45:01 -0000 @@ -7,22 +7,6 @@ */ /** - * Implement 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 5 Jun 2009 21:45:01 -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.5 diff -u -p -r1.5 menu_test.module --- modules/simpletest/tests/menu_test.module 27 May 2009 18:34:00 -0000 1.5 +++ modules/simpletest/tests/menu_test.module 5 Jun 2009 21:45:01 -0000 @@ -7,47 +7,6 @@ */ /** - * Implement 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 5 Jun 2009 21:45:01 -0000 @@ -0,0 +1,49 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Menu_test module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:01 -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.8 diff -u -p -r1.8 session_test.module --- modules/simpletest/tests/session_test.module 2 Jun 2009 06:58:17 -0000 1.8 +++ modules/simpletest/tests/session_test.module 5 Jun 2009 21:45:01 -0000 @@ -2,52 +2,6 @@ // $Id: session_test.module,v 1.8 2009/06/02 06:58:17 dries Exp $ /** - * Implement 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() { @@ -118,14 +72,3 @@ function _session_test_set_not_started() } } -/** - * Implement 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 5 Jun 2009 21:45:01 -0000 @@ -0,0 +1,54 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Session_test module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:45:01 -0000 @@ -0,0 +1,19 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Session_test module. + */ + +/** + * Implement 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/system_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/system_test.info,v retrieving revision 1.3 diff -u -p -r1.3 system_test.info --- modules/simpletest/tests/system_test.info 24 Oct 2008 23:32:44 -0000 1.3 +++ modules/simpletest/tests/system_test.info 5 Jun 2009 21:45:01 -0000 @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = system_test.module hidden = TRUE +files[] = system_test.registry.inc Index: modules/simpletest/tests/system_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/system_test.module,v retrieving revision 1.11 diff -u -p -r1.11 system_test.module --- modules/simpletest/tests/system_test.module 27 May 2009 18:34:00 -0000 1.11 +++ modules/simpletest/tests/system_test.module 5 Jun 2009 21:45:01 -0000 @@ -1,61 +1,6 @@ <?php // $Id: system_test.module,v 1.11 2009/05/27 18:34:00 dries Exp $ -/** - * Implement hook_menu(). - */ -function system_test_menu() { - $items['system-test/auth'] = array( - 'page callback' => '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() { } /** - * Implement hook_modules_installed(). - */ -function system_test_modules_installed($modules) { - if (in_array('aggregator', $modules)) { - drupal_set_message(t('hook_modules_installed fired for aggregator')); - } -} - -/** - * Implement hook_modules_enabled(). - */ -function system_test_modules_enabled($modules) { - if (in_array('aggregator', $modules)) { - drupal_set_message(t('hook_modules_enabled fired for aggregator')); - } -} - -/** - * Implement hook_modules_disabled(). - */ -function system_test_modules_disabled($modules) { - if (in_array('aggregator', $modules)) { - drupal_set_message(t('hook_modules_disabled fired for aggregator')); - } -} - -/** - * Implement hook_modules_uninstalled(). - */ -function system_test_modules_uninstalled($modules) { - if (in_array('aggregator', $modules)) { - drupal_set_message(t('hook_modules_uninstalled fired for aggregator')); - } -} - -/** * Implement 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 5 Jun 2009 21:45:01 -0000 @@ -0,0 +1,99 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for System_test module. + */ + +/** + * Implement hook_menu(). + */ +function system_test_menu() { + $items['system-test/auth'] = array( + 'page callback' => '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; +} + +/** + * Implement hook_modules_installed(). + */ +function system_test_modules_installed($modules) { + if (in_array('aggregator', $modules)) { + drupal_set_message(t('hook_modules_installed fired for aggregator')); + } +} + +/** + * Implement hook_modules_enabled(). + */ +function system_test_modules_enabled($modules) { + if (in_array('aggregator', $modules)) { + drupal_set_message(t('hook_modules_enabled fired for aggregator')); + } +} + +/** + * Implement hook_modules_disabled(). + */ +function system_test_modules_disabled($modules) { + if (in_array('aggregator', $modules)) { + drupal_set_message(t('hook_modules_disabled fired for aggregator')); + } +} + +/** + * Implement 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 5 Jun 2009 21:45:01 -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.5 diff -u -p -r1.5 taxonomy_test.module --- modules/simpletest/tests/taxonomy_test.module 30 May 2009 11:17:32 -0000 1.5 +++ modules/simpletest/tests/taxonomy_test.module 5 Jun 2009 21:45:01 -0000 @@ -16,52 +16,6 @@ function taxonomy_test_taxonomy_term_loa } /** - * Implement 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(); - } - } - } -} - -/** - * Implement 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(); - } - } - } -} - -/** - * Implement hook_taxonomy_term_delete(). - */ -function taxonomy_test_taxonomy_term_delete($term) { - db_delete('term_antonym') - ->condition('tid', $term->tid) - ->execute(); -} - -/** * Implement 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 5 Jun 2009 21:45:01 -0000 @@ -0,0 +1,54 @@ +<?php +// $Id$ + +/** + * @file + * Taxonomy hooks for Taxonomy_test module. + */ + +/** + * Implement 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(); + } + } + } +} + +/** + * Implement 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(); + } + } + } +} + +/** + * Implement 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 5 Jun 2009 21:45:01 -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.4 diff -u -p -r1.4 xmlrpc_test.module --- modules/simpletest/tests/xmlrpc_test.module 27 May 2009 18:34:00 -0000 1.4 +++ modules/simpletest/tests/xmlrpc_test.module 5 Jun 2009 21:45:01 -0000 @@ -47,23 +47,6 @@ function xmlrpc_test_simpleStructReturnT } /** - * Implement 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 5 Jun 2009 21:45:01 -0000 @@ -0,0 +1,25 @@ +<?php +// $Id$ + +/** + * @file + * XML-RPC hooks for Xmlrpc_test module. + */ + +/** + * Implement 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', + ); +} + 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 5 Jun 2009 21:44:58 -0000 @@ -0,0 +1,41 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for Statistics module. + */ + +/** + * Implement 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; + } +} + +/** + * Implement 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; +} + +/** + * Implement 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 5 Jun 2009 21:44:58 -0000 @@ -0,0 +1,28 @@ +<?php +// $Id$ + +/** + * @file + * Cron functionality for Statistics module. + */ + +/** + * Implement 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(); +} + 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 5 Jun 2009 21:44:58 -0000 @@ -8,3 +8,9 @@ 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 Index: modules/statistics/statistics.module =================================================================== RCS file: /cvs/drupal/drupal/modules/statistics/statistics.module,v retrieving revision 1.304 diff -u -p -r1.304 statistics.module --- modules/statistics/statistics.module 27 May 2009 18:34:01 -0000 1.304 +++ modules/statistics/statistics.module 5 Jun 2009 21:44:58 -0000 @@ -81,26 +81,6 @@ function statistics_exit() { } /** - * Implement 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.'), - ), - ); -} - -/** * Implement hook_node_view(). */ function statistics_node_view($node, $teaser) { @@ -121,111 +101,6 @@ function statistics_node_view($node, $te } /** - * Implement 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; -} - -/** - * Implement 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; - } -} - -/** - * Implement 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 +158,6 @@ function statistics_get($nid) { } /** - * Implement 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; - } -} - -/** - * Implement 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; -} - -/** - * Implement 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']); -} - -/** * Implement hook_block_view(). */ function statistics_block_view($delta = '') { @@ -363,33 +205,6 @@ function _statistics_format_item($title, } /** - * Implement 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(); -} - -/** - * Implement 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)), - ), - ); - } -} - -/** * Implement hook_update_index(). */ function statistics_update_index() { 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 5 Jun 2009 21:44:58 -0000 @@ -0,0 +1,18 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Statistics module. + */ + +/** + * Implement 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(); +} + 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 5 Jun 2009 21:44:58 -0000 @@ -0,0 +1,73 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Statistics module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:44:58 -0000 @@ -0,0 +1,25 @@ +<?php +// $Id$ + +/** + * @file + * Search hooks for Statistics module. + */ + +/** + * Implement 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)), + ), + ); + } +} + 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 5 Jun 2009 21:44:58 -0000 @@ -0,0 +1,48 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Statistics module. + */ + +/** + * Implement 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.'), + ), + ); +} + +/** + * Implement 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 5 Jun 2009 21:44:58 -0000 @@ -0,0 +1,23 @@ +<?php +// $Id$ + +/** + * @file + * Form alter hooks for specific forms for Syslog module. + */ + +/** + * Implement 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 <a href="@syslog_help">Syslog help</a>.', array( + '@syslog_help' => url('admin/help/syslog'))), + ); + $form['buttons']['#weight'] = 1; +} + 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 5 Jun 2009 21:44:58 -0000 @@ -5,3 +5,6 @@ package = Core version = VERSION core = 7.x files[] = syslog.module +files[] = syslog.registry.inc +files[] = syslog.form.inc +files[] = syslog.watchdog.inc Index: modules/syslog/syslog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/syslog/syslog.module,v retrieving revision 1.23 diff -u -p -r1.23 syslog.module --- modules/syslog/syslog.module 27 May 2009 18:34:01 -0000 1.23 +++ modules/syslog/syslog.module 5 Jun 2009 21:44:58 -0000 @@ -26,21 +26,6 @@ function syslog_help($path, $arg) { } } -/** - * Implement 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 <a href="@syslog_help">Syslog help</a>.', 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 +46,6 @@ function syslog_facility_list() { } /** - * Implement 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 5 Jun 2009 21:44:57 -0000 @@ -0,0 +1,16 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Syslog module. + */ + +function syslog_theme() { + return array( + 'syslog_format' => 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 5 Jun 2009 21:44:58 -0000 @@ -0,0 +1,22 @@ +<?php +// $Id$ + +/** + * @file + * Watchdog functionality for Syslog module. + */ + +/** + * Implement 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)); +} + Index: modules/system/system.actions.inc =================================================================== RCS file: modules/system/system.actions.inc diff -N modules/system/system.actions.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/system/system.actions.inc 5 Jun 2009 21:44:56 -0000 @@ -0,0 +1,525 @@ +<?php +// $Id$ + +/** + * @file + * Action hooks for System module. + */ + +/** + * Menu callback. Display an overview of available and configured actions. + */ +function system_actions_manage() { + 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')); + } + $build['system_actions_header'] = array('#markup' => '<h3>' . t('Actions available to Drupal:') . '</h3>'); + $build['system_actions_table'] = array('#markup' => theme('table', $header, $row)); + } + + if ($actions_map) { + $build['system_actions_manage_form'] = drupal_get_form('system_actions_manage_form', $options); + } + + return $build; +} + +/** + * Define the form for the actions overview page. + * + * @see system_actions_manage_form_submit() + * @ingroup forms + * @param $form_state + * An associative array containing the current state of the form; not used. + * @param $options + * An array of configurable actions. + * @return + * Form definition. + */ +function system_actions_manage_form($form_state, $options = array()) { + $form['parent'] = array( + '#type' => 'fieldset', + '#title' => t('Make a new advanced action available'), + '#prefix' => '<div class="container-inline">', + '#suffix' => '</div>', + ); + $form['parent']['action'] = array( + '#type' => 'select', + '#default_value' => '', + '#options' => $options, + '#description' => '', + ); + $form['parent']['buttons']['submit'] = array( + '#type' => 'submit', + '#value' => t('Create'), + ); + return $form; +} + +/** + * Process system_actions_manage form submissions. + */ +function system_actions_manage_form_submit($form, &$form_state) { + if ($form_state['values']['action']) { + $form_state['redirect'] = 'admin/settings/actions/configure/' . $form_state['values']['action']; + } +} + +/** + * Menu callback. Create the form for configuration of a single action. + * + * We provide the "Description" field. The rest of the form + * is provided by the action. We then provide the Save button. + * Because we are combining unknown form elements with the action + * configuration form, we use actions_ prefix on our elements. + * + * @see system_actions_configure_validate() + * @see system_actions_configure_submit() + * @param $action + * md5 hash of action ID or an integer. If it's an md5 hash, we + * are creating a new instance. If it's an integer, we're editing + * an existing instance. + * @return + * Form definition. + */ +function system_actions_configure($form_state, $action = NULL) { + if ($action === NULL) { + drupal_goto('admin/settings/actions'); + } + + $actions_map = actions_actions_map(actions_list()); + $edit = array(); + + // Numeric action denotes saved instance of a configurable action; + // else we are creating a new action instance. + if (is_numeric($action)) { + $aid = $action; + // Load stored parameter values from database. + $data = db_query("SELECT * FROM {actions} WHERE aid = :aid", array(':aid' => $aid))->fetch(); + $edit['actions_description'] = $data->description; + $edit['actions_type'] = $data->type; + $function = $data->callback; + $action = md5($data->callback); + $params = unserialize($data->parameters); + if ($params) { + foreach ($params as $name => $val) { + $edit[$name] = $val; + } + } + } + else { + $function = $actions_map[$action]['callback']; + $edit['actions_description'] = $actions_map[$action]['description']; + $edit['actions_type'] = $actions_map[$action]['type']; + } + + $form['actions_description'] = array( + '#type' => 'textfield', + '#title' => t('Description'), + '#default_value' => $edit['actions_description'], + '#maxlength' => '255', + '#description' => t('A unique description for this advanced action. This description will be displayed in the interface of modules that integrate with actions, such as Trigger module.'), + '#weight' => -10 + ); + $action_form = $function . '_form'; + $form = array_merge($form, $action_form($edit)); + $form['actions_type'] = array( + '#type' => 'value', + '#value' => $edit['actions_type'], + ); + $form['actions_action'] = array( + '#type' => 'hidden', + '#value' => $action, + ); + // $aid is set when configuring an existing action instance. + if (isset($aid)) { + $form['actions_aid'] = array( + '#type' => 'hidden', + '#value' => $aid, + ); + } + $form['actions_configured'] = array( + '#type' => 'hidden', + '#value' => '1', + ); + $form['buttons']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save'), + '#weight' => 13 + ); + + return $form; +} + +/** + * Validate system_actions_configure form submissions. + */ +function system_actions_configure_validate($form, $form_state) { + $function = actions_function_lookup($form_state['values']['actions_action']) . '_validate'; + // Hand off validation to the action. + if (drupal_function_exists($function)) { + $function($form, $form_state); + } +} + +/** + * Process system_actions_configure form submissions. + */ +function system_actions_configure_submit($form, &$form_state) { + $function = actions_function_lookup($form_state['values']['actions_action']); + $submit_function = $function . '_submit'; + + // Action will return keyed array of values to store. + $params = $submit_function($form, $form_state); + $aid = isset($form_state['values']['actions_aid']) ? $form_state['values']['actions_aid'] : NULL; + + actions_save($function, $form_state['values']['actions_type'], $params, $form_state['values']['actions_description'], $aid); + drupal_set_message(t('The action has been successfully saved.')); + + $form_state['redirect'] = 'admin/settings/actions/manage'; +} + +/** + * Create the form for confirmation of deleting an action. + * + * @ingroup forms + * @see system_actions_delete_form_submit() + */ +function system_actions_delete_form($form_state, $action) { + + $form['aid'] = array( + '#type' => 'hidden', + '#value' => $action->aid, + ); + return confirm_form($form, + t('Are you sure you want to delete the action %action?', array('%action' => $action->description)), + 'admin/settings/actions/manage', + t('This cannot be undone.'), + t('Delete'), t('Cancel') + ); +} + +/** + * Process system_actions_delete form submissions. + * + * Post-deletion operations for action deletion. + */ +function system_actions_delete_form_submit($form, &$form_state) { + $aid = $form_state['values']['aid']; + $action = actions_load($aid); + actions_delete($aid); + $description = check_plain($action->description); + watchdog('user', 'Deleted action %aid (%action)', array('%aid' => $aid, '%action' => $description)); + drupal_set_message(t('Action %action was deleted', array('%action' => $description))); + $form_state['redirect'] = 'admin/settings/actions/manage'; +} + +/** + * Post-deletion operations for deleting action orphans. + * + * @param $orphaned + * An array of orphaned actions. + */ +function system_action_delete_orphans_post($orphaned) { + foreach ($orphaned as $callback) { + drupal_set_message(t("Deleted orphaned action (%action).", array('%action' => $callback))); + } +} + +/** + * Remove actions that are in the database but not supported by any enabled module. + */ +function system_actions_remove_orphans() { + actions_synchronize(TRUE); + drupal_goto('admin/settings/actions/manage'); +} + +/** + * Return a form definition so the Send email action can be configured. + * + * @see system_send_email_action_validate() + * @see system_send_email_action_submit() + * @param $context + * Default values (if we are editing an existing action instance). + * @return + * Form definition. + */ +function system_send_email_action_form($context) { + // Set default values for form. + if (!isset($context['recipient'])) { + $context['recipient'] = ''; + } + if (!isset($context['subject'])) { + $context['subject'] = ''; + } + if (!isset($context['message'])) { + $context['message'] = ''; + } + + $form['recipient'] = array( + '#type' => 'textfield', + '#title' => t('Recipient'), + '#default_value' => $context['recipient'], + '#maxlength' => '254', + '#description' => t('The email address to which the message should be sent OR enter %author if you would like to send an e-mail to the author of the original post.', array('%author' => '%author')), + ); + $form['subject'] = array( + '#type' => 'textfield', + '#title' => t('Subject'), + '#default_value' => $context['subject'], + '#maxlength' => '254', + '#description' => t('The subject of the message.'), + ); + $form['message'] = array( + '#type' => 'textarea', + '#title' => t('Message'), + '#default_value' => $context['message'], + '#cols' => '80', + '#rows' => '20', + '#description' => t('The message that should be sent. You may include the following variables: %site_name, %username, %node_url, %node_type, %title, %teaser, %body, %term_name, %term_description, %term_id, %vocabulary_name, %vocabulary_description, %vocabulary_id. Not all variables will be available in all contexts.'), + ); + return $form; +} + +/** + * Validate system_send_email_action form submissions. + */ +function system_send_email_action_validate($form, $form_state) { + $form_values = $form_state['values']; + // Validate the configuration form. + if (!valid_email_address($form_values['recipient']) && $form_values['recipient'] != '%author') { + // We want the literal %author placeholder to be emphasized in the error message. + form_set_error('recipient', t('Please enter a valid email address or %author.', array('%author' => '%author'))); + } +} + +/** + * Process system_send_email_action form submissions. + */ +function system_send_email_action_submit($form, $form_state) { + $form_values = $form_state['values']; + // Process the HTML form to store configuration. The keyed array that + // we return will be serialized to the database. + $params = array( + 'recipient' => $form_values['recipient'], + 'subject' => $form_values['subject'], + 'message' => $form_values['message'], + ); + return $params; +} + +/** + * Implement a configurable Drupal action. Sends an email. + */ +function system_send_email_action($object, $context) { + global $user; + + switch ($context['hook']) { + case 'node': + // Because this is not an action of type 'node' the node + // will not be passed as $object, but it will still be available + // in $context. + $node = $context['node']; + break; + // The comment hook provides nid, in $context. + case 'comment': + $comment = $context['comment']; + $node = node_load($comment->nid); + break; + case 'user': + // Because this is not an action of type 'user' the user + // object is not passed as $object, but it will still be available + // in $context. + $account = $context['account']; + if (isset($context['node'])) { + $node = $context['node']; + } + elseif ($context['recipient'] == '%author') { + // If we don't have a node, we don't have a node author. + watchdog('error', 'Cannot use %author token in this context.'); + return; + } + break; + default: + // We are being called directly. + $node = $object; + } + + $recipient = $context['recipient']; + + if (isset($node)) { + if (!isset($account)) { + $account = user_load($node->uid); + } + if ($recipient == '%author') { + $recipient = $account->mail; + } + } + + if (!isset($account)) { + $account = $user; + + } + $language = user_preferred_language($account); + $params = array('account' => $account, 'object' => $object, 'context' => $context); + if (isset($node)) { + $params['node'] = $node; + } + + if (drupal_mail('system', 'action_send_email', $recipient, $language, $params)) { + watchdog('action', 'Sent email to %recipient', array('%recipient' => $recipient)); + } + else { + watchdog('error', 'Unable to send email to %recipient', array('%recipient' => $recipient)); + } +} + +function system_message_action_form($context) { + $form['message'] = array( + '#type' => 'textarea', + '#title' => t('Message'), + '#default_value' => isset($context['message']) ? $context['message'] : '', + '#required' => TRUE, + '#rows' => '8', + '#description' => t('The message to be displayed to the current user. You may include the following variables: %site_name, %username, %node_url, %node_type, %title, %teaser, %body. Not all variables will be available in all contexts.'), + ); + return $form; +} + +function system_message_action_submit($form, $form_state) { + return array('message' => $form_state['values']['message']); +} + +/** + * A configurable Drupal action. Sends a message to the current user's screen. + */ +function system_message_action(&$object, $context = array()) { + global $user; + $variables = array( + '%site_name' => variable_get('site_name', 'Drupal'), + '%username' => $user->name ? $user->name : variable_get('anonymous', t('Anonymous')), + ); + + // This action can be called in any context, but if placeholders + // are used a node object must be present to be the source + // of substituted text. + switch ($context['hook']) { + case 'node': + // Because this is not an action of type 'node' the node + // will not be passed as $object, but it will still be available + // in $context. + $node = $context['node']; + break; + // The comment hook also provides the node, in context. + case 'comment': + $comment = $context['comment']; + $node = node_load($comment->nid); + break; + case 'taxonomy': + $vocabulary = taxonomy_vocabulary_load($object->vid); + $variables = array_merge($variables, array( + '%term_name' => $object->name, + '%term_description' => $object->description, + '%term_id' => $object->tid, + '%vocabulary_name' => $vocabulary->name, + '%vocabulary_description' => $vocabulary->description, + '%vocabulary_id' => $vocabulary->vid, + ) + ); + break; + default: + // We are being called directly. + $node = $object; + } + + if (isset($node) && is_object($node)) { + $variables = array_merge($variables, array( + '%uid' => $node->uid, + '%node_url' => url('node/' . $node->nid, array('absolute' => TRUE)), + '%node_type' => check_plain(node_type_get_name($node)), + '%title' => filter_xss($node->title), + '%teaser' => filter_xss($node->teaser), + '%body' => filter_xss($node->body), + ) + ); + } + $context['message'] = strtr($context['message'], $variables); + drupal_set_message($context['message']); +} + +/** + * Implement a configurable Drupal action. Redirect user to a URL. + */ +function system_goto_action_form($context) { + $form['url'] = array( + '#type' => 'textfield', + '#title' => t('URL'), + '#description' => t('The URL to which the user should be redirected. This can be an internal URL like node/1234 or an external URL like http://drupal.org.'), + '#default_value' => isset($context['url']) ? $context['url'] : '', + '#required' => TRUE, + ); + return $form; +} + +function system_goto_action_submit($form, $form_state) { + return array( + 'url' => $form_state['values']['url'] + ); +} + +function system_goto_action($object, $context) { + drupal_goto($context['url']); +} + +/** + * Implement a Drupal action. + * Blocks the user's IP address. + */ +function system_block_ip_action() { + $ip = ip_address(); + db_insert('blocked_ips') + ->fields(array('ip' => $ip)) + ->execute(); + watchdog('action', 'Banned IP address %ip', array('%ip' => $ip)); +} + Index: modules/system/system.block.inc =================================================================== RCS file: modules/system/system.block.inc diff -N modules/system/system.block.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/system/system.block.inc 5 Jun 2009 21:44:57 -0000 @@ -0,0 +1,76 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for System module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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; + } +} + +/** + * Implement 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']); + } +} + Index: modules/system/system.cron.inc =================================================================== RCS file: modules/system/system.cron.inc diff -N modules/system/system.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/system/system.cron.inc 5 Jun 2009 21:44:57 -0000 @@ -0,0 +1,56 @@ +<?php +// $Id$ + +/** + * @file + * Cron functionality for System module. + */ + +/** + * Implement 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(); +} + Index: modules/system/system.file.inc =================================================================== RCS file: modules/system/system.file.inc diff -N modules/system/system.file.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/system/system.file.inc 5 Jun 2009 21:44:57 -0000 @@ -0,0 +1,19 @@ +<?php +// $Id$ + +/** + * @file + * File hooks for System module. + */ + +/** + * Implement hook_image_toolkits(). + */ +function system_image_toolkits() { + return array( + 'gd' => array( + 'title' => t('GD2 image manipulation toolkit'), + 'available' => drupal_function_exists('image_gd_check_settings') && image_gd_check_settings(), + ), + ); +} Index: modules/system/system.form.inc =================================================================== RCS file: modules/system/system.form.inc diff -N modules/system/system.form.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/system/system.form.inc 5 Jun 2009 21:45:55 -0000 @@ -0,0 +1,42 @@ +<?php +// $Id$ + +/** + * @file + * + */ + +/** + * 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(); +} + 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 5 Jun 2009 21:45:55 -0000 @@ -10,3 +10,11 @@ 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.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 5 Jun 2009 21:44:56 -0000 @@ -0,0 +1,49 @@ +<?php +// $Id$ + +/** + * @file + * Mail hooks for System module. + */ + +/** + * Implement hook_mail(). + */ +function system_mail($key, &$message, $params) { + $account = $params['account']; + $context = $params['context']; + $variables = array( + '%site_name' => 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_type_get_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.708 diff -u -p -r1.708 system.module --- modules/system/system.module 5 Jun 2009 05:28:28 -0000 1.708 +++ modules/system/system.module 5 Jun 2009 21:45:55 -0000 @@ -130,100 +130,6 @@ function system_help($path, $arg) { } /** - * Implement 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(), - )); -} - -/** - * Implement 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.'), - ), - ); -} - -/** * Implement hook_rdf_namespaces(). */ function system_rdf_namespaces() { @@ -243,552 +149,6 @@ function system_rdf_namespaces() { } /** - * Implement 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; -} - -/** - * Implement 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 callback' => 'system_admin_menu_block_access', - 'access arguments' => array('admin/content', '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 callback' => 'system_admin_menu_block_access', - 'access arguments' => array('admin/settings', '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 callback' => 'system_admin_menu_block_access', - 'access arguments' => array('admin/build', '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, - ); - - // Development menu category. - $items['admin/development'] = array( - 'title' => 'Development', - 'description' => 'Development tools.', - 'position' => 'right', - 'weight' => -7, - 'page callback' => 'system_admin_menu_block_page', - 'access callback' => 'system_admin_menu_block_access', - 'access arguments' => array('admin/development', 'access administration pages'), - ); - - // 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 callback' => 'system_admin_menu_block_access', - 'access arguments' => array('admin/reports', '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 @@ -861,141 +221,6 @@ function system_preprocess_page(&$variab } /** - * Implement 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; - } -} - -/** - * Implement 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; - } -} - -/** - * Implement 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 <a href="@user-edit">account time zone setting</a>.', 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'); - } -} - -/** - * Implement 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; -} - -/** - * Implement 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; - } -} - -/** - * Implement 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']); - } -} - -/** * Implement hook_block_view(). * * Generate a block with a promotional link to Drupal.org and @@ -1451,40 +676,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) { @@ -1627,674 +818,6 @@ function system_get_module_admin_tasks($ } /** - * Implement 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(); -} - -/** - * Implement hook_hook_info(). - */ -function system_hook_info() { - return array( - 'system' => array( - 'cron' => array( - 'run' => array( - 'runs when' => t('When cron runs'), - ), - ), - ), - ); -} - -/** - * Implement 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() { - 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')); - } - $build['system_actions_header'] = array('#markup' => '<h3>' . t('Actions available to Drupal:') . '</h3>'); - $build['system_actions_table'] = array('#markup' => theme('table', $header, $row)); - } - - if ($actions_map) { - $build['system_actions_manage_form'] = drupal_get_form('system_actions_manage_form', $options); - } - - return $build; -} - -/** - * Define the form for the actions overview page. - * - * @see system_actions_manage_form_submit() - * @ingroup forms - * @param $form_state - * An associative array containing the current state of the form; not used. - * @param $options - * An array of configurable actions. - * @return - * Form definition. - */ -function system_actions_manage_form($form_state, $options = array()) { - $form['parent'] = array( - '#type' => 'fieldset', - '#title' => t('Make a new advanced action available'), - '#prefix' => '<div class="container-inline">', - '#suffix' => '</div>', - ); - $form['parent']['action'] = array( - '#type' => 'select', - '#default_value' => '', - '#options' => $options, - '#description' => '', - ); - $form['parent']['buttons']['submit'] = array( - '#type' => 'submit', - '#value' => t('Create'), - ); - return $form; -} - -/** - * Process system_actions_manage form submissions. - */ -function system_actions_manage_form_submit($form, &$form_state) { - if ($form_state['values']['action']) { - $form_state['redirect'] = 'admin/settings/actions/configure/' . $form_state['values']['action']; - } -} - -/** - * Menu callback. Create the form for configuration of a single action. - * - * We provide the "Description" field. The rest of the form - * is provided by the action. We then provide the Save button. - * Because we are combining unknown form elements with the action - * configuration form, we use actions_ prefix on our elements. - * - * @see system_actions_configure_validate() - * @see system_actions_configure_submit() - * @param $action - * md5 hash of action ID or an integer. If it's an md5 hash, we - * are creating a new instance. If it's an integer, we're editing - * an existing instance. - * @return - * Form definition. - */ -function system_actions_configure($form_state, $action = NULL) { - if ($action === NULL) { - drupal_goto('admin/settings/actions'); - } - - $actions_map = actions_actions_map(actions_list()); - $edit = array(); - - // Numeric action denotes saved instance of a configurable action; - // else we are creating a new action instance. - if (is_numeric($action)) { - $aid = $action; - // Load stored parameter values from database. - $data = db_query("SELECT * FROM {actions} WHERE aid = :aid", array(':aid' => $aid))->fetch(); - $edit['actions_description'] = $data->description; - $edit['actions_type'] = $data->type; - $function = $data->callback; - $action = md5($data->callback); - $params = unserialize($data->parameters); - if ($params) { - foreach ($params as $name => $val) { - $edit[$name] = $val; - } - } - } - else { - $function = $actions_map[$action]['callback']; - $edit['actions_description'] = $actions_map[$action]['description']; - $edit['actions_type'] = $actions_map[$action]['type']; - } - - $form['actions_description'] = array( - '#type' => 'textfield', - '#title' => t('Description'), - '#default_value' => $edit['actions_description'], - '#maxlength' => '255', - '#description' => t('A unique description for this advanced action. This description will be displayed in the interface of modules that integrate with actions, such as Trigger module.'), - '#weight' => -10 - ); - $action_form = $function . '_form'; - $form = array_merge($form, $action_form($edit)); - $form['actions_type'] = array( - '#type' => 'value', - '#value' => $edit['actions_type'], - ); - $form['actions_action'] = array( - '#type' => 'hidden', - '#value' => $action, - ); - // $aid is set when configuring an existing action instance. - if (isset($aid)) { - $form['actions_aid'] = array( - '#type' => 'hidden', - '#value' => $aid, - ); - } - $form['actions_configured'] = array( - '#type' => 'hidden', - '#value' => '1', - ); - $form['buttons']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save'), - '#weight' => 13 - ); - - return $form; -} - -/** - * Validate system_actions_configure form submissions. - */ -function system_actions_configure_validate($form, $form_state) { - $function = actions_function_lookup($form_state['values']['actions_action']) . '_validate'; - // Hand off validation to the action. - if (drupal_function_exists($function)) { - $function($form, $form_state); - } -} - -/** - * Process system_actions_configure form submissions. - */ -function system_actions_configure_submit($form, &$form_state) { - $function = actions_function_lookup($form_state['values']['actions_action']); - $submit_function = $function . '_submit'; - - // Action will return keyed array of values to store. - $params = $submit_function($form, $form_state); - $aid = isset($form_state['values']['actions_aid']) ? $form_state['values']['actions_aid'] : NULL; - - actions_save($function, $form_state['values']['actions_type'], $params, $form_state['values']['actions_description'], $aid); - drupal_set_message(t('The action has been successfully saved.')); - - $form_state['redirect'] = 'admin/settings/actions/manage'; -} - -/** - * Create the form for confirmation of deleting an action. - * - * @ingroup forms - * @see system_actions_delete_form_submit() - */ -function system_actions_delete_form($form_state, $action) { - - $form['aid'] = array( - '#type' => 'hidden', - '#value' => $action->aid, - ); - return confirm_form($form, - t('Are you sure you want to delete the action %action?', array('%action' => $action->description)), - 'admin/settings/actions/manage', - t('This cannot be undone.'), - t('Delete'), t('Cancel') - ); -} - -/** - * Process system_actions_delete form submissions. - * - * Post-deletion operations for action deletion. - */ -function system_actions_delete_form_submit($form, &$form_state) { - $aid = $form_state['values']['aid']; - $action = actions_load($aid); - actions_delete($aid); - $description = check_plain($action->description); - watchdog('user', 'Deleted action %aid (%action)', array('%aid' => $aid, '%action' => $description)); - drupal_set_message(t('Action %action was deleted', array('%action' => $description))); - $form_state['redirect'] = 'admin/settings/actions/manage'; -} - -/** - * Post-deletion operations for deleting action orphans. - * - * @param $orphaned - * An array of orphaned actions. - */ -function system_action_delete_orphans_post($orphaned) { - foreach ($orphaned as $callback) { - drupal_set_message(t("Deleted orphaned action (%action).", array('%action' => $callback))); - } -} - -/** - * Remove actions that are in the database but not supported by any enabled module. - */ -function system_actions_remove_orphans() { - actions_synchronize(TRUE); - drupal_goto('admin/settings/actions/manage'); -} - -/** - * Return a form definition so the Send email action can be configured. - * - * @see system_send_email_action_validate() - * @see system_send_email_action_submit() - * @param $context - * Default values (if we are editing an existing action instance). - * @return - * Form definition. - */ -function system_send_email_action_form($context) { - // Set default values for form. - if (!isset($context['recipient'])) { - $context['recipient'] = ''; - } - if (!isset($context['subject'])) { - $context['subject'] = ''; - } - if (!isset($context['message'])) { - $context['message'] = ''; - } - - $form['recipient'] = array( - '#type' => 'textfield', - '#title' => t('Recipient'), - '#default_value' => $context['recipient'], - '#maxlength' => '254', - '#description' => t('The email address to which the message should be sent OR enter %author if you would like to send an e-mail to the author of the original post.', array('%author' => '%author')), - ); - $form['subject'] = array( - '#type' => 'textfield', - '#title' => t('Subject'), - '#default_value' => $context['subject'], - '#maxlength' => '254', - '#description' => t('The subject of the message.'), - ); - $form['message'] = array( - '#type' => 'textarea', - '#title' => t('Message'), - '#default_value' => $context['message'], - '#cols' => '80', - '#rows' => '20', - '#description' => t('The message that should be sent. You may include the following variables: %site_name, %username, %node_url, %node_type, %title, %teaser, %body, %term_name, %term_description, %term_id, %vocabulary_name, %vocabulary_description, %vocabulary_id. Not all variables will be available in all contexts.'), - ); - return $form; -} - -/** - * Validate system_send_email_action form submissions. - */ -function system_send_email_action_validate($form, $form_state) { - $form_values = $form_state['values']; - // Validate the configuration form. - if (!valid_email_address($form_values['recipient']) && $form_values['recipient'] != '%author') { - // We want the literal %author placeholder to be emphasized in the error message. - form_set_error('recipient', t('Please enter a valid email address or %author.', array('%author' => '%author'))); - } -} - -/** - * Process system_send_email_action form submissions. - */ -function system_send_email_action_submit($form, $form_state) { - $form_values = $form_state['values']; - // Process the HTML form to store configuration. The keyed array that - // we return will be serialized to the database. - $params = array( - 'recipient' => $form_values['recipient'], - 'subject' => $form_values['subject'], - 'message' => $form_values['message'], - ); - return $params; -} - -/** - * Implement a configurable Drupal action. Sends an email. - */ -function system_send_email_action($object, $context) { - global $user; - - switch ($context['hook']) { - case 'node': - // Because this is not an action of type 'node' the node - // will not be passed as $object, but it will still be available - // in $context. - $node = $context['node']; - break; - // The comment hook provides nid, in $context. - case 'comment': - $comment = $context['comment']; - $node = node_load($comment->nid); - break; - case 'user': - // Because this is not an action of type 'user' the user - // object is not passed as $object, but it will still be available - // in $context. - $account = $context['account']; - if (isset($context['node'])) { - $node = $context['node']; - } - elseif ($context['recipient'] == '%author') { - // If we don't have a node, we don't have a node author. - watchdog('error', 'Cannot use %author token in this context.'); - return; - } - break; - default: - // We are being called directly. - $node = $object; - } - - $recipient = $context['recipient']; - - if (isset($node)) { - if (!isset($account)) { - $account = user_load($node->uid); - } - if ($recipient == '%author') { - $recipient = $account->mail; - } - } - - if (!isset($account)) { - $account = $user; - - } - $language = user_preferred_language($account); - $params = array('account' => $account, 'object' => $object, 'context' => $context); - if (isset($node)) { - $params['node'] = $node; - } - - if (drupal_mail('system', 'action_send_email', $recipient, $language, $params)) { - watchdog('action', 'Sent email to %recipient', array('%recipient' => $recipient)); - } - else { - watchdog('error', 'Unable to send email to %recipient', array('%recipient' => $recipient)); - } -} - -/** - * Implement hook_mail(). - */ -function system_mail($key, &$message, $params) { - $account = $params['account']; - $context = $params['context']; - $variables = array( - '%site_name' => 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_type_get_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); -} - -function system_message_action_form($context) { - $form['message'] = array( - '#type' => 'textarea', - '#title' => t('Message'), - '#default_value' => isset($context['message']) ? $context['message'] : '', - '#required' => TRUE, - '#rows' => '8', - '#description' => t('The message to be displayed to the current user. You may include the following variables: %site_name, %username, %node_url, %node_type, %title, %teaser, %body. Not all variables will be available in all contexts.'), - ); - return $form; -} - -function system_message_action_submit($form, $form_state) { - return array('message' => $form_state['values']['message']); -} - -/** - * A configurable Drupal action. Sends a message to the current user's screen. - */ -function system_message_action(&$object, $context = array()) { - global $user; - $variables = array( - '%site_name' => variable_get('site_name', 'Drupal'), - '%username' => $user->name ? $user->name : variable_get('anonymous', t('Anonymous')), - ); - - // This action can be called in any context, but if placeholders - // are used a node object must be present to be the source - // of substituted text. - switch ($context['hook']) { - case 'node': - // Because this is not an action of type 'node' the node - // will not be passed as $object, but it will still be available - // in $context. - $node = $context['node']; - break; - // The comment hook also provides the node, in context. - case 'comment': - $comment = $context['comment']; - $node = node_load($comment->nid); - break; - case 'taxonomy': - $vocabulary = taxonomy_vocabulary_load($object->vid); - $variables = array_merge($variables, array( - '%term_name' => $object->name, - '%term_description' => $object->description, - '%term_id' => $object->tid, - '%vocabulary_name' => $vocabulary->name, - '%vocabulary_description' => $vocabulary->description, - '%vocabulary_id' => $vocabulary->vid, - ) - ); - break; - default: - // We are being called directly. - $node = $object; - } - - if (isset($node) && is_object($node)) { - $variables = array_merge($variables, array( - '%uid' => $node->uid, - '%node_url' => url('node/' . $node->nid, array('absolute' => TRUE)), - '%node_type' => check_plain(node_type_get_name($node)), - '%title' => filter_xss($node->title), - '%teaser' => filter_xss($node->teaser), - '%body' => filter_xss($node->body), - ) - ); - } - $context['message'] = strtr($context['message'], $variables); - drupal_set_message($context['message']); -} - -/** - * Implement a configurable Drupal action. Redirect user to a URL. - */ -function system_goto_action_form($context) { - $form['url'] = array( - '#type' => 'textfield', - '#title' => t('URL'), - '#description' => t('The URL to which the user should be redirected. This can be an internal URL like node/1234 or an external URL like http://drupal.org.'), - '#default_value' => isset($context['url']) ? $context['url'] : '', - '#required' => TRUE, - ); - return $form; -} - -function system_goto_action_submit($form, $form_state) { - return array( - 'url' => $form_state['values']['url'] - ); -} - -function system_goto_action($object, $context) { - drupal_goto($context['url']); -} - -/** - * Implement a Drupal action. - * Blocks the user's IP address. - */ -function system_block_ip_action() { - $ip = ip_address(); - db_insert('blocked_ips') - ->fields(array('ip' => $ip)) - ->execute(); - watchdog('action', 'Banned IP address %ip', array('%ip' => $ip)); -} - -/** * Generate an array of time zones and their local time&date. * * @param $blank @@ -2394,14 +917,3 @@ function theme_meta_generator_header($ve drupal_set_header('X-Generator', 'Drupal ' . $version . ' (http://drupal.org)'); } -/** - * Implement hook_image_toolkits(). - */ -function system_image_toolkits() { - return array( - 'gd' => array( - 'title' => t('GD2 image manipulation toolkit'), - 'available' => drupal_function_exists('image_gd_check_settings') && image_gd_check_settings(), - ), - ); -} Index: modules/system/system.registry.inc =================================================================== RCS file: modules/system/system.registry.inc diff -N modules/system/system.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/system/system.registry.inc 5 Jun 2009 21:44:55 -0000 @@ -0,0 +1,674 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for System module. + */ + +/** + * Implement 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 callback' => 'system_admin_menu_block_access', + 'access arguments' => array('admin/content', '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 callback' => 'system_admin_menu_block_access', + 'access arguments' => array('admin/settings', '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 callback' => 'system_admin_menu_block_access', + 'access arguments' => array('admin/build', '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, + ); + + // Development menu category. + $items['admin/development'] = array( + 'title' => 'Development', + 'description' => 'Development tools.', + 'position' => 'right', + 'weight' => -7, + 'page callback' => 'system_admin_menu_block_page', + 'access callback' => 'system_admin_menu_block_access', + 'access arguments' => array('admin/development', 'access administration pages'), + ); + + // 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 callback' => 'system_admin_menu_block_access', + 'access arguments' => array('admin/reports', '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; +} + +/** + * Implement 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(), + )); +} + +/** + * Implement 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; +} + +/** + * Implement hook_hook_info(). + */ +function system_hook_info() { + return array( + 'system' => array( + 'cron' => array( + 'run' => array( + 'runs when' => t('When cron runs'), + ), + ), + ), + ); +} + +/** + * Implement 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'), + ) + ) + ); +} + Index: modules/system/system.user.inc =================================================================== RCS file: modules/system/system.user.inc diff -N modules/system/system.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/system/system.user.inc 5 Jun 2009 21:44:56 -0000 @@ -0,0 +1,111 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for System module. + */ + +/** + * Implement 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.'), + ), + ); +} + +/** + * Implement 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; + } +} + +/** + * Implement 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; + } +} + +/** + * Implement 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 <a href="@user-edit">account time zone setting</a>.', 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'); + } +} + Index: modules/taxonomy/taxonomy.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.admin.inc,v retrieving revision 1.53 diff -u -p -r1.53 taxonomy.admin.inc --- modules/taxonomy/taxonomy.admin.inc 4 Jun 2009 03:33:29 -0000 1.53 +++ modules/taxonomy/taxonomy.admin.inc 5 Jun 2009 21:45:56 -0000 @@ -932,3 +932,10 @@ function taxonomy_vocabulary_confirm_res watchdog('taxonomy', 'Reset vocabulary %name to alphabetical order.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE); $form_state['redirect'] = 'admin/content/taxonomy/' . $form_state['values']['vid']; } +/** + * Return the vocabulary name given the vocabulary object. + */ +function taxonomy_admin_vocabulary_title_callback($vocabulary) { + return check_plain($vocabulary->name); +} + 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 5 Jun 2009 21:44:51 -0000 @@ -8,3 +8,6 @@ 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 Index: modules/taxonomy/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v retrieving revision 1.477 diff -u -p -r1.477 taxonomy.module --- modules/taxonomy/taxonomy.module 5 Jun 2009 05:23:57 -0000 1.477 +++ modules/taxonomy/taxonomy.module 5 Jun 2009 21:45:56 -0000 @@ -7,35 +7,6 @@ */ /** - * Implement hook_perm(). - */ -function taxonomy_perm() { - return array( - 'administer taxonomy' => array( - 'title' => t('Administer taxonomy'), - 'description' => t('Manage taxonomy vocabularies and terms.'), - ), - ); -} - -/** - * Implement 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) { } /** - * Implement 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) { @@ -773,111 +646,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(); - } -} - -/** - * Implement 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') { @@ -1572,84 +1340,6 @@ function taxonomy_node_load($nodes) { } /** - * Implement hook_node_insert(). - */ -function taxonomy_node_insert($node) { - if (!empty($node->taxonomy)) { - taxonomy_node_save($node, $node->taxonomy); - } -} - -/** - * Implement hook_node_update(). - */ -function taxonomy_node_update($node) { - if (!empty($node->taxonomy)) { - taxonomy_node_save($node, $node->taxonomy); - } -} - -/** - * Implement 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'); -} - -/** - * Implement 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'); -} - -/** - * Implement 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))); - } - } - } - } -} - -/** - * Implement hook_node_update_index(). - */ -function taxonomy_node_update_index($node) { - $output = array(); - if (isset($node->taxonomy) && is_array($node->taxonomy)) { - foreach ($node->taxonomy as $term) { - $output[] = $term->name; - } - } - if (count($output)) { - return '<strong>(' . implode(', ', $output) . ')</strong>'; - } -} - -/** * Parses a comma or plus separated string of term IDs. * * @param $str_tids @@ -1739,23 +1429,3 @@ function taxonomy_implode_tags($tags, $v return implode(', ', $typed_tags); } -/** - * Implement 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 5 Jun 2009 21:45:56 -0000 @@ -0,0 +1,191 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Taxonomy module. + */ + +/** + * Implement 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'); +} + +/** + * Implement hook_node_insert(). + */ +function taxonomy_node_insert($node) { + if (!empty($node->taxonomy)) { + taxonomy_node_save($node, $node->taxonomy); + } +} + +/** + * Implement hook_node_update(). + */ +function taxonomy_node_update($node) { + if (!empty($node->taxonomy)) { + taxonomy_node_save($node, $node->taxonomy); + } +} + +/** + * Implement 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'); +} + +/** + * Implement 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'); +} + +/** + * Implement 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))); + } + } + } + } +} + +/** + * Implement hook_node_update_index(). + */ +function taxonomy_node_update_index($node) { + $output = array(); + if (isset($node->taxonomy) && is_array($node->taxonomy)) { + foreach ($node->taxonomy as $term) { + $output[] = $term->name; + } + } + if (count($output)) { + return '<strong>(' . implode(', ', $output) . ')</strong>'; + } +} + +/** + * 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 5 Jun 2009 21:44:50 -0000 @@ -0,0 +1,136 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Taxonomy module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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()), + ), + ); +} + +/** + * Implement 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 5 Jun 2009 21:44:51 -0000 @@ -0,0 +1,20 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Taxonomy module. + */ + +/** + * Implement hook_perm(). + */ +function taxonomy_perm() { + return array( + 'administer taxonomy' => array( + 'title' => t('Administer taxonomy'), + 'description' => t('Manage taxonomy vocabularies and terms.'), + ), + ); +} + 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 5 Jun 2009 21:44:49 -0000 @@ -7,3 +7,4 @@ version = VERSION core = 7.x files[] = tracker.module files[] = tracker.pages.inc +files[] = tracker.registry.inc Index: modules/tracker/tracker.module =================================================================== RCS file: /cvs/drupal/drupal/modules/tracker/tracker.module,v retrieving revision 1.158 diff -u -p -r1.158 tracker.module --- modules/tracker/tracker.module 27 May 2009 18:34:01 -0000 1.158 +++ modules/tracker/tracker.module 5 Jun 2009 21:44:49 -0000 @@ -20,43 +20,6 @@ function tracker_help($path, $arg) { } /** - * Implement 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 5 Jun 2009 21:44:49 -0000 @@ -0,0 +1,45 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Tracker module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:44:49 -0000 @@ -0,0 +1,18 @@ +<?php +// $Id$ + +/** + * @file + * Form alter hooks for specific forms for Translation module. + */ + +/** + * Implement 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 <a href="!languages">enabled languages</a>. 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.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 5 Jun 2009 21:44:49 -0000 @@ -7,3 +7,7 @@ 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 Index: modules/translation/translation.module =================================================================== RCS file: /cvs/drupal/drupal/modules/translation/translation.module,v retrieving revision 1.46 diff -u -p -r1.46 translation.module --- modules/translation/translation.module 27 May 2009 18:34:02 -0000 1.46 +++ modules/translation/translation.module 5 Jun 2009 21:44:49 -0000 @@ -51,23 +51,6 @@ function translation_help($path, $arg) { } /** - * Implement 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 +65,6 @@ function _translation_tab_access($node) } /** - * Implement hook_perm(). - */ -function translation_perm() { - return array( - 'translate content' => array( - 'title' => t('Translate content'), - 'description' => t('Translate website content.'), - ), - ); -} - -/** - * Implement 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 <a href="!languages">enabled languages</a>. 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'))); -} - -/** * Implement hook_form_alter(). * * - Add translation option to content type form. @@ -190,123 +151,6 @@ function translation_node_view($node, $t } /** - * Implement 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); - } - } -} - -/** - * Implement 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(); - } - } -} - -/** - * Implement 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(); - } - } - } -} - -/** - * Implement 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.')); - } - } -} - -/** - * Implement 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 5 Jun 2009 21:44:48 -0000 @@ -0,0 +1,125 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Translation module. + */ + +/** + * Implement 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); + } + } +} + +/** + * Implement 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(); + } + } +} + +/** + * Implement 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(); + } + } + } +} + +/** + * Implement 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.')); + } + } +} + +/** + * Implement 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 5 Jun 2009 21:44:48 -0000 @@ -0,0 +1,25 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Translation module. + */ + +/** + * Implement 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; +} + 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 5 Jun 2009 21:44:48 -0000 @@ -0,0 +1,20 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Translation module. + */ + +/** + * Implement hook_perm(). + */ +function translation_perm() { + return array( + 'translate content' => 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 5 Jun 2009 21:44:47 -0000 @@ -0,0 +1,18 @@ +<?php +// $Id$ + +/** + * @file + * Action hooks for Trigger module. + */ + +/** + * Implement hook_actions_delete(). + * + * Remove all trigger entries for the given action, when deleted. + */ +function trigger_actions_delete($aid) { + db_delete('trigger_assignments') + ->condition('aid', $aid) + ->execute(); +} Index: modules/trigger/trigger.comment.inc =================================================================== RCS file: modules/trigger/trigger.comment.inc diff -N modules/trigger/trigger.comment.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/trigger.comment.inc 5 Jun 2009 21:44:47 -0000 @@ -0,0 +1,29 @@ +<?php +// $Id$ + +/** + * @file + * Comment hooks for Trigger module. + */ + +/** + * Implement hook_comment_insert(). + */ +function trigger_comment_insert($form_values) { + _trigger_comment($form_values, 'insert'); +} + +/** + * Implement hook_comment_update(). + */ +function trigger_comment_update($form_values) { + _trigger_comment($form_values, 'update'); +} + +/** + * Implement hook_comment_delete(). + */ +function trigger_comment_delete($comment) { + _trigger_comment($comment, 'delete'); +} + Index: modules/trigger/trigger.cron.inc =================================================================== RCS file: modules/trigger/trigger.cron.inc diff -N modules/trigger/trigger.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/trigger.cron.inc 5 Jun 2009 21:44:47 -0000 @@ -0,0 +1,22 @@ +<?php +// $Id$ + +/** + * @file + * Cron functionality for Trigger module. + */ + +/** + * Implement hook_cron(). + */ +function trigger_cron() { + $aids = _trigger_get_hook_aids('cron', 'run'); + $context = array( + 'hook' => 'cron', + 'op' => 'run', + ); + // Cron does not act on any specific object. + $object = NULL; + actions_do(array_keys($aids), $object, $context); +} + 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 5 Jun 2009 21:44:47 -0000 @@ -7,3 +7,10 @@ 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 Index: modules/trigger/trigger.module =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/trigger.module,v retrieving revision 1.38 diff -u -p -r1.38 trigger.module --- modules/trigger/trigger.module 5 Jun 2009 15:41:05 -0000 1.38 +++ modules/trigger/trigger.module 5 Jun 2009 21:44:47 -0000 @@ -32,93 +32,6 @@ function trigger_help($path, $arg) { } /** - * Implement 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_select('system') - ->condition('name', $module) - ->execute() - ->fetchField(); - $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) { @@ -144,18 +57,6 @@ function _trigger_get_hook_aids($hook, $ } /** - * Implement hook_theme(). - */ -function trigger_theme() { - return array( - 'trigger_display' => array( - 'arguments' => array('element'), - 'file' => 'trigger.admin.inc', - ), - ); -} - -/** * Implement hook_forms(). We reuse code by using the * same assignment form definition for each node-op combination. */ @@ -250,34 +151,6 @@ function trigger_node_view($node, $tease } /** - * Implement hook_node_update(). - */ -function trigger_node_update($node) { - _trigger_node($node, 'update'); -} - -/** - * Implement hook_node_presave(). - */ -function trigger_node_presave($node) { - _trigger_node($node, 'presave'); -} - -/** - * Implement hook_node_insert(). - */ -function trigger_node_insert($node) { - _trigger_node($node, 'insert'); -} - -/** - * Implement 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 @@ -304,27 +177,6 @@ function _trigger_normalize_comment_cont } /** - * Implement hook_comment_insert(). - */ -function trigger_comment_insert($form_values) { - _trigger_comment($form_values, 'insert'); -} - -/** - * Implement hook_comment_update(). - */ -function trigger_comment_update($form_values) { - _trigger_comment($form_values, 'update'); -} - -/** - * Implement hook_comment_delete(). - */ -function trigger_comment_delete($comment) { - _trigger_comment($comment, 'delete'); -} - -/** * Implement hook_comment_view(). */ function trigger_comment_view($comment) { @@ -369,20 +221,6 @@ function _trigger_comment($a1, $op) { } /** - * Implement hook_cron(). - */ -function trigger_cron() { - $aids = _trigger_get_hook_aids('cron', 'run'); - $context = array( - 'hook' => 'cron', - 'op' => 'run', - ); - // 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 @@ -414,46 +252,6 @@ function _trigger_normalize_user_context } /** - * trigger_user_login - */ -function trigger_user_login(&$edit, &$account, $category) { - _trigger_user('login', $edit, $account, $category); -} - -/** - * Implement hook_user_logout(). - */ -function trigger_user_logout($edit, $account) { - _trigger_user('logout', $edit, $account); -} - -/** - * Implement hook_user_insert(). - */ -function trigger_user_insert(&$edit, &$account, $category) { - _trigger_user('insert', $edit, $account, $category); -} - -/** - * Implement hook_user_update(). - */ -function trigger_user_update(&$edit, &$account, $category) { - _trigger_user('update', $edit, $account, $category); -} - -/** - * Implement 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; - } -} - -/** * Implement hook_user_view(). */ function trigger_user_view(&$edit, &$account, $category) { @@ -489,21 +287,6 @@ function _trigger_user($op, &$edit, &$ac } /** - * Implement 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 - ); - actions_do(array_keys($aids), (object) $array, $context); -} - -/** * Often we generate a select field of all actions. This function * generates the options for that select. * @@ -526,13 +309,3 @@ function trigger_options($type = 'all') } } -/** - * Implement hook_actions_delete(). - * - * Remove all trigger entries for the given action, when deleted. - */ -function trigger_actions_delete($aid) { - db_delete('trigger_assignments') - ->condition('aid', $aid) - ->execute(); -} 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 5 Jun 2009 21:44:47 -0000 @@ -0,0 +1,36 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Trigger module. + */ + +/** + * Implement hook_node_update(). + */ +function trigger_node_update($node) { + _trigger_node($node, 'update'); +} + +/** + * Implement hook_node_presave(). + */ +function trigger_node_presave($node) { + _trigger_node($node, 'presave'); +} + +/** + * Implement hook_node_insert(). + */ +function trigger_node_insert($node) { + _trigger_node($node, 'insert'); +} + +/** + * Implement hook_node_delete(). + */ +function trigger_node_delete($node) { + _trigger_node($node, 'delete'); +} + Index: modules/trigger/trigger.registry.inc =================================================================== RCS file: modules/trigger/trigger.registry.inc diff -N modules/trigger/trigger.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/trigger.registry.inc 5 Jun 2009 21:44:47 -0000 @@ -0,0 +1,107 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Trigger module. + */ + +/** + * Implement 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_select('system') + ->condition('name', $module) + ->execute() + ->fetchField(); + $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; +} + +/** + * Implement 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 5 Jun 2009 21:44:47 -0000 @@ -0,0 +1,23 @@ +<?php +// $Id$ + +/** + * @file + * Taxonomy hooks for Trigger module. + */ + +/** + * Implement 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 + ); + actions_do(array_keys($aids), (object) $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 5 Jun 2009 21:44:47 -0000 @@ -0,0 +1,48 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Trigger module. + */ + +/** + * trigger_user_login + */ +function trigger_user_login(&$edit, &$account, $category) { + _trigger_user('login', $edit, $account, $category); +} + +/** + * Implement hook_user_logout(). + */ +function trigger_user_logout($edit, $account) { + _trigger_user('logout', $edit, $account); +} + +/** + * Implement hook_user_insert(). + */ +function trigger_user_insert(&$edit, &$account, $category) { + _trigger_user('insert', $edit, $account, $category); +} + +/** + * Implement hook_user_update(). + */ +function trigger_user_update(&$edit, &$account, $category) { + _trigger_user('update', $edit, $account, $category); +} + +/** + * Implement 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; + } +} + Index: modules/trigger/tests/trigger_test.actions.inc =================================================================== RCS file: modules/trigger/tests/trigger_test.actions.inc diff -N modules/trigger/tests/trigger_test.actions.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/tests/trigger_test.actions.inc 5 Jun 2009 21:44:47 -0000 @@ -0,0 +1,51 @@ +<?php +// $Id$ + +/** + * @file + * Action hooks for Trigger_test module. + */ + +/** + * Action fired during the "cron run" trigger test. + */ +function trigger_test_system_cron_action() { + // Indicate successful execution by setting a persistent variable. + variable_set('trigger_test_system_cron_action', TRUE); +} + +/** + * Implement a configurable Drupal action. + */ +function trigger_test_system_cron_conf_action($object, $context) { + // Indicate successful execution by incrementing a persistent variable. + $value = variable_get('trigger_test_system_cron_conf_action', 0) + 1; + variable_set('trigger_test_system_cron_conf_action', $value); +} + +/** + * Form for configurable test action. + */ +function trigger_test_system_cron_conf_action_form($context) { + if (!isset($context['subject'])) { + $context['subject'] = ''; + } + $form['subject'] = array( + '#type' => 'textfield', + '#default_value' => $context['subject'], + ); + return $form; +} + +/** + * Form submission handler for configurable test action. + */ +function trigger_test_system_cron_conf_action_submit($form, $form_state) { + $form_values = $form_state['values']; + // Process the HTML form to store configuration. The keyed array that + // we return will be serialized to the database. + $params = array( + 'subject' => $form_values['subject'], + ); + return $params; +} Index: modules/trigger/tests/trigger_test.info =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/tests/trigger_test.info,v retrieving revision 1.1 diff -u -p -r1.1 trigger_test.info --- modules/trigger/tests/trigger_test.info 27 May 2009 16:29:05 -0000 1.1 +++ modules/trigger/tests/trigger_test.info 5 Jun 2009 21:44:47 -0000 @@ -5,3 +5,5 @@ package = Testing core = 7.x files[] = trigger_test.module hidden = TRUE +files[] = trigger_test.registry.inc +files[] = trigger_test.actions.inc Index: modules/trigger/tests/trigger_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/trigger/tests/trigger_test.module,v retrieving revision 1.2 diff -u -p -r1.2 trigger_test.module --- modules/trigger/tests/trigger_test.module 31 May 2009 03:12:19 -0000 1.2 +++ modules/trigger/tests/trigger_test.module 5 Jun 2009 21:44:47 -0000 @@ -6,71 +6,3 @@ * Mock module to aid in testing trigger.module. */ -/** - * Implementation of hook_action_info(). - */ -function trigger_test_action_info() { - // Register an action that can be assigned to the trigger "cron run". - return array( - 'trigger_test_system_cron_action' => array( - 'type' => 'system', - 'description' => t('Cron test action'), - 'configurable' => FALSE, - 'hooks' => array( - 'cron' => array('run'), - ), - ), - 'trigger_test_system_cron_conf_action' => array( - 'type' => 'system', - 'description' => t('Cron test configurable action'), - 'configurable' => TRUE, - 'hooks' => array( - 'cron' => array('run'), - ), - ), - ); -} - -/** - * Action fired during the "cron run" trigger test. - */ -function trigger_test_system_cron_action() { - // Indicate successful execution by setting a persistent variable. - variable_set('trigger_test_system_cron_action', TRUE); -} - -/** - * Implement a configurable Drupal action. - */ -function trigger_test_system_cron_conf_action($object, $context) { - // Indicate successful execution by incrementing a persistent variable. - $value = variable_get('trigger_test_system_cron_conf_action', 0) + 1; - variable_set('trigger_test_system_cron_conf_action', $value); -} - -/** - * Form for configurable test action. - */ -function trigger_test_system_cron_conf_action_form($context) { - if (!isset($context['subject'])) { - $context['subject'] = ''; - } - $form['subject'] = array( - '#type' => 'textfield', - '#default_value' => $context['subject'], - ); - return $form; -} - -/** - * Form submission handler for configurable test action. - */ -function trigger_test_system_cron_conf_action_submit($form, $form_state) { - $form_values = $form_state['values']; - // Process the HTML form to store configuration. The keyed array that - // we return will be serialized to the database. - $params = array( - 'subject' => $form_values['subject'], - ); - return $params; -} Index: modules/trigger/tests/trigger_test.registry.inc =================================================================== RCS file: modules/trigger/tests/trigger_test.registry.inc diff -N modules/trigger/tests/trigger_test.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/trigger/tests/trigger_test.registry.inc 5 Jun 2009 21:44:47 -0000 @@ -0,0 +1,33 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Trigger_test module. + */ + +/** + * Implementation of hook_action_info(). + */ +function trigger_test_action_info() { + // Register an action that can be assigned to the trigger "cron run". + return array( + 'trigger_test_system_cron_action' => array( + 'type' => 'system', + 'description' => t('Cron test action'), + 'configurable' => FALSE, + 'hooks' => array( + 'cron' => array('run'), + ), + ), + 'trigger_test_system_cron_conf_action' => array( + 'type' => 'system', + 'description' => t('Cron test configurable action'), + 'configurable' => TRUE, + 'hooks' => array( + 'cron' => array('run'), + ), + ), + ); +} + Index: modules/update/update.cron.inc =================================================================== RCS file: modules/update/update.cron.inc diff -N modules/update/update.cron.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/update/update.cron.inc 5 Jun 2009 21:44:46 -0000 @@ -0,0 +1,22 @@ +<?php +// $Id$ + +/** + * @file + * Cron functionality for Update module. + */ + +/** + * Implement 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(); + } +} + 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 5 Jun 2009 21:44:46 -0000 @@ -0,0 +1,32 @@ +<?php +// $Id$ + +/** + * @file + * Form alter hooks for specific forms for Update module. + */ + +/** + * Implement 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'; +} + +/** + * Implement 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'; +} + 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 5 Jun 2009 21:44:46 -0000 @@ -10,3 +10,7 @@ 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 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 5 Jun 2009 21:44:46 -0000 @@ -0,0 +1,37 @@ +<?php +// $Id$ + +/** + * @file + * Mail hooks for Update module. + */ + +/** + * Implement 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)); +} + Index: modules/update/update.module =================================================================== RCS file: /cvs/drupal/drupal/modules/update/update.module,v retrieving revision 1.35 diff -u -p -r1.35 update.module --- modules/update/update.module 27 May 2009 18:34:02 -0000 1.35 +++ modules/update/update.module 5 Jun 2009 21:44:46 -0000 @@ -112,53 +112,6 @@ function update_help($path, $arg) { } /** - * Implement 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; -} - -/** - * Implement 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), - ), - ); -} - -/** * Implement hook_requirements(). * * @return @@ -272,44 +225,6 @@ function _update_requirement_check($proj } /** - * Implement 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(); - } -} - -/** - * Implement 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'; -} - -/** - * Implement 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 +298,6 @@ function update_refresh() { } /** - * Implement 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 +482,5 @@ function _update_cache_clear($cid = NULL } /** - * Implement 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 5 Jun 2009 21:44:46 -0000 @@ -0,0 +1,78 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Update module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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), + ), + ); +} + +/** + * Implement 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 5 Jun 2009 21:44:45 -0000 @@ -0,0 +1,46 @@ +<?php +// $Id$ + +/** + * @file + * File hooks for Upload module. + */ + +/** + * Implement 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; + } +} + +/** + * Implement 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); + } +} + +/** + * Implement 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 5 Jun 2009 21:45:57 -0000 @@ -0,0 +1,54 @@ +<?php +// $Id$ + +/** + * @file + * + */ + +/** + * 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'); + } +} + 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 5 Jun 2009 21:45:57 -0000 @@ -7,3 +7,9 @@ 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.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.241 diff -u -p -r1.241 upload.module --- modules/upload/upload.module 27 May 2009 18:34:02 -0000 1.241 +++ modules/upload/upload.module 5 Jun 2009 21:45:57 -0000 @@ -23,39 +23,6 @@ function upload_help($path, $arg) { } /** - * Implement 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), - ), - ); -} - -/** - * Implement 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 +50,6 @@ function upload_node_links($node, $tease } /** - * Implement 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 +92,6 @@ function _upload_file_limits($user) { ); } -/** - * Implement 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( @@ -277,26 +160,6 @@ function upload_file_load($files) { } /** - * Implement 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); - } -} - -/** - * Implement hook_file_delete(). - */ -function upload_file_delete($file) { - // Delete all information associated with the file. - db_delete('upload')->condition('fid', $file->fid)->execute(); -} - -/** * Implement hook_node_load(). */ function upload_node_load($nodes, $types) { @@ -381,50 +244,6 @@ function upload_node_view($node, $teaser } /** - * Implement hook_node_insert(). - */ -function upload_node_insert($node) { - if (user_access('upload files')) { - upload_save($node); - } -} - -/** - * Implement hook_node_update(). - */ -function upload_node_update($node) { - if (user_access('upload files')) { - upload_save($node); - } -} - -/** - * Implement 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); - } -} - -/** - * Implement 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); - } -} - -/** * Implement hook_node_search_result(). */ function upload_node_search_result($node) { @@ -631,69 +450,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 5 Jun 2009 21:44:45 -0000 @@ -0,0 +1,52 @@ +<?php +// $Id$ + +/** + * @file + * Node hooks for Upload module. + */ + +/** + * Implement hook_node_insert(). + */ +function upload_node_insert($node) { + if (user_access('upload files')) { + upload_save($node); + } +} + +/** + * Implement hook_node_update(). + */ +function upload_node_update($node) { + if (user_access('upload files')) { + upload_save($node); + } +} + +/** + * Implement 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); + } +} + +/** + * Implement 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 5 Jun 2009 21:45:57 -0000 @@ -0,0 +1,74 @@ +<?php +// $Id$ + +/** + * @file + * + */ + +/** + * 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.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 5 Jun 2009 21:44:44 -0000 @@ -0,0 +1,45 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for Upload module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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 5 Jun 2009 21:44:45 -0000 @@ -0,0 +1,24 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for Upload module. + */ + +/** + * Implement 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.'), + ), + ); +} + 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 5 Jun 2009 21:44:41 -0000 @@ -0,0 +1,31 @@ +<?php +// $Id$ + +/** + * @file + * Action hooks for User module. + */ + +/** + * Implement 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)); +} + 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 5 Jun 2009 21:44:42 -0000 @@ -0,0 +1,69 @@ +<?php +// $Id$ + +/** + * @file + * Block hooks for User module. + */ + +/** + * Implement 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; +} + +/** + * Implement 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' => '<p>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.</p>'); + return $form; + } +} + +/** + * Implement 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 5 Jun 2009 21:44:44 -0000 @@ -0,0 +1,43 @@ +<?php +// $Id$ + +/** + * @file + * File hooks for User module. + */ + +/** + * Implement 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']); + } +} + +/** + * Implement 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); + } +} + +/** + * Implement 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 5 Jun 2009 21:45:59 -0000 @@ -0,0 +1,277 @@ +<?php +// $Id$ + +/** + * @file + * + */ + +/** + * 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; +} + +/** + * 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. <a href="@password">Have you forgotten your password?</a>', 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; +} + +/** + * 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('</p><p> Your password is <strong>%pass</strong>. You may change your password below.</p>', 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 <a href="@url">%name</a>. 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 <a href="@url">%name</a>.', 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.<br />In the meantime, a welcome message with further instructions has been sent to your e-mail address.')); + $form_state['redirect'] = ''; + return; + + } + } +} + 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 5 Jun 2009 21:45:59 -0000 @@ -9,3 +9,11 @@ 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.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 5 Jun 2009 21:44:41 -0000 @@ -0,0 +1,18 @@ +<?php +// $Id$ + +/** + * @file + * Mail hooks for User module. + */ + +/** + * Implement 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); +} + Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.999 diff -u -p -r1.999 user.module --- modules/user/user.module 4 Jun 2009 11:25:03 -0000 1.999 +++ modules/user/user.module 5 Jun 2009 21:45:59 -0000 @@ -30,85 +30,6 @@ function user_module_invoke($type, &$arr } } -/** - * Implement hook_theme(). - */ -function user_theme() { - return array( - 'user_picture' => 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), - ), - ); -} - -/** - * Implement hook_fieldable_info(). - */ -function user_fieldable_info() { - $return = array( - 'user' => array( - 'name' => t('User'), - 'id key' => 'uid', - ), - ); - return $return; -} - -/** - * Implement 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) { } /** - * Implement 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 <a href="@user-settings-url">user settings</a>.', 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.'))), - ), - ); -} - -/** - * Implement 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']); - } -} - -/** - * Implement 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); - } -} - -/** - * Implement 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(); -} - -/** - * Implement 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; - } - } -} - -/** - * Implement hook_elements(). - */ -function user_elements() { - return array( - 'user_profile_category' => array( - '#theme_wrapper' => 'user_profile_category' - ), - 'user_profile_item' => array( - '#theme' => 'user_profile_item' - ), - ); -} - -/** * Implement hook_user_view(). */ function user_user_view(&$edit, &$account, $category = NULL) { @@ -925,182 +729,6 @@ function user_user_view(&$edit, &$accoun } /** - * Implement 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); - } -} - -/** - * Implement 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. <a href="@password">Have you forgotten your password?</a>', 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']))); - } - } - } -} - -/** - * Implement 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']); - } - } -} - -/** - * Implement hook_user_categories(). - */ -function user_user_categories() { - 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; -} - -/** - * Implement 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; -} - -/** - * Implement 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' => '<p>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.</p>'); - return $form; - } -} - -/** - * Implement 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; - } -} - -/** * Implement hook_block_view(). */ function user_block_view($delta = '') { @@ -1276,193 +904,6 @@ function user_load_self($arg) { return $arg; } -/** - * Implement 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 callback' => 'system_admin_menu_block_access', - 'access arguments' => array('admin/user', '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'), - ); - - if (($categories = _user_categories()) && (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'); } @@ -1576,39 +1017,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 @@ -1630,36 +1038,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. <a href="@password">Have you forgotten your password?</a>', 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 @@ -1727,20 +1105,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. @@ -2059,16 +1423,6 @@ function user_build_content(&$account) { } /** - * Implement 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. @@ -2186,205 +1540,6 @@ function user_roles($membersonly = FALSE } /** - * Implement 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' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE); - // array_filter() returns only elements with TRUE values. - foreach (array_filter($edit['accounts']) as $uid => $value) { - $user = db_query('SELECT name FROM {users} WHERE uid = :uid', array(':uid' => $uid))->fetchField(); - $form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '<li>', '#suffix' => check_plain($user) . "</li>\n"); - } - - $form['operation'] = array('#type' => 'hidden', '#value' => 'cancel'); - - module_load_include('inc', 'user', 'user.pages'); - $form['user_cancel_method'] = array( - '#type' => 'item', - '#title' => t('When cancelling these accounts'), - ); - $form['user_cancel_method'] += user_cancel_methods(); - // Remove method descriptions. - foreach (element_children($form['user_cancel_method']) as $element) { - unset($form['user_cancel_method'][$element]['#description']); - } - - // Allow to send the account cancellation confirmation mail. - $form['user_cancel_confirm'] = array( - '#type' => 'checkbox', - '#title' => t('Require e-mail confirmation to cancel account.'), - '#default_value' => FALSE, - '#description' => t('When enabled, the user must confirm the account cancellation via e-mail.'), - ); - // Also allow to send account canceled notification mail, if enabled. - $form['user_cancel_notify'] = array( - '#type' => 'checkbox', - '#title' => t('Notify user when account is canceled.'), - '#default_value' => FALSE, - '#access' => variable_get('user_mail_status_canceled_notify', FALSE), - '#description' => t('When enabled, the user will receive an e-mail notification after the account has been cancelled.'), - ); - - return confirm_form($form, - t('Are you sure you want to cancel these user accounts?'), - 'admin/user/user', t('This action cannot be undone.'), - t('Cancel accounts'), t('Cancel')); -} - -/** - * Submit handler for mass-account cancellation form. - * - * @see user_multiple_cancel_confirm() - * @see user_cancel_confirm_form_submit() - */ -function user_multiple_cancel_confirm_submit($form, &$form_state) { - global $user; - - if ($form_state['values']['confirm']) { - foreach ($form_state['values']['accounts'] as $uid => $value) { - // Prevent user administrators from deleting themselves without confirmation. - if ($uid == $user->uid) { - $admin_form_state = $form_state; - unset($admin_form_state['values']['user_cancel_confirm']); - $admin_form_state['values']['_account'] = $user; - user_cancel_confirm_form_submit(array(), $admin_form_state); - } - else { - user_cancel($form_state['values'], $uid, $form_state['values']['user_cancel_method']); - } - } - } - $form_state['redirect'] = 'admin/user/user'; - return; -} - -/** * Implement hook_help(). */ function user_help($path, $arg) { @@ -2691,234 +1846,6 @@ function user_node_load($nodes, $types) } /** - * Implement 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") - ), - ), - ), - ); -} - -/** - * Implement 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(), - ), - ); -} - -/** - * Implement 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('</p><p> Your password is <strong>%pass</strong>. You may change your password below.</p>', 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 <a href="@url">%name</a>. 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 <a href="@url">%name</a>.', 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.<br />In the meantime, a welcome message with further instructions has been sent to your e-mail address.')); - $form_state['redirect'] = ''; - return; - - } - } -} - -/** - * 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'); -} - -/** * Retrieve a list of all form elements for the specified category. */ function _user_forms(&$edit, $account, $category, $hook = 'form') { Index: modules/user/user.registry.inc =================================================================== RCS file: modules/user/user.registry.inc diff -N modules/user/user.registry.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/user/user.registry.inc 5 Jun 2009 21:44:41 -0000 @@ -0,0 +1,332 @@ +<?php +// $Id$ + +/** + * @file + * Registry-type hooks for User module. + */ + +/** + * Implement 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 callback' => 'system_admin_menu_block_access', + 'access arguments' => array('admin/user', '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'), + ); + + if (($categories = _user_categories()) && (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; +} + +/** + * Implement hook_theme(). + */ +function user_theme() { + return array( + 'user_picture' => 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), + ), + ); +} + +/** + * Implement hook_elements(). + */ +function user_elements() { + return array( + 'user_profile_category' => array( + '#theme_wrapper' => 'user_profile_category' + ), + 'user_profile_item' => array( + '#theme' => 'user_profile_item' + ), + ); +} + +/** + * Implement hook_fieldable_info(). + */ +function user_fieldable_info() { + $return = array( + 'user' => array( + 'name' => t('User'), + 'id key' => 'uid', + ), + ); + return $return; +} + +/** + * Implement 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; +} + +/** + * Implement 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") + ), + ), + ), + ); +} + +/** + * Implement 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(), + ), + ); +} + Index: modules/user/user.search.inc =================================================================== RCS file: modules/user/user.search.inc diff -N modules/user/user.search.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/user/user.search.inc 5 Jun 2009 21:44:43 -0000 @@ -0,0 +1,44 @@ +<?php +// $Id$ + +/** + * @file + * Search hooks for User module. + */ + +/** + * Implement 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; + } + } +} + Index: modules/user/user.user.inc =================================================================== RCS file: modules/user/user.user.inc diff -N modules/user/user.user.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/user/user.user.inc 5 Jun 2009 21:45:59 -0000 @@ -0,0 +1,323 @@ +<?php +// $Id$ + +/** + * @file + * User hooks for User module. + */ + +/** + * Implement 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 <a href="@user-settings-url">user settings</a>.', 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.'))), + ), + ); +} + +/** + * Implement 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); + } +} + +/** + * Implement 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. <a href="@password">Have you forgotten your password?</a>', 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']))); + } + } + } +} + +/** + * Implement 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']); + } + } +} + +/** + * Implement hook_user_categories(). + */ +function user_user_categories() { + return array(array( + 'name' => 'account', + 'title' => t('Account settings'), + 'weight' => 1, + )); +} + +/** + * Implement 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' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE); + // array_filter() returns only elements with TRUE values. + foreach (array_filter($edit['accounts']) as $uid => $value) { + $user = db_query('SELECT name FROM {users} WHERE uid = :uid', array(':uid' => $uid))->fetchField(); + $form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '<li>', '#suffix' => check_plain($user) . "</li>\n"); + } + + $form['operation'] = array('#type' => 'hidden', '#value' => 'cancel'); + + module_load_include('inc', 'user', 'user.pages'); + $form['user_cancel_method'] = array( + '#type' => 'item', + '#title' => t('When cancelling these accounts'), + ); + $form['user_cancel_method'] += user_cancel_methods(); + // Remove method descriptions. + foreach (element_children($form['user_cancel_method']) as $element) { + unset($form['user_cancel_method'][$element]['#description']); + } + + // Allow to send the account cancellation confirmation mail. + $form['user_cancel_confirm'] = array( + '#type' => 'checkbox', + '#title' => t('Require e-mail confirmation to cancel account.'), + '#default_value' => FALSE, + '#description' => t('When enabled, the user must confirm the account cancellation via e-mail.'), + ); + // Also allow to send account canceled notification mail, if enabled. + $form['user_cancel_notify'] = array( + '#type' => 'checkbox', + '#title' => t('Notify user when account is canceled.'), + '#default_value' => FALSE, + '#access' => variable_get('user_mail_status_canceled_notify', FALSE), + '#description' => t('When enabled, the user will receive an e-mail notification after the account has been cancelled.'), + ); + + return confirm_form($form, + t('Are you sure you want to cancel these user accounts?'), + 'admin/user/user', t('This action cannot be undone.'), + t('Cancel accounts'), t('Cancel')); +} + +/** + * Submit handler for mass-account cancellation form. + * + * @see user_multiple_cancel_confirm() + * @see user_cancel_confirm_form_submit() + */ +function user_multiple_cancel_confirm_submit($form, &$form_state) { + global $user; + + if ($form_state['values']['confirm']) { + foreach ($form_state['values']['accounts'] as $uid => $value) { + // Prevent user administrators from deleting themselves without confirmation. + if ($uid == $user->uid) { + $admin_form_state = $form_state; + unset($admin_form_state['values']['user_cancel_confirm']); + $admin_form_state['values']['_account'] = $user; + user_cancel_confirm_form_submit(array(), $admin_form_state); + } + else { + user_cancel($form_state['values'], $uid, $form_state['values']['user_cancel_method']); + } + } + } + $form_state['redirect'] = 'admin/user/user'; + return; +} +