=== modified file 'database/database.mysql' --- database/database.mysql 2004-05-19 14:55:19 +0000 +++ database/database.mysql 2004-06-18 15:04:33 +0000 @@ -268,8 +268,7 @@ CREATE TABLE menu ( path varchar(255) NOT NULL default '', title varchar(255) NOT NULL default '', weight tinyint(4) NOT NULL default '0', - visibility int(1) unsigned NOT NULL default '0', - status int(1) unsigned NOT NULL default '0', + type int(2) unsigned NOT NULL default '0', PRIMARY KEY (mid) ) TYPE=MyISAM; === modified file 'database/database.pgsql' --- database/database.pgsql 2004-05-19 14:55:19 +0000 +++ database/database.pgsql 2004-06-18 15:04:33 +0000 @@ -268,8 +268,7 @@ CREATE TABLE menu ( path varchar(255) NOT NULL default '', title varchar(255) NOT NULL default '', weight smallint NOT NULL default '0', - visibility smallint NOT NULL default '0', - status smallint NOT NULL default '0', + type smallint NOT NULL default '0', PRIMARY KEY (mid) ); === modified file 'database/updates.inc' --- database/updates.inc 2004-05-22 21:28:51 +0000 +++ database/updates.inc 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ "function"); $sql_updates = array( @@ -58,7 +58,8 @@ $sql_updates = array( "2004-04-21" => "update_84", "2004-04-27" => "update_85", "2004-05-10" => "update_86", - "2004-05-18" => "update_87" + "2004-05-18" => "update_87", + "2004-06-11" => "update_88" ); function update_32() { @@ -1093,6 +1094,15 @@ function update_87() { return $ret; } +function update_88() { + $ret = array(); + $ret[] = update_sql("ALTER TABLE {menu} DROP status"); + $ret[] = update_sql("ALTER TABLE {menu} DROP visibility"); + $ret[] = update_sql("ALTER TABLE {menu} ADD type INT(2) UNSIGNED DEFAULT '0' NOT NULL"); + $ret[] = update_sql("DELETE FROM {menu}"); + return $ret; +} + function update_sql($sql) { $edit = $_POST["edit"]; $result = db_query($sql); === modified file 'includes/common.inc' --- includes/common.inc 2004-06-04 18:10:05 +0000 +++ includes/common.inc 2004-06-18 15:04:33 +0000 @@ -1,9 +1,5 @@ name; } - if (arg(0) == "admin" and user_access("administer users")) { - $output = l($name, "admin/user/edit/$object->uid", array("title" => t("Administer user profile."))); - } - else { - $output = l($name, "user/view/$object->uid", array("title" => t("View user profile."))); - } + $output = l($name, "user/$object->uid", array("title" => t("View user profile."))); } else if ($object->name) { /* === modified file 'includes/menu.inc' --- includes/menu.inc 2004-06-01 21:58:45 +0000 +++ includes/menu.inc 2004-06-18 15:04:33 +0000 @@ -1,56 +1,83 @@ $title, 'callback' => $callback, 'weight' => $weight, 'visibility' => $visibility, 'status' => $status); -} +/** + * Normal menu items show up in the menu tree and can be moved/hidden by + * the administrator. + */ +define('MENU_NORMAL_ITEM', MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB | MENU_MODIFIABLE_BY_ADMIN); + +/** + * Item groupings are used for pages like "node/add" that simply list + * subpages to visit. + */ +define('MENU_ITEM_GROUPING', MENU_VISIBLE_IF_HAS_CHILDREN | MENU_VISIBLE_IN_BREADCRUMB | MENU_MODIFIABLE_BY_ADMIN); + +/** + * Callbacks simply register a path so that the correct function is fired + * when the URL is accessed. + */ +define('MENU_CALLBACK', MENU_VISIBLE_IN_BREADCRUMB); + +/** + * Dynamic menu items change frequently, and so should not be stored in the + * database for administrative customization. + */ +define('MENU_DYNAMIC_ITEM', MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB); + +/** + * Modules may "suggest" menu items that the administrator may enable. + */ +define('MENU_SUGGESTED_ITEM', MENU_MODIFIABLE_BY_ADMIN); + +/** + * Local tasks are rendered as tabs by default. + */ +define('MENU_LOCAL_TASK', MENU_IS_LOCAL_TASK); + +/** + * Local subtasks are rendered as a horizontal listing below the tabs by default. + */ +define('MENU_LOCAL_SUBTASK', MENU_IS_LOCAL_SUBTASK); + +/** + * Custom items are those defined by the administrator. + */ +define('MENU_CUSTOM_ITEM', MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB | MENU_CREATED_BY_ADMIN | MENU_MODIFIABLE_BY_ADMIN); + +/** + * Custom menus are those defined by the administrator. + */ +define('MENU_CUSTOM_MENU', MENU_IS_ROOT | MENU_VISIBLE_IN_TREE | MENU_CREATED_BY_ADMIN | MENU_MODIFIABLE_BY_ADMIN); + +/** + * Status codes for menu callbacks. + */ +define('MENU_FOUND', 1); +define('MENU_NOT_FOUND', 2); +define('MENU_ACCESS_DENIED', 3); /** * Return the menu data structure. * - * @ingroup menu * The returned structure contains much information that is useful only * internally in the menu system. External modules are likely to need only * the ['visible'] element of the returned array. All menu items that are @@ -76,38 +103,117 @@ function menu_get_menu() { global $user; if (!isset($_menu['items'])) { - menu_build(); + _menu_build(); } return $_menu; } /** - * Returns an array with the menu items that lead to the specified path. + * Change the current menu location of the user. + * + * Frequently, modules may want to make a page or node act as if it were + * in the menu tree somewhere, even though it was not registered in a + * hook_menu() implementation. If the administrator has rearranged the menu, + * the newly set location should respect this in the breadcrumb trail and + * expanded/collapsed status of menu items in the tree. This function + * allows this behavior. + * + * @param $location + * An array specifying a complete or partial breadcrumb trail for the + * new location, in the same format as the return value of hook_menu(). + * The last element of this array should be the new location itself. + * + * This function will set the new breadcrumb trail to the passed-in value, + * but if any elements of this trail are visible in the site tree, the + * trail will be "spliced in" to the existing site navigation at that point. */ -function menu_get_trail($path) { - $menu = menu_get_menu(); +function menu_set_location($location) { + global $_menu; + $temp_id = min(array_keys($_menu['items'])) - 1; + $prev_id = 0; - $trail = array(); + foreach (array_reverse($location) as $item) { + if (isset($_menu['path index'][$item['path']])) { + $mid = $_menu['path index'][$item['path']]; + if (isset ($_menu['visible'][$mid])) { + // Splice in the breadcrumb at this location. + if ($prev_id) { + $_menu['items'][$prev_id]['pid'] = $mid; + } + $prev_id = 0; + break; + } + else { + // A hidden item; show it, but only temporarily. + $_menu['items'][$mid]['type'] |= MENU_VISIBLE_IN_BREADCRUMB; + if ($prev_id) { + $_menu['items'][$prev_id]['pid'] = $mid; + } + $prev_id = $mid; + } + } + else { + $item['type'] |= MENU_VISIBLE_IN_BREADCRUMB; + if ($prev_id) { + $_menu['items'][$prev_id]['pid'] = $temp_id; + } + $_menu['items'][$temp_id] = $item; + $_menu['path index'][$item['path']] = $temp_id; - // Find the ID of the given path. - while ($path && !$menu['path index'][$path]) { + $prev_id = $temp_id; + $temp_id--; + } + } + + if ($prev_id) { + // Didn't find a home, so attach this to the main navigation menu. + $_menu['items'][$prev_id]['pid'] = 1; + } + + $final_item = array_pop($location); + menu_set_active_item($final_item['path']); +} + +/** + * Execute the handler associated with the active menu item. + * + * This is called early in the page request. The active menu item is at + * this point determined excusively by the URL. The handler that is called + * here may, as a side effect, change the active menu item so that later + * menu functions (that display the menus and breadcrumbs, for example) + * act as if the user were in a different location on the site. + */ +function menu_execute_active_handler() { + $menu = menu_get_menu(); + + // Determine the menu item containing the callback. + $path = $_GET['q']; + while ($path && (!$menu['path index'][$path] || !$menu['items'][$menu['path index'][$path]]['callback'])) { $path = substr($path, 0, strrpos($path, '/')); } $mid = $menu['path index'][$path]; - // Follow the parents up the chain to get the trail. - while ($mid && $menu['items'][$mid]) { - array_unshift($trail, $mid); - $mid = $menu['items'][$mid]['pid']; + if (!is_string($menu['items'][$mid]['callback'])) { + return MENU_NOT_FOUND; } - return $trail; + if (!_menu_item_is_accessible(menu_get_active_item())) { + return MENU_ACCESS_DENIED; + } + + // We found one, and are allowed to execute it. + $arguments = $menu['items'][$mid]['callback arguments'] ? $menu['items'][$mid]['callback arguments'] : array(); + $arg = substr($_GET['q'], strlen($menu['items'][$mid]['path']) + 1); + if (strlen($arg)) { + $arguments = array_merge($arguments, explode('/', $arg)); + } + call_user_func_array($menu['items'][$mid]['callback'], $arguments); + return MENU_FOUND; } /** * Returns the ID of the active menu item. - * @ingroup menu */ function menu_get_active_item() { return menu_set_active_item(); @@ -115,7 +221,6 @@ function menu_get_active_item() { /** * Sets the path of the active menu item. - * @ingroup menu */ function menu_set_active_item($path = NULL) { static $stored_mid; @@ -139,12 +244,30 @@ function menu_set_active_item($path = NU } /** + * Returns the ID of the current menu item or, if the current item is a + * local task, the menu item to which this task is attached. + */ +function menu_get_active_nontask_item() { + $menu = menu_get_menu(); + $mid = menu_get_active_item(); + + // Find the first non-task item: + while ($mid && (($menu['items'][$mid]['type'] & MENU_LOCAL_TASK) || ($menu['items'][$mid]['type'] & MENU_LOCAL_SUBTASK))) { + $mid = $menu['items'][$mid]['pid']; + } + + if ($mid) { + return $mid; + } +} + +/** * Returns the title of the active menu item. */ function menu_get_active_title() { $menu = menu_get_menu(); - if ($mid = menu_get_active_item()) { + if ($mid = menu_get_active_nontask_item()) { return ucfirst($menu['items'][$mid]['title']); } } @@ -153,19 +276,21 @@ function menu_get_active_title() { * Returns the help associated with the active menu item. */ function menu_get_active_help() { + $path = $_GET['q']; + $output = ''; - if (menu_active_handler_exists()) { - $path = $_GET['q']; - $output = ''; + if (!_menu_item_is_accessible(menu_get_active_item())) { + // Don't return help text for areas the user cannot access. + return; + } - $return = module_invoke_all('help', $path); - foreach ($return as $item) { - if (!empty($item)) { - $output .= $item ."\n"; - } + $return = module_invoke_all('help', $path); + foreach ($return as $item) { + if (!empty($item)) { + $output .= $item ."\n"; } - return $output; } + return $output; } /** @@ -176,105 +301,96 @@ function menu_get_active_breadcrumb() { $links[] = l(t('Home'), ''); - $trail = menu_get_trail(drupal_get_path_alias($_GET['q'])); - - // The last item in the trail is the page title; don't display it here. - array_pop($trail); - + $trail = _menu_get_trail($_GET['q']); foreach ($trail as $mid) { - // Don't show hidden menu items or items without valid link targets. - if (isset($menu['visible'][$mid]) && $menu['items'][$mid]['path'] != '') { - $links[] = _menu_render_item($mid); + if ($menu['items'][$mid]['type'] & MENU_VISIBLE_IN_BREADCRUMB) { + $links[] = theme('menu_item', $mid); } } + // The last item in the trail is the page title; don't display it here. + array_pop($links); + return $links; } /** - * Execute the handler associated with the active menu item. + * Returns true when the menu item is in the active trail. */ -function menu_execute_active_handler() { - $menu = menu_get_menu(); - - $path = $_GET['q']; - while ($path && (!$menu['path index'][$path] || $menu['items'][$menu['path index'][$path]]['callback'] === MENU_FALLTHROUGH)) { - $path = substr($path, 0, strrpos($path, '/')); - } - $mid = $menu['path index'][$path]; - if ($menu['items'][$mid]['callback'] === MENU_DENIED) { - return MENU_DENIED; - } +function menu_in_active_trail($mid) { + static $trail; - if (is_string($menu['items'][$mid]['callback'])) { - $arg = substr($_GET['q'], strlen($menu['items'][$mid]['path']) + 1); - if (strlen($arg)) { - call_user_func_array($menu['items'][$mid]['callback'], explode('/', $arg)); - } - else { - call_user_func($menu['items'][$mid]['callback']); - } - return MENU_FOUND; + if (empty($trail)) { + $trail = _menu_get_trail($_GET['q']); } - return MENU_FALLTHROUGH; + return in_array($mid, $trail); } /** - * Return true if a valid callback can be called from the current path. + * Populate the database representation of the menu. + * + * This need only be called at the start of pages that modify the menu. */ -function menu_active_handler_exists() { +function menu_rebuild() { + cache_clear_all(); + _menu_build(); $menu = menu_get_menu(); - $path = $_GET['q']; - while ($path && (!$menu['path index'][$path] || $menu['items'][$menu['path index'][$path]]['callback'] === MENU_FALLTHROUGH)) { - $path = substr($path, 0, strrpos($path, '/')); - } - $mid = $menu['path index'][$path]; + $new_items = array(); + foreach ($menu['items'] as $mid => $item) { + if ($mid < 0 && ($item['type'] & MENU_MODIFIABLE_BY_ADMIN)) { + $new_mid = db_next_id('menu_mid'); + if (isset($new_items[$item['pid']])) { + $new_pid = $new_items[$item['pid']]['mid']; + } + else { + $new_pid = $item['pid']; + } + + // Fix parent IDs for menu items already added. + if ($item['children']) { + foreach ($item['children'] as $child) { + if (isset($new_items[$child])) { + $new_items[$child]['pid'] = $new_mid; + } + } + } - if ($menu['items'][$mid]['callback'] === MENU_FALLTHROUGH) { - return FALSE; + $new_items[$mid] = array('mid' => $new_mid, 'pid' => $new_pid, 'path' => $item['path'], 'title' => $item['title'], 'weight' => $item['weight'], 'type' => $item['type']); + } } - if ($menu['items'][$mid]['callback'] === MENU_DENIED) { - return FALSE; + + foreach ($new_items as $item) { + db_query('INSERT INTO {menu} (mid, pid, path, title, weight, type) VALUES (%d, %d, \'%s\', \'%s\', %d, %d)', $item['mid'], $item['pid'], $item['path'], $item['title'], $item['weight'], $item['type']); } - return function_exists($menu['items'][$mid]['callback']); + // Rebuild the menu to account for any changes. + _menu_build(); } +/** @} end of "menu" function group */ + /** - * Returns true when the path is in the active trail. + * @addtogroup themeable + * @{ */ -function menu_in_active_trail($mid) { - static $trail; - - if (empty($trail)) { - $trail = menu_get_trail(drupal_get_path_alias($_GET['q'])); - } - - return in_array($mid, $trail); -} /** * Returns a rendered menu tree. */ -function menu_tree($pid = 1) { - static $trail; +function theme_menu_tree($pid = 1, $all = FALSE) { $menu = menu_get_menu(); $output = ''; - if (empty($trail)) { - $trail = menu_get_trail($_GET['q']); - } - if (isset($menu['visible'][$pid]) && $menu['visible'][$pid]['children']) { foreach ($menu['visible'][$pid]['children'] as $mid) { $style = (count($menu['visible'][$mid]['children']) ? (menu_in_active_trail($mid) ? 'expanded' : 'collapsed') : 'leaf'); $output .= "
  • "; - $output .= _menu_render_item($mid); - if (menu_in_active_trail($mid)) { - $output .= menu_tree($mid); + $output .= theme('menu_item', $mid); + if ($all || menu_in_active_trail($mid)) { + $output .= theme('menu_tree', $mid); } $output .= "
  • \n"; } @@ -288,29 +404,166 @@ function menu_tree($pid = 1) { } /** + * Generate the HTML representing a given menu item ID. + * + * @param $mid + * The menu ID to render. + */ +function theme_menu_item($mid) { + $menu = menu_get_menu(); + + return l($menu['items'][$mid]['title'], $menu['items'][$mid]['path']); +} + +/** + * Returns the rendered local tasks. The default implementation renders + * them as tabs. + */ +function theme_menu_local_tasks() { + + $active = true; + + if ($mid = menu_get_active_nontask_item()) { + $menu = menu_get_menu(); + + if ($children = $menu['items'][$mid]['children']) { + foreach ($menu['items'][$mid]['children'] as $cid) { + if (($menu['items'][$cid]['type'] & MENU_IS_LOCAL_TASK) && _menu_item_is_accessible($cid)) { + if (menu_in_active_trail($cid)) { + $tabs[] = theme('menu_local_task', $cid, TRUE); + $active = false; + } + else { + $tabs[] = theme('menu_local_task', $cid, FALSE); + } + } + } + + if ($tabs) { + // We add a default view-tab for the parent: + $output = "\n"; + } + } + } + + return $output; +} + +/** + * Generate the HTML representing a given menu item ID as a set of tabs. + * + * @param $mid + * The menu ID to render. + * @param $active + * Whether this tab or a subtab is the active menu item. + */ +function theme_menu_local_task($mid, $active) { + if ($active) { + return '
  • '. theme('menu_item', $mid) . theme('menu_local_subtasks', $mid) ."
  • \n"; + } + else { + return '
  • '. theme('menu_item', $mid) ."
  • \n"; + } +} + +/** + * Generate the HTML representing the children of a given menu item ID + * as a set of tabs. + * + * @param $pid + * The menu ID of the parent item. + */ +function theme_menu_local_subtasks($pid) { + $menu = menu_get_menu(); + + $tabs = ''; + if ($children = $menu['items'][$pid]['children']) { + foreach ($children as $cid) { + if (_menu_item_is_accessible($cid) && ($menu['items'][$cid]['type'] & MENU_IS_LOCAL_SUBTASK)) { + $tabs .= theme('menu_local_task', $cid, menu_in_active_trail($cid)); + } + } + + if ($tabs) { + return "\n"; + } + } +} + +/** @} End of addtogroup themeable */ + +/** + * Returns an array with the menu items that lead to the specified path. + */ +function _menu_get_trail($path) { + $menu = menu_get_menu(); + + $trail = array(); + + // Find the ID of the given path. + while ($path && !$menu['path index'][$path]) { + $path = substr($path, 0, strrpos($path, '/')); + } + $mid = $menu['path index'][$path]; + + // Follow the parents up the chain to get the trail. + while ($mid && $menu['items'][$mid]) { + array_unshift($trail, $mid); + $mid = $menu['items'][$mid]['pid']; + } + + return $trail; +} + +/** + * Comparator routine for use in sorting menu items. + */ +function _menu_sort($a, $b) { + $menu = menu_get_menu(); + + $a = &$menu['items'][$a]; + $b = &$menu['items'][$b]; + + return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : ($a['title'] < $b['title'] ? -1 : 1)); +} + +/** * Build the menu by querying both modules and the database. */ -function menu_build() { +function _menu_build() { global $_menu; global $user; // Start from a clean slate. $_menu = array(); - // Build a sequential list of all menu items. - module_invoke_all('link', 'system'); - $_menu['path index'] = array(); // Set up items array, including default "Navigation" menu. - $_menu['items'] = array(0 => array(), 1 => array('pid' => 0, 'title' => t('Navigation'), 'weight' => -50, 'visibility' => MENU_SHOW, 'status' => MENU_LOCKED)); + $_menu['items'] = array( + 0 => array('type' => MENU_IS_ROOT), + 1 => array('pid' => 0, 'title' => t('Navigation'), 'weight' => -50, 'access' => TRUE, 'type' => MENU_IS_ROOT | MENU_VISIBLE_IN_TREE) + ); + + // Build a sequential list of all menu items. + $menu_item_list = module_invoke_all('menu'); // Menu items not in the DB get temporary negative IDs. $temp_mid = -1; - foreach ($_menu['list'] as $path => $data) { + foreach ($menu_item_list as $item) { + if (!isset($item['type'])) { + $item['type'] = MENU_NORMAL_ITEM; + } $mid = $temp_mid; - $_menu['items'][$mid] = array('path' => $path, 'title' => $data['title'], 'callback' => $data['callback'], 'weight' => $data['weight'], 'visibility' => $data['visibility'], 'status' => $data['status']); - $_menu['path index'][$path] = $mid; + if (isset($_menu['path index'][$item['path']])) { + // Newer menu items overwrite older ones. + unset($_menu['items'][$_menu['path index'][$item['path']]]); + } + $_menu['items'][$mid] = $item; + $_menu['path index'][$item['path']] = $mid; $temp_mid--; } @@ -319,25 +572,24 @@ function menu_build() { if (module_exist('menu')) { $result = db_query('SELECT * FROM {menu}'); while ($item = db_fetch_object($result)) { - // First, add any custom items added by the administrator. - if ($item->status == MENU_CUSTOM) { - $_menu['items'][$item->mid] = array('pid' => $item->pid, 'path' => $item->path, 'title' => $item->title, 'callback' => MENU_FALLTHROUGH, 'weight' => $item->weight, 'visibility' => MENU_SHOW, 'status' => MENU_CUSTOM); - $_menu['path index'][$item->path] = $item->mid; - } // Don't display non-custom menu items if no module declared them. - else if ($old_mid = $_menu['path index'][$item->path]) { + if ($old_mid = $_menu['path index'][$item->path]) { $_menu['items'][$item->mid] = $_menu['items'][$old_mid]; unset($_menu['items'][$old_mid]); $_menu['path index'][$item->path] = $item->mid; // If administrator has changed item position, reflect the change. - if ($item->status == MENU_MODIFIED) { + if ($item->type & MENU_MODIFIED_BY_ADMIN) { $_menu['items'][$item->mid]['title'] = $item->title; $_menu['items'][$item->mid]['pid'] = $item->pid; $_menu['items'][$item->mid]['weight'] = $item->weight; - $_menu['items'][$item->mid]['visibility'] = $item->visibility; - $_menu['items'][$item->mid]['status'] = $item->status; + $_menu['items'][$item->mid]['type'] = $item->type; } } + // Next, add any custom items added by the administrator. + else if ($item->type & MENU_CREATED_BY_ADMIN) { + $_menu['items'][$item->mid] = array('pid' => $item->pid, 'path' => $item->path, 'title' => $item->title, 'access' => TRUE, 'weight' => $item->weight, 'type' => $item->type); + $_menu['path index'][$item->path] = $item->mid; + } } } @@ -372,7 +624,29 @@ function menu_build() { } // Prepare to display trees to the user as required. - menu_build_visible_tree(); + _menu_build_visible_tree(); +} + +/** + * Determine whether the given menu item is accessible to the current user. + * + * Use this instead of just checking the "access" property of a menu item + * to properly handle items with fall-through semantics. + */ +function _menu_item_is_accessible($mid) { + $menu = menu_get_menu(); + + if (isset($menu['items'][$mid]['access'])) { + return $menu['items'][$mid]['access']; + } + + // Follow the path up to find the actual callback. + $path = $menu['items'][$mid]['path']; + while ($path && (!$menu['path index'][$path] || !$menu['items'][$menu['path index'][$path]]['callback'])) { + $path = substr($path, 0, strrpos($path, '/')); + } + $callback_mid = $menu['path index'][$path]; + return $menu['items'][$callback_mid]['access']; } /** @@ -381,7 +655,7 @@ function menu_build() { * Since this is only for display, we only need title, path, and children * for each item. */ -function menu_build_visible_tree($pid = 0) { +function _menu_build_visible_tree($pid = 0) { global $_menu; if (isset($_menu['items'][$pid])) { @@ -391,26 +665,14 @@ function menu_build_visible_tree($pid = if ($parent['children']) { usort($parent['children'], '_menu_sort'); foreach ($parent['children'] as $mid) { - $children = array_merge($children, menu_build_visible_tree($mid)); + $children = array_merge($children, _menu_build_visible_tree($mid)); } } - $visible = ($parent['visibility'] == MENU_SHOW) || - ($parent['visibility'] == MENU_HIDE_NOCHILD && count($children) > 0); + $visible = ($parent['type'] & MENU_VISIBLE_IN_TREE) || + ($parent['type'] & MENU_VISIBLE_IF_HAS_CHILDREN && count($children) > 0); + $allowed = _menu_item_is_accessible($pid); - if ($parent['callback'] === MENU_FALLTHROUGH) { - // Follow the path up to find the actual callback. - $path = $parent['path']; - while ($path && (!$_menu['path index'][$path] || $_menu['items'][$_menu['path index'][$path]]['callback'] === MENU_FALLTHROUGH)) { - $path = substr($path, 0, strrpos($path, '/')); - } - $callback_mid = $_menu['path index'][$path]; - $allowed = $_menu['items'][$callback_mid]['callback'] !== MENU_DENIED; - } - else { - $allowed = $parent['callback'] !== MENU_DENIED; - } - - if ($visible && $allowed) { + if (($parent['type'] & MENU_IS_ROOT) || ($visible && $allowed)) { $_menu['visible'][$pid] = array('title' => $parent['title'], 'path' => $parent['path'], 'children' => $children); foreach ($children as $mid) { $_menu['visible'][$mid]['pid'] = $pid; @@ -425,66 +687,4 @@ function menu_build_visible_tree($pid = return array(); } -/** - * Populate the database representation of the menu. - * - * @ingroup menu - * This need only be called at the start of pages that modify the menu. - */ -function menu_rebuild() { - cache_clear_all(); - menu_build(); - $menu = menu_get_menu(); - - $new_items = array(); - foreach ($menu['items'] as $mid => $item) { - if ($mid < 0 && ($item->status != MENU_LOCKED)) { - $new_mid = db_next_id('menu_mid'); - if (isset($new_items[$item['pid']])) { - $new_pid = $new_items[$item['pid']]['mid']; - } - else { - $new_pid = $item['pid']; - } - - // Fix parent IDs for menu items already added. - if ($item['children']) { - foreach ($item['children'] as $child) { - if (isset($new_items[$child])) { - $new_items[$child]['pid'] = $new_mid; - } - } - } - - $new_items[$mid] = array('mid' => $new_mid, 'pid' => $new_pid, 'path' => $item['path'], 'title' => $item['title'], 'weight' => $item['weight'], 'visibility' => $item['visibility'], 'status' => $item['status']); - } - } - - foreach ($new_items as $item) { - db_query('INSERT INTO {menu} (mid, pid, path, title, weight, visibility, status) VALUES (%d, %d, \'%s\', \'%s\', %d, %d, %d)', $item['mid'], $item['pid'], $item['path'], $item['title'], $item['weight'], $item['visibility'], $item['status']); - } - - // Rebuild the menu to account for any changes. - menu_build(); -} - -/** - * Comparator routine for use in sorting menu items. - */ -function _menu_sort($a, $b) { - $menu = menu_get_menu(); - - $a = &$menu['items'][$a]; - $b = &$menu['items'][$b]; - - return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : ($a['title'] < $b['title'] ? -1 : 1)); -} - -function _menu_render_item($mid) { - $menu = menu_get_menu(); - - return l($menu['items'][$mid]['title'], $menu['items'][$mid]['path']); -} - - ?> === modified file 'includes/theme.inc' --- includes/theme.inc 2004-06-02 05:35:50 +0000 +++ includes/theme.inc 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ Theme system + * @see Theme system * @see themeable */ @@ -24,7 +24,7 @@ function theme_help($section) { $output = ''; switch ($section) { - case 'admin/system/themes#description': + case 'admin/themes#description': $output = t("The base theme"); break; } @@ -142,6 +142,7 @@ function theme_page($content, $title = N if (isset($title)) { drupal_set_title($title); } + if (isset($breadcrumb)) { drupal_set_breadcrumb($breadcrumb); } @@ -162,6 +163,11 @@ function theme_page($content, $title = N $output .= theme("breadcrumb", drupal_get_breadcrumb()); $output .= "

    " . drupal_get_title() . "

    "; + + if ($tabs = theme('menu_local_tasks')) { + $output .= $tabs; + } + if ($help = menu_get_active_help()) { $output .= "$help
    "; } @@ -300,6 +306,17 @@ function theme_form_element($title, $val return $output; } + +/** + * Returns themed sub menu, typically displayed under the tabs. + * + * @param $menus an associative array of links. + */ + +function theme_submenu($links) { + return "
    ". implode(' | ', $links) ."
    "; +} + /** * Returns themed table. * === modified file 'index.php' --- index.php 2004-04-21 13:56:37 +0000 +++ index.php 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ 'admin', 'title' => t('administer'), + 'access' => user_access('access administration pages'), + 'callback' => 'admin_main_page', + 'weight' => 9); + return $items; } /** === modified file 'modules/aggregator.module' --- modules/aggregator.module 2004-06-02 19:01:40 +0000 +++ modules/aggregator.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ To learn much more about RSS, read Mark Pilgrim\'s What is RSS and WebReference.com\'s The Evolution of RSS.

    NOTE: Enable your site\'s XML syndication button by turning on the Syndicate block in block management.

    Adding news feeds

    -

    To subscribe to an RSS feed on another site, use the RSS/RDF administration page.

    -

    Once there, select new feed from the menu. Drupal will then ask for the following:

    +

    To subscribe to an RSS feed on another site, use the aggregation page.

    +

    Once there, click the new feed tab. Drupal will then ask for the following:

    -

    Once you submit your new feed, check to see if it is working properly. Select update items on the RSS/RDF page. If you do not see any items listed for that feed, edit the feed and make sure that the URL was entered correctly.

    +

    Once you submit your new feed, check to see if it is working properly. Select update items on the aggregation page. If you do not see any items listed for that feed, edit the feed and make sure that the URL was entered correctly.

    Adding categories

    -

    News items can be filed into categories. To create a category, start at the RSS/RDF administration page.

    +

    News items can be filed into categories. To create a category, start at the aggregation page.

    Once there, select new category from the menu. Drupal will then ask for the following:

    Creating a poll is much like creating any other node. Click \"create poll\" in your user box. The title of the poll should be the question, then enter the answers and the \"base\" vote counts. You can also choose the time period over which the vote will run.

    The Poll item in the navigation links will take you to a page where you can see all the current polls, vote on them (if you haven't already) and view the results.

    ", array("%permissions" => url("admin/user/permission"), "%poll" => url("poll"))); - case 'admin/system/modules#description': + case 'admin/modules#description': return t("Enables your site to capture votes on different topics in the form of multiple choice questions."); case 'node/add#poll': return t("A poll is a multiple-choice question which visitors can vote on."); @@ -185,11 +185,7 @@ function poll_insert($node) { function poll_link($type, $node = 0, $main) { $links = array(); - if ($type == 'system') { - menu('node/add/poll', t('poll'), user_access('create polls') ? MENU_FALLTHROUGH : MENU_DENIED, 0); - menu('poll', t('polls'), user_access('access content') ? 'poll_page' : MENU_DENIED, 0, MENU_HIDE); - } - else if ($type == 'page' && user_access('access content')) { + if ($type == 'page' && user_access('access content')) { $links[] = l(t('polls'), 'poll', array('title' => t('View the list of polls on this site.'))); } else if ($type == 'node' && $node->type == 'poll') { @@ -200,10 +196,10 @@ function poll_link($type, $node = 0, $ma if ($node->allowvotes) { if (arg(3) == 'results') { - $links[] = l(t('voting form'), 'node/view/'. $node->nid); + $links[] = l(t('voting form'), 'node/'. $node->nid); } else { - $links[] = l(t('view results'), 'node/view/'. $node->nid .'/results'); + $links[] = l(t('view results'), 'node/'. $node->nid .'/results'); } } } @@ -212,6 +208,20 @@ function poll_link($type, $node = 0, $ma } /** + * Implementation of hook_menu(). + */ +function poll_menu() { + $items = array(); + $items[] = array('path' => 'node/add/poll', 'title' => t('poll'), + 'access' => user_access('create polls')); + $items[] = array('path' => 'poll', 'title' => t('polls'), + 'callback' => 'poll_page', + 'access' => user_access('access content'), + 'type' => MENU_SUGGESTED_ITEM); + return $items; +} + +/** * Determine an adjusted user id, to allow for basic tracking of anonymous * users (IP-based). */ @@ -261,7 +271,7 @@ function poll_page() { $result = pager_query("SELECT n.nid, n.title, p.active, SUM(c.chvotes) AS votes FROM {node} n INNER JOIN {poll} p ON n.nid=p.nid INNER JOIN {poll_choices} c ON n.nid=c.nid WHERE type = 'poll' AND status = '1' AND moderate = '0' GROUP BY n.nid, n.title, p.active, n.created ORDER BY n.created DESC", 15); $output = ''; $output .= theme("pager", NULL, 15); @@ -307,7 +317,7 @@ function poll_view_voting(&$node, $main, $form .= form_hidden('nid', $node->nid); $form .= form_submit(t('Vote'), 'vote') .''; - $output .= form($form, 'post', url('node/view/'. $node->nid)); + $output .= form($form, 'post', url('node/'. $node->nid)); $output .= ''; return $output; === modified file 'modules/profile.module' --- modules/profile.module 2004-06-01 21:58:45 +0000 +++ modules/profile.module 2004-06-18 15:04:33 +0000 @@ -1,33 +1,49 @@ 'profile', 'title' => t('browse'), + 'callback' => 'profile_browse', + 'access' => TRUE, + 'type' => MENU_SUGGESTED_ITEM); + $items[] = array('path' => 'admin/user/configure/profile', 'title' => t('profiles'), + 'callback' => 'profile_admin_overview', + 'access' => user_access('administer users'), + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/profile/add', 'title' => t('add field'), + 'callback' => 'profile_browse', + 'access' => user_access('administer users'), + 'type' => MENU_CALLBACK); + $items[] = array('path' => 'admin/user/configure/profile/edit', 'title' => t('edit field'), + 'callback' => 'profile_browse', + 'access' => user_access('administer users'), + 'type' => MENU_CALLBACK); + $items[] = array('path' => 'admin/user/configure/profile/delete', 'title' => t('delete field'), + 'callback' => 'profile_browse', + 'access' => user_access('administer users'), + 'type' => MENU_CALLBACK); + return $items; } +/** + * Menu callback; display a list of user information. + */ function profile_browse() { $name = strip_tags(arg(1)); @@ -38,7 +54,7 @@ function profile_browse() { if ($field->fid) { // Compile a list of fields to show $fields = array(); - $result = db_query("SELECT name, title, type FROM {profile_fields} WHERE fid != %d AND overview = 1", $field->fid); + $result = db_query('SELECT name, title, type FROM {profile_fields} WHERE fid != %d AND overview = 1', $field->fid); while ($record = db_fetch_object($result)) { $fields[] = $record; } @@ -71,7 +87,7 @@ function profile_browse() { else { $title = $field->page; } - $output .= ""; + $output .= ''; print theme('page', $output, $title); } @@ -111,7 +127,7 @@ function profile_view_field($user, $fiel case 'checkbox': return l($field->title, "profile/$field->name"); case 'url': - return "". strip_tags($value) .""; case 'list': + return ''. strip_tags($value) .''; case 'list': $values = split("[\n\r]", $value); $fields = array(); foreach ($values as $value) { @@ -157,7 +173,7 @@ function profile_edit_profile($edit, $us $fields[$field->category] .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, $field->explanation, NULL, $field->required); break; case 'list': - $fields[$field->category] .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, $field->explanation ." ". t('Put each entry on a separate line. No HTML allowed.'), NULL, $field->required); + $fields[$field->category] .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, $field->explanation .' '. t('Put each entry on a separate line. No HTML allowed.'), NULL, $field->required); break; case 'checkbox': $fields[$field->category] .= form_checkbox($field->title, $field->name, 1, $edit[$field->name], $field->explanation, NULL, $field->required); @@ -185,17 +201,20 @@ function profile_validate_profile($edit) while ($field = db_fetch_object($result)) { if ($edit[$field->name]) { if ($field->type == 'url' && !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))); + form_set_error($field->name, t('The value provided for "%field" is not a valid URL.', array('%field' => $field->title))); } } else if ($field->required) { - form_set_error($field->name, t("The field '%field' is required.", array('%field' => $field->title))); + form_set_error($field->name, t('The field "%field" is required.', array('%field' => $field->title))); } } return $edit; } +/** + * Implementation of hook_user(). + */ function profile_user($type, &$edit, &$user) { switch ($type) { case 'load': @@ -236,6 +255,9 @@ function profile_validate_form($edit) { } } +/** + * Menu callback; adds a new field to all user profiles. + */ function profile_admin_add($type) { $type = _profile_field_types($type); @@ -267,6 +289,9 @@ function profile_admin_add($type) { print theme('page', _profile_field_form($type, $data), t('Add new %type', array('%type' => $type))); } +/** + * Menu callback; displays the profile field editing form. + */ function profile_admin_edit($fid) { if ($_POST['op']) { @@ -288,6 +313,9 @@ function profile_admin_edit($fid) { print theme('page', _profile_field_form($data['type'], $data), t('Edit %type', array('%type' => $edit['type']))); } +/** + * Menu callback; deletes a field from all user profiles. + */ function profile_admin_delete($fid) { db_query('DELETE FROM {profile_fields} WHERE fid = %d', $fid); drupal_set_message(t('the field has been deleted.')); @@ -296,24 +324,24 @@ function profile_admin_delete($fid) { function _profile_field_form($type, $edit = array()) { - $group = form_textfield(t('Category'), 'category', $edit['category'], 70, 128, t("The category the new field should be part of. Categories are used to group fields logically. An example category is 'Personal information'.")); - $group .= form_textfield(t('Title'), 'title', $edit['title'], 70, 128, t("The title of the new field. The title will be shown to the user. An example title is 'Favorite color'.")); - $group .= form_textfield(t('Form name'), 'name', $edit['name'], 70, 128, t("The name of the field. The form name is not shown to the user but used internally in the HTML code and URLs. -Unless you know what you are doing, it is highly recommended that you prefix the form name with profile_ to avoid name clashes with other fields. Spaces or any other special characters except dash (-) and underscore (_) are not allowed. An example name is 'profile_favorite_color' or perhaps just 'profile_color'.")); - $group .= form_textarea(t('Explanation'), 'explanation', $edit['explanation'], 70, 3, t("An optional explanation to go with the new field. The explanation will be shown to the user.")); + $group = form_textfield(t('Category'), 'category', $edit['category'], 70, 128, t('The category the new field should be part of. Categories are used to group fields logically. An example category is "Personal information".')); + $group .= form_textfield(t('Title'), 'title', $edit['title'], 70, 128, t('The title of the new field. The title will be shown to the user. An example title is "Favorite color".')); + $group .= form_textfield(t('Form name'), 'name', $edit['name'], 70, 128, t('The name of the field. The form name is not shown to the user but used internally in the HTML code and URLs. +Unless you know what you are doing, it is highly recommended that you prefix the form name with profile_ to avoid name clashes with other fields. Spaces or any other special characters except dash (-) and underscore (_) are not allowed. An example name is "profile_favorite_color" or perhaps just "profile_color".')); + $group .= form_textarea(t('Explanation'), 'explanation', $edit['explanation'], 70, 3, t('An optional explanation to go with the new field. The explanation will be shown to the user.')); if ($type == 'selection') { - $group .= form_textarea(t('Selection options'), 'options', $edit['options'], 70, 8, t("A list of all options. Put each option on a separate line. Example options are 'red', 'blue', 'green', etc.")); + $group .= form_textarea(t('Selection options'), 'options', $edit['options'], 70, 8, t('A list of all options. Put each option on a separate line. Example options are "red", "blue", "green", etc.')); } - $group .= form_weight(t('Weight'), 'weight', $edit['weight'], 5, t("The weights define the order in which the form fields are shown. Lighter fields \"float up\" towards the top of the category.")); + $group .= form_weight(t('Weight'), 'weight', $edit['weight'], 5, t('The weights define the order in which the form fields are shown. Lighter fields "float up" towards the top of the category.')); $group .= form_checkbox(t('Required field.'), 'required', 1, $edit['required']); $output = form_group(t('Field settings'), $group); $group = ''; if ($type == 'selection' || $type == 'list') { - $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t("The title of the page showing all users with the specified field. The word %value will be substituted with the corresponding value. An example page title is 'People whose favorite color is %value'.")); + $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t('The title of the page showing all users with the specified field. The word %value will be substituted with the corresponding value. An example page title is "People whose favorite color is %value".')); } else { - $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t("The title of the page showing all users with the specified field.")); + $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t('The title of the page showing all users with the specified field.')); } $group .= form_checkbox(t('Should this field be shown on the member listing pages.'), 'overview', 1, $edit['overview']); @@ -323,11 +351,14 @@ Unless you know what you are doing, it i return form($output); } +/** + * Menu callback; display a listing of all editable profile fields. + */ function profile_admin_overview() { $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight'); while ($field = db_fetch_object($result)) { - $rows[] = array($field->title, $field->name, $field->type, $field->category, l(t('edit'), "admin/system/modules/profile/edit/$field->fid"), l(t('delete'), "admin/system/modules/profile/delete/$field->fid")); + $rows[] = array($field->title, $field->name, $field->type, $field->category, l(t('edit'), "admin/user/configure/profile/edit/$field->fid"), l(t('delete'), "admin/user/configure/profile/delete/$field->fid")); } $header = array(t('title'), t('name'), t('type'), t('category'), array('data' => t('operations'), 'colspan' => '2')); @@ -336,7 +367,7 @@ function profile_admin_overview() { $output .= '

    '. t('Create new field') .'

    '; $output .= ''; @@ -347,7 +378,7 @@ function theme_profile_profile($user, $f $output = "
    \n"; $output .= theme('user_picture', $user); - $output .= "
    ". format_name($user) ."
    \n"; + $output .= '
    '. format_name($user) ."
    \n"; foreach ($fields as $field) { if ($value = profile_view_field($user, $field)) { === modified file 'modules/profile/profile.module' --- modules/profile/profile.module 2004-06-01 21:58:45 +0000 +++ modules/profile/profile.module 2004-06-18 15:04:33 +0000 @@ -1,33 +1,49 @@ 'profile', 'title' => t('browse'), + 'callback' => 'profile_browse', + 'access' => TRUE, + 'type' => MENU_SUGGESTED_ITEM); + $items[] = array('path' => 'admin/user/configure/profile', 'title' => t('profiles'), + 'callback' => 'profile_admin_overview', + 'access' => user_access('administer users'), + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/profile/add', 'title' => t('add field'), + 'callback' => 'profile_browse', + 'access' => user_access('administer users'), + 'type' => MENU_CALLBACK); + $items[] = array('path' => 'admin/user/configure/profile/edit', 'title' => t('edit field'), + 'callback' => 'profile_browse', + 'access' => user_access('administer users'), + 'type' => MENU_CALLBACK); + $items[] = array('path' => 'admin/user/configure/profile/delete', 'title' => t('delete field'), + 'callback' => 'profile_browse', + 'access' => user_access('administer users'), + 'type' => MENU_CALLBACK); + return $items; } +/** + * Menu callback; display a list of user information. + */ function profile_browse() { $name = strip_tags(arg(1)); @@ -38,7 +54,7 @@ function profile_browse() { if ($field->fid) { // Compile a list of fields to show $fields = array(); - $result = db_query("SELECT name, title, type FROM {profile_fields} WHERE fid != %d AND overview = 1", $field->fid); + $result = db_query('SELECT name, title, type FROM {profile_fields} WHERE fid != %d AND overview = 1', $field->fid); while ($record = db_fetch_object($result)) { $fields[] = $record; } @@ -71,7 +87,7 @@ function profile_browse() { else { $title = $field->page; } - $output .= "
    "; + $output .= ''; print theme('page', $output, $title); } @@ -111,7 +127,7 @@ function profile_view_field($user, $fiel case 'checkbox': return l($field->title, "profile/$field->name"); case 'url': - return "". strip_tags($value) .""; case 'list': + return ''. strip_tags($value) .''; case 'list': $values = split("[\n\r]", $value); $fields = array(); foreach ($values as $value) { @@ -157,7 +173,7 @@ function profile_edit_profile($edit, $us $fields[$field->category] .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, $field->explanation, NULL, $field->required); break; case 'list': - $fields[$field->category] .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, $field->explanation ." ". t('Put each entry on a separate line. No HTML allowed.'), NULL, $field->required); + $fields[$field->category] .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, $field->explanation .' '. t('Put each entry on a separate line. No HTML allowed.'), NULL, $field->required); break; case 'checkbox': $fields[$field->category] .= form_checkbox($field->title, $field->name, 1, $edit[$field->name], $field->explanation, NULL, $field->required); @@ -185,17 +201,20 @@ function profile_validate_profile($edit) while ($field = db_fetch_object($result)) { if ($edit[$field->name]) { if ($field->type == 'url' && !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))); + form_set_error($field->name, t('The value provided for "%field" is not a valid URL.', array('%field' => $field->title))); } } else if ($field->required) { - form_set_error($field->name, t("The field '%field' is required.", array('%field' => $field->title))); + form_set_error($field->name, t('The field "%field" is required.', array('%field' => $field->title))); } } return $edit; } +/** + * Implementation of hook_user(). + */ function profile_user($type, &$edit, &$user) { switch ($type) { case 'load': @@ -236,6 +255,9 @@ function profile_validate_form($edit) { } } +/** + * Menu callback; adds a new field to all user profiles. + */ function profile_admin_add($type) { $type = _profile_field_types($type); @@ -267,6 +289,9 @@ function profile_admin_add($type) { print theme('page', _profile_field_form($type, $data), t('Add new %type', array('%type' => $type))); } +/** + * Menu callback; displays the profile field editing form. + */ function profile_admin_edit($fid) { if ($_POST['op']) { @@ -288,6 +313,9 @@ function profile_admin_edit($fid) { print theme('page', _profile_field_form($data['type'], $data), t('Edit %type', array('%type' => $edit['type']))); } +/** + * Menu callback; deletes a field from all user profiles. + */ function profile_admin_delete($fid) { db_query('DELETE FROM {profile_fields} WHERE fid = %d', $fid); drupal_set_message(t('the field has been deleted.')); @@ -296,24 +324,24 @@ function profile_admin_delete($fid) { function _profile_field_form($type, $edit = array()) { - $group = form_textfield(t('Category'), 'category', $edit['category'], 70, 128, t("The category the new field should be part of. Categories are used to group fields logically. An example category is 'Personal information'.")); - $group .= form_textfield(t('Title'), 'title', $edit['title'], 70, 128, t("The title of the new field. The title will be shown to the user. An example title is 'Favorite color'.")); - $group .= form_textfield(t('Form name'), 'name', $edit['name'], 70, 128, t("The name of the field. The form name is not shown to the user but used internally in the HTML code and URLs. -Unless you know what you are doing, it is highly recommended that you prefix the form name with profile_ to avoid name clashes with other fields. Spaces or any other special characters except dash (-) and underscore (_) are not allowed. An example name is 'profile_favorite_color' or perhaps just 'profile_color'.")); - $group .= form_textarea(t('Explanation'), 'explanation', $edit['explanation'], 70, 3, t("An optional explanation to go with the new field. The explanation will be shown to the user.")); + $group = form_textfield(t('Category'), 'category', $edit['category'], 70, 128, t('The category the new field should be part of. Categories are used to group fields logically. An example category is "Personal information".')); + $group .= form_textfield(t('Title'), 'title', $edit['title'], 70, 128, t('The title of the new field. The title will be shown to the user. An example title is "Favorite color".')); + $group .= form_textfield(t('Form name'), 'name', $edit['name'], 70, 128, t('The name of the field. The form name is not shown to the user but used internally in the HTML code and URLs. +Unless you know what you are doing, it is highly recommended that you prefix the form name with profile_ to avoid name clashes with other fields. Spaces or any other special characters except dash (-) and underscore (_) are not allowed. An example name is "profile_favorite_color" or perhaps just "profile_color".')); + $group .= form_textarea(t('Explanation'), 'explanation', $edit['explanation'], 70, 3, t('An optional explanation to go with the new field. The explanation will be shown to the user.')); if ($type == 'selection') { - $group .= form_textarea(t('Selection options'), 'options', $edit['options'], 70, 8, t("A list of all options. Put each option on a separate line. Example options are 'red', 'blue', 'green', etc.")); + $group .= form_textarea(t('Selection options'), 'options', $edit['options'], 70, 8, t('A list of all options. Put each option on a separate line. Example options are "red", "blue", "green", etc.')); } - $group .= form_weight(t('Weight'), 'weight', $edit['weight'], 5, t("The weights define the order in which the form fields are shown. Lighter fields \"float up\" towards the top of the category.")); + $group .= form_weight(t('Weight'), 'weight', $edit['weight'], 5, t('The weights define the order in which the form fields are shown. Lighter fields "float up" towards the top of the category.')); $group .= form_checkbox(t('Required field.'), 'required', 1, $edit['required']); $output = form_group(t('Field settings'), $group); $group = ''; if ($type == 'selection' || $type == 'list') { - $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t("The title of the page showing all users with the specified field. The word %value will be substituted with the corresponding value. An example page title is 'People whose favorite color is %value'.")); + $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t('The title of the page showing all users with the specified field. The word %value will be substituted with the corresponding value. An example page title is "People whose favorite color is %value".')); } else { - $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t("The title of the page showing all users with the specified field.")); + $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t('The title of the page showing all users with the specified field.')); } $group .= form_checkbox(t('Should this field be shown on the member listing pages.'), 'overview', 1, $edit['overview']); @@ -323,11 +351,14 @@ Unless you know what you are doing, it i return form($output); } +/** + * Menu callback; display a listing of all editable profile fields. + */ function profile_admin_overview() { $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight'); while ($field = db_fetch_object($result)) { - $rows[] = array($field->title, $field->name, $field->type, $field->category, l(t('edit'), "admin/system/modules/profile/edit/$field->fid"), l(t('delete'), "admin/system/modules/profile/delete/$field->fid")); + $rows[] = array($field->title, $field->name, $field->type, $field->category, l(t('edit'), "admin/user/configure/profile/edit/$field->fid"), l(t('delete'), "admin/user/configure/profile/delete/$field->fid")); } $header = array(t('title'), t('name'), t('type'), t('category'), array('data' => t('operations'), 'colspan' => '2')); @@ -336,7 +367,7 @@ function profile_admin_overview() { $output .= '

    '. t('Create new field') .'

    '; $output .= ''; @@ -347,7 +378,7 @@ function theme_profile_profile($user, $f $output = "
    \n"; $output .= theme('user_picture', $user); - $output .= "
    ". format_name($user) ."
    \n"; + $output .= '
    '. format_name($user) ."
    \n"; foreach ($fields as $field) { if ($value = profile_view_field($user, $field)) { === modified file 'modules/queue.module' --- modules/queue.module 2004-06-15 19:47:42 +0000 +++ modules/queue.module 2004-06-18 15:04:33 +0000 @@ -1,56 +1,56 @@ moderation. Users can moderate a post up (give it a point), or down (subtract a point). The settings below give you control over how many points are required for the status of a post to be automatically changed. See individual items for details."); - break; + case 'admin/modules#description': + return t("Enables content to be moderated by the community."); + case 'admin/settings/queue': + return t("The queue provides a way for your users to vote on submitted content. This is called moderation. Users can moderate a post up (give it a point), or down (subtract a point). The settings below give you control over how many points are required for the status of a post to be automatically changed. See individual items for details."); } - return $output; } function queue_settings() { $post_and_expire = drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100)); $dump = drupal_map_assoc(array(-1, -2, -3, -4, -5, -6, -7, -8, -8, -10, -11, -12, -13, -14, -15, -20, -25, -30)); - $output .= form_select(t("Post threshold"), "queue_threshold_post", variable_get("queue_threshold_post", 4), $post_and_expire, t("When a post gets this number of moderation points, it is promoted to the front page automatically.")); - $output .= form_select(t("Dump threshold"), "queue_threshold_dump", variable_get("queue_threshold_dump", -2), $dump, t("When a post drops below this number of points, its status is changed to unpublished.")); - $output .= form_select(t("Expiration threshold"), "queue_threshold_expire", variable_get("queue_threshold_expire", 8), $post_and_expire, t("When a post gets this number of points, its status is changed to unpublished.")); - $output .= form_item(t("Show comments"), form_checkbox(t("Enabled"), "queue_show_comments", 1, variable_get("queue_show_comments", 1)), t("Tick the box to show comments below the moderation form.")); + $output .= form_select(t('Post threshold'), 'queue_threshold_post', variable_get('queue_threshold_post', 4), $post_and_expire, t('When a post gets this number of moderation points, it is promoted to the front page automatically.')); + $output .= form_select(t('Dump threshold'), 'queue_threshold_dump', variable_get('queue_threshold_dump', -2), $dump, t('When a post drops below this number of points, its status is changed to unpublished.')); + $output .= form_select(t('Expiration threshold'), 'queue_threshold_expire', variable_get('queue_threshold_expire', 8), $post_and_expire, t('When a post gets this number of points, its status is changed to unpublished.')); + $output .= form_item(t('Show comments'), form_checkbox(t('Enabled'), 'queue_show_comments', 1, variable_get('queue_show_comments', 1)), t('Tick the box to show comments below the moderation form.')); return $output; } +/** + * Implementation of hook_perm(). + */ function queue_perm() { - return array("access submission queue"); + return array('access submission queue'); } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function queue_link($type) { - $links = array(); - - if ($type == 'system') { - menu('queue', t('submission queue'), user_access('access submission queue') ? 'queue_page' : MENU_DENIED, 1); - } - - return $links; +function queue_menu($type) { + $items = array(); + $items[] = array('path' => 'queue', 'title' => t('submission queue'), + 'callback' => 'queue_page', + 'access' => user_access('access submission queue'), + 'weight' => 1); + return $items; } function queue_count() { - $result = db_query("SELECT COUNT(nid) FROM {node} WHERE moderate = 1"); + $result = db_query('SELECT COUNT(nid) FROM {node} WHERE moderate = 1'); return ($result) ? db_result($result, 0) : 0; } function queue_score($id) { - $result = db_query("SELECT score FROM {node} WHERE nid = %d", $id); + $result = db_query('SELECT score FROM {node} WHERE nid = %d', $id); return ($result) ? db_result($result, 0) : 0; } @@ -59,23 +59,23 @@ function queue_vote($node, $vote) { if (!field_get($node->users, $user->uid)) { // Update submission's score- and votes-field: - db_query("UPDATE {node} SET score = score $vote, votes = votes + 1, users = '". field_set($node->users, $user->uid, $vote) ."' WHERE nid = '$node->nid'"); + db_query("UPDATE {node} SET score = score $vote, votes = votes + 1, users = '". field_set($node->users, $user->uid, $vote) ."' WHERE nid = %d", $node->nid); // Reload the updated node from the database: - $node = node_load(array("nid" => $node->nid)); + $node = node_load(array('nid' => $node->nid)); $terms = module_invoke('taxonomy', 'node_get_terms', $node->nid, 'tid'); foreach ($terms as $term) { $node->taxonomy[] = $term->tid; } - if (variable_get("queue_threshold_post", 4) <= $node->score) { + if (variable_get('queue_threshold_post', 4) <= $node->score) { $node->moderate = 0; $node->promote = 1; node_save($node); watchdog('special', t('moderation: approved "%node-title"', array('%node-title' => $node->title))); } - else if (variable_get("queue_threshold_dump", -2) >= $node->score) { + else if (variable_get('queue_threshold_dump', -2) >= $node->score) { if ($node->revisions) { node_revision_rollback($node, end(node_revision_list($node))); watchdog('special', t('moderation: declined "%node-title" (rollback)', array('%node-title' => $node->title))); @@ -87,7 +87,7 @@ function queue_vote($node, $vote) { watchdog('special', t('moderation: declined "%node-title"', array('%node-title' => $node->title))); } } - else if (variable_get("queue_threshold_expire", 8) <= $node->votes) { + else if (variable_get('queue_threshold_expire', 8) <= $node->votes) { if ($node->revisions) { node_revision_rollback($node, end(node_revision_list($node))); watchdog('special', t('moderation: expired "%node-title" (rollback)', array('%node-title' => $node->title))); @@ -102,135 +102,131 @@ function queue_vote($node, $vote) { } } +/** + * Display a page listing the nodes in the submission queue. + */ function queue_overview() { global $user; - $header = array(array("data" => t("subject")), array("data" => t("author")), array("data" => t("type")), array("data" => t("score"))); + $header = array(array('data' => t('subject')), array('data' => t('author')), array('data' => t('type')), array('data' => t('score'))); - $sresult = pager_query("SELECT n.*, u.name, u.uid FROM {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE n.moderate = 1", 10, 0); + $sresult = pager_query('SELECT n.*, u.name, u.uid FROM {node} n INNER JOIN {users} u ON n.uid = u.uid WHERE n.moderate = 1', 10, 0); while ($node = db_fetch_object($sresult)) { if ($user->uid == $node->uid || field_get($node->users, $user->uid)) { - $rows[] = array(array("data" => l($node->title, "queue/$node->nid"), "class" => "title"), array("data" => format_name($node), "class" => "name"), array("data" => module_invoke($node->type, "node_name", $node), "class" => "type"), array("data" => queue_score($node->nid), "class" => "score")); + $rows[] = array(array('data' => l($node->title, 'queue/'. $node->nid), 'class' => 'title'), array('data' => format_name($node), 'class' => 'name'), array('data' => module_invoke($node->type, 'node_name', $node), 'class' => 'type'), array('data' => queue_score($node->nid), 'class' => 'score')); } else { - $rows[] = array(array("data" => l($node->title, "queue/$node->nid"), "class" => "title"), array("data" => format_name($node), "class" => "name"), array("data" => module_invoke($node->type, "node_name", $node), "class" => "type"), array("data" => l(t("vote"), "queue/$node->nid"), "class" => "score")); + $rows[] = array(array('data' => l($node->title, 'queue/'. $node->nid), 'class' => 'title'), array('data' => format_name($node), 'class' => 'name'), array('data' => module_invoke($node->type, 'node_name', $node), 'class' => 'type'), array('data' => l(t('vote'), 'queue/', $node->nid), 'class' => 'score')); } } - if ($pager = theme("pager", NULL, 10, 0, tablesort_pager())) { - $rows[] = array(array("data" => $pager, "colspan" => 4)); + if ($pager = theme('pager', NULL, 10, 0, tablesort_pager())) { + $rows[] = array(array('data' => $pager, 'colspan' => 4)); } - $output = "
    "; - $output .= theme("table", $header, $rows); - $output .= "
    "; + $output = '
    '; + $output .= theme('table', $header, $rows); + $output .= '
    '; - drupal_set_title(t("Submission queue")); + drupal_set_title(t('Submission queue')); - print theme("page", $output); + print theme('page', $output); } +/** + * Display a queued node along with voting options for it. + */ function queue_view($nid) { global $user; - $op = $_POST["op"]; - $edit = $_POST["edit"]; - - /* - ** An associative array with the possible voting options: - */ + $op = $_POST['op']; + $edit = $_POST['edit']; - $votes = array("+ 0" => t("neutral (+0)"), "+ 1" => t("post it (+1)"), "- 1" => t("dump it (-1)")); + // An associative array with the possible voting options. + $votes = array('+ 0' => t('neutral (+0)'), '+ 1' => t('post it (+1)'), '- 1' => t('dump it (-1)')); - /* - ** Load the node from the database: - */ - - $node = node_load(array("nid" => $nid, "moderate" => 1)); + // Load the node from the database. + $node = node_load(array('nid' => $nid, 'moderate' => 1)); if ($node) { if ($user->uid != $node->uid && !field_get($node->users, $user->uid)) { - if ($op == t("Vote") && $votes[$edit["vote"]]) { - /* - ** If it is a valid vote, record it. - */ + if ($op == t('Vote') && $votes[$edit['vote']]) { + // If it is a valid vote, record it. - queue_vote($node, $edit["vote"]); + queue_vote($node, $edit['vote']); - $output = t("Your vote has been recorded."); + $output = t('Your vote has been recorded.'); } else { - /* - ** Display some explanation or voting guidelines: - */ - - $output .= "

    ". t("When new content is submitted it goes into the submission queue. Registered users with the appropriate permission can access this queue and vote whether they think the content should be approved or not. When enough people vote to approve the content it is displayed on the front page. On the other hand, if enough people vote to drop it, the content will disappear.") ."

    "; - - /* - ** Display a voting form: - */ - - $output .= form_select(t("Your vote"), "vote", "", $votes); - $output .= form_hidden("id", $node->nid); - $output .= form_submit(t("Vote")); + // Display some explanation or voting guidelines: + $output .= '

    '. t('When new content is submitted, it goes into the submission queue. Registered users with the appropriate permission can access this queue and vote whether they think the content should be approved or not. When enough people vote to approve the content, it is displayed on the front page. On the other hand, if enough people vote to drop it, the content will disappear.') .'

    '; + + // Display a voting form: + $output .= form_select(t('Your vote'), 'vote', '', $votes); + $output .= form_hidden('id', $node->nid); + $output .= form_submit(t('Vote')); $output = form($output); } } $output .= node_view($node); - $output = theme("box", t("Moderate"), $output); + $output = theme('box', t('Moderate'), $output); - if ($node->comment && variable_get("queue_show_comments", 1)) { - $output .= module_invoke("comment", "render", $node); + if ($node->comment && variable_get('queue_show_comments', 1)) { + $output .= module_invoke('comment', 'render', $node); } - print theme("page", $output); + print theme('page', $output); } else { drupal_not_found(); } } -function queue_page() { - global $user, $vote; - - if (arg(1)) { - queue_view(arg(1)); +/** + * Menu callback; displays the queue management page. + */ +function queue_page($nid = 0) { + if ($nid) { + queue_view($nid); } else { queue_overview(); } } -function queue_block($op = "list", $delta = 0) { +/** + * Implementation of hook_block(). + */ +function queue_block($op = 'list', $delta = 0) { global $user; - if ($op == "list") { - $blocks[0]["info"] = t("Moderation results"); + if ($op == 'list') { + $blocks[0]['info'] = t('Moderation results'); return $blocks; } else { - if (user_access("access submission queue") && (arg(0) == "queue") || arg(0) == "node") { + if (user_access('access submission queue') && (arg(0) == 'queue') || arg(0) == 'node') { if ($user->uid) { - if (arg(0) == "queue") { + if (arg(0) == 'queue') { $id = arg(1); } else { $id = arg(2); } - $node = node_load(array("nid" => $id)); + $node = node_load(array('nid' => $id)); if (($user->uid == $node->uid || field_get($node->users, $user->uid)) && $node->moderate == 1) { - foreach (explode(",", $node->users) as $vote) { + foreach (explode(',', $node->users) as $vote) { if ($vote) { - $data = explode("=", $vote); - $account = user_load(array("uid" => $data[0])); - $output .= format_name($account) ." voted '$data[1]'.
    "; + $data = explode('=', $vote); + $account = user_load(array('uid' => $data[0])); + $output .= format_name($account) ." voted \"$data[1]\".
    "; } } - $block["subject"] = t("Moderation results"); - $block["content"] = $output ? $output : t("This node has not yet been moderated."); + $block['subject'] = t('Moderation results'); + $block['content'] = $output ? $output : t('This node has not yet been moderated.'); } } @@ -239,7 +235,10 @@ function queue_block($op = "list", $delt } } -function queue_nodeapi(&$node, $op, $arg = 0) { +/** + * Implementation of hook_nodeapi(). + */ +function queue_nodeapi(&$node, $op) { switch ($op) { case 'fields': return array('score', 'users', 'votes'); @@ -253,7 +252,7 @@ function queue_nodeapi(&$node, $op, $arg break; case 'insert': case 'update': - if ($node->moderate && user_access("access submission queue")) { + if ($node->moderate && user_access('access submission queue')) { drupal_set_message(t('The post is queued for approval. You can check the votes in the submission queue.', array('%queue' => url('queue')))); } else if ($node->moderate) { === modified file 'modules/search.module' --- modules/search.module 2004-06-02 19:01:40 +0000 +++ modules/search.module 2004-06-18 15:04:33 +0000 @@ -1,32 +1,29 @@ Search guidelines

    The search page allows you to search the web site's content. You can specify multiple words, and they will all be searched for. You can also use wildcards, so 'walk*' will match 'walk', 'walking', 'walker', 'walkable' and so on. Furthermore, searches are not case sensitive so searching for 'walk', 'Walk' or 'WALK' will yield exactly the same results.

    Words excluded from the search -

    Words that frequently occur, typically called 'noise words', are ignored. Example words are 'a', 'at', 'and', 'are', 'as', 'how', 'where', etc. Words shorter than %number letters are also ignored.

    ", array("%number" => variable_get("minimum_word_size", 2))); - break; - case 'admin/system/modules#description': - $output = t("Enables site wide keyword searching."); - break; - case 'admin/system/modules/search': - $output = t("The search engine works by keeping an index of \"interesting\" words. To make sure we only get \"interesting\" words you need to set the following."); - break; +

    Words that frequently occur, typically called 'noise words', are ignored. Example words are 'a', 'at', 'and', 'are', 'as', 'how', 'where', etc. Words shorter than %number letters are also ignored.

    ", array('%number' => variable_get('minimum_word_size', 2))); + case 'admin/modules#description': + return t('Enables site-wide keyword searching.'); + case 'admin/settings/search': + return t('The search engine works by keeping an index of "interesting" words. To make sure we only get "interesting" words you need to set the following.'); } - return $output; } /** - * Return an array of valid search access permissions + * Implementation of hook_perm(). */ function search_perm() { - return array("search content", "administer search"); + return array('search content', 'administer search'); } /** @@ -39,29 +36,59 @@ function search_link($type) { $links[] = l(t('search'), 'search', array('title' => t('Search for older content.'))); } - if ($type == 'system') { - menu('search', t('search'), user_access('search content') ? 'search_page' : MENU_DENIED, 0, MENU_HIDE); - } - return $links; } -function search_settings() { - $output = form_textfield(t("Minimum word length to index"), "minimum_word_size", variable_get("minimum_word_size", 2), 10, 10, t("The number of characters a word has to be to be indexed. Words shorter than this will not be searchable.")); - $output .= form_textfield(t("Minimum word length to search for"), "remove_short", variable_get("remove_short", 0), 10, 10, t("The number of characters a word has to be to be searched for.")); - $output .= form_textarea(t("Noise words"), "noisewords", variable_get("noisewords", ""), 70, 10, t("These words will not be indexed, enter comma separated list, linebreaks and whitespace do not matter. Example: and, or, not, a, to, I, it, ...")); - $output .= form_radios(t("Help text position"), "help_pos", variable_get("help_pos", 1), array("1" => t("Above search output"), "2" => t("Below search output"), "3" => t("Link from above search output"), "4" => t("Link from below search output")), t("Where to show the help text for users on the search page.")); +/** + * Implementation of hook_menu(). + */ +function search_menu() { + $items = array(); + $items[] = array('path' => 'search', 'title' => t('search'), + 'callback' => 'search_view', + 'access' => user_access('search content'), + 'type' => MENU_SUGGESTED_ITEM); + $items[] = array('path' => 'search/help', 'title' => t('search help'), + 'callback' => 'search_help_page', + 'access' => user_access('search content'), + 'type' => MENU_SUGGESTED_ITEM); + $items[] = array('path' => 'search/configure', 'title' => t('configure'), + 'callback' => 'search_configure', + 'access' => user_access('administer site configuration'), + 'type' => MENU_LOCAL_TASK); + return $items; +} - return $output; +/** + * Menu callback; displays the search module settings page. + */ +function search_configure() { + if ($_POST) { + system_settings_save(); + } + + // Indexing settings: + $group = form_textfield(t('Minimum word length to index'), 'minimum_word_size', variable_get('minimum_word_size', 2), 10, 10, t('The number of characters a word has to be to be indexed. Words shorter than this will not be searchable.')); + $group .= form_textfield(t('Minimum word length to search for'), 'remove_short', variable_get('remove_short', 0), 10, 10, t('The number of characters a word has to be to be searched for.')); + $group .= form_textarea(t('Noise words'), 'noisewords', variable_get('noisewords', ''), 70, 10, t('These words will not be indexed. Enter a comma separated list; linebreaks and whitespace do not matter. Example: and, or, not, a, to, I, it, ...')); + $output = form_group(t('Indexing settings'), $group); + + // Visual settings: + $group = form_radios(t('Help text position'), 'help_pos', variable_get('help_pos', 1), array('1' => t('Above search output'), '2' => t('Below search output'), '3' => t('Link from above search output'), '4' => t('Link from below search output')), t('Where to show the help text for users on the search page.')); + $output .= form_group(t('Viewing options'), $group); + + print theme('page', system_settings_form($output)); } /** - * perform a regularly run action across all modules that have the - * module_update_index function in them. + * Implementation of hook_cron(). + * + * Fires hook_update_index() in all modules and uses the results to make + * the search index current. */ function search_cron() { foreach (module_list() as $module) { - $module_array = module_invoke($module, "update_index"); + $module_array = module_invoke($module, 'update_index'); if ($module_array) { update_index($module_array); } @@ -71,75 +98,75 @@ function search_cron() { } /** - * Perform a search on a word(s). + * Perform a search on a word or words. * - * Search function called by each node that supports the indexed search. + * This function is called by each node that supports the indexed search. * - * @param $search_array an array as returned from module_search of type - * array("keys" => ..., "type" => ..., "select" => ...) - * @see node_search for an explanation of array items + * @param $search_array + * An array as returned from hook_search(). The format of this array is + * array('keys' => ..., 'type' => ..., 'select' => ...). See the hook_search() + * documentation for an explanation of the array values. * - * @return array of search results, each element being an array indexed with - * "count", "title", "link", "user" (name), "date", "keywords" + * @return + * An array of search results, of which each element is an array with the + * keys "count", "title", "link", "user" (name), "date", and "keywords". */ function do_search($search_array) { - $keys = strtolower($search_array["keys"]); - $type = $search_array["type"]; - $select = $search_array["select"]; + $keys = strtolower($search_array['keys']); + $type = $search_array['type']; + $select = $search_array['select']; - // Replace wildcards with mysql wildcards - $keys = str_replace("*", "%", $keys); + // Replace wildcards with MySQL wildcards. + $keys = str_replace('*', '%', $keys); - // Split the words entered into an array - $words = explode(" ", $keys); + // Split the words entered into an array. + $words = explode(' ', $keys); foreach ($words as $word) { - // If the word is too short, and we've got it set to skip them, loop - if (strlen($word) < variable_get("remove_short", 0)) { + // If the word is too short, and we've got it set to skip them, loop. + if (strlen($word) < variable_get('remove_short', 0)) { continue; } - // Put the next search word into the query and do the query + // Put the next search word into the query and do the query. $query = str_replace("'%'", "'". check_query($word) ."'", $select); $result = db_query($query); - // If we got any results if (db_num_rows($result) != 0) { + // At least one matching record was found. $found = 1; - // Create an in memory array of the results, + // Create an in memory array of the results. while ($row = db_fetch_array($result)) { - $lno = $row["lno"]; - $nid = $row["nid"]; - $title = $row["title"]; - $created = $row["created"]; - $uid = $row["uid"]; - $name = $row["name"]; - $count = $row["count"]; + $lno = $row['lno']; + $nid = $row['nid']; + $title = $row['title']; + $created = $row['created']; + $uid = $row['uid']; + $name = $row['name']; + $count = $row['count']; - // Build reduction variable + // Build reduction variable. $reduction[$lno][$word] = true; - // If the just fetched row is not already in the table - if ($results[$lno]["lno"] != $lno) { - $results[$lno]["count"] = $count; - - $results[$lno]["lno"] = $lno; - $results[$lno]["nid"] = $nid; - $results[$lno]["title"] = $title; - $results[$lno]["created"] = $created; - $results[$lno]["uid"] = $uid; - $results[$lno]["name"] = $name; + // Check whether the just-fetched row is already in the table. + if ($results[$lno]['lno'] != $lno) { + $results[$lno]['count'] = $count; + + $results[$lno]['lno'] = $lno; + $results[$lno]['nid'] = $nid; + $results[$lno]['title'] = $title; + $results[$lno]['created'] = $created; + $results[$lno]['uid'] = $uid; + $results[$lno]['name'] = $name; } else { - /* - ** Different word, but existing "lno", increase the count of - ** matches against this "lno" by the number of times this - ** word appears in the text - */ - $results[$lno]["count"] = $results[$lno]["count"] + $count; + // Different word, but existing "lno". Increase the count of + // matches against this "lno" by the number of times this + // word appears in the text. + $results[$lno]['count'] = $results[$lno]['count'] + $count; } } } @@ -163,24 +190,25 @@ function do_search($search_array) { } } if ($found) { - // Black magic here to sort the results + // Black magic here to sort the results. array_multisort($results, SORT_DESC); - // OK, time to output the results. + // Now, output the results. foreach ($results as $key => $value) { - $lno = $value["lno"]; - $nid = $value["nid"]; - $title = $value["title"]; - $created = $value["created"]; - $uid = $value["uid"]; - $name = $value["name"]; - $count = $value["count"]; + $lno = $value['lno']; + $nid = $value['nid']; + $title = $value['title']; + $created = $value['created']; + $uid = $value['uid']; + $name = $value['name']; + $count = $value['count']; switch ($type) { - case "node": - $find[$i++] = array("count" => $count, "title" => $title, "link" => (strstr(request_uri(), "admin") ? url("admin/node/edit/$lno") : url("node/view/$lno")), "user" => $name, "date" => $created, "keywords" => implode("|", $words)); - break; - case "comment": - $find[$i++] = array("count" => $count, "title" => $title, "link" => (strstr(request_uri(), "admin") ? url("admin/comment/edit/$lno") : url("node/view/$nid", NULL, "comment-$lno")), "user" => $name, "date" => $created, "keywords" => implode("|", $words)); + case 'node': + $find[$i++] = array('count' => $count, 'title' => $title, 'link' => url("node/$lno"), 'user' => $name, 'date' => $created, 'keywords' => implode('|', $words)); + break; + case 'comment': + $find[$i++] = array('count' => $count, 'title' => $title, 'link' => (strstr(request_uri(), 'admin') ? url("admin/comment/edit/$lno") : url("node/$nid", NULL, "comment-$lno")), 'user' => $name, 'date' => $created, 'keywords' => implode('|', $words)); + break; break; } } @@ -190,72 +218,64 @@ function do_search($search_array) { } /** - * Update the search_index table + * Update the search_index table. * - * @param $search_array an array as returned from module_update_index - * of type array("last_update" => ..., "node_type" => ..., "select" => ...) - * @see node_update_index for an explanation of array items + * @param $search_array + * An array as returned from hook_update_index(). */ function update_index($search_array) { - $last_update = variable_get($search_array["last_update"], 1); - $node_type = $search_array["node_type"]; - $select = $search_array["select"]; - $minimum_word_size = variable_get("minimum_word_size", 2); + $last_update = variable_get($search_array['last_update'], 1); + $node_type = $search_array['node_type']; + $select = $search_array['select']; + $minimum_word_size = variable_get('minimum_word_size', 2); - //watchdog("user", "$last_update
    $node_type
    $select"); + //watchdog('user', "$last_update
    $node_type
    $select"); $result = db_query($select); if (db_num_rows($result)) { - // Wohoo, found some, look through the nodes we just selected + // Results were found. Look through the nodes we just selected. while ($node = db_fetch_array ($result)) { - /* - ** Trash any existing entries in the search index for this node, - ** in case its a modified node. - */ - db_query("DELETE from {search_index} where lno = '". $node["lno"] ."' and type = '". $node_type ."'"); - - /* - ** Build the wordlist, teaser not included, as it then gives a - ** false count of the number of hits, and doesn't show up - ** when clicking on a node from the search interface anyway. - */ - $wordlist = $node["text1"] ." ". $node["text2"]; + // Trash any existing entries in the search index for this node, + // in case it is a modified node. + db_query("DELETE from {search_index} where lno = '". $node['lno'] ."' and type = '". $node_type ."'"); + + // Build the word list (teaser not included, as it would give a + // false count of the number of hits). + $wordlist = $node['text1'] .' '. $node['text2']; - // Strip heaps of stuff out of it - $wordlist = preg_replace("'<[\/\!]*?[^<>]*?>'si", "", $wordlist); + // Strip heaps of stuff out of it. + $wordlist = preg_replace("'<[\/\!]*?[^<>]*?>'si", '', $wordlist); - // Remove punctuation and stuff - $wordlist = preg_replace("'(\xBB|\xAB|!|\xA1|%|,|:|;|\(|\)|\&|\"|\'|\.|-|\/|\?|\\\)'", "", $wordlist); + // Remove punctuation/special characters. + $wordlist = preg_replace("'(\xBB|\xAB|!|\xA1|%|,|:|;|\(|\)|\&|\"|\'|\.|-|\/|\?|\\\)'", '', $wordlist); // Strip out (now mangled) http and tags. - $wordlist = preg_replace("'http\w+'", "", $wordlist); - $wordlist = preg_replace("'www\w+'", "", $wordlist); + $wordlist = preg_replace("'http\w+'", '', $wordlist); + $wordlist = preg_replace("'www\w+'", '', $wordlist); - // Remove all newlines of any type - $wordlist = preg_replace("'([\r\n]|[\r]|[\n])'", " ", $wordlist); + // Remove all newlines of any type. + $wordlist = preg_replace("'([\r\n]|[\r]|[\n])'", ' ', $wordlist); // Lower case the whole thing. $wordlist = strtolower($wordlist); - // Remove "noisewords" - $noise = explode(",", variable_get("noisewords", "")); + // Remove "noise words". + $noise = explode(',', variable_get('noisewords', '')); foreach ($noise as $word) { $word = trim($word); - $wordlist = trim(preg_replace("' $word '", " ", " " .$wordlist. " ")); + $wordlist = trim(preg_replace("' $word '", ' ', ' ' .$wordlist. ' ')); } - // Remove whitespace - $wordlist = preg_replace("'[\s]+'", " ", $wordlist); + // Remove whitespace. + $wordlist = preg_replace("'[\s]+'", ' ', $wordlist); - // Make it an array - $eachword = explode(" ", $wordlist); + // Make it an array. + $eachword = explode(' ', $wordlist); - /* - ** walk through the array, giving a "weight" to each word, based on - ** the number of times it appears in a page. - */ + // Walk through the array, giving a "weight" to each word based on + // the number of times it appears in a page. foreach ($eachword as $word) { if (strlen($word) >= $minimum_word_size) { if ($newwords[$word]) { @@ -267,23 +287,21 @@ function update_index($search_array) { } } - /* - ** Walk through the weighted words array, inserting them into - ** the search index - */ + // Walk through the weighted words array, inserting them into + // the search index. if ($newwords) { foreach ($newwords as $key => $value) { - db_query("INSERT INTO {search_index} VALUES('%s', %d, '%s', %d)", $key, $node["lno"], $node_type, $value); + db_query("INSERT INTO {search_index} VALUES('%s', %d, '%s', %d)", $key, $node['lno'], $node_type, $value); } } - // Zap the weighted words array, so we don't add multiples. + // Reset the weighted words array, so we don't add multiples. $newwords = array (); } } - // update the last time this process was run. - variable_set($search_array["last_update"], time()); + // Update the last time this process was run. + variable_set($search_array['last_update'], time()); return true; } @@ -291,9 +309,9 @@ function update_index($search_array) { function search_invalidate() { foreach (module_list() as $module) { - $module_array = module_invoke($module, "update_index"); + $module_array = module_invoke($module, 'update_index'); if ($module_array) { - variable_set($module_array["last_update"], 1); + variable_set($module_array['last_update'], 1); } $module_array = null; } @@ -303,59 +321,64 @@ function search_invalidate() { /** * Save the values entered by the administrator for the search module * - * @param $edit An array of fields as setup via calling form_textfield, - * form_textarea etc + * @param $edit + * An array of fields as set up by calling form_textfield(), + * form_textarea(), etc. */ function search_save($edit) { - variable_set("minimum_word_size", $edit["minimum_word_size"]); + variable_set('minimum_word_size', $edit['minimum_word_size']); - $data = strtr($edit["noisewords"], "\n\r\t", " "); - $data = str_replace(" ", "", $data); - variable_set("noisewords", $data); - variable_set("help_pos", $edit["help_pos"]); - variable_set("remove_short", $edit["remove_short"]); + $data = strtr($edit['noisewords'], "\n\r\t", ' '); + $data = str_replace(' ', '', $data); + variable_set('noisewords', $data); + variable_set('help_pos', $edit['help_pos']); + variable_set('remove_short', $edit['remove_short']); } -function search_view($keys) { +/** + * Menu callback; presents the search form and/or search results. + */ +function search_view() { global $type; + $keys = isset($_GET['keys']) ? $_GET['keys'] : $_POST['keys']; - if (user_access("search content")) { - // Construct the search form: + if (user_access('search content')) { + // Construct the search form. $output = search_form(NULL, $keys, TRUE); - // Display form and search results: - $help_link = l(t("search help"), "search/help"); - switch (variable_get("help_pos", 1)) { - case "1": - $output = search_help(). $output ."
    "; + // Display form and search results. + $help_link = l(t('search help'), 'search/help'); + switch (variable_get('help_pos', 1)) { + case '1': + $output = search_help(). $output .'
    '; break; - case "2": - $output .= search_help() ."
    "; + case '2': + $output .= search_help() .'
    '; break; - case "3": - $output = $help_link. "
    ". $output ."
    "; + case '3': + $output = $help_link. '
    '. $output .'
    '; break; - case "4": - $output .= "
    ". $help_link ."
    "; + case '4': + $output .= '
    '. $help_link .'
    '; } // Only perform search if there is non-whitespace search term: if (trim($keys)) { // Log the search keys: - watchdog('search', t('search: "%keys"', array('%keys' => $keys)), l("view results", "search", NULL, "keys=". urlencode($keys))); + watchdog('search', t('search: "%keys"', array('%keys' => $keys)), l('view results', 'search', NULL, 'keys='. urlencode($keys))); // Collect the search results: $results = search_data($keys); if ($results) { - $output .= theme("box", t("Search Results"), $results); + $output .= theme('box', t('Search Results'), $results); } else { - $output .= theme("box", t("Search Results"), t("Your search yielded no results.")); + $output .= theme('box', t('Search Results'), t('Your search yielded no results.')); } } - print theme("page", $output, t("Search")); + print theme('page', $output, t('Search')); } else { drupal_access_denied(); @@ -363,16 +386,11 @@ function search_view($keys) { } -function search_page() { - $keys = isset($_GET["keys"]) ? $_GET["keys"] : $_POST["keys"]; - - switch (arg(1)) { - case "help": - print theme("page", search_help(), t("Search Help")); - break; - default: - search_view($keys); - } +/** + * Menu callback; prints the search engine help page. + */ +function search_help_page() { + print theme('page', search_help()); } ?> === modified file 'modules/search/search.module' --- modules/search/search.module 2004-06-02 19:01:40 +0000 +++ modules/search/search.module 2004-06-18 15:04:33 +0000 @@ -1,32 +1,29 @@ Search guidelines

    The search page allows you to search the web site's content. You can specify multiple words, and they will all be searched for. You can also use wildcards, so 'walk*' will match 'walk', 'walking', 'walker', 'walkable' and so on. Furthermore, searches are not case sensitive so searching for 'walk', 'Walk' or 'WALK' will yield exactly the same results.

    Words excluded from the search -

    Words that frequently occur, typically called 'noise words', are ignored. Example words are 'a', 'at', 'and', 'are', 'as', 'how', 'where', etc. Words shorter than %number letters are also ignored.

    ", array("%number" => variable_get("minimum_word_size", 2))); - break; - case 'admin/system/modules#description': - $output = t("Enables site wide keyword searching."); - break; - case 'admin/system/modules/search': - $output = t("The search engine works by keeping an index of \"interesting\" words. To make sure we only get \"interesting\" words you need to set the following."); - break; +

    Words that frequently occur, typically called 'noise words', are ignored. Example words are 'a', 'at', 'and', 'are', 'as', 'how', 'where', etc. Words shorter than %number letters are also ignored.

    ", array('%number' => variable_get('minimum_word_size', 2))); + case 'admin/modules#description': + return t('Enables site-wide keyword searching.'); + case 'admin/settings/search': + return t('The search engine works by keeping an index of "interesting" words. To make sure we only get "interesting" words you need to set the following.'); } - return $output; } /** - * Return an array of valid search access permissions + * Implementation of hook_perm(). */ function search_perm() { - return array("search content", "administer search"); + return array('search content', 'administer search'); } /** @@ -39,29 +36,59 @@ function search_link($type) { $links[] = l(t('search'), 'search', array('title' => t('Search for older content.'))); } - if ($type == 'system') { - menu('search', t('search'), user_access('search content') ? 'search_page' : MENU_DENIED, 0, MENU_HIDE); - } - return $links; } -function search_settings() { - $output = form_textfield(t("Minimum word length to index"), "minimum_word_size", variable_get("minimum_word_size", 2), 10, 10, t("The number of characters a word has to be to be indexed. Words shorter than this will not be searchable.")); - $output .= form_textfield(t("Minimum word length to search for"), "remove_short", variable_get("remove_short", 0), 10, 10, t("The number of characters a word has to be to be searched for.")); - $output .= form_textarea(t("Noise words"), "noisewords", variable_get("noisewords", ""), 70, 10, t("These words will not be indexed, enter comma separated list, linebreaks and whitespace do not matter. Example: and, or, not, a, to, I, it, ...")); - $output .= form_radios(t("Help text position"), "help_pos", variable_get("help_pos", 1), array("1" => t("Above search output"), "2" => t("Below search output"), "3" => t("Link from above search output"), "4" => t("Link from below search output")), t("Where to show the help text for users on the search page.")); +/** + * Implementation of hook_menu(). + */ +function search_menu() { + $items = array(); + $items[] = array('path' => 'search', 'title' => t('search'), + 'callback' => 'search_view', + 'access' => user_access('search content'), + 'type' => MENU_SUGGESTED_ITEM); + $items[] = array('path' => 'search/help', 'title' => t('search help'), + 'callback' => 'search_help_page', + 'access' => user_access('search content'), + 'type' => MENU_SUGGESTED_ITEM); + $items[] = array('path' => 'search/configure', 'title' => t('configure'), + 'callback' => 'search_configure', + 'access' => user_access('administer site configuration'), + 'type' => MENU_LOCAL_TASK); + return $items; +} - return $output; +/** + * Menu callback; displays the search module settings page. + */ +function search_configure() { + if ($_POST) { + system_settings_save(); + } + + // Indexing settings: + $group = form_textfield(t('Minimum word length to index'), 'minimum_word_size', variable_get('minimum_word_size', 2), 10, 10, t('The number of characters a word has to be to be indexed. Words shorter than this will not be searchable.')); + $group .= form_textfield(t('Minimum word length to search for'), 'remove_short', variable_get('remove_short', 0), 10, 10, t('The number of characters a word has to be to be searched for.')); + $group .= form_textarea(t('Noise words'), 'noisewords', variable_get('noisewords', ''), 70, 10, t('These words will not be indexed. Enter a comma separated list; linebreaks and whitespace do not matter. Example: and, or, not, a, to, I, it, ...')); + $output = form_group(t('Indexing settings'), $group); + + // Visual settings: + $group = form_radios(t('Help text position'), 'help_pos', variable_get('help_pos', 1), array('1' => t('Above search output'), '2' => t('Below search output'), '3' => t('Link from above search output'), '4' => t('Link from below search output')), t('Where to show the help text for users on the search page.')); + $output .= form_group(t('Viewing options'), $group); + + print theme('page', system_settings_form($output)); } /** - * perform a regularly run action across all modules that have the - * module_update_index function in them. + * Implementation of hook_cron(). + * + * Fires hook_update_index() in all modules and uses the results to make + * the search index current. */ function search_cron() { foreach (module_list() as $module) { - $module_array = module_invoke($module, "update_index"); + $module_array = module_invoke($module, 'update_index'); if ($module_array) { update_index($module_array); } @@ -71,75 +98,75 @@ function search_cron() { } /** - * Perform a search on a word(s). + * Perform a search on a word or words. * - * Search function called by each node that supports the indexed search. + * This function is called by each node that supports the indexed search. * - * @param $search_array an array as returned from module_search of type - * array("keys" => ..., "type" => ..., "select" => ...) - * @see node_search for an explanation of array items + * @param $search_array + * An array as returned from hook_search(). The format of this array is + * array('keys' => ..., 'type' => ..., 'select' => ...). See the hook_search() + * documentation for an explanation of the array values. * - * @return array of search results, each element being an array indexed with - * "count", "title", "link", "user" (name), "date", "keywords" + * @return + * An array of search results, of which each element is an array with the + * keys "count", "title", "link", "user" (name), "date", and "keywords". */ function do_search($search_array) { - $keys = strtolower($search_array["keys"]); - $type = $search_array["type"]; - $select = $search_array["select"]; + $keys = strtolower($search_array['keys']); + $type = $search_array['type']; + $select = $search_array['select']; - // Replace wildcards with mysql wildcards - $keys = str_replace("*", "%", $keys); + // Replace wildcards with MySQL wildcards. + $keys = str_replace('*', '%', $keys); - // Split the words entered into an array - $words = explode(" ", $keys); + // Split the words entered into an array. + $words = explode(' ', $keys); foreach ($words as $word) { - // If the word is too short, and we've got it set to skip them, loop - if (strlen($word) < variable_get("remove_short", 0)) { + // If the word is too short, and we've got it set to skip them, loop. + if (strlen($word) < variable_get('remove_short', 0)) { continue; } - // Put the next search word into the query and do the query + // Put the next search word into the query and do the query. $query = str_replace("'%'", "'". check_query($word) ."'", $select); $result = db_query($query); - // If we got any results if (db_num_rows($result) != 0) { + // At least one matching record was found. $found = 1; - // Create an in memory array of the results, + // Create an in memory array of the results. while ($row = db_fetch_array($result)) { - $lno = $row["lno"]; - $nid = $row["nid"]; - $title = $row["title"]; - $created = $row["created"]; - $uid = $row["uid"]; - $name = $row["name"]; - $count = $row["count"]; + $lno = $row['lno']; + $nid = $row['nid']; + $title = $row['title']; + $created = $row['created']; + $uid = $row['uid']; + $name = $row['name']; + $count = $row['count']; - // Build reduction variable + // Build reduction variable. $reduction[$lno][$word] = true; - // If the just fetched row is not already in the table - if ($results[$lno]["lno"] != $lno) { - $results[$lno]["count"] = $count; - - $results[$lno]["lno"] = $lno; - $results[$lno]["nid"] = $nid; - $results[$lno]["title"] = $title; - $results[$lno]["created"] = $created; - $results[$lno]["uid"] = $uid; - $results[$lno]["name"] = $name; + // Check whether the just-fetched row is already in the table. + if ($results[$lno]['lno'] != $lno) { + $results[$lno]['count'] = $count; + + $results[$lno]['lno'] = $lno; + $results[$lno]['nid'] = $nid; + $results[$lno]['title'] = $title; + $results[$lno]['created'] = $created; + $results[$lno]['uid'] = $uid; + $results[$lno]['name'] = $name; } else { - /* - ** Different word, but existing "lno", increase the count of - ** matches against this "lno" by the number of times this - ** word appears in the text - */ - $results[$lno]["count"] = $results[$lno]["count"] + $count; + // Different word, but existing "lno". Increase the count of + // matches against this "lno" by the number of times this + // word appears in the text. + $results[$lno]['count'] = $results[$lno]['count'] + $count; } } } @@ -163,24 +190,25 @@ function do_search($search_array) { } } if ($found) { - // Black magic here to sort the results + // Black magic here to sort the results. array_multisort($results, SORT_DESC); - // OK, time to output the results. + // Now, output the results. foreach ($results as $key => $value) { - $lno = $value["lno"]; - $nid = $value["nid"]; - $title = $value["title"]; - $created = $value["created"]; - $uid = $value["uid"]; - $name = $value["name"]; - $count = $value["count"]; + $lno = $value['lno']; + $nid = $value['nid']; + $title = $value['title']; + $created = $value['created']; + $uid = $value['uid']; + $name = $value['name']; + $count = $value['count']; switch ($type) { - case "node": - $find[$i++] = array("count" => $count, "title" => $title, "link" => (strstr(request_uri(), "admin") ? url("admin/node/edit/$lno") : url("node/view/$lno")), "user" => $name, "date" => $created, "keywords" => implode("|", $words)); - break; - case "comment": - $find[$i++] = array("count" => $count, "title" => $title, "link" => (strstr(request_uri(), "admin") ? url("admin/comment/edit/$lno") : url("node/view/$nid", NULL, "comment-$lno")), "user" => $name, "date" => $created, "keywords" => implode("|", $words)); + case 'node': + $find[$i++] = array('count' => $count, 'title' => $title, 'link' => url("node/$lno"), 'user' => $name, 'date' => $created, 'keywords' => implode('|', $words)); + break; + case 'comment': + $find[$i++] = array('count' => $count, 'title' => $title, 'link' => (strstr(request_uri(), 'admin') ? url("admin/comment/edit/$lno") : url("node/$nid", NULL, "comment-$lno")), 'user' => $name, 'date' => $created, 'keywords' => implode('|', $words)); + break; break; } } @@ -190,72 +218,64 @@ function do_search($search_array) { } /** - * Update the search_index table + * Update the search_index table. * - * @param $search_array an array as returned from module_update_index - * of type array("last_update" => ..., "node_type" => ..., "select" => ...) - * @see node_update_index for an explanation of array items + * @param $search_array + * An array as returned from hook_update_index(). */ function update_index($search_array) { - $last_update = variable_get($search_array["last_update"], 1); - $node_type = $search_array["node_type"]; - $select = $search_array["select"]; - $minimum_word_size = variable_get("minimum_word_size", 2); + $last_update = variable_get($search_array['last_update'], 1); + $node_type = $search_array['node_type']; + $select = $search_array['select']; + $minimum_word_size = variable_get('minimum_word_size', 2); - //watchdog("user", "$last_update
    $node_type
    $select"); + //watchdog('user', "$last_update
    $node_type
    $select"); $result = db_query($select); if (db_num_rows($result)) { - // Wohoo, found some, look through the nodes we just selected + // Results were found. Look through the nodes we just selected. while ($node = db_fetch_array ($result)) { - /* - ** Trash any existing entries in the search index for this node, - ** in case its a modified node. - */ - db_query("DELETE from {search_index} where lno = '". $node["lno"] ."' and type = '". $node_type ."'"); - - /* - ** Build the wordlist, teaser not included, as it then gives a - ** false count of the number of hits, and doesn't show up - ** when clicking on a node from the search interface anyway. - */ - $wordlist = $node["text1"] ." ". $node["text2"]; + // Trash any existing entries in the search index for this node, + // in case it is a modified node. + db_query("DELETE from {search_index} where lno = '". $node['lno'] ."' and type = '". $node_type ."'"); + + // Build the word list (teaser not included, as it would give a + // false count of the number of hits). + $wordlist = $node['text1'] .' '. $node['text2']; - // Strip heaps of stuff out of it - $wordlist = preg_replace("'<[\/\!]*?[^<>]*?>'si", "", $wordlist); + // Strip heaps of stuff out of it. + $wordlist = preg_replace("'<[\/\!]*?[^<>]*?>'si", '', $wordlist); - // Remove punctuation and stuff - $wordlist = preg_replace("'(\xBB|\xAB|!|\xA1|%|,|:|;|\(|\)|\&|\"|\'|\.|-|\/|\?|\\\)'", "", $wordlist); + // Remove punctuation/special characters. + $wordlist = preg_replace("'(\xBB|\xAB|!|\xA1|%|,|:|;|\(|\)|\&|\"|\'|\.|-|\/|\?|\\\)'", '', $wordlist); // Strip out (now mangled) http and tags. - $wordlist = preg_replace("'http\w+'", "", $wordlist); - $wordlist = preg_replace("'www\w+'", "", $wordlist); + $wordlist = preg_replace("'http\w+'", '', $wordlist); + $wordlist = preg_replace("'www\w+'", '', $wordlist); - // Remove all newlines of any type - $wordlist = preg_replace("'([\r\n]|[\r]|[\n])'", " ", $wordlist); + // Remove all newlines of any type. + $wordlist = preg_replace("'([\r\n]|[\r]|[\n])'", ' ', $wordlist); // Lower case the whole thing. $wordlist = strtolower($wordlist); - // Remove "noisewords" - $noise = explode(",", variable_get("noisewords", "")); + // Remove "noise words". + $noise = explode(',', variable_get('noisewords', '')); foreach ($noise as $word) { $word = trim($word); - $wordlist = trim(preg_replace("' $word '", " ", " " .$wordlist. " ")); + $wordlist = trim(preg_replace("' $word '", ' ', ' ' .$wordlist. ' ')); } - // Remove whitespace - $wordlist = preg_replace("'[\s]+'", " ", $wordlist); + // Remove whitespace. + $wordlist = preg_replace("'[\s]+'", ' ', $wordlist); - // Make it an array - $eachword = explode(" ", $wordlist); + // Make it an array. + $eachword = explode(' ', $wordlist); - /* - ** walk through the array, giving a "weight" to each word, based on - ** the number of times it appears in a page. - */ + // Walk through the array, giving a "weight" to each word based on + // the number of times it appears in a page. foreach ($eachword as $word) { if (strlen($word) >= $minimum_word_size) { if ($newwords[$word]) { @@ -267,23 +287,21 @@ function update_index($search_array) { } } - /* - ** Walk through the weighted words array, inserting them into - ** the search index - */ + // Walk through the weighted words array, inserting them into + // the search index. if ($newwords) { foreach ($newwords as $key => $value) { - db_query("INSERT INTO {search_index} VALUES('%s', %d, '%s', %d)", $key, $node["lno"], $node_type, $value); + db_query("INSERT INTO {search_index} VALUES('%s', %d, '%s', %d)", $key, $node['lno'], $node_type, $value); } } - // Zap the weighted words array, so we don't add multiples. + // Reset the weighted words array, so we don't add multiples. $newwords = array (); } } - // update the last time this process was run. - variable_set($search_array["last_update"], time()); + // Update the last time this process was run. + variable_set($search_array['last_update'], time()); return true; } @@ -291,9 +309,9 @@ function update_index($search_array) { function search_invalidate() { foreach (module_list() as $module) { - $module_array = module_invoke($module, "update_index"); + $module_array = module_invoke($module, 'update_index'); if ($module_array) { - variable_set($module_array["last_update"], 1); + variable_set($module_array['last_update'], 1); } $module_array = null; } @@ -303,59 +321,64 @@ function search_invalidate() { /** * Save the values entered by the administrator for the search module * - * @param $edit An array of fields as setup via calling form_textfield, - * form_textarea etc + * @param $edit + * An array of fields as set up by calling form_textfield(), + * form_textarea(), etc. */ function search_save($edit) { - variable_set("minimum_word_size", $edit["minimum_word_size"]); + variable_set('minimum_word_size', $edit['minimum_word_size']); - $data = strtr($edit["noisewords"], "\n\r\t", " "); - $data = str_replace(" ", "", $data); - variable_set("noisewords", $data); - variable_set("help_pos", $edit["help_pos"]); - variable_set("remove_short", $edit["remove_short"]); + $data = strtr($edit['noisewords'], "\n\r\t", ' '); + $data = str_replace(' ', '', $data); + variable_set('noisewords', $data); + variable_set('help_pos', $edit['help_pos']); + variable_set('remove_short', $edit['remove_short']); } -function search_view($keys) { +/** + * Menu callback; presents the search form and/or search results. + */ +function search_view() { global $type; + $keys = isset($_GET['keys']) ? $_GET['keys'] : $_POST['keys']; - if (user_access("search content")) { - // Construct the search form: + if (user_access('search content')) { + // Construct the search form. $output = search_form(NULL, $keys, TRUE); - // Display form and search results: - $help_link = l(t("search help"), "search/help"); - switch (variable_get("help_pos", 1)) { - case "1": - $output = search_help(). $output ."
    "; + // Display form and search results. + $help_link = l(t('search help'), 'search/help'); + switch (variable_get('help_pos', 1)) { + case '1': + $output = search_help(). $output .'
    '; break; - case "2": - $output .= search_help() ."
    "; + case '2': + $output .= search_help() .'
    '; break; - case "3": - $output = $help_link. "
    ". $output ."
    "; + case '3': + $output = $help_link. '
    '. $output .'
    '; break; - case "4": - $output .= "
    ". $help_link ."
    "; + case '4': + $output .= '
    '. $help_link .'
    '; } // Only perform search if there is non-whitespace search term: if (trim($keys)) { // Log the search keys: - watchdog('search', t('search: "%keys"', array('%keys' => $keys)), l("view results", "search", NULL, "keys=". urlencode($keys))); + watchdog('search', t('search: "%keys"', array('%keys' => $keys)), l('view results', 'search', NULL, 'keys='. urlencode($keys))); // Collect the search results: $results = search_data($keys); if ($results) { - $output .= theme("box", t("Search Results"), $results); + $output .= theme('box', t('Search Results'), $results); } else { - $output .= theme("box", t("Search Results"), t("Your search yielded no results.")); + $output .= theme('box', t('Search Results'), t('Your search yielded no results.')); } } - print theme("page", $output, t("Search")); + print theme('page', $output, t('Search')); } else { drupal_access_denied(); @@ -363,16 +386,11 @@ function search_view($keys) { } -function search_page() { - $keys = isset($_GET["keys"]) ? $_GET["keys"] : $_POST["keys"]; - - switch (arg(1)) { - case "help": - print theme("page", search_help(), t("Search Help")); - break; - default: - search_view($keys); - } +/** + * Menu callback; prints the search engine help page. + */ +function search_help_page() { + print theme('page', search_help()); } ?> === modified file 'modules/statistics.module' --- modules/statistics.module 2004-05-17 22:00:06 +0000 +++ modules/statistics.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ administer statistics module - enable for user roles that get to configure the statistics module.
  • administer statistics - enable for user roles that get to view the referrer statistics.
  • If 'administer statistics' and 'access statistics' are both enabled, the user will see a link from each node to that node's referrer statistics (if enabled).

    ", - array('%modules' => url('admin/system/modules'), '%permissions' => url('admin/user/permission'), '%referer' => url('admin/logs/referrer'), '%access' => url('admin/logs/access'), '%configuration' => url('admin/system/modules/statistics'), '%block' => url('admin/system/block'))); - case 'admin/system/modules#description': + array('%modules' => url('admin/modules'), '%permissions' => url('admin/user/permission'), '%referer' => url('admin/logs/referrer'), '%access' => url('admin/logs/access'), '%configuration' => url('admin/settings/statistics'), '%block' => url('admin/block'))); + case 'admin/modules#description': return t('Logs access statistics for your site.'); - case 'admin/system/modules/statistics': + case 'admin/settings/statistics': return t('Settings for the statistical information that Drupal will keep about the site. See site statistics for the actual information.', array('%statistics' => url('admin/logs/topnodes'))); case 'admin/logs/topnodes': return t('This page gives you an at-a-glance look at your most popular content.'); @@ -140,21 +140,36 @@ function statistics_link($type, $node = } } - if ($type == 'system') { - menu('statistics', t('most popular content'), user_access('access content') ? 'statistics_page' : MENU_DENIED, 0, MENU_HIDE); - - $access = user_access('administer statistics module') || user_access('administer statistics'); - - menu('admin/logs/topnodes', t('top nodes'), $access ? 'statistics_admin_topnodes' : MENU_DENIED, 1); - menu('admin/logs/referrer', t('referrer'), $access ? 'statistics_top_refer' : MENU_DENIED, 2); - menu('admin/logs/referrer/internal', t('internal referrers only'), MENU_FALLTHROUGH); - menu('admin/logs/referrer/external', t('external referrers only'), MENU_FALLTHROUGH); - menu('admin/logs/access', t('access'), $access ? 'statistics_admin_displaylog' : MENU_DENIED, 3); - } - return $links; } +/** + * Implementation of hook_menu(). + */ +function statistics_menu() { + $items = array(); + $items[] = array('path' => 'statistics', 'title' => t('most popular content'), + 'callback' => 'statistics_page', + 'access' => user_access('access content'), + 'type' => MENU_SUGGESTED_ITEM); + + $access = user_access('administer statistics module') || user_access('administer statistics'); + $items[] = array('path' => 'admin/logs/topnodes', 'title' => t('top nodes'), + 'callback' => 'statistics_admin_topnodes', 'access' => $access, + 'weight' => 1); + $items[] = array('path' => 'admin/logs/referrer', 'title' => t('referrer'), + 'callback' => 'statistics_top_refer', 'access' => $access, + 'weight' => 2); + $items[] = array('path' => 'admin/logs/referrer/internal', 'title' => t('internal referrers only'), + 'access' => $access); + $items[] = array('path' => 'admin/logs/referrer/external', 'title' => t('external referrers only'), + 'access' => $access); + $items[] = array('path' => 'admin/logs/access', 'title' => t('access'), + 'callback' => 'statistics_admin_displaylog', 'access' => $access, + 'weight' => 3); + return $items; +} + function statistics_admin_topnodes_table() { $header = array( @@ -169,7 +184,7 @@ function statistics_admin_topnodes_table $result = pager_query($sql, 20); // WHERE s.%s <> '0' while ($nid = db_fetch_array($result)) { - $rows[] = array(l($nid['title'], 'node/view/'. $nid['nid'], array('title' => t('View this posting.'))), $nid['daycount'], $nid['totalcount'], format_date($nid['timestamp'], 'small'), l('track node', "admin/logs/access/node/$nid[nid]")); + $rows[] = array(l($nid['title'], 'node/'. $nid['nid'], array('title' => t('View this posting.'))), $nid['daycount'], $nid['totalcount'], format_date($nid['timestamp'], 'small'), l('track node', "admin/logs/access/node/$nid[nid]")); } if ($pager = theme('pager', NULL, 20, 0, tablesort_pager())) { $rows[] = array(array('data' => $pager, 'colspan' => 5)); @@ -226,7 +241,7 @@ function statistics_admin_accesslog_tabl $url = message_na(); } - $rows[] = array(array('data' => format_date($log->timestamp, 'small'), 'nowrap' => 'nowrap'), ($log->nid ? l($log->title, "node/view/$log->nid") : message_na()), format_name($user), $log->hostname ? $log->hostname : message_na(), $url, ($log->nid ? l(t('track node'), "admin/logs/access/node/$log->nid") : ''), ($user->uid ? l(t('track user'), "admin/logs/access/user/$user->uid") : ''), ($log->hostname ? l(t('track host'), "admin/logs/access/host/$log->hostname") : '')); + $rows[] = array(array('data' => format_date($log->timestamp, 'small'), 'nowrap' => 'nowrap'), ($log->nid ? l($log->title, "node/$log->nid") : message_na()), format_name($user), $log->hostname ? $log->hostname : message_na(), $url, ($log->nid ? l(t('track node'), "admin/logs/access/node/$log->nid") : ''), ($user->uid ? l(t('track user'), "admin/logs/access/user/$user->uid") : ''), ($log->hostname ? l(t('track host'), "admin/logs/access/host/$log->hostname") : '')); } if ($pager = theme('pager', NULL, 50, 0, tablesort_pager())) { @@ -513,7 +528,7 @@ function statistics_summary($dbfield, $d $content = node_load(array('nid' => $nid['nid'])); $links = link_node($content, 1); - $output .= ''. l($nid['title'], 'node/view/'. $nid['nid'], array('title' => t('View this posting.'))) .''. t('Submitted by %a on %b', array('%a' => format_name($content), '%b' => format_date($content->created, 'large'))) .''; + $output .= ''. l($nid['title'], 'node/'. $nid['nid'], array('title' => t('View this posting.'))) .''. t('Submitted by %a on %b', array('%a' => format_name($content), '%b' => format_date($content->created, 'large'))) .''; $output .= '
    '. check_output($content->teaser) .'
    '; $output .= '[ '. theme('links', $links) .' ]

    '; } === modified file 'modules/statistics/statistics.module' --- modules/statistics/statistics.module 2004-05-17 22:00:06 +0000 +++ modules/statistics/statistics.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ administer statistics module - enable for user roles that get to configure the statistics module.
  • administer statistics - enable for user roles that get to view the referrer statistics.
  • If 'administer statistics' and 'access statistics' are both enabled, the user will see a link from each node to that node's referrer statistics (if enabled).

    ", - array('%modules' => url('admin/system/modules'), '%permissions' => url('admin/user/permission'), '%referer' => url('admin/logs/referrer'), '%access' => url('admin/logs/access'), '%configuration' => url('admin/system/modules/statistics'), '%block' => url('admin/system/block'))); - case 'admin/system/modules#description': + array('%modules' => url('admin/modules'), '%permissions' => url('admin/user/permission'), '%referer' => url('admin/logs/referrer'), '%access' => url('admin/logs/access'), '%configuration' => url('admin/settings/statistics'), '%block' => url('admin/block'))); + case 'admin/modules#description': return t('Logs access statistics for your site.'); - case 'admin/system/modules/statistics': + case 'admin/settings/statistics': return t('Settings for the statistical information that Drupal will keep about the site. See site statistics for the actual information.', array('%statistics' => url('admin/logs/topnodes'))); case 'admin/logs/topnodes': return t('This page gives you an at-a-glance look at your most popular content.'); @@ -140,21 +140,36 @@ function statistics_link($type, $node = } } - if ($type == 'system') { - menu('statistics', t('most popular content'), user_access('access content') ? 'statistics_page' : MENU_DENIED, 0, MENU_HIDE); - - $access = user_access('administer statistics module') || user_access('administer statistics'); - - menu('admin/logs/topnodes', t('top nodes'), $access ? 'statistics_admin_topnodes' : MENU_DENIED, 1); - menu('admin/logs/referrer', t('referrer'), $access ? 'statistics_top_refer' : MENU_DENIED, 2); - menu('admin/logs/referrer/internal', t('internal referrers only'), MENU_FALLTHROUGH); - menu('admin/logs/referrer/external', t('external referrers only'), MENU_FALLTHROUGH); - menu('admin/logs/access', t('access'), $access ? 'statistics_admin_displaylog' : MENU_DENIED, 3); - } - return $links; } +/** + * Implementation of hook_menu(). + */ +function statistics_menu() { + $items = array(); + $items[] = array('path' => 'statistics', 'title' => t('most popular content'), + 'callback' => 'statistics_page', + 'access' => user_access('access content'), + 'type' => MENU_SUGGESTED_ITEM); + + $access = user_access('administer statistics module') || user_access('administer statistics'); + $items[] = array('path' => 'admin/logs/topnodes', 'title' => t('top nodes'), + 'callback' => 'statistics_admin_topnodes', 'access' => $access, + 'weight' => 1); + $items[] = array('path' => 'admin/logs/referrer', 'title' => t('referrer'), + 'callback' => 'statistics_top_refer', 'access' => $access, + 'weight' => 2); + $items[] = array('path' => 'admin/logs/referrer/internal', 'title' => t('internal referrers only'), + 'access' => $access); + $items[] = array('path' => 'admin/logs/referrer/external', 'title' => t('external referrers only'), + 'access' => $access); + $items[] = array('path' => 'admin/logs/access', 'title' => t('access'), + 'callback' => 'statistics_admin_displaylog', 'access' => $access, + 'weight' => 3); + return $items; +} + function statistics_admin_topnodes_table() { $header = array( @@ -169,7 +184,7 @@ function statistics_admin_topnodes_table $result = pager_query($sql, 20); // WHERE s.%s <> '0' while ($nid = db_fetch_array($result)) { - $rows[] = array(l($nid['title'], 'node/view/'. $nid['nid'], array('title' => t('View this posting.'))), $nid['daycount'], $nid['totalcount'], format_date($nid['timestamp'], 'small'), l('track node', "admin/logs/access/node/$nid[nid]")); + $rows[] = array(l($nid['title'], 'node/'. $nid['nid'], array('title' => t('View this posting.'))), $nid['daycount'], $nid['totalcount'], format_date($nid['timestamp'], 'small'), l('track node', "admin/logs/access/node/$nid[nid]")); } if ($pager = theme('pager', NULL, 20, 0, tablesort_pager())) { $rows[] = array(array('data' => $pager, 'colspan' => 5)); @@ -226,7 +241,7 @@ function statistics_admin_accesslog_tabl $url = message_na(); } - $rows[] = array(array('data' => format_date($log->timestamp, 'small'), 'nowrap' => 'nowrap'), ($log->nid ? l($log->title, "node/view/$log->nid") : message_na()), format_name($user), $log->hostname ? $log->hostname : message_na(), $url, ($log->nid ? l(t('track node'), "admin/logs/access/node/$log->nid") : ''), ($user->uid ? l(t('track user'), "admin/logs/access/user/$user->uid") : ''), ($log->hostname ? l(t('track host'), "admin/logs/access/host/$log->hostname") : '')); + $rows[] = array(array('data' => format_date($log->timestamp, 'small'), 'nowrap' => 'nowrap'), ($log->nid ? l($log->title, "node/$log->nid") : message_na()), format_name($user), $log->hostname ? $log->hostname : message_na(), $url, ($log->nid ? l(t('track node'), "admin/logs/access/node/$log->nid") : ''), ($user->uid ? l(t('track user'), "admin/logs/access/user/$user->uid") : ''), ($log->hostname ? l(t('track host'), "admin/logs/access/host/$log->hostname") : '')); } if ($pager = theme('pager', NULL, 50, 0, tablesort_pager())) { @@ -513,7 +528,7 @@ function statistics_summary($dbfield, $d $content = node_load(array('nid' => $nid['nid'])); $links = link_node($content, 1); - $output .= ''. l($nid['title'], 'node/view/'. $nid['nid'], array('title' => t('View this posting.'))) .''. t('Submitted by %a on %b', array('%a' => format_name($content), '%b' => format_date($content->created, 'large'))) .''; + $output .= ''. l($nid['title'], 'node/'. $nid['nid'], array('title' => t('View this posting.'))) .''. t('Submitted by %a on %b', array('%a' => format_name($content), '%b' => format_date($content->created, 'large'))) .''; $output .= '
    '. check_output($content->teaser) .'
    '; $output .= '[ '. theme('links', $links) .' ]

    '; } === modified file 'modules/story.module' --- modules/story.module 2004-05-08 07:17:47 +0000 +++ modules/story.module 2004-06-18 15:04:33 +0000 @@ -1,14 +1,14 @@ submit -> moderate -> post to the main page -> comments. Below you may fix a minimum word count for stories and also write some submission or content guidelines for users wanting to post a story."); case 'admin/help#story': return t(" @@ -17,7 +17,7 @@ function story_help($section) {

    User access permissions for stories

    create stories: Allows a role to create stories. They cannot edit or delete stories, even if they are the authors. You must enable this permission to in order for a role to create a story.

    maintain personal stories: Allows a role to add/edit stories if they own the story. Use this permission if you want users to be able to edit and maintain their own stories.

    - ", array('%story-config' => url('admin/system/modules/story'))); + ", array('%story-config' => url('admin/settings/story'))); case 'node/add/story': return variable_get('story_help', ''); case 'node/add#story': @@ -78,14 +78,10 @@ function story_access($op, $node) { function story_link($type, $node = 0, $main) { $links = array(); - if ($type == 'system') { - menu('node/add/story', t('story'), story_access('create', $node) ? MENU_FALLTHROUGH : MENU_DENIED, 0); - } - if ($type == 'node' && $node->type == 'story') { - /* Don't display a redundant edit link if they are node administrators */ + // Don't display a redundant edit link if they are node administrators. if (story_access('update', $node) && !user_access('administer nodes')) { - $links[] = l(t('edit this story'), "node/edit/$node->nid"); + $links[] = l(t('edit this story'), "node/$node->nid/edit"); } } @@ -93,6 +89,16 @@ function story_link($type, $node = 0, $m } /** + * Implementation of hook_menu(). + */ +function story_menu() { + $items = array(); + $items[] = array('path' => 'node/add/story', 'title' => t('story'), + 'access' => story_access('create', NULL)); + return $items; +} + +/** * Implementation of hook_validate(). * * Ensures the story is of adequate length. === modified file 'modules/story/story.module' --- modules/story/story.module 2004-05-08 07:17:47 +0000 +++ modules/story/story.module 2004-06-18 15:04:33 +0000 @@ -1,14 +1,14 @@ submit -> moderate -> post to the main page -> comments. Below you may fix a minimum word count for stories and also write some submission or content guidelines for users wanting to post a story."); case 'admin/help#story': return t(" @@ -17,7 +17,7 @@ function story_help($section) {

    User access permissions for stories

    create stories: Allows a role to create stories. They cannot edit or delete stories, even if they are the authors. You must enable this permission to in order for a role to create a story.

    maintain personal stories: Allows a role to add/edit stories if they own the story. Use this permission if you want users to be able to edit and maintain their own stories.

    - ", array('%story-config' => url('admin/system/modules/story'))); + ", array('%story-config' => url('admin/settings/story'))); case 'node/add/story': return variable_get('story_help', ''); case 'node/add#story': @@ -78,14 +78,10 @@ function story_access($op, $node) { function story_link($type, $node = 0, $main) { $links = array(); - if ($type == 'system') { - menu('node/add/story', t('story'), story_access('create', $node) ? MENU_FALLTHROUGH : MENU_DENIED, 0); - } - if ($type == 'node' && $node->type == 'story') { - /* Don't display a redundant edit link if they are node administrators */ + // Don't display a redundant edit link if they are node administrators. if (story_access('update', $node) && !user_access('administer nodes')) { - $links[] = l(t('edit this story'), "node/edit/$node->nid"); + $links[] = l(t('edit this story'), "node/$node->nid/edit"); } } @@ -93,6 +89,16 @@ function story_link($type, $node = 0, $m } /** + * Implementation of hook_menu(). + */ +function story_menu() { + $items = array(); + $items[] = array('path' => 'node/add/story', 'title' => t('story'), + 'access' => story_access('create', NULL)); + return $items; +} + +/** * Implementation of hook_validate(). * * Ensures the story is of adequate length. === modified file 'modules/system.module' --- modules/system.module 2004-05-01 09:14:49 +0000 +++ modules/system.module 2004-06-18 15:04:33 +0000 @@ -1,22 +1,21 @@ permissions might be made available. Modules can automatically be temporarily disabled to reduce server load when your site becomes extremely busy by checking throttle. The auto-throttle functionality must be enabled on the throttle configuration page after having enabled the throttle module.", array("%permissions" => url("admin/user/permission"), "%throttle" => url("admin/system/modules/throttle"))); - break; + case 'admin': + return t('General configuration options for your site. Set up the name of the site, e-mail address used in mail-outs, clean URL options, caching, etc.'); + case 'admin/themes': + return t('Select which themes are available to your users and specify the default theme.'); + case 'admin/modules': + return t("Modules are plugins for Drupal that extend its core functionality. Here you can select which modules are enabled. Click on the name of the module in the navigation menu for their individual configuration pages. Once a module is enabled, new permissions might be made available. Modules can automatically be temporarily disabled to reduce server load when your site becomes extremely busy by checking throttle. The auto-throttle functionality must be enabled on the throttle configuration page after having enabled the throttle module.", array('%permissions' => url('admin/user/permission'), '%throttle' => url('admin/settings/throttle'))); case 'admin/help#system': - $output .= t(" + return t("

    Drupal comes with system-wide defaults but the setting-module provides control over many Drupal preferences, behaviours including visual and operational settings.

    Cron

    Some modules require regularly scheduled actions, such as cleaning up logfiles. Cron, which stands for chronograph, is a periodic command scheduler executing commands at intervals specified in seconds. It can be used to control the execution of daily, weekly and monthly jobs (or anything with a period measured in seconds). Automating tasks is one of the best ways to keep a system running smoothly, and if most of your administration does not require your direct involvement, cron is an ideal solution.

    @@ -27,75 +26,92 @@ function system_help($section = "admin/h
         00 * * * * /home/www/drupal/scripts/cron-lynx.sh
    Note that it is essential to access cron.php using a browser on the web site's domain; do not run it using command line PHP and avoid using localhost or 127.0.0.1 or some of the environment varibles will not be set correctly and features may not work as expected.

    Cache

    -

    Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached.

    ", array("%base_url" => $base_url, "%cron-link" => "$base_url/cron.php", "%lynx" => "http://lynx.browser.org", "%wget" => "http://www.gnu.org/software/wget/wget.html" )); - break; - case 'admin/system/modules#description': - $output = t("Configuration system that lets administrators modify the workings of the site."); - break; +

    Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached.

    ", array('%base_url' => $base_url, '%cron-link' => "$base_url/cron.php", '%lynx' => 'http://lynx.browser.org', '%wget' => 'http://www.gnu.org/software/wget/wget.html' )); + case 'admin/modules#description': + return t('Configuration system that lets administrators modify the workings of the site.'); } - - return $output; } +/** + * Menu callback; presents system-specific help text from admin/help. + */ function system_help_page() { - print theme("page", system_help()); + print theme('page', system_help('admin/help#system')); } +/** + * Implementation of hook_perm(). + */ function system_perm() { - return array("administer site configuration", "access administration pages", "bypass input data check", "create php content"); + return array('administer site configuration', 'access administration pages', 'bypass input data check', 'create php content'); } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function system_link($type) { - if ($type == 'system') { - menu('system/files', t('file download'), 'file_download', 0, MENU_HIDE, MENU_LOCKED); - $access = user_access('administer site configuration'); - - menu('admin/system', t('configuration'), $access ? 'system_admin' : MENU_DENIED, 3); - menu('admin/system/themes', t('themes'), $access ? 'system_admin' : MENU_DENIED, 2); - - foreach (list_themes() as $theme) { - // TODO: reenable 'forced refresh' once we move the menu_build() later in the request. it added overhead with no benefit - // NOTE: refresh the list because some themes might have been enabled/disabled. - include_once "$theme->filename"; - $function = $theme->name .'_settings'; - if (function_exists($function)) { - menu("admin/system/themes/$theme->name", $theme->name, $access ? 'system_admin' : MENU_DENIED); - } +function system_menu() { + $items = array(); + $items[] = array('path' => 'system/files', 'title' => t('file download'), + 'callback' => 'file_download', + 'access' => TRUE, + 'type' => MENU_CALLBACK); + + $access = user_access('administer site configuration'); + // Themes: + $items[] = array('path' => 'admin/themes', 'title' => t('themes'), + 'callback' => 'system_themes', 'access' => $access); + foreach (list_themes() as $theme) { + // TODO: reenable 'forced refresh' once we move the menu_build() later + // in the request. It added overhead with no benefit. + // NOTE: refresh the list because some themes might have been enabled/disabled. + include_once $theme->filename; + $function = $theme->name .'_settings'; + if (function_exists($function)) { + $items[] = array('path' => 'admin/themes/'. $theme->name, 'title' => $theme->name, + 'callback' => 'system_configure_theme', 'access' => $access); } + } - menu('admin/system/modules', t('modules'), $access ? 'system_admin' : MENU_DENIED, 3); - foreach (module_list() as $name) { - // TODO: reenable 'forced refresh' once we move the menu_build() later in the request. it added overhead with no benefit - // NOTE: refresh the list because some modules might have been enabled/disabled. - if (module_hook($name, 'settings')) { - menu("admin/system/modules/$name", t($name), $access ? 'system_admin' : MENU_DENIED); - } + // Modules: + $items[] = array('path' => 'admin/settings', 'title' => t('settings'), + 'callback' => 'system_site_settings', 'access' => $access); + foreach (module_list() as $name) { + // TODO: reenable 'forced refresh' once we move the menu_build() later + // in the request. It added overhead with no benefit. + // NOTE: refresh the list because some modules might have been enabled/disabled. + if (module_hook($name, 'settings')) { + $items[] = array('path' => 'admin/settings/'. $name, 'title' => t($name)); } - menu('admin/system/help', t('help'), $access ? 'system_help_page' : MENU_DENIED, 9); } + $items[] = array('path' => 'admin/modules', 'title' => t('modules'), + 'callback' => 'system_modules', 'access' => $access); + + return $items; } +/** + * Implementation of hook_user(). + * + * Allows users to individually set their theme and time zone. + */ function system_user($type, $edit, &$user) { if ($type == 'form') { - $options = "\n"; + $options = '\n"; if (count($themes = list_themes()) > 1) { foreach ($themes as $key => $value) { - $options .= "\n"; + $options .= "\n"; } - $data[t('Theme settings')] = form_item(t("Theme"), "", t("Selecting a different theme will change the look and feel of the site.")); + $data[t('Theme settings')] = form_item(t('Theme'), "", t('Selecting a different theme will change the look and feel of the site.')); } - if (!variable_get("sitewide_timezone", 0)) { + if (!variable_get('sitewide_timezone', 0)) { $timestamp = time(); $zonelist = array(-11, -10, -9.5, -9, -8, -7, -6, -5, -4, -3.5, -3, -2, -1, 0, 1, 2, 3, 3.5, 4, 5, 5.5, 5.75, 6, 6.5, 7, 8, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 14); foreach ($zonelist as $offset) { $zone = $offset * 3600; $zones[$zone] = format_date($timestamp, 'custom', variable_get('date_format_long', 'l, F j, Y - H:i') . ' O', $zone); } - $data[t('Locale settings')] = form_select(t("Time zone"), "timezone", $edit["timezone"], $zones, t("Select what time you currently have and your time zone settings will be set appropriate.")); + $data[t('Locale settings')] = form_select(t('Time zone'), 'timezone', $edit['timezone'], $zones, t('Select what time you currently have and your time zone settings will be set appropriately.')); } return $data; } @@ -105,23 +121,28 @@ function system_view_general() { global $conf; // general settings: - $group = form_textfield(t("Name"), "site_name", variable_get("site_name", "drupal"), 70, 70, t("The name of this web site.")); - $group .= form_textfield(t("E-mail address"), "site_mail", variable_get("site_mail", ini_get("sendmail_from")), 70, 128, t("A valid e-mail address for this website, used by the auto-mailer during registration, new password requests, notifications, etc.")); - $group .= form_textfield(t("Slogan"), "site_slogan", variable_get("site_slogan", ""), 70, 128, t("The slogan of this website. Some themes display a slogan when available.")); - $group .= form_textarea(t("Mission"), "site_mission", variable_get("site_mission", ""), 70, 5, t("Your site's mission statement or focus.")); - $group .= form_textarea(t("Footer message"), "site_footer", variable_get("site_footer", ""), 70, 5, t("This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.")); - $group .= form_textfield(t("Anonymous user"), "anonymous", variable_get("anonymous", "Anonymous"), 70, 70, t("The name used to indicate anonymous users.")); - $group .= form_textfield(t("Default front page"), "site_frontpage", variable_get("site_frontpage", "node"), 70, 70, t("The home page displays content from this relative URL. If you are not using clean URLs, specify the part after '?q='. If unsure, specify 'node'.")); - $group .= form_textfield(t("Default 403 (access denied) page"), "site_403", variable_get("site_403", ""), 70, 70, t("This page is displayed when the requested document is denied to the current user. If you are not using clean URLs, specify the part after '?q='. If unsure, specify nothing.")); - $group .= form_textfield(t("Default 404 (not found) page"), "site_404", variable_get("site_404", ""), 70, 70, t("This page is displayed when no other content matches the requested document. If you are not using clean URLs, specify the part after '?q='. If unsure, specify nothing.")); - $group .= form_radios(t("Clean URLs"), "clean_url", variable_get("clean_url", 0), array(t("Disabled"), t("Enabled")), t("Enable or disable clean URLs. If enabled, you'll need ModRewrite support. See also the .htaccess file in Drupal's top-level directory.")); + $group = form_textfield(t('Name'), 'site_name', variable_get('site_name', 'drupal'), 70, 70, t('The name of this web site.')); + $group .= form_textfield(t('E-mail address'), 'site_mail', variable_get('site_mail', ini_get('sendmail_from')), 70, 128, t('A valid e-mail address for this website, used by the auto-mailer during registration, new password requests, notifications, etc.')); + $group .= form_textfield(t('Slogan'), 'site_slogan', variable_get('site_slogan', ''), 70, 128, t('The slogan of this website. Some themes display a slogan when available.')); + $group .= form_textarea(t('Mission'), 'site_mission', variable_get('site_mission', ''), 70, 5, t('Your site\'s mission statement or focus.')); + $group .= form_textarea(t('Footer message'), 'site_footer', variable_get('site_footer', ''), 70, 5, t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.')); + $group .= form_textfield(t('Anonymous user'), 'anonymous', variable_get('anonymous', 'Anonymous'), 70, 70, t('The name used to indicate anonymous users.')); + $group .= form_textfield(t('Default front page'), 'site_frontpage', variable_get('site_frontpage', 'node'), 70, 70, t('The home page displays content from this relative URL. If you are not using clean URLs, specify the part after "?q=". If unsure, specify "node".')); + $group .= form_textfield(t('Default 403 (access denied) page'), 'site_403', variable_get('site_403', ''), 70, 70, t('This page is displayed when the requested document is denied to the current user. If you are not using clean URLs, specify the part after "?q=". If unsure, specify nothing.')); + $group .= form_textfield(t('Default 404 (not found) page'), 'site_404', variable_get('site_404', ''), 70, 70, t('This page is displayed when no other content matches the requested document. If you are not using clean URLs, specify the part after "?q=". If unsure, specify nothing.')); + $group .= form_radios(t('Clean URLs'), 'clean_url', variable_get('clean_url', 0), array(t('Disabled'), t('Enabled')), t('Enable or disable clean URLs. If enabled, you\'ll need ModRewrite support. See also the .htaccess file in Drupal\'s top-level directory.')); + + // watchdog setting: + $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval'); + $period['1000000000'] = t('Never'); + $group .= form_select(t('Discard log entries older than'), 'watchdog_clear', variable_get('watchdog_clear', 604800), $period, t('The time watchdog entries should be kept. Older entries will be automatically discarded. Requires crontab.')); - $output = form_group(t("General settings"), $group); + $output = form_group(t('General settings'), $group); // caching: - $group = form_radios(t("Cache support"), "cache", variable_get("cache", 0), array(t("Disabled"), t("Enabled")), t("Enable or disable the caching of rendered pages. When caching is enabled, Drupal will flush the cache when required to make sure updates take effect immediately. Check the cache documentation for information on Drupal's cache system.", array("%documentation" => url("admin/system/help", NULL, NULL, "cache")))); + $group = form_radios(t('Cache support'), 'cache', variable_get('cache', 0), array(t('Disabled'), t('Enabled')), t('Enable or disable the caching of rendered pages. When caching is enabled, Drupal will flush the cache when required to make sure updates take effect immediately. Check the cache documentation for information on Drupal\'s cache system.', array('%documentation' => url('admin/help', NULL, NULL, 'cache')))); - $output .= form_group(t("Cache settings"), $group); + $output .= form_group(t('Cache settings'), $group); // file system: if (!file_check_directory(variable_get('file_directory_path', 'files'))) { @@ -144,93 +165,50 @@ function system_view_general() { } // date settings: possible date formats - $dateshort = array("m/d/Y - H:i", "d/m/Y - H:i", "Y/m/d - H:i", - "m/d/Y - g:ia", "d/m/Y - g:ia", "Y/m/d - g:ia", - "M j Y - H:i", "j M Y - H:i", "Y M j - H:i", - "M j Y - g:ia", "j M Y - g:ia", "Y M j - g:ia"); - $datemedium = array("D, m/d/Y - H:i", "D, d/m/Y - H:i", "D, Y/m/d - H:i", - "F j, Y - H:i", "j F, Y - H:i", "Y, F j - H:i", - "D, m/d/Y - g:ia", "D, d/m/Y - g:ia", "D, Y/m/d - g:ia", - "F j, Y - g:ia", "j F, Y - g:ia", "Y, F j - g:ia"); - $datelong = array("l, F j, Y - H:i", "l, j F, Y - H:i", "l, Y, F j - H:i", - "l, F j, Y - g:ia", "l, j F, Y - g:ia", "l, Y, F j - g:ia"); + $dateshort = array('m/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i', + 'm/d/Y - g:ia', 'd/m/Y - g:ia', 'Y/m/d - g:ia', + 'M j Y - H:i', 'j M Y - H:i', 'Y M j - H:i', + 'M j Y - g:ia', 'j M Y - g:ia', 'Y M j - g:ia'); + $datemedium = array('D, m/d/Y - H:i', 'D, d/m/Y - H:i', 'D, Y/m/d - H:i', + 'F j, Y - H:i', 'j F, Y - H:i', 'Y, F j - H:i', + 'D, m/d/Y - g:ia', 'D, d/m/Y - g:ia', 'D, Y/m/d - g:ia', + 'F j, Y - g:ia', 'j F, Y - g:ia', 'Y, F j - g:ia'); + $datelong = array('l, F j, Y - H:i', 'l, j F, Y - H:i', 'l, Y, F j - H:i', + 'l, F j, Y - g:ia', 'l, j F, Y - g:ia', 'l, Y, F j - g:ia'); // date settings: construct choices for user foreach ($dateshort as $f) { - $dateshortchoices[$f] = format_date(time(), "custom", $f); + $dateshortchoices[$f] = format_date(time(), 'custom', $f); } foreach ($datemedium as $f) { - $datemediumchoices[$f] = format_date(time(), "custom", $f); + $datemediumchoices[$f] = format_date(time(), 'custom', $f); } foreach ($datelong as $f) { - $datelongchoices[$f] = format_date(time(), "custom", $f); + $datelongchoices[$f] = format_date(time(), 'custom', $f); } - $group = form_select(t("Time zone"), "date_default_timezone", variable_get('date_default_timezone', 0), $zones, t("Select the default site timezone.")); - $group .= form_radios(t("Use sitewide timezone"), "sitewide_timezone", variable_get("sitewide_timezone", 0), array(t("Disabled"), t("Enabled")), t("Enable or disable the sidewide timezone feature. Disabled means that users could choose their own timezone.")); - $group .= form_select(t("Date format (short)"), "date_format_short", variable_get("date_format_short", $dateshort[0]), $dateshortchoices, t("The short format of date display.")); - $group .= form_select(t("Date format (medium)"), "date_format_medium", variable_get("date_format_medium", $datemedium[0]), $datemediumchoices, t("The medium sized date display.")); - $group .= form_select(t("Date format (long)"), "date_format_long", variable_get("date_format_long", $datelong[0]), $datelongchoices, t("Longer date format used for detailed display.")); + $group = form_select(t('Time zone'), 'date_default_timezone', variable_get('date_default_timezone', 0), $zones, t('Select the default site timezone.')); + $group .= form_radios(t('Use sitewide timezone'), 'sitewide_timezone', variable_get('sitewide_timezone', 0), array(t('Disabled'), t('Enabled')), t('Enable or disable the sidewide timezone feature. Disabled means that users could choose their own timezone.')); + $group .= form_select(t('Date format (short)'), 'date_format_short', variable_get('date_format_short', $dateshort[0]), $dateshortchoices, t('The short format of date display.')); + $group .= form_select(t('Date format (medium)'), 'date_format_medium', variable_get('date_format_medium', $datemedium[0]), $datemediumchoices, t('The medium sized date display.')); + $group .= form_select(t('Date format (long)'), 'date_format_long', variable_get('date_format_long', $datelong[0]), $datelongchoices, t('Longer date format used for detailed display.')); - $output .= form_group(t("Date format settings"), $group); + $output .= form_group(t('Date format settings'), $group); return $output; } -function system_view_theme($name) { - $themes = list_themes(); - $theme = $themes[$name]; - if ($theme) { - include_once "$theme->filename"; - - $function = $theme->name ."_settings"; - if (function_exists($function)) { - $output .= $function(); - } - } - else { - $output = t("Invalid theme specified"); - } - return $output; -} - -function system_view($type, $arg = "") { - // The module/theme lists don't use the generic settings handler - if (($type == "modules" || $type == "themes") && $arg == "") { - system_listing_save(); - $form = system_listing($type); - $form .= form_submit(t("Save configuration")); - return form($form); - } - - system_settings_save(); - - switch ($type) { - case "modules": - $form = module_invoke($arg, "settings"); - break; - case "themes": - $form = system_view_theme($arg); - break; - default: - $form = system_view_general(); - break; - } - - return system_settings_form($form); -} - function system_listing($type) { // Pick appropriate directory and filetype switch ($type) { - case "modules": - $directory = "modules"; - $type = "module"; + case 'modules': + $directory = 'modules'; + $type = 'module'; break; - case "themes": + case 'themes': default: - $directory = "themes"; - $type = "theme"; + $directory = 'themes'; + $type = 'theme'; break; } @@ -249,23 +227,23 @@ function system_listing($type) { ksort($files); - if ($type == "module") { - $required = array("modules/admin.module", "modules/filter.module", "modules/system.module", "modules/user.module", "modules/watchdog.module"); + if ($type == 'module') { + $required = array('modules/admin.module', 'modules/filter.module', 'modules/system.module', 'modules/user.module', 'modules/watchdog.module'); // the throttle mechanism requires additional modules always be enabled - $throttle_required = array_merge($required, array("modules/statistics.module", "modules/throttle.module")); + $throttle_required = array_merge($required, array('modules/statistics.module', 'modules/throttle.module')); - $header = array(t("name"), t("description"), t("status"), t("throttle")); + $header = array(t('name'), t('description'), t('status'), t('throttle')); } else { $required = array(); - $header = array(t("name"), t("description"), t("enable"), t("default")); + $header = array(t('name'), t('description'), t('enable'), t('default')); } foreach ($files as $filename => $file) { include_once($filename); - if ($type == "module") { - $info->name = module_invoke($file->name, "help", "admin/system/modules#name") ? module_invoke($file->name, "help", "admin/system/modules#name") : module_invoke($file->name, "system", "name") ? module_invoke($file->name, "system", "name") : $file->name; - $info->description = module_invoke($file->name, "help", "admin/system/modules#description") ? module_invoke($file->name, "help", "admin/system/modules#description") : module_invoke($file->name, "system", "description"); + if ($type == 'module') { + $info->name = module_invoke($file->name, 'help', 'admin/modules#name') ? module_invoke($file->name, 'help', 'admin/modules#name') : module_invoke($file->name, 'system', 'name') ? module_invoke($file->name, 'system', 'name') : $file->name; + $info->description = module_invoke($file->name, 'help', 'admin/modules#description') ? module_invoke($file->name, 'help', 'admin/modules#description') : module_invoke($file->name, 'system', 'description'); // log the critical hooks implemented by this module $bootstrap = 0; foreach (bootstrap_hooks() as $hook) { @@ -275,13 +253,13 @@ function system_listing($type) { } } } - elseif ($type == "theme") { + elseif ($type == 'theme') { $info->name = $file->name; - $info->description = module_invoke($file->name, "help", "admin/system/themes#description"); + $info->description = module_invoke($file->name, 'help', 'admin/themes#description'); $themes[] = $info->name; // Enable the default theme: - if ($info->name == variable_get("theme_default", 0)) { + if ($info->name == variable_get('theme_default', 0)) { $file->status = 1; } } @@ -290,63 +268,63 @@ function system_listing($type) { db_query("DELETE FROM {system} WHERE filename = '%s' AND type = '%s'", $filename, $type); db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $info->name, $info->description, $type, $filename, $file->status, $file->throttle, $bootstrap); - $row = array($info->name, $info->description, array("data" => (in_array($filename, $required) ? form_hidden("status][$filename", 1) . t("required") : form_checkbox("", "status][$filename", 1, $file->status)), "align" => "center")); - if ($type == "module") { - $row[] = array("data" => (in_array($filename, $throttle_required) ? form_hidden("throttle][$filename", 0) . t("required") : form_checkbox(NULL, "throttle][$filename", 1, $file->throttle, NULL, module_exist('throttle') ? NULL : array("disabled" => "disabled"))), "align" => "center"); + $row = array($info->name, $info->description, array('data' => (in_array($filename, $required) ? form_hidden("status][$filename", 1) . t('required') : form_checkbox('', "status][$filename", 1, $file->status)), 'align' => 'center')); + if ($type == 'module') { + $row[] = array('data' => (in_array($filename, $throttle_required) ? form_hidden("throttle][$filename", 0) . t('required') : form_checkbox(NULL, "throttle][$filename", 1, $file->throttle, NULL, module_exist('throttle') ? NULL : array('disabled' => 'disabled'))), 'align' => 'center'); } - else if ($type == "theme") { - $row[] = array("data" => form_radio("", "theme_default", $info->name, (variable_get("theme_default",0) == $info->name) ? 1 : 0), "align" => "center"); + else if ($type == 'theme') { + $row[] = array('data' => form_radio('', 'theme_default', $info->name, (variable_get('theme_default', 0) == $info->name) ? 1 : 0), 'align' => 'center'); } $rows[] = $row; } - $output = theme("table", $header, $rows); - $output .= form_hidden("type", $type); + $output = theme('table', $header, $rows); + $output .= form_hidden('type', $type); return $output; } function system_listing_save($edit = array()) { - $op = $_POST["op"]; - $edit = $_POST["edit"]; + $op = $_POST['op']; + $edit = $_POST['edit']; - if ($op == t("Save configuration")) { - db_query("UPDATE {system} SET status = '0' WHERE type = '%s'", $edit["type"]); - foreach ($edit["status"] as $filename => $status) { - db_query("UPDATE {system} SET status = %d, throttle = %d WHERE filename = '$filename'", $status, $edit["throttle"]["$filename"]); + if ($op == t('Save configuration')) { + db_query("UPDATE {system} SET status = 0 WHERE type = '%s'", $edit['type']); + foreach ($edit['status'] as $filename => $status) { + db_query("UPDATE {system} SET status = %d, throttle = %d WHERE filename = '%s'", $status, $edit['throttle'][$filename], $filename); } - if ($edit["type"] == "theme") { - variable_set("theme_default", $edit["theme_default"]); + if ($edit['type'] == 'theme') { + variable_set('theme_default', $edit['theme_default']); } cache_clear_all(); - drupal_set_message(t("the configuration options have been saved.")); + drupal_set_message(t('the configuration options have been saved.')); } } function system_settings_form($form) { - $form .= form_submit(t("Save configuration")); - $form .= form_submit(t("Reset to defaults")); + $form .= form_submit(t('Save configuration')); + $form .= form_submit(t('Reset to defaults')); return form($form); } function system_settings_save() { - $op = $_POST["op"]; - $edit = $_POST["edit"]; + $op = $_POST['op']; + $edit = $_POST['edit']; - if ($op == t("Reset to defaults")) { + if ($op == t('Reset to defaults')) { foreach ($edit as $name => $value) { variable_del($name); } - drupal_set_message(t("the configuration options have been reset to their default values.")); + drupal_set_message(t('the configuration options have been reset to their default values.')); } - if ($op == t("Save configuration")) { + if ($op == t('Save configuration')) { foreach ($edit as $name => $value) { variable_set($name, $value); } - drupal_set_message(t("the configuration options have been saved.")); + drupal_set_message(t('the configuration options have been saved.')); } else { return; @@ -355,9 +333,62 @@ function system_settings_save() { cache_clear_all(); } -function system_admin() { - $output = system_view(arg(2), arg(3)); - print theme("page", $output); +/** + * Menu callback; displays a listing of all themes. + */ +function system_themes() { + system_listing_save(); + $form = system_listing('themes'); + $form .= form_submit(t('Save configuration')); + print theme('page', form($form)); +} + +/** + * Menu callback; displays a listing of all modules. + */ +function system_modules() { + system_listing_save(); + $form = system_listing('modules'); + $form .= form_submit(t('Save configuration')); + print theme('page', form($form)); +} + +/** + * Menu callback; displays a theme's settings page. + */ +function system_configure_theme() { + system_settings_save(); + + $name = arg(2); + $themes = list_themes(); + $theme = $themes[$name]; + + if ($theme) { + include_once "$theme->filename"; + + $function = $theme->name .'_settings'; + if (function_exists($function)) { + $form .= $function(); + } + } + + print theme('page', system_settings_form($form)); +} + +/** + * Menu callback; displays a module's settings page. + */ +function system_site_settings($module = NULL) { + system_settings_save(); + + if ($module) { + $form = module_invoke($module, 'settings'); + } + else { + $form = system_view_general(); + } + + print theme('page', system_settings_form($form)); } ?> === modified file 'modules/system/system.module' --- modules/system/system.module 2004-05-01 09:14:49 +0000 +++ modules/system/system.module 2004-06-18 15:04:33 +0000 @@ -1,22 +1,21 @@ permissions might be made available. Modules can automatically be temporarily disabled to reduce server load when your site becomes extremely busy by checking throttle. The auto-throttle functionality must be enabled on the throttle configuration page after having enabled the throttle module.", array("%permissions" => url("admin/user/permission"), "%throttle" => url("admin/system/modules/throttle"))); - break; + case 'admin': + return t('General configuration options for your site. Set up the name of the site, e-mail address used in mail-outs, clean URL options, caching, etc.'); + case 'admin/themes': + return t('Select which themes are available to your users and specify the default theme.'); + case 'admin/modules': + return t("Modules are plugins for Drupal that extend its core functionality. Here you can select which modules are enabled. Click on the name of the module in the navigation menu for their individual configuration pages. Once a module is enabled, new permissions might be made available. Modules can automatically be temporarily disabled to reduce server load when your site becomes extremely busy by checking throttle. The auto-throttle functionality must be enabled on the throttle configuration page after having enabled the throttle module.", array('%permissions' => url('admin/user/permission'), '%throttle' => url('admin/settings/throttle'))); case 'admin/help#system': - $output .= t(" + return t("

    Drupal comes with system-wide defaults but the setting-module provides control over many Drupal preferences, behaviours including visual and operational settings.

    Cron

    Some modules require regularly scheduled actions, such as cleaning up logfiles. Cron, which stands for chronograph, is a periodic command scheduler executing commands at intervals specified in seconds. It can be used to control the execution of daily, weekly and monthly jobs (or anything with a period measured in seconds). Automating tasks is one of the best ways to keep a system running smoothly, and if most of your administration does not require your direct involvement, cron is an ideal solution.

    @@ -27,75 +26,92 @@ function system_help($section = "admin/h
         00 * * * * /home/www/drupal/scripts/cron-lynx.sh
    Note that it is essential to access cron.php using a browser on the web site's domain; do not run it using command line PHP and avoid using localhost or 127.0.0.1 or some of the environment varibles will not be set correctly and features may not work as expected.

    Cache

    -

    Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached.

    ", array("%base_url" => $base_url, "%cron-link" => "$base_url/cron.php", "%lynx" => "http://lynx.browser.org", "%wget" => "http://www.gnu.org/software/wget/wget.html" )); - break; - case 'admin/system/modules#description': - $output = t("Configuration system that lets administrators modify the workings of the site."); - break; +

    Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached.

    ", array('%base_url' => $base_url, '%cron-link' => "$base_url/cron.php", '%lynx' => 'http://lynx.browser.org', '%wget' => 'http://www.gnu.org/software/wget/wget.html' )); + case 'admin/modules#description': + return t('Configuration system that lets administrators modify the workings of the site.'); } - - return $output; } +/** + * Menu callback; presents system-specific help text from admin/help. + */ function system_help_page() { - print theme("page", system_help()); + print theme('page', system_help('admin/help#system')); } +/** + * Implementation of hook_perm(). + */ function system_perm() { - return array("administer site configuration", "access administration pages", "bypass input data check", "create php content"); + return array('administer site configuration', 'access administration pages', 'bypass input data check', 'create php content'); } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function system_link($type) { - if ($type == 'system') { - menu('system/files', t('file download'), 'file_download', 0, MENU_HIDE, MENU_LOCKED); - $access = user_access('administer site configuration'); - - menu('admin/system', t('configuration'), $access ? 'system_admin' : MENU_DENIED, 3); - menu('admin/system/themes', t('themes'), $access ? 'system_admin' : MENU_DENIED, 2); - - foreach (list_themes() as $theme) { - // TODO: reenable 'forced refresh' once we move the menu_build() later in the request. it added overhead with no benefit - // NOTE: refresh the list because some themes might have been enabled/disabled. - include_once "$theme->filename"; - $function = $theme->name .'_settings'; - if (function_exists($function)) { - menu("admin/system/themes/$theme->name", $theme->name, $access ? 'system_admin' : MENU_DENIED); - } +function system_menu() { + $items = array(); + $items[] = array('path' => 'system/files', 'title' => t('file download'), + 'callback' => 'file_download', + 'access' => TRUE, + 'type' => MENU_CALLBACK); + + $access = user_access('administer site configuration'); + // Themes: + $items[] = array('path' => 'admin/themes', 'title' => t('themes'), + 'callback' => 'system_themes', 'access' => $access); + foreach (list_themes() as $theme) { + // TODO: reenable 'forced refresh' once we move the menu_build() later + // in the request. It added overhead with no benefit. + // NOTE: refresh the list because some themes might have been enabled/disabled. + include_once $theme->filename; + $function = $theme->name .'_settings'; + if (function_exists($function)) { + $items[] = array('path' => 'admin/themes/'. $theme->name, 'title' => $theme->name, + 'callback' => 'system_configure_theme', 'access' => $access); } + } - menu('admin/system/modules', t('modules'), $access ? 'system_admin' : MENU_DENIED, 3); - foreach (module_list() as $name) { - // TODO: reenable 'forced refresh' once we move the menu_build() later in the request. it added overhead with no benefit - // NOTE: refresh the list because some modules might have been enabled/disabled. - if (module_hook($name, 'settings')) { - menu("admin/system/modules/$name", t($name), $access ? 'system_admin' : MENU_DENIED); - } + // Modules: + $items[] = array('path' => 'admin/settings', 'title' => t('settings'), + 'callback' => 'system_site_settings', 'access' => $access); + foreach (module_list() as $name) { + // TODO: reenable 'forced refresh' once we move the menu_build() later + // in the request. It added overhead with no benefit. + // NOTE: refresh the list because some modules might have been enabled/disabled. + if (module_hook($name, 'settings')) { + $items[] = array('path' => 'admin/settings/'. $name, 'title' => t($name)); } - menu('admin/system/help', t('help'), $access ? 'system_help_page' : MENU_DENIED, 9); } + $items[] = array('path' => 'admin/modules', 'title' => t('modules'), + 'callback' => 'system_modules', 'access' => $access); + + return $items; } +/** + * Implementation of hook_user(). + * + * Allows users to individually set their theme and time zone. + */ function system_user($type, $edit, &$user) { if ($type == 'form') { - $options = "\n"; + $options = '\n"; if (count($themes = list_themes()) > 1) { foreach ($themes as $key => $value) { - $options .= "\n"; + $options .= "\n"; } - $data[t('Theme settings')] = form_item(t("Theme"), "", t("Selecting a different theme will change the look and feel of the site.")); + $data[t('Theme settings')] = form_item(t('Theme'), "", t('Selecting a different theme will change the look and feel of the site.')); } - if (!variable_get("sitewide_timezone", 0)) { + if (!variable_get('sitewide_timezone', 0)) { $timestamp = time(); $zonelist = array(-11, -10, -9.5, -9, -8, -7, -6, -5, -4, -3.5, -3, -2, -1, 0, 1, 2, 3, 3.5, 4, 5, 5.5, 5.75, 6, 6.5, 7, 8, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 14); foreach ($zonelist as $offset) { $zone = $offset * 3600; $zones[$zone] = format_date($timestamp, 'custom', variable_get('date_format_long', 'l, F j, Y - H:i') . ' O', $zone); } - $data[t('Locale settings')] = form_select(t("Time zone"), "timezone", $edit["timezone"], $zones, t("Select what time you currently have and your time zone settings will be set appropriate.")); + $data[t('Locale settings')] = form_select(t('Time zone'), 'timezone', $edit['timezone'], $zones, t('Select what time you currently have and your time zone settings will be set appropriately.')); } return $data; } @@ -105,23 +121,28 @@ function system_view_general() { global $conf; // general settings: - $group = form_textfield(t("Name"), "site_name", variable_get("site_name", "drupal"), 70, 70, t("The name of this web site.")); - $group .= form_textfield(t("E-mail address"), "site_mail", variable_get("site_mail", ini_get("sendmail_from")), 70, 128, t("A valid e-mail address for this website, used by the auto-mailer during registration, new password requests, notifications, etc.")); - $group .= form_textfield(t("Slogan"), "site_slogan", variable_get("site_slogan", ""), 70, 128, t("The slogan of this website. Some themes display a slogan when available.")); - $group .= form_textarea(t("Mission"), "site_mission", variable_get("site_mission", ""), 70, 5, t("Your site's mission statement or focus.")); - $group .= form_textarea(t("Footer message"), "site_footer", variable_get("site_footer", ""), 70, 5, t("This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.")); - $group .= form_textfield(t("Anonymous user"), "anonymous", variable_get("anonymous", "Anonymous"), 70, 70, t("The name used to indicate anonymous users.")); - $group .= form_textfield(t("Default front page"), "site_frontpage", variable_get("site_frontpage", "node"), 70, 70, t("The home page displays content from this relative URL. If you are not using clean URLs, specify the part after '?q='. If unsure, specify 'node'.")); - $group .= form_textfield(t("Default 403 (access denied) page"), "site_403", variable_get("site_403", ""), 70, 70, t("This page is displayed when the requested document is denied to the current user. If you are not using clean URLs, specify the part after '?q='. If unsure, specify nothing.")); - $group .= form_textfield(t("Default 404 (not found) page"), "site_404", variable_get("site_404", ""), 70, 70, t("This page is displayed when no other content matches the requested document. If you are not using clean URLs, specify the part after '?q='. If unsure, specify nothing.")); - $group .= form_radios(t("Clean URLs"), "clean_url", variable_get("clean_url", 0), array(t("Disabled"), t("Enabled")), t("Enable or disable clean URLs. If enabled, you'll need ModRewrite support. See also the .htaccess file in Drupal's top-level directory.")); + $group = form_textfield(t('Name'), 'site_name', variable_get('site_name', 'drupal'), 70, 70, t('The name of this web site.')); + $group .= form_textfield(t('E-mail address'), 'site_mail', variable_get('site_mail', ini_get('sendmail_from')), 70, 128, t('A valid e-mail address for this website, used by the auto-mailer during registration, new password requests, notifications, etc.')); + $group .= form_textfield(t('Slogan'), 'site_slogan', variable_get('site_slogan', ''), 70, 128, t('The slogan of this website. Some themes display a slogan when available.')); + $group .= form_textarea(t('Mission'), 'site_mission', variable_get('site_mission', ''), 70, 5, t('Your site\'s mission statement or focus.')); + $group .= form_textarea(t('Footer message'), 'site_footer', variable_get('site_footer', ''), 70, 5, t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.')); + $group .= form_textfield(t('Anonymous user'), 'anonymous', variable_get('anonymous', 'Anonymous'), 70, 70, t('The name used to indicate anonymous users.')); + $group .= form_textfield(t('Default front page'), 'site_frontpage', variable_get('site_frontpage', 'node'), 70, 70, t('The home page displays content from this relative URL. If you are not using clean URLs, specify the part after "?q=". If unsure, specify "node".')); + $group .= form_textfield(t('Default 403 (access denied) page'), 'site_403', variable_get('site_403', ''), 70, 70, t('This page is displayed when the requested document is denied to the current user. If you are not using clean URLs, specify the part after "?q=". If unsure, specify nothing.')); + $group .= form_textfield(t('Default 404 (not found) page'), 'site_404', variable_get('site_404', ''), 70, 70, t('This page is displayed when no other content matches the requested document. If you are not using clean URLs, specify the part after "?q=". If unsure, specify nothing.')); + $group .= form_radios(t('Clean URLs'), 'clean_url', variable_get('clean_url', 0), array(t('Disabled'), t('Enabled')), t('Enable or disable clean URLs. If enabled, you\'ll need ModRewrite support. See also the .htaccess file in Drupal\'s top-level directory.')); + + // watchdog setting: + $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval'); + $period['1000000000'] = t('Never'); + $group .= form_select(t('Discard log entries older than'), 'watchdog_clear', variable_get('watchdog_clear', 604800), $period, t('The time watchdog entries should be kept. Older entries will be automatically discarded. Requires crontab.')); - $output = form_group(t("General settings"), $group); + $output = form_group(t('General settings'), $group); // caching: - $group = form_radios(t("Cache support"), "cache", variable_get("cache", 0), array(t("Disabled"), t("Enabled")), t("Enable or disable the caching of rendered pages. When caching is enabled, Drupal will flush the cache when required to make sure updates take effect immediately. Check the cache documentation for information on Drupal's cache system.", array("%documentation" => url("admin/system/help", NULL, NULL, "cache")))); + $group = form_radios(t('Cache support'), 'cache', variable_get('cache', 0), array(t('Disabled'), t('Enabled')), t('Enable or disable the caching of rendered pages. When caching is enabled, Drupal will flush the cache when required to make sure updates take effect immediately. Check the cache documentation for information on Drupal\'s cache system.', array('%documentation' => url('admin/help', NULL, NULL, 'cache')))); - $output .= form_group(t("Cache settings"), $group); + $output .= form_group(t('Cache settings'), $group); // file system: if (!file_check_directory(variable_get('file_directory_path', 'files'))) { @@ -144,93 +165,50 @@ function system_view_general() { } // date settings: possible date formats - $dateshort = array("m/d/Y - H:i", "d/m/Y - H:i", "Y/m/d - H:i", - "m/d/Y - g:ia", "d/m/Y - g:ia", "Y/m/d - g:ia", - "M j Y - H:i", "j M Y - H:i", "Y M j - H:i", - "M j Y - g:ia", "j M Y - g:ia", "Y M j - g:ia"); - $datemedium = array("D, m/d/Y - H:i", "D, d/m/Y - H:i", "D, Y/m/d - H:i", - "F j, Y - H:i", "j F, Y - H:i", "Y, F j - H:i", - "D, m/d/Y - g:ia", "D, d/m/Y - g:ia", "D, Y/m/d - g:ia", - "F j, Y - g:ia", "j F, Y - g:ia", "Y, F j - g:ia"); - $datelong = array("l, F j, Y - H:i", "l, j F, Y - H:i", "l, Y, F j - H:i", - "l, F j, Y - g:ia", "l, j F, Y - g:ia", "l, Y, F j - g:ia"); + $dateshort = array('m/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i', + 'm/d/Y - g:ia', 'd/m/Y - g:ia', 'Y/m/d - g:ia', + 'M j Y - H:i', 'j M Y - H:i', 'Y M j - H:i', + 'M j Y - g:ia', 'j M Y - g:ia', 'Y M j - g:ia'); + $datemedium = array('D, m/d/Y - H:i', 'D, d/m/Y - H:i', 'D, Y/m/d - H:i', + 'F j, Y - H:i', 'j F, Y - H:i', 'Y, F j - H:i', + 'D, m/d/Y - g:ia', 'D, d/m/Y - g:ia', 'D, Y/m/d - g:ia', + 'F j, Y - g:ia', 'j F, Y - g:ia', 'Y, F j - g:ia'); + $datelong = array('l, F j, Y - H:i', 'l, j F, Y - H:i', 'l, Y, F j - H:i', + 'l, F j, Y - g:ia', 'l, j F, Y - g:ia', 'l, Y, F j - g:ia'); // date settings: construct choices for user foreach ($dateshort as $f) { - $dateshortchoices[$f] = format_date(time(), "custom", $f); + $dateshortchoices[$f] = format_date(time(), 'custom', $f); } foreach ($datemedium as $f) { - $datemediumchoices[$f] = format_date(time(), "custom", $f); + $datemediumchoices[$f] = format_date(time(), 'custom', $f); } foreach ($datelong as $f) { - $datelongchoices[$f] = format_date(time(), "custom", $f); + $datelongchoices[$f] = format_date(time(), 'custom', $f); } - $group = form_select(t("Time zone"), "date_default_timezone", variable_get('date_default_timezone', 0), $zones, t("Select the default site timezone.")); - $group .= form_radios(t("Use sitewide timezone"), "sitewide_timezone", variable_get("sitewide_timezone", 0), array(t("Disabled"), t("Enabled")), t("Enable or disable the sidewide timezone feature. Disabled means that users could choose their own timezone.")); - $group .= form_select(t("Date format (short)"), "date_format_short", variable_get("date_format_short", $dateshort[0]), $dateshortchoices, t("The short format of date display.")); - $group .= form_select(t("Date format (medium)"), "date_format_medium", variable_get("date_format_medium", $datemedium[0]), $datemediumchoices, t("The medium sized date display.")); - $group .= form_select(t("Date format (long)"), "date_format_long", variable_get("date_format_long", $datelong[0]), $datelongchoices, t("Longer date format used for detailed display.")); + $group = form_select(t('Time zone'), 'date_default_timezone', variable_get('date_default_timezone', 0), $zones, t('Select the default site timezone.')); + $group .= form_radios(t('Use sitewide timezone'), 'sitewide_timezone', variable_get('sitewide_timezone', 0), array(t('Disabled'), t('Enabled')), t('Enable or disable the sidewide timezone feature. Disabled means that users could choose their own timezone.')); + $group .= form_select(t('Date format (short)'), 'date_format_short', variable_get('date_format_short', $dateshort[0]), $dateshortchoices, t('The short format of date display.')); + $group .= form_select(t('Date format (medium)'), 'date_format_medium', variable_get('date_format_medium', $datemedium[0]), $datemediumchoices, t('The medium sized date display.')); + $group .= form_select(t('Date format (long)'), 'date_format_long', variable_get('date_format_long', $datelong[0]), $datelongchoices, t('Longer date format used for detailed display.')); - $output .= form_group(t("Date format settings"), $group); + $output .= form_group(t('Date format settings'), $group); return $output; } -function system_view_theme($name) { - $themes = list_themes(); - $theme = $themes[$name]; - if ($theme) { - include_once "$theme->filename"; - - $function = $theme->name ."_settings"; - if (function_exists($function)) { - $output .= $function(); - } - } - else { - $output = t("Invalid theme specified"); - } - return $output; -} - -function system_view($type, $arg = "") { - // The module/theme lists don't use the generic settings handler - if (($type == "modules" || $type == "themes") && $arg == "") { - system_listing_save(); - $form = system_listing($type); - $form .= form_submit(t("Save configuration")); - return form($form); - } - - system_settings_save(); - - switch ($type) { - case "modules": - $form = module_invoke($arg, "settings"); - break; - case "themes": - $form = system_view_theme($arg); - break; - default: - $form = system_view_general(); - break; - } - - return system_settings_form($form); -} - function system_listing($type) { // Pick appropriate directory and filetype switch ($type) { - case "modules": - $directory = "modules"; - $type = "module"; + case 'modules': + $directory = 'modules'; + $type = 'module'; break; - case "themes": + case 'themes': default: - $directory = "themes"; - $type = "theme"; + $directory = 'themes'; + $type = 'theme'; break; } @@ -249,23 +227,23 @@ function system_listing($type) { ksort($files); - if ($type == "module") { - $required = array("modules/admin.module", "modules/filter.module", "modules/system.module", "modules/user.module", "modules/watchdog.module"); + if ($type == 'module') { + $required = array('modules/admin.module', 'modules/filter.module', 'modules/system.module', 'modules/user.module', 'modules/watchdog.module'); // the throttle mechanism requires additional modules always be enabled - $throttle_required = array_merge($required, array("modules/statistics.module", "modules/throttle.module")); + $throttle_required = array_merge($required, array('modules/statistics.module', 'modules/throttle.module')); - $header = array(t("name"), t("description"), t("status"), t("throttle")); + $header = array(t('name'), t('description'), t('status'), t('throttle')); } else { $required = array(); - $header = array(t("name"), t("description"), t("enable"), t("default")); + $header = array(t('name'), t('description'), t('enable'), t('default')); } foreach ($files as $filename => $file) { include_once($filename); - if ($type == "module") { - $info->name = module_invoke($file->name, "help", "admin/system/modules#name") ? module_invoke($file->name, "help", "admin/system/modules#name") : module_invoke($file->name, "system", "name") ? module_invoke($file->name, "system", "name") : $file->name; - $info->description = module_invoke($file->name, "help", "admin/system/modules#description") ? module_invoke($file->name, "help", "admin/system/modules#description") : module_invoke($file->name, "system", "description"); + if ($type == 'module') { + $info->name = module_invoke($file->name, 'help', 'admin/modules#name') ? module_invoke($file->name, 'help', 'admin/modules#name') : module_invoke($file->name, 'system', 'name') ? module_invoke($file->name, 'system', 'name') : $file->name; + $info->description = module_invoke($file->name, 'help', 'admin/modules#description') ? module_invoke($file->name, 'help', 'admin/modules#description') : module_invoke($file->name, 'system', 'description'); // log the critical hooks implemented by this module $bootstrap = 0; foreach (bootstrap_hooks() as $hook) { @@ -275,13 +253,13 @@ function system_listing($type) { } } } - elseif ($type == "theme") { + elseif ($type == 'theme') { $info->name = $file->name; - $info->description = module_invoke($file->name, "help", "admin/system/themes#description"); + $info->description = module_invoke($file->name, 'help', 'admin/themes#description'); $themes[] = $info->name; // Enable the default theme: - if ($info->name == variable_get("theme_default", 0)) { + if ($info->name == variable_get('theme_default', 0)) { $file->status = 1; } } @@ -290,63 +268,63 @@ function system_listing($type) { db_query("DELETE FROM {system} WHERE filename = '%s' AND type = '%s'", $filename, $type); db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $info->name, $info->description, $type, $filename, $file->status, $file->throttle, $bootstrap); - $row = array($info->name, $info->description, array("data" => (in_array($filename, $required) ? form_hidden("status][$filename", 1) . t("required") : form_checkbox("", "status][$filename", 1, $file->status)), "align" => "center")); - if ($type == "module") { - $row[] = array("data" => (in_array($filename, $throttle_required) ? form_hidden("throttle][$filename", 0) . t("required") : form_checkbox(NULL, "throttle][$filename", 1, $file->throttle, NULL, module_exist('throttle') ? NULL : array("disabled" => "disabled"))), "align" => "center"); + $row = array($info->name, $info->description, array('data' => (in_array($filename, $required) ? form_hidden("status][$filename", 1) . t('required') : form_checkbox('', "status][$filename", 1, $file->status)), 'align' => 'center')); + if ($type == 'module') { + $row[] = array('data' => (in_array($filename, $throttle_required) ? form_hidden("throttle][$filename", 0) . t('required') : form_checkbox(NULL, "throttle][$filename", 1, $file->throttle, NULL, module_exist('throttle') ? NULL : array('disabled' => 'disabled'))), 'align' => 'center'); } - else if ($type == "theme") { - $row[] = array("data" => form_radio("", "theme_default", $info->name, (variable_get("theme_default",0) == $info->name) ? 1 : 0), "align" => "center"); + else if ($type == 'theme') { + $row[] = array('data' => form_radio('', 'theme_default', $info->name, (variable_get('theme_default', 0) == $info->name) ? 1 : 0), 'align' => 'center'); } $rows[] = $row; } - $output = theme("table", $header, $rows); - $output .= form_hidden("type", $type); + $output = theme('table', $header, $rows); + $output .= form_hidden('type', $type); return $output; } function system_listing_save($edit = array()) { - $op = $_POST["op"]; - $edit = $_POST["edit"]; + $op = $_POST['op']; + $edit = $_POST['edit']; - if ($op == t("Save configuration")) { - db_query("UPDATE {system} SET status = '0' WHERE type = '%s'", $edit["type"]); - foreach ($edit["status"] as $filename => $status) { - db_query("UPDATE {system} SET status = %d, throttle = %d WHERE filename = '$filename'", $status, $edit["throttle"]["$filename"]); + if ($op == t('Save configuration')) { + db_query("UPDATE {system} SET status = 0 WHERE type = '%s'", $edit['type']); + foreach ($edit['status'] as $filename => $status) { + db_query("UPDATE {system} SET status = %d, throttle = %d WHERE filename = '%s'", $status, $edit['throttle'][$filename], $filename); } - if ($edit["type"] == "theme") { - variable_set("theme_default", $edit["theme_default"]); + if ($edit['type'] == 'theme') { + variable_set('theme_default', $edit['theme_default']); } cache_clear_all(); - drupal_set_message(t("the configuration options have been saved.")); + drupal_set_message(t('the configuration options have been saved.')); } } function system_settings_form($form) { - $form .= form_submit(t("Save configuration")); - $form .= form_submit(t("Reset to defaults")); + $form .= form_submit(t('Save configuration')); + $form .= form_submit(t('Reset to defaults')); return form($form); } function system_settings_save() { - $op = $_POST["op"]; - $edit = $_POST["edit"]; + $op = $_POST['op']; + $edit = $_POST['edit']; - if ($op == t("Reset to defaults")) { + if ($op == t('Reset to defaults')) { foreach ($edit as $name => $value) { variable_del($name); } - drupal_set_message(t("the configuration options have been reset to their default values.")); + drupal_set_message(t('the configuration options have been reset to their default values.')); } - if ($op == t("Save configuration")) { + if ($op == t('Save configuration')) { foreach ($edit as $name => $value) { variable_set($name, $value); } - drupal_set_message(t("the configuration options have been saved.")); + drupal_set_message(t('the configuration options have been saved.')); } else { return; @@ -355,9 +333,62 @@ function system_settings_save() { cache_clear_all(); } -function system_admin() { - $output = system_view(arg(2), arg(3)); - print theme("page", $output); +/** + * Menu callback; displays a listing of all themes. + */ +function system_themes() { + system_listing_save(); + $form = system_listing('themes'); + $form .= form_submit(t('Save configuration')); + print theme('page', form($form)); +} + +/** + * Menu callback; displays a listing of all modules. + */ +function system_modules() { + system_listing_save(); + $form = system_listing('modules'); + $form .= form_submit(t('Save configuration')); + print theme('page', form($form)); +} + +/** + * Menu callback; displays a theme's settings page. + */ +function system_configure_theme() { + system_settings_save(); + + $name = arg(2); + $themes = list_themes(); + $theme = $themes[$name]; + + if ($theme) { + include_once "$theme->filename"; + + $function = $theme->name .'_settings'; + if (function_exists($function)) { + $form .= $function(); + } + } + + print theme('page', system_settings_form($form)); +} + +/** + * Menu callback; displays a module's settings page. + */ +function system_site_settings($module = NULL) { + system_settings_save(); + + if ($module) { + $form = module_invoke($module, 'settings'); + } + else { + $form = system_view_general(); + } + + print theme('page', system_settings_form($form)); } ?> === modified file 'modules/taxonomy.module' --- modules/taxonomy.module 2004-06-17 18:10:05 +0000 +++ modules/taxonomy.module 2004-06-18 15:04:33 +0000 @@ -1,24 +1,27 @@ tids[0]); - $channel["link"] = url("taxonomy/view/$taxonomy->operator/$taxonomy->str_tids", NULL, NULL, TRUE); - $channel["title"] = variable_get("site_name", "drupal") ." - ". $term->name; - $channel["description"] = $term->description; + $channel['link'] = url("taxonomy/view/$taxonomy->operator/$taxonomy->str_tids", NULL, NULL, TRUE); + $channel['title'] = variable_get('site_name', 'drupal') .' - '. $term->name; + $channel['description'] = $term->description; node_feed($result, $channel); } } +/** + * Implementation of hook_perm(). + */ function taxonomy_perm() { - return array("administer taxonomy"); + return array('administer taxonomy'); } /** @@ -33,14 +36,7 @@ function taxonomy_perm() { * } */ function taxonomy_link($type, $node = NULL) { - if ($type == 'system') { - menu('admin/taxonomy', t('categories'), user_access('administer taxonomy') ? 'taxonomy_admin' : MENU_DENIED, 3); - menu('admin/taxonomy/add/vocabulary', t('create new vocabulary'), user_access('administer taxonomy') ? 'taxonomy_admin' : MENU_DENIED); - menu('admin/taxonomy/help', t('help'), user_access('administer taxonomy') ? 'taxonomy_admin' : MENU_DENIED, 9); - - menu('taxonomy', t('taxonomy'), user_access('access content') ? 'taxonomy_page' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED); - } - else if ($type == 'taxonomy terms' && $node != NULL) { + if ($type == 'taxonomy terms' && $node != NULL) { $links = array(); if ($node->taxonomy) { foreach ($node->taxonomy as $tid) { @@ -59,53 +55,68 @@ function taxonomy_link($type, $node = NU } } -/* -** admin pages (form, save, overview) -*/ +/** + * Implementation of hook_menu(). + */ +function taxonomy_menu() { + $items = array(); + $items[] = array('path' => 'admin/taxonomy', 'title' => t('categories'), + 'callback' => 'taxonomy_admin', + 'access' => user_access('administer taxonomy')); + $items[] = array('path' => 'admin/taxonomy/add/vocabulary', 'title' => t('add vocabulary'), + 'callback' => 'taxonomy_admin', + 'access' => user_access('administer taxonomy'), + 'type' => MENU_LOCAL_TASK); + $items[] = array('path' => 'taxonomy', 'title' => t('taxonomy'), + 'callback' => 'taxonomy_page', + 'access' => user_access('access content'), + 'type' => MENU_CALLBACK); + return $items; +} function taxonomy_form_vocabulary($edit = array()) { foreach (node_list() as $type) { - $nodetypes[$type] = node_invoke($type, "node_name"); + $nodetypes[$type] = node_invoke($type, 'node_name'); } - $form .= form_textfield(t("Vocabulary name"), "name", $edit["name"], 50, 64, t("Required") .". ". t("The name for this vocabulary. Example: 'Topic'") ."."); - $form .= form_textarea(t("Description"), "description", $edit["description"], 60, 5, t("Optional") .". ". t("Description of the vocabulary, can be used by modules.")); - $form .= form_textfield(t("Help text"), "help", $edit["help"], 50, 255, t("Optional") .". ". t("Instructions to present to the user when choosing a term.") ."."); - $form .= form_checkboxes(t("Types"), "nodes", explode(",", $edit["nodes"]), $nodetypes, t("Required") .". ". t("A list of node types you want to associate this vocabulary with.")); - $form .= form_checkbox(t("Related terms"), "relations", 1, $edit["relations"], t("Optional") .". ". t("Allows related terms in this vocabulary.", array("%help-url" => url("admin/taxonomy/help", NULL, NULL, "related-terms")))); - $form .= form_radios(t("Hierarchy"), "hierarchy", $edit["hierarchy"], array(t("Disabled"), t("Single"), t("Multiple")), t("Optional") .". ". t("Allows a tree-like hierarchy between terms of this vocabulary.", array("%help-url" => url("admin/taxonomy/help", NULL, NULL, "hierarchy"))), ""); - $form .= form_checkbox(t("Multiple select"), "multiple", 1, $edit["multiple"], t("Optional") .". ". t("Allows nodes to have more than one term in this vocabulary.")); - $form .= form_checkbox(t("Required"), "required", 1, $edit["required"], t("If enabled every node must have at least one term in this vocabulary")); - $form .= form_weight(t("Weight"), "weight", $edit["weight"], 10, t("Optional. In listings, the heavier vocabularies will sink and the lighter vocabularies will be positioned nearer the top.")); - $form .= form_submit(t("Submit")); - - if ($edit["vid"]) { - $form .= form_submit(t("Delete")); - $form .= form_hidden("vid", $edit["vid"]); + $form .= form_textfield(t('Vocabulary name'), 'name', $edit['name'], 50, 64, t('Required') .'. '. t('The name for this vocabulary. Example: "Topic"') .'.'); + $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5, t('Optional') .'. '. t('Description of the vocabulary; can be used by modules.')); + $form .= form_textfield(t('Help text'), 'help', $edit['help'], 50, 255, t('Optional') .'. '. t('Instructions to present to the user when choosing a term.') .'.'); + $form .= form_checkboxes(t('Types'), 'nodes', explode(',', $edit['nodes']), $nodetypes, t('Required') .'. '. t('A list of node types you want to associate with this vocabulary.')); + $form .= form_checkbox(t('Related terms'), 'relations', 1, $edit['relations'], t('Optional') .'. '. t('Allows related terms in this vocabulary.', array('%help-url' => url('admin/taxonomy/help', NULL, NULL, 'related-terms')))); + $form .= form_radios(t('Hierarchy'), 'hierarchy', $edit['hierarchy'], array(t('Disabled'), t('Single'), t('Multiple')), t('Optional') .'. '. t('Allows a tree-like hierarchy between terms of this vocabulary.', array('%help-url' => url('admin/taxonomy/help', NULL, NULL, 'hierarchy'))), ''); + $form .= form_checkbox(t('Multiple select'), 'multiple', 1, $edit['multiple'], t('Optional') .'. '. t('Allows nodes to have more than one term in this vocabulary.')); + $form .= form_checkbox(t('Required'), 'required', 1, $edit['required'], t('If enabled, every node must have at least one term in this vocabulary.')); + $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('Optional. In listings, the heavier vocabularies will sink and the lighter vocabularies will be positioned nearer the top.')); + $form .= form_submit(t('Submit')); + + if ($edit['vid']) { + $form .= form_submit(t('Delete')); + $form .= form_hidden('vid', $edit['vid']); } return form($form); } function taxonomy_save_vocabulary($edit) { - if (!$edit["nodes"]) { - $edit["nodes"] = array(); + if (!$edit['nodes']) { + $edit['nodes'] = array(); } - $data = array("name" => $edit["name"], "nodes" => implode(",", $edit["nodes"]), "description" => $edit["description"], "help" => $edit["help"], "multiple" => $edit["multiple"], "required" => $edit["required"], "hierarchy" => $edit["hierarchy"], "relations" => $edit["relations"], "weight" => $edit["weight"]); - if ($edit["vid"] && $edit["name"]) { - db_query("UPDATE {vocabulary} SET ". _prepare_update($data) ." WHERE vid = %d", $edit["vid"]); - module_invoke_all("taxonomy", "update", "vocabulary", $edit); - $message = t("updated vocabulary '%name'.", array("%name" => $edit["name"])); + $data = array('name' => $edit['name'], 'nodes' => implode(',', $edit['nodes']), 'description' => $edit['description'], 'help' => $edit['help'], 'multiple' => $edit['multiple'], 'required' => $edit['required'], 'hierarchy' => $edit['hierarchy'], 'relations' => $edit['relations'], 'weight' => $edit['weight']); + if ($edit['vid'] && $edit['name']) { + db_query('UPDATE {vocabulary} SET '. _prepare_update($data) .' WHERE vid = %d', $edit['vid']); + module_invoke_all('taxonomy', 'update', 'vocabulary', $edit); + $message = t('updated vocabulary "%name".', array('%name' => $edit['name'])); } - else if ($edit["vid"]) { - $message = taxonomy_del_vocabulary($edit["vid"]); + else if ($edit['vid']) { + $message = taxonomy_del_vocabulary($edit['vid']); } else { - $data["vid"] = $edit["vid"] = db_next_id("{vocabulary}_vid"); - db_query("INSERT INTO {vocabulary} ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2)); - module_invoke_all("taxonomy", "insert", "vocabulary", $edit); - $message = t("created new vocabulary '%name'.", array("%name" => $edit["name"])); + $data['vid'] = $edit['vid'] = db_next_id('{vocabulary}_vid'); + db_query('INSERT INTO {vocabulary} '. _prepare_insert($data, 1) .' VALUES '. _prepare_insert($data, 2)); + module_invoke_all('taxonomy', 'insert', 'vocabulary', $edit); + $message = t('created new vocabulary "%name".', array('%name' => $edit['name'])); } cache_clear_all(); @@ -117,121 +128,119 @@ function taxonomy_save_vocabulary($edit) function taxonomy_del_vocabulary($vid) { $vocabulary = taxonomy_get_vocabulary($vid); - db_query("DELETE FROM {vocabulary} WHERE vid = %d", $vid); - $result = db_query("SELECT tid FROM {term_data} WHERE vid = %d", $vid); + db_query('DELETE FROM {vocabulary} WHERE vid = %d', $vid); + $result = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $vid); while ($term = db_fetch_object($result)) { taxonomy_del_term($term->tid); } - module_invoke_all("taxonomy", "delete", "vocabulary", $vocabulary); + module_invoke_all('taxonomy', 'delete', 'vocabulary', $vocabulary); cache_clear_all(); - return t("deleted vocabulary '%name'.", array("%name" => $vocabulary->name)); + return t('deleted vocabulary "%name".', array('%name' => $vocabulary->name)); } function _taxonomy_confirm_del_vocabulary($vid) { $vocabulary = taxonomy_get_vocabulary($vid); - $form .= form_hidden("confirm", 1); - $form .= form_hidden("type", "vocabulary"); - $form .= form_hidden("vid", $vid); - $form .= form_submit(t("Delete")); - $form .= form_submit(t("Cancel")); + $form .= form_hidden('confirm', 1); + $form .= form_hidden('type', 'vocabulary'); + $form .= form_hidden('vid', $vid); + $form .= form_submit(t('Delete')); + $form .= form_submit(t('Cancel')); - return form(form_item(t("Delete vocabulary '%name'", array("%name" => $vocabulary->name)), $form, t("Are you sure you want to delete the vocabulary and all its terms?"))); + return form(form_item(t('Delete vocabulary "%name"', array('%name' => $vocabulary->name)), $form, t('Are you sure you want to delete the vocabulary and all its terms?'))); } function taxonomy_form_term($edit = array()) { - $vocabulary_id = isset($edit["vid"]) ? $edit["vid"] : arg(4); + $vocabulary_id = isset($edit['vid']) ? $edit['vid'] : arg(4); $vocabulary = taxonomy_get_vocabulary($vocabulary_id); - $form = form_textfield(t("Term name"), "name", $edit["name"], 50, 64, t("Required") .". ". t("The name for this term. Example: 'Linux'.")); - $form .= form_textarea(t("Description"), "description", $edit["description"], 60, 5, t("Optional") .". ". t("A description of the term.")); + $form = form_textfield(t('Term name'), 'name', $edit['name'], 50, 64, t('Required') .'. '. t('The name for this term. Example: "Linux".')); + $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5, t('Optional') .'. '. t('A description of the term.')); if ($vocabulary->hierarchy) { - $parent = array_keys(taxonomy_get_parents($edit["tid"])); - $children = taxonomy_get_tree($vocabulary_id, $edit["tid"]); + $parent = array_keys(taxonomy_get_parents($edit['tid'])); + $children = taxonomy_get_tree($vocabulary_id, $edit['tid']); - // you can't be son of yourself nor of your children + // A term can't be the child of itself, nor of its children. foreach ($children as $child) { $exclude[] = $child->tid; } - $exclude[] = $edit["tid"]; + $exclude[] = $edit['tid']; if ($vocabulary->hierarchy == 1) { - $form .= _taxonomy_term_select(t("Parent"), "parent", $parent, $vocabulary_id, t("Required") .". ". l(t("Parent term"), "admin/taxonomy/help", NULL, NULL, "parent") .".", 0, "<". t("root") .">", $exclude); + $form .= _taxonomy_term_select(t('Parent'), 'parent', $parent, $vocabulary_id, t('Required') .'. '. l(t('Parent term'), 'admin/taxonomy/help', NULL, NULL, 'parent') .'.', 0, '<'. t('root') .'>', $exclude); } elseif ($vocabulary->hierarchy == 2) { - $form .= _taxonomy_term_select(t("Parents"), "parent", $parent, $vocabulary_id, t("Required") .". ". l(t("Parent terms"), "admin/taxonomy/help", NULL, NULL, "parent") .".", 1, "<". t("root") .">", $exclude); + $form .= _taxonomy_term_select(t('Parents'), 'parent', $parent, $vocabulary_id, t('Required') .'. '. l(t('Parent terms'), 'admin/taxonomy/help', NULL, NULL, 'parent') .'.', 1, '<'. t('root') .'>', $exclude); } } if ($vocabulary->relations) { - $form .= _taxonomy_term_select(t("Related terms"), "relations", array_keys(taxonomy_get_related($edit["tid"])), $vocabulary_id, t("Optional") .". ", 1, "<". t("none") .">", array($edit["tid"])); + $form .= _taxonomy_term_select(t('Related terms'), 'relations', array_keys(taxonomy_get_related($edit['tid'])), $vocabulary_id, t('Optional') .'. ', 1, '<'. t('none') .'>', array($edit['tid'])); } - $form .= form_textarea(t("Synonyms"), "synonyms", implode("\n", taxonomy_get_synonyms($edit["tid"])), 30, 5, t("Optional") . ". ". t("Synonyms of this term, one synonym per line.", array("%help-url" => url("admin/taxonomy/help", NULL, NULL, "synonyms")))); - $form .= form_weight(t("Weight"), "weight", $edit["weight"], 10, t("Optional. In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top.")); - $form .= form_hidden("vid", $vocabulary->vid); - $form .= form_submit(t("Submit")); + $form .= form_textarea(t('Synonyms'), 'synonyms', implode("\n", taxonomy_get_synonyms($edit['tid'])), 30, 5, t('Optional') . '. '. t('Synonyms of this term, one synonym per line.', array('%help-url' => url('admin/taxonomy/help', NULL, NULL, 'synonyms')))); + $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('Optional. In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top.')); + $form .= form_hidden('vid', $vocabulary->vid); + $form .= form_submit(t('Submit')); - if ($edit["tid"]) { - $form .= form_submit(t("Delete")); - $form .= form_hidden("tid", $edit["tid"]); + if ($edit['tid']) { + $form .= form_submit(t('Delete')); + $form .= form_hidden('tid', $edit['tid']); } return form($form); } function taxonomy_save_term($edit) { - if ($edit["tid"] && $edit["name"]) { - $data = array("name" => $edit["name"], "description" => $edit["description"], "weight" => $edit["weight"]); + if ($edit['tid'] && $edit['name']) { + $data = array('name' => $edit['name'], 'description' => $edit['description'], 'weight' => $edit['weight']); - db_query("UPDATE {term_data} SET ". _prepare_update($data) ." WHERE tid = %d", $edit["tid"]); - module_invoke_all("taxonomy", "update", "term", $edit); - $message = t("the term '%a' has been updated.", array("%a" => $edit["name"])); + db_query('UPDATE {term_data} SET '. _prepare_update($data) .' WHERE tid = %d', $edit['tid']); + module_invoke_all('taxonomy', 'update', 'term', $edit); + $message = t('the term "%a" has been updated.', array('%a' => $edit['name'])); } - else if ($edit["tid"]) { - return taxonomy_del_term($edit["tid"]); + else if ($edit['tid']) { + return taxonomy_del_term($edit['tid']); } else { - $edit["tid"] = db_next_id("{term_data}_tid"); - $data = array("tid" => $edit["tid"], "name" => $edit["name"], "description" => $edit["description"], "vid" => $edit["vid"], "weight" => $edit["weight"]); - db_query("INSERT INTO {term_data} ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2)); - module_invoke_all("taxonomy", "insert", "term", $edit); - $message = t("created new term '%name'.", array("%name" => $edit["name"])); + $edit['tid'] = db_next_id('{term_data}_tid'); + $data = array('tid' => $edit['tid'], 'name' => $edit['name'], 'description' => $edit['description'], 'vid' => $edit['vid'], 'weight' => $edit['weight']); + db_query('INSERT INTO {term_data} '. _prepare_insert($data, 1) .' VALUES '. _prepare_insert($data, 2)); + module_invoke_all('taxonomy', 'insert', 'term', $edit); + $message = t('created new term "%name".', array('%name' => $edit['name'])); } - // relations (seem very powerful, but I have to understand it completely) - db_query("DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d", $edit["tid"], $edit["tid"]); - if ($edit["relations"]) { - foreach ($edit["relations"] as $related_id) { + db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $edit['tid'], $edit['tid']); + if ($edit['relations']) { + foreach ($edit['relations'] as $related_id) { if ($related_id != 0) { - db_query("INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)", $edit["tid"], $related_id); + db_query('INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)', $edit['tid'], $related_id); } } } - // hierarchy - db_query("DELETE FROM {term_hierarchy} WHERE tid = %d", $edit["tid"]); - if (!isset($edit["parent"])) { - $edit["parent"] = 0; + db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $edit['tid']); + if (!isset($edit['parent'])) { + $edit['parent'] = 0; } - if (is_array($edit["parent"])) { - foreach ($edit["parent"] as $parent) { - db_query("INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $edit["tid"], $parent); + if (is_array($edit['parent'])) { + foreach ($edit['parent'] as $parent) { + db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $parent); } } else { - db_query("INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $edit["tid"], $edit["parent"][0]); + db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $edit['parent'][0]); } - db_query("DELETE FROM {term_synonym} WHERE tid = %d", $edit["tid"]); - if ($edit["synonyms"]) { - foreach (explode ("\n", str_replace("\r", "", $edit["synonyms"])) as $synonym) { + db_query('DELETE FROM {term_synonym} WHERE tid = %d', $edit['tid']); + if ($edit['synonyms']) { + foreach (explode ("\n", str_replace("\r", '', $edit['synonyms'])) as $synonym) { if ($synonym) { - db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $edit["tid"], chop($synonym)); + db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $edit['tid'], chop($synonym)); } } } @@ -245,86 +254,90 @@ function taxonomy_save_term($edit) { function taxonomy_del_term($tid) { $term = taxonomy_get_term($tid); - db_query("DELETE FROM {term_data} WHERE tid = %d", $tid); - db_query("DELETE FROM {term_hierarchy} WHERE tid = %d", $tid); - db_query("DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d", $tid, $tid); - db_query("DELETE FROM {term_synonym} WHERE tid = %d", $tid); - db_query("DELETE FROM {term_node} WHERE tid = %d", $tid); + db_query('DELETE FROM {term_data} WHERE tid = %d', $tid); + db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $tid); + db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid); + db_query('DELETE FROM {term_synonym} WHERE tid = %d', $tid); + db_query('DELETE FROM {term_node} WHERE tid = %d', $tid); - module_invoke_all("taxonomy", "delete", "term", $term); + module_invoke_all('taxonomy', 'delete', 'term', $term); cache_clear_all(); - return t("deleted term '%name'.", array("%name" => $term->name)); + return t('deleted term "%name".', array('%name' => $term->name)); } function _taxonomy_confirm_del_term($tid) { $term = taxonomy_get_term($tid); - $form .= form_hidden("confirm", 1); - $form .= form_hidden("type", "term"); - $form .= form_hidden("tid", $tid); - $form .= form_submit(t("Delete")); - $form .= form_submit(t("Cancel")); + $form .= form_hidden('confirm', 1); + $form .= form_hidden('type', 'term'); + $form .= form_hidden('tid', $tid); + $form .= form_submit(t('Delete')); + $form .= form_submit(t('Cancel')); - return form(form_item(t("Delete term '%name'", array("%name" => $term->name)), $form, t("Are you sure you want to delete the term?"))); + return form(form_item(t('Delete term "%name"', array('%name' => $term->name)), $form, t('Are you sure you want to delete the term?'))); } +/** + * Generate a tabular listing of administrative functions for vocabularies. + */ function taxonomy_overview() { - - $output .= "

    ". t("Vocabularies overview") ."

    "; - - $header = array(t("name"), t("node types"), array("data" => t("operations"), "colspan" => 3)); + $header = array(t('name'), t('node types'), array('data' => t('operations'), 'colspan' => 3)); $vocabularies = taxonomy_get_vocabularies(); foreach ($vocabularies as $vocabulary) { $links = array(); $types = array(); - foreach(explode(",", $vocabulary->nodes) as $type) { - $types[] = node_invoke($type, "node_name"); + foreach(explode(',', $vocabulary->nodes) as $type) { + $types[] = node_invoke($type, 'node_name'); } - $rows[] = array($vocabulary->name, array("data" => implode(", ", $types), "align" => "center"), l(t("edit vocabulary"), "admin/taxonomy/edit/vocabulary/$vocabulary->vid"), l(t("add term"), "admin/taxonomy/add/term/$vocabulary->vid"), l(t("preview form"), "admin/taxonomy/preview/vocabulary/$vocabulary->vid")); + $rows[] = array($vocabulary->name, array('data' => implode(', ', $types), 'align' => 'center'), l(t('edit vocabulary'), "admin/taxonomy/edit/vocabulary/$vocabulary->vid"), l(t('add term'), "admin/taxonomy/add/term/$vocabulary->vid"), l(t('preview form'), "admin/taxonomy/preview/vocabulary/$vocabulary->vid")); $tree = taxonomy_get_tree($vocabulary->vid); if ($tree) { unset($data); foreach ($tree as $term) { - $data .= _taxonomy_depth($term->depth) ." ". $term->name ." (". l(t("edit term"), "admin/taxonomy/edit/term/$term->tid") .")
    "; + $data .= _taxonomy_depth($term->depth) .' '. $term->name .' ('. l(t('edit term'), "admin/taxonomy/edit/term/$term->tid") .')
    '; } - $rows[] = array(array("data" => $data, "colspan" => 5)); + $rows[] = array(array('data' => $data, 'colspan' => 5)); } } - return theme("table", $header, $rows); + return theme('table', $header, $rows); } -function taxonomy_form($vocabulary_id, $value = 0, $error = array(), $help = NULL) { - $vocabulary = taxonomy_get_vocabulary($vocabulary_id); +/** + * Generate a form element for selecting terms from a vocabulary. + */ +function taxonomy_form($vid, $value = 0, $error = array(), $help = NULL) { + $vocabulary = taxonomy_get_vocabulary($vid); $help = ($help) ? $help : $vocabulary->help; if ($vocabulary->required) { $blank = 0; } else { - $blank = "<". t("none") .">"; + $blank = '<'. t('none') .'>'; } $help .= $error['taxonomy']; - return _taxonomy_term_select($vocabulary->name, 'taxonomy', $value, $vocabulary_id, $help, intval($vocabulary->multiple), $blank); + return _taxonomy_term_select($vocabulary->name, 'taxonomy', $value, $vid, $help, intval($vocabulary->multiple), $blank); } -/* -** API functions -*/ - -// return array of vocabularies, as objects -function taxonomy_get_vocabularies($type = '', $key = "vid") { +/** + * Return an array of all vocabulary objects. + * + * @param $type + * If set, return only those vocabularies associated with this node type. + */ +function taxonomy_get_vocabularies($type = '', $key = 'vid') { if ($type) { $result = db_query("SELECT * FROM {vocabulary} WHERE nodes LIKE '%%%s%%' ORDER BY weight, name", $type); } else { - $result = db_query("SELECT * FROM {vocabulary} ORDER BY weight, name"); + $result = db_query('SELECT * FROM {vocabulary} ORDER BY weight, name'); } $vocabularies = array(); while ($voc = db_fetch_object($result)) { @@ -334,7 +347,9 @@ function taxonomy_get_vocabularies($type return $vocabularies; } -// return form with current term +/** + * Generate a form for selecting terms to associate with a node. + */ function taxonomy_node_form($type, $node = '', $error = array()) { if (!$node->taxonomy) { if ($node->nid) { @@ -355,16 +370,20 @@ function taxonomy_node_form($type, $node return $result ? $result : array(); } -// return 1 if node identified by $nid contains a taxonomy term identified by $tid in his body or title +/** + * Determine whether a node mentions the name of a term. + */ function taxonomy_node_has_term($nid, $tid) { - $term_name = db_result(db_query("SELECT name FROM {term_data} WHERE tid = %d", $tid)); + $term_name = db_result(db_query('SELECT name FROM {term_data} WHERE tid = %d', $tid)); return db_result(db_query("SELECT COUNT(n.nid) FROM {node} n WHERE n.nid = %d AND ((n.body LIKE '%%%s%%') OR (n.body LIKE '%%%s%%'))", $nid, $term_name, $term_name)); } -// return array of terms of a node beloging to a particular vocabulary identified by $vid -function taxonomy_node_get_terms_by_vocabulary($nid, $vid, $key = "tid") { - $result = db_query("SELECT t.* FROM {term_data} t, {term_node} r WHERE t.tid = r.tid AND t.vid = %d AND r.nid = %d ORDER BY weight", $vid, $nid); +/** + * Find all terms associated to the given node, within one vocabulary. + */ +function taxonomy_node_get_terms_by_vocabulary($nid, $vid, $key = 'tid') { + $result = db_query('SELECT t.* FROM {term_data} t, {term_node} r WHERE t.tid = r.tid AND t.vid = %d AND r.nid = %d ORDER BY weight', $vid, $nid); $terms = array(); while ($term = db_fetch_object($result)) { $terms[$term->$key] = $term; @@ -372,12 +391,14 @@ function taxonomy_node_get_terms_by_voca return $terms; } -// return array of terms of a node -function taxonomy_node_get_terms($nid, $key = "tid") { +/** + * Find all terms associated to the given node. + */ +function taxonomy_node_get_terms($nid, $key = 'tid') { static $terms; if (!isset($terms[$nid])) { - $result = db_query("SELECT t.* FROM {term_data} t, {term_node} r WHERE r.tid = t.tid AND r.nid = %d ORDER BY weight, name", $nid); + $result = db_query('SELECT t.* FROM {term_data} t, {term_node} r WHERE r.tid = t.tid AND r.nid = %d ORDER BY weight, name', $nid); $terms[$nid] = array(); while ($term = db_fetch_object($result)) { $terms[$nid][$term->$key] = $term; @@ -386,28 +407,34 @@ function taxonomy_node_get_terms($nid, $ return $terms[$nid]; } -// save terms of a node +/** + * Save term associations for a given node. + */ function taxonomy_node_save($nid, $terms) { taxonomy_node_delete($nid); if ($terms) { foreach ($terms as $term) { if ($term) { - db_query("INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)", $nid, $term); + db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $term); } } } } -// clean up terms +/** + * Remove associations of a node to its terms. + */ function taxonomy_node_delete($nid) { - db_query("DELETE FROM {term_node} WHERE nid = %d", $nid); + db_query('DELETE FROM {term_node} WHERE nid = %d', $nid); } -// relations: return array of related terms -function taxonomy_get_related($tid, $key = "tid") { +/** + * Find all term objects related to a given term ID. + */ +function taxonomy_get_related($tid, $key = 'tid') { if ($tid) { - $result = db_query("SELECT t.*, tid1, tid2 FROM {term_relation} , {term_data} t WHERE (t.tid = tid1 OR t.tid = tid2) AND (tid1 = %d OR tid2 = %d) AND t.tid != %d ORDER BY weight, name", $tid, $tid, $tid); + $result = db_query('SELECT t.*, tid1, tid2 FROM {term_relation}, {term_data} t WHERE (t.tid = tid1 OR t.tid = tid2) AND (tid1 = %d OR tid2 = %d) AND t.tid != %d ORDER BY weight, name', $tid, $tid, $tid); $related = array(); while ($term = db_fetch_object($result)) { $related[$term->$key] = $term; @@ -419,10 +446,12 @@ function taxonomy_get_related($tid, $key } } -// hierarchy: get parent terms -function taxonomy_get_parents($tid, $key = "tid") { +/** + * Find all parents of a given term ID. + */ +function taxonomy_get_parents($tid, $key = 'tid') { if ($tid) { - $result = db_query("SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE h.parent = t.tid AND h.tid = %d ORDER BY weight, name", $tid); + $result = db_query('SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE h.parent = t.tid AND h.tid = %d ORDER BY weight, name', $tid); $parents = array(); while ($parent = db_fetch_object($result)) { $parents[$parent->$key] = $parent; @@ -434,8 +463,10 @@ function taxonomy_get_parents($tid, $key } } -// Gets all parents, parents of parents, etc. -function taxonomy_get_parents_all($tid, $key = "tid") { +/** + * Find all ancestors of a given term ID. + */ +function taxonomy_get_parents_all($tid) { $parents = array(); if ($tid) { $parents[] = taxonomy_get_term($tid); @@ -448,13 +479,15 @@ function taxonomy_get_parents_all($tid, return $parents; } -// hierarchy: get children -function taxonomy_get_children($tid, $vid = 0, $key = "tid") { +/** + * Find all children of a term ID. + */ +function taxonomy_get_children($tid, $vid = 0, $key = 'tid') { if ($vid) { - $result = db_query("SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE t.vid = %d AND h.tid = t.tid AND h.parent = %d ORDER BY weight, name", $vid, $tid); + $result = db_query('SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE t.vid = %d AND h.tid = t.tid AND h.parent = %d ORDER BY weight, name', $vid, $tid); } else { - $result = db_query("SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE h.tid = t.tid AND parent = %d ORDER BY weight", $tid); + $result = db_query('SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE h.tid = t.tid AND parent = %d ORDER BY weight', $tid); } $children = array(); while ($term = db_fetch_object($result)) { @@ -463,34 +496,52 @@ function taxonomy_get_children($tid, $vi return $children; } -// hierarchy: get whole family, with tid, parent and depth; useful to show -function taxonomy_get_tree($vocabulary_id, $parent = 0, $depth = -1, $max_depth = NULL) { +/** + * Create a hierarchical representation of a vocabulary. + * + * @param $vid + * Which vocabulary to generate the tree for. + * + * @param $parent + * The term ID under which to generate the tree. If 0, generate the tree + * for the entire vocabulary. + * + * @param $depth + * Internal use only. + * + * @return + * An array of all term objects in the tree. Each term object is extended + * to have "depth" and "parents" attributes in addition to its normal ones. + */ +function taxonomy_get_tree($vid, $parent = 0, $depth = -1, $max_depth = NULL) { static $children, $parents, $terms; $depth++; - // we cache trees, so it's not cpu-intensive to call get_tree on a term and its children too - if (!isset($children[$vocabulary_id])) { - $children[$vocabulary_id] = array(); + // We cache trees, so it's not CPU-intensive to call get_tree() on a term + // and its children, too. + if (!isset($children[$vid])) { + $children[$vid] = array(); - $result = db_query("SELECT t.*, parent FROM {term_data} t, {term_hierarchy} h WHERE t.tid = h.tid AND t.vid = %d ORDER BY weight, name", $vocabulary_id); + $result = db_query('SELECT t.*, parent FROM {term_data} t, {term_hierarchy} h WHERE t.tid = h.tid AND t.vid = %d ORDER BY weight, name', $vid); while ($term = db_fetch_object($result)) { - $children[$vocabulary_id][$term->parent][] = $term->tid; - $parents[$vocabulary_id][$term->tid][] = $term->parent; - $terms[$vocabulary_id][$term->tid] = $term; + $children[$vid][$term->parent][] = $term->tid; + $parents[$vid][$term->tid][] = $term->parent; + $terms[$vid][$term->tid] = $term; } } - $max_depth = ($max_depth == '') ? count($children[$vocabulary_id]) : $max_depth; - if ($children[$vocabulary_id][$parent]) { - foreach ($children[$vocabulary_id][$parent] as $child) { + $max_depth = ($max_depth == '') ? count($children[$vid]) : $max_depth; + if ($children[$vid][$parent]) { + foreach ($children[$vid][$parent] as $child) { if ($max_depth > $depth) { - $terms[$vocabulary_id][$child]->depth = $depth; - unset($terms[$vocabulary_id][$child]->parent); // this is not useful as it would show one parent only - $terms[$vocabulary_id][$child]->parents = $parents[$vocabulary_id][$child]; - $tree[] = $terms[$vocabulary_id][$child]; + $terms[$vid][$child]->depth = $depth; + // The "parent" attribute is not useful, as it would show one parent only. + unset($terms[$vid][$child]->parent); + $terms[$vid][$child]->parents = $parents[$vid][$child]; + $tree[] = $terms[$vid][$child]; - $tree = array_merge($tree, taxonomy_get_tree($vocabulary_id, $child, $depth, $max_depth)); + $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $depth, $max_depth)); } } } @@ -498,12 +549,14 @@ function taxonomy_get_tree($vocabulary_i return $tree ? $tree : array(); } -// synonyms: return array of synonyms +/** + * Return an array of synonyms of the given term ID. + */ function taxonomy_get_synonyms($tid) { if ($tid) { - $result = db_query("SELECT name FROM {term_synonym} WHERE tid = %d", $tid); + $result = db_query('SELECT name FROM {term_synonym} WHERE tid = %d', $tid); while ($synonym = db_fetch_array($result)) { - $synonyms[] = $synonym["name"]; + $synonyms[] = $synonym['name']; } return $synonyms ? $synonyms : array(); } @@ -512,19 +565,23 @@ function taxonomy_get_synonyms($tid) { } } -// synonyms: return original term -function taxonomy_get_synonym_root($term) { - return db_fetch_object(db_query("SELECT * FROM {term_synonym} s, {term_data} t WHERE t.tid = s.tid AND s.name = '%s'", $term)); +/** + * Return the term object that has the given string as a synonym. + */ +function taxonomy_get_synonym_root($synonym) { + return db_fetch_object(db_query("SELECT * FROM {term_synonym} s, {term_data} t WHERE t.tid = s.tid AND s.name = '%s'", $synonym)); } -// given a term id, count number of published nodes in it +/** + * Given a term id, count the number of published nodes in it. + */ function taxonomy_term_count_nodes($tid, $type = 0) { static $count; if (!isset($count[$type])) { // $type == 0 always evaluates true is $type is a string if (is_numeric($type)) { - $result = db_query("SELECT t.tid, COUNT(*) AS c FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 GROUP BY t.tid"); + $result = db_query('SELECT t.tid, COUNT(*) AS c FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 GROUP BY t.tid'); } else { $result = db_query("SELECT t.tid, COUNT(*) AS c FROM {term_node} t, {node} n WHERE t.nid = n.nid AND n.status = 1 AND n.type = '%s' GROUP BY t.tid", $type); @@ -540,12 +597,14 @@ function taxonomy_term_count_nodes($tid, return $count[$type][$tid] + $children_count; } -// helper for above function +/** + * Helper for taxonomy_term_count_nodes(). + */ function _taxonomy_term_children($tid) { static $children; if (!isset($children)) { - $result = db_query("SELECT tid, parent FROM {term_hierarchy} "); + $result = db_query('SELECT tid, parent FROM {term_hierarchy}'); while ($term = db_fetch_object($result)) { $children[$term->parent][] = $term->tid; } @@ -554,14 +613,18 @@ function _taxonomy_term_children($tid) { } /** - * Try to map a string to existing vocabularies. Provide case insensitive and - * trimmed map so as to maximize likelihood of successful mapping. + * Try to map a string to an existing vocabulary. + * + * Provides a case-insensitive and trimmed mapping, to maximize the + * likelihood of a successful match. + * + * @param name + * Name of the vocabulary to search for. * - * @param $name Name of the vocabulary to search - * @return array of matching vocabularies, as objects + * @return + * An array of matching vocabulary objects. */ function taxonomy_get_vocabulary_by_name($name) { - // LOWER is ANSI SQL-92 $db_result = db_query("SELECT * FROM {vocabulary} WHERE LOWER('%s') LIKE LOWER(name)", trim($name)); $result = array(); while ($vocabulary = db_fetch_object($db_result)) { @@ -572,14 +635,18 @@ function taxonomy_get_vocabulary_by_name } /** - * Try to map a string to existing terms Provide case insensitive and trimmed - * map so as to maximize likelihood of successful mapping. + * Try to map a string to an existing term, as for glossary use. * - * @param name Name of the term to search - * @return rray of matching terms, as objects + * Provides a case-insensitive and trimmed mapping, to maximize the + * likelihood of a successful match. + * + * @param name + * Name of the term to search for. + * + * @return + * An array of matching term objects. */ function taxonomy_get_term_by_name($name) { - // LOWER is ANSI SQL-92 $db_result = db_query("SELECT * FROM {term_data} WHERE LOWER('%s') LIKE LOWER(name)", trim($name)); $result = array(); while ($term = db_fetch_object($db_result)) { @@ -589,20 +656,21 @@ function taxonomy_get_term_by_name($name return $result; } +/** + * Return the vocabulary object matching a vocabulary ID. + */ function taxonomy_get_vocabulary($vid) { - // simple cache using a static var? - return db_fetch_object(db_query("SELECT * FROM {vocabulary} WHERE vid = %d", $vid)); + return db_fetch_object(db_query('SELECT * FROM {vocabulary} WHERE vid = %d', $vid)); } +/** + * Return the term object matching a term ID. + */ function taxonomy_get_term($tid) { // simple cache using a static var? - return db_fetch_object(db_query("SELECT * FROM {term_data} WHERE tid = %d", $tid)); + return db_fetch_object(db_query('SELECT * FROM {term_data} WHERE tid = %d', $tid)); } -/* -** service functions -*/ - function _taxonomy_term_select($title, $name, $value, $vocabulary_id, $description, $multiple, $blank, $exclude = array()) { $tree = taxonomy_get_tree($vocabulary_id); @@ -615,13 +683,13 @@ function _taxonomy_term_select($title, $ } if ($blank) { - $options[] = array("tid" => 0, "name" => $blank); + $options[] = array('tid' => 0, 'name' => $blank); } if ($tree) { foreach ($tree as $term) { if (!in_array($term->tid, $exclude)) { - $options[] = array("tid" => $term->tid, "name" => _taxonomy_depth($term->depth, '-').$term->name); + $options[] = array('tid' => $term->tid, 'name' => _taxonomy_depth($term->depth, '-').$term->name); } } if (!$blank && !$value) { @@ -632,12 +700,12 @@ function _taxonomy_term_select($title, $ if (count($options) > 0) { foreach ($options as $option) { - $select .= ""; + $select .= ''; } $size = min(12, count($options)); - return form_item($title, "", $description); + return form_item($title, "", $description); } } @@ -652,46 +720,57 @@ function _prepare_update($data) { foreach ($data as $key => $value) { $q[] = "$key = '". check_query($value) ."'"; } - $result = implode(", ", $q); + $result = implode(', ', $q); return $result; } function _prepare_insert($data, $stage) { if ($stage == 1) { - $result = implode(", ", array_keys($data)); + $result = implode(', ', array_keys($data)); } else { foreach (array_values($data) as $value) { $q[] = "'". check_query($value) ."'"; } - $result = implode(", ", $q); + $result = implode(', ', $q); } return "($result)"; } -/* -** Accepts taxonomy conditions and returns a resource identifier. If -** you intend to use the nodes without a pager (eg. in a XML feed), -** then set $pager to false. -*/ -function taxonomy_select_nodes($taxonomy, $pager = 1) { - global $user; - +/** + * Finds all nodes that match selected taxonomy conditions. + * + * @param $taxonomy + * An object containing the conditions to match. The attributes of this + * object are: + * - "tids": An array of term IDs to match. + * - "str_tids": A comma-separated list of the same IDs. + * - "operator": How to interpret multiple IDs in the array. Can be + * "or" or "and". + * + * @param $pager + * Whether the nodes are to be used with a pager (the case on most Drupal + * pages) or not (in an XML feed, for example). + * + * @return + * A resource identifier pointing to the query results. + */ +function taxonomy_select_nodes($taxonomy, $pager = TRUE) { if ($taxonomy->str_tids) { - if ($taxonomy->operator == "or") { - $sql = "SELECT DISTINCT(n.nid), n.title, n.type, n.created, n.changed, n.uid, n.static, n.created, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = '1' ORDER BY static DESC, created DESC"; - $sql_count = "SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = '1'"; + if ($taxonomy->operator == 'or') { + $sql = "SELECT DISTINCT(n.nid), n.title, n.type, n.created, n.changed, n.uid, n.static, n.created, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1 ORDER BY static DESC, created DESC"; + $sql_count = "SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1"; } else { - $sql = "SELECT n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = '1' GROUP BY n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name HAVING COUNT(n.nid) = ". count($taxonomy->tids) ." ORDER BY static DESC, created DESC"; + $sql = "SELECT n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1 GROUP BY n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name HAVING COUNT(n.nid) = ". count($taxonomy->tids) ." ORDER BY static DESC, created DESC"; // Special trick as we could not find anything better: - $count = db_num_rows(db_query("SELECT n.nid FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = '1' GROUP BY n.nid HAVING COUNT(n.nid) = ". count($taxonomy->tids))); + $count = db_num_rows(db_query("SELECT n.nid FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1 GROUP BY n.nid HAVING COUNT(n.nid) = ". count($taxonomy->tids))); $sql_count = "SELECT $count"; } if ($pager) { - $result = pager_query($sql, variable_get("default_nodes_main", 10) , 0, $sql_count); + $result = pager_query($sql, variable_get('default_nodes_main', 10) , 0, $sql_count); } else { $result = db_query_range($sql, 0, 15); @@ -701,29 +780,31 @@ function taxonomy_select_nodes($taxonomy return $result; } -/* -** Accepts the result of a db_query() and formats each node along -** with a pager. +/** + * Accepts the result of a pager_query() call, such as that performed by + * taxonomy_select_nodes(), and formats each node along with a pager. */ function taxonomy_render_nodes($result) { while ($node = db_fetch_object($result)) { - $output .= node_view(node_load(array("nid" => $node->nid, "type" => $node->type)), 1); + $output .= node_view(node_load(array('nid' => $node->nid, 'type' => $node->type)), 1); } - $output .= theme("pager", NULL, variable_get("default_nodes_main", 10), 0); + $output .= theme('pager', NULL, variable_get('default_nodes_main', 10), 0); return $output; } +/** + * Implementation of hook_nodeapi(). + */ function taxonomy_nodeapi($node, $op, $arg = 0) { - switch ($op) { - case "insert": + case 'insert': taxonomy_node_save($node->nid, $node->taxonomy); break; - case "update": + case 'update': taxonomy_node_save($node->nid, $node->taxonomy); break; - case "delete": + case 'delete': taxonomy_node_delete($node->nid); break; } @@ -733,11 +814,11 @@ function taxonomy_page() { $taxonomy->operator = arg(2); $taxonomy->str_tids = check_query(arg(3)); - $taxonomy->tids = explode(",", $taxonomy->str_tids); + $taxonomy->tids = explode(',', $taxonomy->str_tids); - if (ereg("^([0-9]+,){0,}[0-9]+$", $taxonomy->str_tids)) { + if (ereg('^([0-9]+,){0,}[0-9]+$', $taxonomy->str_tids)) { switch (arg(1)) { - case "feed": + case 'feed': taxonomy_feed($taxonomy); break; default: @@ -751,17 +832,18 @@ function taxonomy_page() { // Build breadcrumb based on first hierarchy of first term: $current->tid = $taxonomy->tids[0]; + $breadcrumbs = array(array('path' => $_GET['q'])); while ($parents = taxonomy_get_parents($current->tid)) { $current = array_shift($parents); - $breadcrumbs[] = l($current->name, "taxonomy/view/or/$current->tid"); + $breadcrumbs[] = array('path' => 'taxonomy/view/or/'. $current->tid, 'title' => $current->name); } - $breadcrumbs[] = l(t('Home'), ''); $breadcrumbs = array_reverse($breadcrumbs); + menu_set_location($breadcrumbs); drupal_set_html_head('str_tids") .'" />'); $output = taxonomy_render_nodes(taxonomy_select_nodes($taxonomy)); - print theme("page", $output, implode(', ', $names), $breadcrumbs); + print theme('page', $output, implode(', ', $names)); break; } } @@ -770,62 +852,61 @@ function taxonomy_page() { } } -/* -** admin -*/ - +/** + * Menu callback; dispatches to the proper taxonomy administration function. + */ function taxonomy_admin() { - $op = $_POST["op"]; - $edit = $_POST["edit"]; + $op = $_POST['op']; + $edit = $_POST['edit']; if (empty($op)) { $op = arg(2); } switch ($op) { - case "add": - if (arg(3) == "vocabulary") { + case 'add': + if (arg(3) == 'vocabulary') { $output .= taxonomy_form_vocabulary(); } - else if (arg(3) == "term") { + else if (arg(3) == 'term') { $output .= taxonomy_form_term(); } break; - case "edit": - if (arg(3) == "vocabulary") { + case 'edit': + if (arg(3) == 'vocabulary') { $output .= taxonomy_form_vocabulary(object2array(taxonomy_get_vocabulary(arg(4)))); } - else if (arg(3) == "term") { + else if (arg(3) == 'term') { $output .= taxonomy_form_term(object2array(taxonomy_get_term(arg(4)))); } break; - case "preview": + case 'preview': $output .= taxonomy_form(arg(4)); break; - case "help": + case 'help': $output .= taxonomy_help(); break; - case t("Delete"): - if (!$edit["confirm"]) { - if (arg(3) == "vocabulary") { - $output .= _taxonomy_confirm_del_vocabulary($edit["vid"]); + case t('Delete'): + if (!$edit['confirm']) { + if (arg(3) == 'vocabulary') { + $output .= _taxonomy_confirm_del_vocabulary($edit['vid']); } else { - $output .= _taxonomy_confirm_del_term($edit["tid"]); + $output .= _taxonomy_confirm_del_term($edit['tid']); } break; } else { - $edit["name"] = 0; + $edit['name'] = 0; // fall through: } - case t("Submit"): - if (arg(3) == "vocabulary") { + case t('Submit'): + if (arg(3) == 'vocabulary') { taxonomy_save_vocabulary($edit); } else { taxonomy_save_term($edit); - if (!$edit["tid"]) { + if (!$edit['tid']) { // if INSERT show form again $output .= taxonomy_form_term(); break; @@ -837,24 +918,22 @@ function taxonomy_admin() { $output .= taxonomy_overview(); } - print theme("page", $output); + print theme('page', $output); } -function taxonomy_help($section = "admin/help#taxonomy") { - $output = ""; - +/** + * Implementation of hook_help(). + */ +function taxonomy_help($section = 'admin/help#taxonomy') { switch ($section) { - case 'admin/system/modules#description': - $output = t("Enables the organization of content into categories."); - break; + case 'admin/modules#description': + return t('Enables the organization of content into categories.'); case 'admin/taxonomy': - $output = t("The taxonomy module allows you to classify content into categories and subcategories; it allows multiple lists of categories for classification (controlled vocabularies) and offers the possibility of creating thesauri (controlled vocabularies that indicate the relationship of terms) and taxonomies (controlled vocabularies where relationships are indicated hierarchically). To delete a term choose \"edit term\". To delete a vocabulary, and all its terms, choose \"edit vocabulary\"."); - break; + return t('The taxonomy module allows you to classify content into categories and subcategories; it allows multiple lists of categories for classification (controlled vocabularies) and offers the possibility of creating thesauri (controlled vocabularies that indicate the relationship of terms) and taxonomies (controlled vocabularies where relationships are indicated hierarchically). To delete a term choose "edit term". To delete a vocabulary, and all its terms, choose "edit vocabulary".'); case 'admin/taxonomy/add/vocabulary': - $output = t("When you create a controlled vocabulary you are creating a set of terms to use for describing content (known as descriptors in indexing lingo). Drupal allows you to describe each node type (blog, story, etc.) using one or many of these terms. For simple implementations, you might create a set of categories without subcategories, similar to Slashdot.org's or Kuro5hin.org's sections. For more complex implementations, you might create a hierarchical list of categories."); - break; + return t("When you create a controlled vocabulary you are creating a set of terms to use for describing content (known as descriptors in indexing lingo). Drupal allows you to describe each node type (blog, story, etc.) using one or many of these terms. For simple implementations, you might create a set of categories without subcategories, similar to Slashdot.org's or Kuro5hin.org's sections. For more complex implementations, you might create a hierarchical list of categories."); case 'admin/help#taxonomy': - $output .= t(" + return t("

    Background

    Taxonomy is the study of classification. Drupal's taxonomy module allows you to define categories which are used to classify content. The module supports hierarchical classification and association between terms, allowing for truly flexible information retrieval and classification. For more details about classification types and insight into the development of the taxonomy.module, see this drupal.org discussion.

    An example taxonomy: food

    @@ -886,10 +965,7 @@ function taxonomy_help($section = "admin

    Displaying nodes organized by term(s)

    In order to view the nodes associated with a term or a collection of terms, you should browse to a properly formed Taxonomy URL. For example, taxonomy/page/or/1,2. Taxonomy URLs always contain one or more term IDs (tid) at the end of the URL (a.k.a the querystring). You may learn the term ID for a given term by hovering over that term in the taxonomy overview page and noting the number at the end or the URL. To build a Taxonomy URL start with \"taxonomy/page\". Now add the querystring parameter, either or, which chooses nodes tagged with any of the given term IDs, or and, which chooses nodes tagged with all of the given Term IDs. Thus or is less specific than and. Finally add a comma seperated list of term IDs.

    RSS feeds

    -

    Every term, or collection of terms, provides an RSS feed to which interested users may subscribe. The URL format for a sample RSS feed is node/feed/or/1,2. Built like a Taxonomy URL, see above it starts with \"node/feed\", then has the querystring parameter, and finally the Term IDs.

    ", array("%classification-types" => "http://www.eleganthack.com/archives/002165.html#002165", "%drupal-dis" => "http://www.drupal.org/node/view/55", "%slashdot" => "http://www.slashdot.com/", "%taxo-example" => url("taxonomy/page/or/1,2"), "%taxo-overview" => url("admin/taxonomy"), "%userland-rss" => "http://backend.userland.com/stories/rss", "%sample-rss" => url("node/feed/or/1,2"), "%taxo-help" => url("admin/taxonomy/help", NULL, "taxonomy-url"))); - break; +

    Every term, or collection of terms, provides an RSS feed to which interested users may subscribe. The URL format for a sample RSS feed is node/feed/or/1,2. Built like a Taxonomy URL, see above it starts with \"node/feed\", then has the querystring parameter, and finally the Term IDs.

    ", array('%classification-types' => 'http://www.eleganthack.com/archives/002165.html#002165', '%drupal-dis' => 'http://www.drupal.org/node/55', '%slashdot' => 'http://www.slashdot.com/', '%taxo-example' => url('taxonomy/page/or/1,2'), '%taxo-overview' => url('admin/taxonomy'), '%userland-rss' => 'http://backend.userland.com/stories/rss', '%sample-rss' => url('node/feed/or/1,2'), '%taxo-help' => url('admin/taxonomy/help', NULL, 'taxonomy-url'))); } - - return $output; } ?> === modified file 'modules/taxonomy/taxonomy.module' --- modules/taxonomy/taxonomy.module 2004-06-17 18:10:05 +0000 +++ modules/taxonomy/taxonomy.module 2004-06-18 15:04:33 +0000 @@ -1,24 +1,27 @@ tids[0]); - $channel["link"] = url("taxonomy/view/$taxonomy->operator/$taxonomy->str_tids", NULL, NULL, TRUE); - $channel["title"] = variable_get("site_name", "drupal") ." - ". $term->name; - $channel["description"] = $term->description; + $channel['link'] = url("taxonomy/view/$taxonomy->operator/$taxonomy->str_tids", NULL, NULL, TRUE); + $channel['title'] = variable_get('site_name', 'drupal') .' - '. $term->name; + $channel['description'] = $term->description; node_feed($result, $channel); } } +/** + * Implementation of hook_perm(). + */ function taxonomy_perm() { - return array("administer taxonomy"); + return array('administer taxonomy'); } /** @@ -33,14 +36,7 @@ function taxonomy_perm() { * } */ function taxonomy_link($type, $node = NULL) { - if ($type == 'system') { - menu('admin/taxonomy', t('categories'), user_access('administer taxonomy') ? 'taxonomy_admin' : MENU_DENIED, 3); - menu('admin/taxonomy/add/vocabulary', t('create new vocabulary'), user_access('administer taxonomy') ? 'taxonomy_admin' : MENU_DENIED); - menu('admin/taxonomy/help', t('help'), user_access('administer taxonomy') ? 'taxonomy_admin' : MENU_DENIED, 9); - - menu('taxonomy', t('taxonomy'), user_access('access content') ? 'taxonomy_page' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED); - } - else if ($type == 'taxonomy terms' && $node != NULL) { + if ($type == 'taxonomy terms' && $node != NULL) { $links = array(); if ($node->taxonomy) { foreach ($node->taxonomy as $tid) { @@ -59,53 +55,68 @@ function taxonomy_link($type, $node = NU } } -/* -** admin pages (form, save, overview) -*/ +/** + * Implementation of hook_menu(). + */ +function taxonomy_menu() { + $items = array(); + $items[] = array('path' => 'admin/taxonomy', 'title' => t('categories'), + 'callback' => 'taxonomy_admin', + 'access' => user_access('administer taxonomy')); + $items[] = array('path' => 'admin/taxonomy/add/vocabulary', 'title' => t('add vocabulary'), + 'callback' => 'taxonomy_admin', + 'access' => user_access('administer taxonomy'), + 'type' => MENU_LOCAL_TASK); + $items[] = array('path' => 'taxonomy', 'title' => t('taxonomy'), + 'callback' => 'taxonomy_page', + 'access' => user_access('access content'), + 'type' => MENU_CALLBACK); + return $items; +} function taxonomy_form_vocabulary($edit = array()) { foreach (node_list() as $type) { - $nodetypes[$type] = node_invoke($type, "node_name"); + $nodetypes[$type] = node_invoke($type, 'node_name'); } - $form .= form_textfield(t("Vocabulary name"), "name", $edit["name"], 50, 64, t("Required") .". ". t("The name for this vocabulary. Example: 'Topic'") ."."); - $form .= form_textarea(t("Description"), "description", $edit["description"], 60, 5, t("Optional") .". ". t("Description of the vocabulary, can be used by modules.")); - $form .= form_textfield(t("Help text"), "help", $edit["help"], 50, 255, t("Optional") .". ". t("Instructions to present to the user when choosing a term.") ."."); - $form .= form_checkboxes(t("Types"), "nodes", explode(",", $edit["nodes"]), $nodetypes, t("Required") .". ". t("A list of node types you want to associate this vocabulary with.")); - $form .= form_checkbox(t("Related terms"), "relations", 1, $edit["relations"], t("Optional") .". ". t("Allows related terms in this vocabulary.", array("%help-url" => url("admin/taxonomy/help", NULL, NULL, "related-terms")))); - $form .= form_radios(t("Hierarchy"), "hierarchy", $edit["hierarchy"], array(t("Disabled"), t("Single"), t("Multiple")), t("Optional") .". ". t("Allows a tree-like hierarchy between terms of this vocabulary.", array("%help-url" => url("admin/taxonomy/help", NULL, NULL, "hierarchy"))), ""); - $form .= form_checkbox(t("Multiple select"), "multiple", 1, $edit["multiple"], t("Optional") .". ". t("Allows nodes to have more than one term in this vocabulary.")); - $form .= form_checkbox(t("Required"), "required", 1, $edit["required"], t("If enabled every node must have at least one term in this vocabulary")); - $form .= form_weight(t("Weight"), "weight", $edit["weight"], 10, t("Optional. In listings, the heavier vocabularies will sink and the lighter vocabularies will be positioned nearer the top.")); - $form .= form_submit(t("Submit")); - - if ($edit["vid"]) { - $form .= form_submit(t("Delete")); - $form .= form_hidden("vid", $edit["vid"]); + $form .= form_textfield(t('Vocabulary name'), 'name', $edit['name'], 50, 64, t('Required') .'. '. t('The name for this vocabulary. Example: "Topic"') .'.'); + $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5, t('Optional') .'. '. t('Description of the vocabulary; can be used by modules.')); + $form .= form_textfield(t('Help text'), 'help', $edit['help'], 50, 255, t('Optional') .'. '. t('Instructions to present to the user when choosing a term.') .'.'); + $form .= form_checkboxes(t('Types'), 'nodes', explode(',', $edit['nodes']), $nodetypes, t('Required') .'. '. t('A list of node types you want to associate with this vocabulary.')); + $form .= form_checkbox(t('Related terms'), 'relations', 1, $edit['relations'], t('Optional') .'. '. t('Allows related terms in this vocabulary.', array('%help-url' => url('admin/taxonomy/help', NULL, NULL, 'related-terms')))); + $form .= form_radios(t('Hierarchy'), 'hierarchy', $edit['hierarchy'], array(t('Disabled'), t('Single'), t('Multiple')), t('Optional') .'. '. t('Allows a tree-like hierarchy between terms of this vocabulary.', array('%help-url' => url('admin/taxonomy/help', NULL, NULL, 'hierarchy'))), ''); + $form .= form_checkbox(t('Multiple select'), 'multiple', 1, $edit['multiple'], t('Optional') .'. '. t('Allows nodes to have more than one term in this vocabulary.')); + $form .= form_checkbox(t('Required'), 'required', 1, $edit['required'], t('If enabled, every node must have at least one term in this vocabulary.')); + $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('Optional. In listings, the heavier vocabularies will sink and the lighter vocabularies will be positioned nearer the top.')); + $form .= form_submit(t('Submit')); + + if ($edit['vid']) { + $form .= form_submit(t('Delete')); + $form .= form_hidden('vid', $edit['vid']); } return form($form); } function taxonomy_save_vocabulary($edit) { - if (!$edit["nodes"]) { - $edit["nodes"] = array(); + if (!$edit['nodes']) { + $edit['nodes'] = array(); } - $data = array("name" => $edit["name"], "nodes" => implode(",", $edit["nodes"]), "description" => $edit["description"], "help" => $edit["help"], "multiple" => $edit["multiple"], "required" => $edit["required"], "hierarchy" => $edit["hierarchy"], "relations" => $edit["relations"], "weight" => $edit["weight"]); - if ($edit["vid"] && $edit["name"]) { - db_query("UPDATE {vocabulary} SET ". _prepare_update($data) ." WHERE vid = %d", $edit["vid"]); - module_invoke_all("taxonomy", "update", "vocabulary", $edit); - $message = t("updated vocabulary '%name'.", array("%name" => $edit["name"])); + $data = array('name' => $edit['name'], 'nodes' => implode(',', $edit['nodes']), 'description' => $edit['description'], 'help' => $edit['help'], 'multiple' => $edit['multiple'], 'required' => $edit['required'], 'hierarchy' => $edit['hierarchy'], 'relations' => $edit['relations'], 'weight' => $edit['weight']); + if ($edit['vid'] && $edit['name']) { + db_query('UPDATE {vocabulary} SET '. _prepare_update($data) .' WHERE vid = %d', $edit['vid']); + module_invoke_all('taxonomy', 'update', 'vocabulary', $edit); + $message = t('updated vocabulary "%name".', array('%name' => $edit['name'])); } - else if ($edit["vid"]) { - $message = taxonomy_del_vocabulary($edit["vid"]); + else if ($edit['vid']) { + $message = taxonomy_del_vocabulary($edit['vid']); } else { - $data["vid"] = $edit["vid"] = db_next_id("{vocabulary}_vid"); - db_query("INSERT INTO {vocabulary} ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2)); - module_invoke_all("taxonomy", "insert", "vocabulary", $edit); - $message = t("created new vocabulary '%name'.", array("%name" => $edit["name"])); + $data['vid'] = $edit['vid'] = db_next_id('{vocabulary}_vid'); + db_query('INSERT INTO {vocabulary} '. _prepare_insert($data, 1) .' VALUES '. _prepare_insert($data, 2)); + module_invoke_all('taxonomy', 'insert', 'vocabulary', $edit); + $message = t('created new vocabulary "%name".', array('%name' => $edit['name'])); } cache_clear_all(); @@ -117,121 +128,119 @@ function taxonomy_save_vocabulary($edit) function taxonomy_del_vocabulary($vid) { $vocabulary = taxonomy_get_vocabulary($vid); - db_query("DELETE FROM {vocabulary} WHERE vid = %d", $vid); - $result = db_query("SELECT tid FROM {term_data} WHERE vid = %d", $vid); + db_query('DELETE FROM {vocabulary} WHERE vid = %d', $vid); + $result = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $vid); while ($term = db_fetch_object($result)) { taxonomy_del_term($term->tid); } - module_invoke_all("taxonomy", "delete", "vocabulary", $vocabulary); + module_invoke_all('taxonomy', 'delete', 'vocabulary', $vocabulary); cache_clear_all(); - return t("deleted vocabulary '%name'.", array("%name" => $vocabulary->name)); + return t('deleted vocabulary "%name".', array('%name' => $vocabulary->name)); } function _taxonomy_confirm_del_vocabulary($vid) { $vocabulary = taxonomy_get_vocabulary($vid); - $form .= form_hidden("confirm", 1); - $form .= form_hidden("type", "vocabulary"); - $form .= form_hidden("vid", $vid); - $form .= form_submit(t("Delete")); - $form .= form_submit(t("Cancel")); + $form .= form_hidden('confirm', 1); + $form .= form_hidden('type', 'vocabulary'); + $form .= form_hidden('vid', $vid); + $form .= form_submit(t('Delete')); + $form .= form_submit(t('Cancel')); - return form(form_item(t("Delete vocabulary '%name'", array("%name" => $vocabulary->name)), $form, t("Are you sure you want to delete the vocabulary and all its terms?"))); + return form(form_item(t('Delete vocabulary "%name"', array('%name' => $vocabulary->name)), $form, t('Are you sure you want to delete the vocabulary and all its terms?'))); } function taxonomy_form_term($edit = array()) { - $vocabulary_id = isset($edit["vid"]) ? $edit["vid"] : arg(4); + $vocabulary_id = isset($edit['vid']) ? $edit['vid'] : arg(4); $vocabulary = taxonomy_get_vocabulary($vocabulary_id); - $form = form_textfield(t("Term name"), "name", $edit["name"], 50, 64, t("Required") .". ". t("The name for this term. Example: 'Linux'.")); - $form .= form_textarea(t("Description"), "description", $edit["description"], 60, 5, t("Optional") .". ". t("A description of the term.")); + $form = form_textfield(t('Term name'), 'name', $edit['name'], 50, 64, t('Required') .'. '. t('The name for this term. Example: "Linux".')); + $form .= form_textarea(t('Description'), 'description', $edit['description'], 60, 5, t('Optional') .'. '. t('A description of the term.')); if ($vocabulary->hierarchy) { - $parent = array_keys(taxonomy_get_parents($edit["tid"])); - $children = taxonomy_get_tree($vocabulary_id, $edit["tid"]); + $parent = array_keys(taxonomy_get_parents($edit['tid'])); + $children = taxonomy_get_tree($vocabulary_id, $edit['tid']); - // you can't be son of yourself nor of your children + // A term can't be the child of itself, nor of its children. foreach ($children as $child) { $exclude[] = $child->tid; } - $exclude[] = $edit["tid"]; + $exclude[] = $edit['tid']; if ($vocabulary->hierarchy == 1) { - $form .= _taxonomy_term_select(t("Parent"), "parent", $parent, $vocabulary_id, t("Required") .". ". l(t("Parent term"), "admin/taxonomy/help", NULL, NULL, "parent") .".", 0, "<". t("root") .">", $exclude); + $form .= _taxonomy_term_select(t('Parent'), 'parent', $parent, $vocabulary_id, t('Required') .'. '. l(t('Parent term'), 'admin/taxonomy/help', NULL, NULL, 'parent') .'.', 0, '<'. t('root') .'>', $exclude); } elseif ($vocabulary->hierarchy == 2) { - $form .= _taxonomy_term_select(t("Parents"), "parent", $parent, $vocabulary_id, t("Required") .". ". l(t("Parent terms"), "admin/taxonomy/help", NULL, NULL, "parent") .".", 1, "<". t("root") .">", $exclude); + $form .= _taxonomy_term_select(t('Parents'), 'parent', $parent, $vocabulary_id, t('Required') .'. '. l(t('Parent terms'), 'admin/taxonomy/help', NULL, NULL, 'parent') .'.', 1, '<'. t('root') .'>', $exclude); } } if ($vocabulary->relations) { - $form .= _taxonomy_term_select(t("Related terms"), "relations", array_keys(taxonomy_get_related($edit["tid"])), $vocabulary_id, t("Optional") .". ", 1, "<". t("none") .">", array($edit["tid"])); + $form .= _taxonomy_term_select(t('Related terms'), 'relations', array_keys(taxonomy_get_related($edit['tid'])), $vocabulary_id, t('Optional') .'. ', 1, '<'. t('none') .'>', array($edit['tid'])); } - $form .= form_textarea(t("Synonyms"), "synonyms", implode("\n", taxonomy_get_synonyms($edit["tid"])), 30, 5, t("Optional") . ". ". t("Synonyms of this term, one synonym per line.", array("%help-url" => url("admin/taxonomy/help", NULL, NULL, "synonyms")))); - $form .= form_weight(t("Weight"), "weight", $edit["weight"], 10, t("Optional. In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top.")); - $form .= form_hidden("vid", $vocabulary->vid); - $form .= form_submit(t("Submit")); + $form .= form_textarea(t('Synonyms'), 'synonyms', implode("\n", taxonomy_get_synonyms($edit['tid'])), 30, 5, t('Optional') . '. '. t('Synonyms of this term, one synonym per line.', array('%help-url' => url('admin/taxonomy/help', NULL, NULL, 'synonyms')))); + $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('Optional. In listings, the heavier terms will sink and the lighter terms will be positioned nearer the top.')); + $form .= form_hidden('vid', $vocabulary->vid); + $form .= form_submit(t('Submit')); - if ($edit["tid"]) { - $form .= form_submit(t("Delete")); - $form .= form_hidden("tid", $edit["tid"]); + if ($edit['tid']) { + $form .= form_submit(t('Delete')); + $form .= form_hidden('tid', $edit['tid']); } return form($form); } function taxonomy_save_term($edit) { - if ($edit["tid"] && $edit["name"]) { - $data = array("name" => $edit["name"], "description" => $edit["description"], "weight" => $edit["weight"]); + if ($edit['tid'] && $edit['name']) { + $data = array('name' => $edit['name'], 'description' => $edit['description'], 'weight' => $edit['weight']); - db_query("UPDATE {term_data} SET ". _prepare_update($data) ." WHERE tid = %d", $edit["tid"]); - module_invoke_all("taxonomy", "update", "term", $edit); - $message = t("the term '%a' has been updated.", array("%a" => $edit["name"])); + db_query('UPDATE {term_data} SET '. _prepare_update($data) .' WHERE tid = %d', $edit['tid']); + module_invoke_all('taxonomy', 'update', 'term', $edit); + $message = t('the term "%a" has been updated.', array('%a' => $edit['name'])); } - else if ($edit["tid"]) { - return taxonomy_del_term($edit["tid"]); + else if ($edit['tid']) { + return taxonomy_del_term($edit['tid']); } else { - $edit["tid"] = db_next_id("{term_data}_tid"); - $data = array("tid" => $edit["tid"], "name" => $edit["name"], "description" => $edit["description"], "vid" => $edit["vid"], "weight" => $edit["weight"]); - db_query("INSERT INTO {term_data} ". _prepare_insert($data, 1) ." VALUES ". _prepare_insert($data, 2)); - module_invoke_all("taxonomy", "insert", "term", $edit); - $message = t("created new term '%name'.", array("%name" => $edit["name"])); + $edit['tid'] = db_next_id('{term_data}_tid'); + $data = array('tid' => $edit['tid'], 'name' => $edit['name'], 'description' => $edit['description'], 'vid' => $edit['vid'], 'weight' => $edit['weight']); + db_query('INSERT INTO {term_data} '. _prepare_insert($data, 1) .' VALUES '. _prepare_insert($data, 2)); + module_invoke_all('taxonomy', 'insert', 'term', $edit); + $message = t('created new term "%name".', array('%name' => $edit['name'])); } - // relations (seem very powerful, but I have to understand it completely) - db_query("DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d", $edit["tid"], $edit["tid"]); - if ($edit["relations"]) { - foreach ($edit["relations"] as $related_id) { + db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $edit['tid'], $edit['tid']); + if ($edit['relations']) { + foreach ($edit['relations'] as $related_id) { if ($related_id != 0) { - db_query("INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)", $edit["tid"], $related_id); + db_query('INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)', $edit['tid'], $related_id); } } } - // hierarchy - db_query("DELETE FROM {term_hierarchy} WHERE tid = %d", $edit["tid"]); - if (!isset($edit["parent"])) { - $edit["parent"] = 0; + db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $edit['tid']); + if (!isset($edit['parent'])) { + $edit['parent'] = 0; } - if (is_array($edit["parent"])) { - foreach ($edit["parent"] as $parent) { - db_query("INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $edit["tid"], $parent); + if (is_array($edit['parent'])) { + foreach ($edit['parent'] as $parent) { + db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $parent); } } else { - db_query("INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $edit["tid"], $edit["parent"][0]); + db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $edit['tid'], $edit['parent'][0]); } - db_query("DELETE FROM {term_synonym} WHERE tid = %d", $edit["tid"]); - if ($edit["synonyms"]) { - foreach (explode ("\n", str_replace("\r", "", $edit["synonyms"])) as $synonym) { + db_query('DELETE FROM {term_synonym} WHERE tid = %d', $edit['tid']); + if ($edit['synonyms']) { + foreach (explode ("\n", str_replace("\r", '', $edit['synonyms'])) as $synonym) { if ($synonym) { - db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $edit["tid"], chop($synonym)); + db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $edit['tid'], chop($synonym)); } } } @@ -245,86 +254,90 @@ function taxonomy_save_term($edit) { function taxonomy_del_term($tid) { $term = taxonomy_get_term($tid); - db_query("DELETE FROM {term_data} WHERE tid = %d", $tid); - db_query("DELETE FROM {term_hierarchy} WHERE tid = %d", $tid); - db_query("DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d", $tid, $tid); - db_query("DELETE FROM {term_synonym} WHERE tid = %d", $tid); - db_query("DELETE FROM {term_node} WHERE tid = %d", $tid); + db_query('DELETE FROM {term_data} WHERE tid = %d', $tid); + db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $tid); + db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid); + db_query('DELETE FROM {term_synonym} WHERE tid = %d', $tid); + db_query('DELETE FROM {term_node} WHERE tid = %d', $tid); - module_invoke_all("taxonomy", "delete", "term", $term); + module_invoke_all('taxonomy', 'delete', 'term', $term); cache_clear_all(); - return t("deleted term '%name'.", array("%name" => $term->name)); + return t('deleted term "%name".', array('%name' => $term->name)); } function _taxonomy_confirm_del_term($tid) { $term = taxonomy_get_term($tid); - $form .= form_hidden("confirm", 1); - $form .= form_hidden("type", "term"); - $form .= form_hidden("tid", $tid); - $form .= form_submit(t("Delete")); - $form .= form_submit(t("Cancel")); + $form .= form_hidden('confirm', 1); + $form .= form_hidden('type', 'term'); + $form .= form_hidden('tid', $tid); + $form .= form_submit(t('Delete')); + $form .= form_submit(t('Cancel')); - return form(form_item(t("Delete term '%name'", array("%name" => $term->name)), $form, t("Are you sure you want to delete the term?"))); + return form(form_item(t('Delete term "%name"', array('%name' => $term->name)), $form, t('Are you sure you want to delete the term?'))); } +/** + * Generate a tabular listing of administrative functions for vocabularies. + */ function taxonomy_overview() { - - $output .= "

    ". t("Vocabularies overview") ."

    "; - - $header = array(t("name"), t("node types"), array("data" => t("operations"), "colspan" => 3)); + $header = array(t('name'), t('node types'), array('data' => t('operations'), 'colspan' => 3)); $vocabularies = taxonomy_get_vocabularies(); foreach ($vocabularies as $vocabulary) { $links = array(); $types = array(); - foreach(explode(",", $vocabulary->nodes) as $type) { - $types[] = node_invoke($type, "node_name"); + foreach(explode(',', $vocabulary->nodes) as $type) { + $types[] = node_invoke($type, 'node_name'); } - $rows[] = array($vocabulary->name, array("data" => implode(", ", $types), "align" => "center"), l(t("edit vocabulary"), "admin/taxonomy/edit/vocabulary/$vocabulary->vid"), l(t("add term"), "admin/taxonomy/add/term/$vocabulary->vid"), l(t("preview form"), "admin/taxonomy/preview/vocabulary/$vocabulary->vid")); + $rows[] = array($vocabulary->name, array('data' => implode(', ', $types), 'align' => 'center'), l(t('edit vocabulary'), "admin/taxonomy/edit/vocabulary/$vocabulary->vid"), l(t('add term'), "admin/taxonomy/add/term/$vocabulary->vid"), l(t('preview form'), "admin/taxonomy/preview/vocabulary/$vocabulary->vid")); $tree = taxonomy_get_tree($vocabulary->vid); if ($tree) { unset($data); foreach ($tree as $term) { - $data .= _taxonomy_depth($term->depth) ." ". $term->name ." (". l(t("edit term"), "admin/taxonomy/edit/term/$term->tid") .")
    "; + $data .= _taxonomy_depth($term->depth) .' '. $term->name .' ('. l(t('edit term'), "admin/taxonomy/edit/term/$term->tid") .')
    '; } - $rows[] = array(array("data" => $data, "colspan" => 5)); + $rows[] = array(array('data' => $data, 'colspan' => 5)); } } - return theme("table", $header, $rows); + return theme('table', $header, $rows); } -function taxonomy_form($vocabulary_id, $value = 0, $error = array(), $help = NULL) { - $vocabulary = taxonomy_get_vocabulary($vocabulary_id); +/** + * Generate a form element for selecting terms from a vocabulary. + */ +function taxonomy_form($vid, $value = 0, $error = array(), $help = NULL) { + $vocabulary = taxonomy_get_vocabulary($vid); $help = ($help) ? $help : $vocabulary->help; if ($vocabulary->required) { $blank = 0; } else { - $blank = "<". t("none") .">"; + $blank = '<'. t('none') .'>'; } $help .= $error['taxonomy']; - return _taxonomy_term_select($vocabulary->name, 'taxonomy', $value, $vocabulary_id, $help, intval($vocabulary->multiple), $blank); + return _taxonomy_term_select($vocabulary->name, 'taxonomy', $value, $vid, $help, intval($vocabulary->multiple), $blank); } -/* -** API functions -*/ - -// return array of vocabularies, as objects -function taxonomy_get_vocabularies($type = '', $key = "vid") { +/** + * Return an array of all vocabulary objects. + * + * @param $type + * If set, return only those vocabularies associated with this node type. + */ +function taxonomy_get_vocabularies($type = '', $key = 'vid') { if ($type) { $result = db_query("SELECT * FROM {vocabulary} WHERE nodes LIKE '%%%s%%' ORDER BY weight, name", $type); } else { - $result = db_query("SELECT * FROM {vocabulary} ORDER BY weight, name"); + $result = db_query('SELECT * FROM {vocabulary} ORDER BY weight, name'); } $vocabularies = array(); while ($voc = db_fetch_object($result)) { @@ -334,7 +347,9 @@ function taxonomy_get_vocabularies($type return $vocabularies; } -// return form with current term +/** + * Generate a form for selecting terms to associate with a node. + */ function taxonomy_node_form($type, $node = '', $error = array()) { if (!$node->taxonomy) { if ($node->nid) { @@ -355,16 +370,20 @@ function taxonomy_node_form($type, $node return $result ? $result : array(); } -// return 1 if node identified by $nid contains a taxonomy term identified by $tid in his body or title +/** + * Determine whether a node mentions the name of a term. + */ function taxonomy_node_has_term($nid, $tid) { - $term_name = db_result(db_query("SELECT name FROM {term_data} WHERE tid = %d", $tid)); + $term_name = db_result(db_query('SELECT name FROM {term_data} WHERE tid = %d', $tid)); return db_result(db_query("SELECT COUNT(n.nid) FROM {node} n WHERE n.nid = %d AND ((n.body LIKE '%%%s%%') OR (n.body LIKE '%%%s%%'))", $nid, $term_name, $term_name)); } -// return array of terms of a node beloging to a particular vocabulary identified by $vid -function taxonomy_node_get_terms_by_vocabulary($nid, $vid, $key = "tid") { - $result = db_query("SELECT t.* FROM {term_data} t, {term_node} r WHERE t.tid = r.tid AND t.vid = %d AND r.nid = %d ORDER BY weight", $vid, $nid); +/** + * Find all terms associated to the given node, within one vocabulary. + */ +function taxonomy_node_get_terms_by_vocabulary($nid, $vid, $key = 'tid') { + $result = db_query('SELECT t.* FROM {term_data} t, {term_node} r WHERE t.tid = r.tid AND t.vid = %d AND r.nid = %d ORDER BY weight', $vid, $nid); $terms = array(); while ($term = db_fetch_object($result)) { $terms[$term->$key] = $term; @@ -372,12 +391,14 @@ function taxonomy_node_get_terms_by_voca return $terms; } -// return array of terms of a node -function taxonomy_node_get_terms($nid, $key = "tid") { +/** + * Find all terms associated to the given node. + */ +function taxonomy_node_get_terms($nid, $key = 'tid') { static $terms; if (!isset($terms[$nid])) { - $result = db_query("SELECT t.* FROM {term_data} t, {term_node} r WHERE r.tid = t.tid AND r.nid = %d ORDER BY weight, name", $nid); + $result = db_query('SELECT t.* FROM {term_data} t, {term_node} r WHERE r.tid = t.tid AND r.nid = %d ORDER BY weight, name', $nid); $terms[$nid] = array(); while ($term = db_fetch_object($result)) { $terms[$nid][$term->$key] = $term; @@ -386,28 +407,34 @@ function taxonomy_node_get_terms($nid, $ return $terms[$nid]; } -// save terms of a node +/** + * Save term associations for a given node. + */ function taxonomy_node_save($nid, $terms) { taxonomy_node_delete($nid); if ($terms) { foreach ($terms as $term) { if ($term) { - db_query("INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)", $nid, $term); + db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $term); } } } } -// clean up terms +/** + * Remove associations of a node to its terms. + */ function taxonomy_node_delete($nid) { - db_query("DELETE FROM {term_node} WHERE nid = %d", $nid); + db_query('DELETE FROM {term_node} WHERE nid = %d', $nid); } -// relations: return array of related terms -function taxonomy_get_related($tid, $key = "tid") { +/** + * Find all term objects related to a given term ID. + */ +function taxonomy_get_related($tid, $key = 'tid') { if ($tid) { - $result = db_query("SELECT t.*, tid1, tid2 FROM {term_relation} , {term_data} t WHERE (t.tid = tid1 OR t.tid = tid2) AND (tid1 = %d OR tid2 = %d) AND t.tid != %d ORDER BY weight, name", $tid, $tid, $tid); + $result = db_query('SELECT t.*, tid1, tid2 FROM {term_relation}, {term_data} t WHERE (t.tid = tid1 OR t.tid = tid2) AND (tid1 = %d OR tid2 = %d) AND t.tid != %d ORDER BY weight, name', $tid, $tid, $tid); $related = array(); while ($term = db_fetch_object($result)) { $related[$term->$key] = $term; @@ -419,10 +446,12 @@ function taxonomy_get_related($tid, $key } } -// hierarchy: get parent terms -function taxonomy_get_parents($tid, $key = "tid") { +/** + * Find all parents of a given term ID. + */ +function taxonomy_get_parents($tid, $key = 'tid') { if ($tid) { - $result = db_query("SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE h.parent = t.tid AND h.tid = %d ORDER BY weight, name", $tid); + $result = db_query('SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE h.parent = t.tid AND h.tid = %d ORDER BY weight, name', $tid); $parents = array(); while ($parent = db_fetch_object($result)) { $parents[$parent->$key] = $parent; @@ -434,8 +463,10 @@ function taxonomy_get_parents($tid, $key } } -// Gets all parents, parents of parents, etc. -function taxonomy_get_parents_all($tid, $key = "tid") { +/** + * Find all ancestors of a given term ID. + */ +function taxonomy_get_parents_all($tid) { $parents = array(); if ($tid) { $parents[] = taxonomy_get_term($tid); @@ -448,13 +479,15 @@ function taxonomy_get_parents_all($tid, return $parents; } -// hierarchy: get children -function taxonomy_get_children($tid, $vid = 0, $key = "tid") { +/** + * Find all children of a term ID. + */ +function taxonomy_get_children($tid, $vid = 0, $key = 'tid') { if ($vid) { - $result = db_query("SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE t.vid = %d AND h.tid = t.tid AND h.parent = %d ORDER BY weight, name", $vid, $tid); + $result = db_query('SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE t.vid = %d AND h.tid = t.tid AND h.parent = %d ORDER BY weight, name', $vid, $tid); } else { - $result = db_query("SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE h.tid = t.tid AND parent = %d ORDER BY weight", $tid); + $result = db_query('SELECT t.* FROM {term_hierarchy} h, {term_data} t WHERE h.tid = t.tid AND parent = %d ORDER BY weight', $tid); } $children = array(); while ($term = db_fetch_object($result)) { @@ -463,34 +496,52 @@ function taxonomy_get_children($tid, $vi return $children; } -// hierarchy: get whole family, with tid, parent and depth; useful to show -function taxonomy_get_tree($vocabulary_id, $parent = 0, $depth = -1, $max_depth = NULL) { +/** + * Create a hierarchical representation of a vocabulary. + * + * @param $vid + * Which vocabulary to generate the tree for. + * + * @param $parent + * The term ID under which to generate the tree. If 0, generate the tree + * for the entire vocabulary. + * + * @param $depth + * Internal use only. + * + * @return + * An array of all term objects in the tree. Each term object is extended + * to have "depth" and "parents" attributes in addition to its normal ones. + */ +function taxonomy_get_tree($vid, $parent = 0, $depth = -1, $max_depth = NULL) { static $children, $parents, $terms; $depth++; - // we cache trees, so it's not cpu-intensive to call get_tree on a term and its children too - if (!isset($children[$vocabulary_id])) { - $children[$vocabulary_id] = array(); + // We cache trees, so it's not CPU-intensive to call get_tree() on a term + // and its children, too. + if (!isset($children[$vid])) { + $children[$vid] = array(); - $result = db_query("SELECT t.*, parent FROM {term_data} t, {term_hierarchy} h WHERE t.tid = h.tid AND t.vid = %d ORDER BY weight, name", $vocabulary_id); + $result = db_query('SELECT t.*, parent FROM {term_data} t, {term_hierarchy} h WHERE t.tid = h.tid AND t.vid = %d ORDER BY weight, name', $vid); while ($term = db_fetch_object($result)) { - $children[$vocabulary_id][$term->parent][] = $term->tid; - $parents[$vocabulary_id][$term->tid][] = $term->parent; - $terms[$vocabulary_id][$term->tid] = $term; + $children[$vid][$term->parent][] = $term->tid; + $parents[$vid][$term->tid][] = $term->parent; + $terms[$vid][$term->tid] = $term; } } - $max_depth = ($max_depth == '') ? count($children[$vocabulary_id]) : $max_depth; - if ($children[$vocabulary_id][$parent]) { - foreach ($children[$vocabulary_id][$parent] as $child) { + $max_depth = ($max_depth == '') ? count($children[$vid]) : $max_depth; + if ($children[$vid][$parent]) { + foreach ($children[$vid][$parent] as $child) { if ($max_depth > $depth) { - $terms[$vocabulary_id][$child]->depth = $depth; - unset($terms[$vocabulary_id][$child]->parent); // this is not useful as it would show one parent only - $terms[$vocabulary_id][$child]->parents = $parents[$vocabulary_id][$child]; - $tree[] = $terms[$vocabulary_id][$child]; + $terms[$vid][$child]->depth = $depth; + // The "parent" attribute is not useful, as it would show one parent only. + unset($terms[$vid][$child]->parent); + $terms[$vid][$child]->parents = $parents[$vid][$child]; + $tree[] = $terms[$vid][$child]; - $tree = array_merge($tree, taxonomy_get_tree($vocabulary_id, $child, $depth, $max_depth)); + $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $depth, $max_depth)); } } } @@ -498,12 +549,14 @@ function taxonomy_get_tree($vocabulary_i return $tree ? $tree : array(); } -// synonyms: return array of synonyms +/** + * Return an array of synonyms of the given term ID. + */ function taxonomy_get_synonyms($tid) { if ($tid) { - $result = db_query("SELECT name FROM {term_synonym} WHERE tid = %d", $tid); + $result = db_query('SELECT name FROM {term_synonym} WHERE tid = %d', $tid); while ($synonym = db_fetch_array($result)) { - $synonyms[] = $synonym["name"]; + $synonyms[] = $synonym['name']; } return $synonyms ? $synonyms : array(); } @@ -512,19 +565,23 @@ function taxonomy_get_synonyms($tid) { } } -// synonyms: return original term -function taxonomy_get_synonym_root($term) { - return db_fetch_object(db_query("SELECT * FROM {term_synonym} s, {term_data} t WHERE t.tid = s.tid AND s.name = '%s'", $term)); +/** + * Return the term object that has the given string as a synonym. + */ +function taxonomy_get_synonym_root($synonym) { + return db_fetch_object(db_query("SELECT * FROM {term_synonym} s, {term_data} t WHERE t.tid = s.tid AND s.name = '%s'", $synonym)); } -// given a term id, count number of published nodes in it +/** + * Given a term id, count the number of published nodes in it. + */ function taxonomy_term_count_nodes($tid, $type = 0) { static $count; if (!isset($count[$type])) { // $type == 0 always evaluates true is $type is a string if (is_numeric($type)) { - $result = db_query("SELECT t.tid, COUNT(*) AS c FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 GROUP BY t.tid"); + $result = db_query('SELECT t.tid, COUNT(*) AS c FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE n.status = 1 GROUP BY t.tid'); } else { $result = db_query("SELECT t.tid, COUNT(*) AS c FROM {term_node} t, {node} n WHERE t.nid = n.nid AND n.status = 1 AND n.type = '%s' GROUP BY t.tid", $type); @@ -540,12 +597,14 @@ function taxonomy_term_count_nodes($tid, return $count[$type][$tid] + $children_count; } -// helper for above function +/** + * Helper for taxonomy_term_count_nodes(). + */ function _taxonomy_term_children($tid) { static $children; if (!isset($children)) { - $result = db_query("SELECT tid, parent FROM {term_hierarchy} "); + $result = db_query('SELECT tid, parent FROM {term_hierarchy}'); while ($term = db_fetch_object($result)) { $children[$term->parent][] = $term->tid; } @@ -554,14 +613,18 @@ function _taxonomy_term_children($tid) { } /** - * Try to map a string to existing vocabularies. Provide case insensitive and - * trimmed map so as to maximize likelihood of successful mapping. + * Try to map a string to an existing vocabulary. + * + * Provides a case-insensitive and trimmed mapping, to maximize the + * likelihood of a successful match. + * + * @param name + * Name of the vocabulary to search for. * - * @param $name Name of the vocabulary to search - * @return array of matching vocabularies, as objects + * @return + * An array of matching vocabulary objects. */ function taxonomy_get_vocabulary_by_name($name) { - // LOWER is ANSI SQL-92 $db_result = db_query("SELECT * FROM {vocabulary} WHERE LOWER('%s') LIKE LOWER(name)", trim($name)); $result = array(); while ($vocabulary = db_fetch_object($db_result)) { @@ -572,14 +635,18 @@ function taxonomy_get_vocabulary_by_name } /** - * Try to map a string to existing terms Provide case insensitive and trimmed - * map so as to maximize likelihood of successful mapping. + * Try to map a string to an existing term, as for glossary use. * - * @param name Name of the term to search - * @return rray of matching terms, as objects + * Provides a case-insensitive and trimmed mapping, to maximize the + * likelihood of a successful match. + * + * @param name + * Name of the term to search for. + * + * @return + * An array of matching term objects. */ function taxonomy_get_term_by_name($name) { - // LOWER is ANSI SQL-92 $db_result = db_query("SELECT * FROM {term_data} WHERE LOWER('%s') LIKE LOWER(name)", trim($name)); $result = array(); while ($term = db_fetch_object($db_result)) { @@ -589,20 +656,21 @@ function taxonomy_get_term_by_name($name return $result; } +/** + * Return the vocabulary object matching a vocabulary ID. + */ function taxonomy_get_vocabulary($vid) { - // simple cache using a static var? - return db_fetch_object(db_query("SELECT * FROM {vocabulary} WHERE vid = %d", $vid)); + return db_fetch_object(db_query('SELECT * FROM {vocabulary} WHERE vid = %d', $vid)); } +/** + * Return the term object matching a term ID. + */ function taxonomy_get_term($tid) { // simple cache using a static var? - return db_fetch_object(db_query("SELECT * FROM {term_data} WHERE tid = %d", $tid)); + return db_fetch_object(db_query('SELECT * FROM {term_data} WHERE tid = %d', $tid)); } -/* -** service functions -*/ - function _taxonomy_term_select($title, $name, $value, $vocabulary_id, $description, $multiple, $blank, $exclude = array()) { $tree = taxonomy_get_tree($vocabulary_id); @@ -615,13 +683,13 @@ function _taxonomy_term_select($title, $ } if ($blank) { - $options[] = array("tid" => 0, "name" => $blank); + $options[] = array('tid' => 0, 'name' => $blank); } if ($tree) { foreach ($tree as $term) { if (!in_array($term->tid, $exclude)) { - $options[] = array("tid" => $term->tid, "name" => _taxonomy_depth($term->depth, '-').$term->name); + $options[] = array('tid' => $term->tid, 'name' => _taxonomy_depth($term->depth, '-').$term->name); } } if (!$blank && !$value) { @@ -632,12 +700,12 @@ function _taxonomy_term_select($title, $ if (count($options) > 0) { foreach ($options as $option) { - $select .= ""; + $select .= ''; } $size = min(12, count($options)); - return form_item($title, "", $description); + return form_item($title, "", $description); } } @@ -652,46 +720,57 @@ function _prepare_update($data) { foreach ($data as $key => $value) { $q[] = "$key = '". check_query($value) ."'"; } - $result = implode(", ", $q); + $result = implode(', ', $q); return $result; } function _prepare_insert($data, $stage) { if ($stage == 1) { - $result = implode(", ", array_keys($data)); + $result = implode(', ', array_keys($data)); } else { foreach (array_values($data) as $value) { $q[] = "'". check_query($value) ."'"; } - $result = implode(", ", $q); + $result = implode(', ', $q); } return "($result)"; } -/* -** Accepts taxonomy conditions and returns a resource identifier. If -** you intend to use the nodes without a pager (eg. in a XML feed), -** then set $pager to false. -*/ -function taxonomy_select_nodes($taxonomy, $pager = 1) { - global $user; - +/** + * Finds all nodes that match selected taxonomy conditions. + * + * @param $taxonomy + * An object containing the conditions to match. The attributes of this + * object are: + * - "tids": An array of term IDs to match. + * - "str_tids": A comma-separated list of the same IDs. + * - "operator": How to interpret multiple IDs in the array. Can be + * "or" or "and". + * + * @param $pager + * Whether the nodes are to be used with a pager (the case on most Drupal + * pages) or not (in an XML feed, for example). + * + * @return + * A resource identifier pointing to the query results. + */ +function taxonomy_select_nodes($taxonomy, $pager = TRUE) { if ($taxonomy->str_tids) { - if ($taxonomy->operator == "or") { - $sql = "SELECT DISTINCT(n.nid), n.title, n.type, n.created, n.changed, n.uid, n.static, n.created, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = '1' ORDER BY static DESC, created DESC"; - $sql_count = "SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = '1'"; + if ($taxonomy->operator == 'or') { + $sql = "SELECT DISTINCT(n.nid), n.title, n.type, n.created, n.changed, n.uid, n.static, n.created, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1 ORDER BY static DESC, created DESC"; + $sql_count = "SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1"; } else { - $sql = "SELECT n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = '1' GROUP BY n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name HAVING COUNT(n.nid) = ". count($taxonomy->tids) ." ORDER BY static DESC, created DESC"; + $sql = "SELECT n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid INNER JOIN {users} u ON n.uid = u.uid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1 GROUP BY n.nid, n.title, n.type, n.created, n.changed, n.uid, u.name HAVING COUNT(n.nid) = ". count($taxonomy->tids) ." ORDER BY static DESC, created DESC"; // Special trick as we could not find anything better: - $count = db_num_rows(db_query("SELECT n.nid FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = '1' GROUP BY n.nid HAVING COUNT(n.nid) = ". count($taxonomy->tids))); + $count = db_num_rows(db_query("SELECT n.nid FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid WHERE r.tid IN ($taxonomy->str_tids) AND n.status = 1 GROUP BY n.nid HAVING COUNT(n.nid) = ". count($taxonomy->tids))); $sql_count = "SELECT $count"; } if ($pager) { - $result = pager_query($sql, variable_get("default_nodes_main", 10) , 0, $sql_count); + $result = pager_query($sql, variable_get('default_nodes_main', 10) , 0, $sql_count); } else { $result = db_query_range($sql, 0, 15); @@ -701,29 +780,31 @@ function taxonomy_select_nodes($taxonomy return $result; } -/* -** Accepts the result of a db_query() and formats each node along -** with a pager. +/** + * Accepts the result of a pager_query() call, such as that performed by + * taxonomy_select_nodes(), and formats each node along with a pager. */ function taxonomy_render_nodes($result) { while ($node = db_fetch_object($result)) { - $output .= node_view(node_load(array("nid" => $node->nid, "type" => $node->type)), 1); + $output .= node_view(node_load(array('nid' => $node->nid, 'type' => $node->type)), 1); } - $output .= theme("pager", NULL, variable_get("default_nodes_main", 10), 0); + $output .= theme('pager', NULL, variable_get('default_nodes_main', 10), 0); return $output; } +/** + * Implementation of hook_nodeapi(). + */ function taxonomy_nodeapi($node, $op, $arg = 0) { - switch ($op) { - case "insert": + case 'insert': taxonomy_node_save($node->nid, $node->taxonomy); break; - case "update": + case 'update': taxonomy_node_save($node->nid, $node->taxonomy); break; - case "delete": + case 'delete': taxonomy_node_delete($node->nid); break; } @@ -733,11 +814,11 @@ function taxonomy_page() { $taxonomy->operator = arg(2); $taxonomy->str_tids = check_query(arg(3)); - $taxonomy->tids = explode(",", $taxonomy->str_tids); + $taxonomy->tids = explode(',', $taxonomy->str_tids); - if (ereg("^([0-9]+,){0,}[0-9]+$", $taxonomy->str_tids)) { + if (ereg('^([0-9]+,){0,}[0-9]+$', $taxonomy->str_tids)) { switch (arg(1)) { - case "feed": + case 'feed': taxonomy_feed($taxonomy); break; default: @@ -751,17 +832,18 @@ function taxonomy_page() { // Build breadcrumb based on first hierarchy of first term: $current->tid = $taxonomy->tids[0]; + $breadcrumbs = array(array('path' => $_GET['q'])); while ($parents = taxonomy_get_parents($current->tid)) { $current = array_shift($parents); - $breadcrumbs[] = l($current->name, "taxonomy/view/or/$current->tid"); + $breadcrumbs[] = array('path' => 'taxonomy/view/or/'. $current->tid, 'title' => $current->name); } - $breadcrumbs[] = l(t('Home'), ''); $breadcrumbs = array_reverse($breadcrumbs); + menu_set_location($breadcrumbs); drupal_set_html_head('str_tids") .'" />'); $output = taxonomy_render_nodes(taxonomy_select_nodes($taxonomy)); - print theme("page", $output, implode(', ', $names), $breadcrumbs); + print theme('page', $output, implode(', ', $names)); break; } } @@ -770,62 +852,61 @@ function taxonomy_page() { } } -/* -** admin -*/ - +/** + * Menu callback; dispatches to the proper taxonomy administration function. + */ function taxonomy_admin() { - $op = $_POST["op"]; - $edit = $_POST["edit"]; + $op = $_POST['op']; + $edit = $_POST['edit']; if (empty($op)) { $op = arg(2); } switch ($op) { - case "add": - if (arg(3) == "vocabulary") { + case 'add': + if (arg(3) == 'vocabulary') { $output .= taxonomy_form_vocabulary(); } - else if (arg(3) == "term") { + else if (arg(3) == 'term') { $output .= taxonomy_form_term(); } break; - case "edit": - if (arg(3) == "vocabulary") { + case 'edit': + if (arg(3) == 'vocabulary') { $output .= taxonomy_form_vocabulary(object2array(taxonomy_get_vocabulary(arg(4)))); } - else if (arg(3) == "term") { + else if (arg(3) == 'term') { $output .= taxonomy_form_term(object2array(taxonomy_get_term(arg(4)))); } break; - case "preview": + case 'preview': $output .= taxonomy_form(arg(4)); break; - case "help": + case 'help': $output .= taxonomy_help(); break; - case t("Delete"): - if (!$edit["confirm"]) { - if (arg(3) == "vocabulary") { - $output .= _taxonomy_confirm_del_vocabulary($edit["vid"]); + case t('Delete'): + if (!$edit['confirm']) { + if (arg(3) == 'vocabulary') { + $output .= _taxonomy_confirm_del_vocabulary($edit['vid']); } else { - $output .= _taxonomy_confirm_del_term($edit["tid"]); + $output .= _taxonomy_confirm_del_term($edit['tid']); } break; } else { - $edit["name"] = 0; + $edit['name'] = 0; // fall through: } - case t("Submit"): - if (arg(3) == "vocabulary") { + case t('Submit'): + if (arg(3) == 'vocabulary') { taxonomy_save_vocabulary($edit); } else { taxonomy_save_term($edit); - if (!$edit["tid"]) { + if (!$edit['tid']) { // if INSERT show form again $output .= taxonomy_form_term(); break; @@ -837,24 +918,22 @@ function taxonomy_admin() { $output .= taxonomy_overview(); } - print theme("page", $output); + print theme('page', $output); } -function taxonomy_help($section = "admin/help#taxonomy") { - $output = ""; - +/** + * Implementation of hook_help(). + */ +function taxonomy_help($section = 'admin/help#taxonomy') { switch ($section) { - case 'admin/system/modules#description': - $output = t("Enables the organization of content into categories."); - break; + case 'admin/modules#description': + return t('Enables the organization of content into categories.'); case 'admin/taxonomy': - $output = t("The taxonomy module allows you to classify content into categories and subcategories; it allows multiple lists of categories for classification (controlled vocabularies) and offers the possibility of creating thesauri (controlled vocabularies that indicate the relationship of terms) and taxonomies (controlled vocabularies where relationships are indicated hierarchically). To delete a term choose \"edit term\". To delete a vocabulary, and all its terms, choose \"edit vocabulary\"."); - break; + return t('The taxonomy module allows you to classify content into categories and subcategories; it allows multiple lists of categories for classification (controlled vocabularies) and offers the possibility of creating thesauri (controlled vocabularies that indicate the relationship of terms) and taxonomies (controlled vocabularies where relationships are indicated hierarchically). To delete a term choose "edit term". To delete a vocabulary, and all its terms, choose "edit vocabulary".'); case 'admin/taxonomy/add/vocabulary': - $output = t("When you create a controlled vocabulary you are creating a set of terms to use for describing content (known as descriptors in indexing lingo). Drupal allows you to describe each node type (blog, story, etc.) using one or many of these terms. For simple implementations, you might create a set of categories without subcategories, similar to Slashdot.org's or Kuro5hin.org's sections. For more complex implementations, you might create a hierarchical list of categories."); - break; + return t("When you create a controlled vocabulary you are creating a set of terms to use for describing content (known as descriptors in indexing lingo). Drupal allows you to describe each node type (blog, story, etc.) using one or many of these terms. For simple implementations, you might create a set of categories without subcategories, similar to Slashdot.org's or Kuro5hin.org's sections. For more complex implementations, you might create a hierarchical list of categories."); case 'admin/help#taxonomy': - $output .= t(" + return t("

    Background

    Taxonomy is the study of classification. Drupal's taxonomy module allows you to define categories which are used to classify content. The module supports hierarchical classification and association between terms, allowing for truly flexible information retrieval and classification. For more details about classification types and insight into the development of the taxonomy.module, see this drupal.org discussion.

    An example taxonomy: food

    @@ -886,10 +965,7 @@ function taxonomy_help($section = "admin

    Displaying nodes organized by term(s)

    In order to view the nodes associated with a term or a collection of terms, you should browse to a properly formed Taxonomy URL. For example, taxonomy/page/or/1,2. Taxonomy URLs always contain one or more term IDs (tid) at the end of the URL (a.k.a the querystring). You may learn the term ID for a given term by hovering over that term in the taxonomy overview page and noting the number at the end or the URL. To build a Taxonomy URL start with \"taxonomy/page\". Now add the querystring parameter, either or, which chooses nodes tagged with any of the given term IDs, or and, which chooses nodes tagged with all of the given Term IDs. Thus or is less specific than and. Finally add a comma seperated list of term IDs.

    RSS feeds

    -

    Every term, or collection of terms, provides an RSS feed to which interested users may subscribe. The URL format for a sample RSS feed is node/feed/or/1,2. Built like a Taxonomy URL, see above it starts with \"node/feed\", then has the querystring parameter, and finally the Term IDs.

    ", array("%classification-types" => "http://www.eleganthack.com/archives/002165.html#002165", "%drupal-dis" => "http://www.drupal.org/node/view/55", "%slashdot" => "http://www.slashdot.com/", "%taxo-example" => url("taxonomy/page/or/1,2"), "%taxo-overview" => url("admin/taxonomy"), "%userland-rss" => "http://backend.userland.com/stories/rss", "%sample-rss" => url("node/feed/or/1,2"), "%taxo-help" => url("admin/taxonomy/help", NULL, "taxonomy-url"))); - break; +

    Every term, or collection of terms, provides an RSS feed to which interested users may subscribe. The URL format for a sample RSS feed is node/feed/or/1,2. Built like a Taxonomy URL, see above it starts with \"node/feed\", then has the querystring parameter, and finally the Term IDs.

    ", array('%classification-types' => 'http://www.eleganthack.com/archives/002165.html#002165', '%drupal-dis' => 'http://www.drupal.org/node/55', '%slashdot' => 'http://www.slashdot.com/', '%taxo-example' => url('taxonomy/page/or/1,2'), '%taxo-overview' => url('admin/taxonomy'), '%userland-rss' => 'http://backend.userland.com/stories/rss', '%sample-rss' => url('node/feed/or/1,2'), '%taxo-help' => url('admin/taxonomy/help', NULL, 'taxonomy-url'))); } - - return $output; } ?> === modified file 'modules/throttle.module' --- modules/throttle.module 2004-06-02 19:01:40 +0000 +++ modules/throttle.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ url('admin/system/modules/statistics'))); + case 'admin/modules/throttle': + return t('If your site gets linked to by a popular website, or otherwise comes under a "Denial of Service" (DoS) attack, your webserver might become overwhelmed. This module provides a mechanism for automatically detecting a surge in incoming traffic. This mechanism is utilized by other Drupal models to automatically optimize their performance by temporarily disabling CPU-intensive functionality. To use the auto-throttle, the access log must be enabled. It is advised that you carefully read the explainations below and then properly tune this module based on your site\'s requirements and your webserver\'s capabilities.', array('%access' => url('admin/modules/statistics'))); case 'admin/help#throttle': return t("

    Introduction

    @@ -96,7 +96,7 @@ function throttle_help($section) { else { // throttle limit not reached, execute normally } -

    ", array('%statistics-module' => url('admin/statistics'), '%throttle-block' => url('admin/user/permission'), '%modules-enable' => url('admin/system/modules'), '%throttle-config' => url('admin/system/modules/throttle'), '%statistics-config' => url('admin/system/modules/statistics'), '%throttle-access' => url('admin/user/permission'), '%throttle-block-enable' => url('admin/block'), '%permissions' => url('admin/user/permission'))); +

    ", array('%statistics-module' => url('admin/statistics'), '%throttle-block' => url('admin/user/permission'), '%modules-enable' => url('admin/modules'), '%throttle-config' => url('admin/modules/throttle'), '%statistics-config' => url('admin/modules/statistics'), '%throttle-access' => url('admin/user/permission'), '%throttle-block-enable' => url('admin/block'), '%permissions' => url('admin/user/permission'))); } } === modified file 'modules/throttle/throttle.module' --- modules/throttle/throttle.module 2004-06-02 19:01:40 +0000 +++ modules/throttle/throttle.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ url('admin/system/modules/statistics'))); + case 'admin/modules/throttle': + return t('If your site gets linked to by a popular website, or otherwise comes under a "Denial of Service" (DoS) attack, your webserver might become overwhelmed. This module provides a mechanism for automatically detecting a surge in incoming traffic. This mechanism is utilized by other Drupal models to automatically optimize their performance by temporarily disabling CPU-intensive functionality. To use the auto-throttle, the access log must be enabled. It is advised that you carefully read the explainations below and then properly tune this module based on your site\'s requirements and your webserver\'s capabilities.', array('%access' => url('admin/modules/statistics'))); case 'admin/help#throttle': return t("

    Introduction

    @@ -96,7 +96,7 @@ function throttle_help($section) { else { // throttle limit not reached, execute normally } -

    ", array('%statistics-module' => url('admin/statistics'), '%throttle-block' => url('admin/user/permission'), '%modules-enable' => url('admin/system/modules'), '%throttle-config' => url('admin/system/modules/throttle'), '%statistics-config' => url('admin/system/modules/statistics'), '%throttle-access' => url('admin/user/permission'), '%throttle-block-enable' => url('admin/block'), '%permissions' => url('admin/user/permission'))); +

    ", array('%statistics-module' => url('admin/statistics'), '%throttle-block' => url('admin/user/permission'), '%modules-enable' => url('admin/modules'), '%throttle-config' => url('admin/modules/throttle'), '%statistics-config' => url('admin/modules/statistics'), '%throttle-access' => url('admin/user/permission'), '%throttle-block-enable' => url('admin/block'), '%permissions' => url('admin/user/permission'))); } } === modified file 'modules/title.module' --- modules/title.module 2004-06-15 18:02:52 +0000 +++ modules/title.module 2004-06-18 15:04:33 +0000 @@ -1,12 +1,12 @@ Link to content on this site using [title|text].', array("%title-help" => url('filter/tips', NULL, 'filter-title'))); @@ -16,12 +16,15 @@ function title_help($section) { } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function title_link($type) { - if ($type == 'system') { - menu('title', t('search'), user_access('access content') ? 'title_page' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED); - } +function title_menu() { + $items = array(); + $items[] = array('path' => 'title', 'title' => t('search'), + 'callback' => 'title_page', + 'access' => user_access('access content'), + 'type' => MENU_CALLBACK); + return $items; } /** @@ -50,7 +53,7 @@ function title_page($query) { $header = array(t('Type'), t('Title'), t('Author')); while ($node = db_fetch_object($result)) { $type = ucfirst(module_invoke($node->type, 'node', 'name')); - $title = l($node->title, "node/view/$node->nid"); + $title = l($node->title, "node/$node->nid"); $author = format_name($node); $rows[] = array(array('data' => $type, 'class' => 'type'), array('data' => $title, 'class' => 'content'), array('data' => $author, 'class' => 'author')); } === modified file 'modules/tracker.module' --- modules/tracker.module 2004-05-24 18:37:50 +0000 +++ modules/tracker.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ The tracker module is a handy module for displaying the most recent posts. By following the recent posts link in the user block, a user may quickly review all recent postings.

    '); - case 'admin/system/modules#description': + case 'admin/modules#description': return t('Enables tracking of recent posts for users.'); } } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function tracker_link($type) { - if ($type == 'system') { - menu('tracker', t('recent posts'), user_access('access content') ? 'tracker_page' : MENU_DENIED, 1); - } +function tracker_menu() { + $items = array(); + $items[] = array('path' => 'tracker', 'title' => t('recent posts'), + 'callback' => 'tracker_page', + 'access' => user_access('access content'), + 'weight' => 1); + return $items; } /** @@ -54,7 +57,7 @@ function tracker_page($uid = 0) { if ($new = comment_num_new($node->nid)) { $comments .= '
    '; - $comments .= l(t('%num new', array('%num' => $new)), "node/view/$node->nid", NULL, NULL, 'new'); + $comments .= l(t('%num new', array('%num' => $new)), "node/$node->nid", NULL, NULL, 'new'); } } else { @@ -63,7 +66,7 @@ function tracker_page($uid = 0) { $rows[] = array( ucfirst(node_invoke($node->type, 'node_name')), - l($node->title, "node/view/$node->nid") .' '. (node_is_new($node->nid, $node->changed) ? theme('mark') : ''), + l($node->title, "node/$node->nid") .' '. (node_is_new($node->nid, $node->changed) ? theme('mark') : ''), format_name($node), array('class' => 'replies', 'data' => $comments), format_interval(time() - $node->last_post) .' '. t('ago') === modified file 'modules/tracker/tracker.module' --- modules/tracker/tracker.module 2004-05-24 18:37:50 +0000 +++ modules/tracker/tracker.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ The tracker module is a handy module for displaying the most recent posts. By following the recent posts link in the user block, a user may quickly review all recent postings.

    '); - case 'admin/system/modules#description': + case 'admin/modules#description': return t('Enables tracking of recent posts for users.'); } } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function tracker_link($type) { - if ($type == 'system') { - menu('tracker', t('recent posts'), user_access('access content') ? 'tracker_page' : MENU_DENIED, 1); - } +function tracker_menu() { + $items = array(); + $items[] = array('path' => 'tracker', 'title' => t('recent posts'), + 'callback' => 'tracker_page', + 'access' => user_access('access content'), + 'weight' => 1); + return $items; } /** @@ -54,7 +57,7 @@ function tracker_page($uid = 0) { if ($new = comment_num_new($node->nid)) { $comments .= '
    '; - $comments .= l(t('%num new', array('%num' => $new)), "node/view/$node->nid", NULL, NULL, 'new'); + $comments .= l(t('%num new', array('%num' => $new)), "node/$node->nid", NULL, NULL, 'new'); } } else { @@ -63,7 +66,7 @@ function tracker_page($uid = 0) { $rows[] = array( ucfirst(node_invoke($node->type, 'node_name')), - l($node->title, "node/view/$node->nid") .' '. (node_is_new($node->nid, $node->changed) ? theme('mark') : ''), + l($node->title, "node/$node->nid") .' '. (node_is_new($node->nid, $node->changed) ? theme('mark') : ''), format_name($node), array('class' => 'replies', 'data' => $comments), format_interval(time() - $node->last_post) .' '. t('ago') === modified file 'modules/user.module' --- modules/user.module 2004-06-14 17:32:51 +0000 +++ modules/user.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ $account->name, 'link' => (strstr(request_uri(), 'admin') ? url("admin/user/edit/$account->uid") : url("user/view/$account->uid")), 'user' => $account->name); + $find[] = array('title' => $account->name, 'link' => url("user/$account->uid/view"), 'user' => $account->name); } return array(t('Matching users'), $find); } @@ -484,7 +484,7 @@ function user_block($op = 'list', $delta } return $block; case 1: - if ($menu = menu_tree()) { + if ($menu = theme('menu_tree')) { $block['subject'] = $user->uid ? $user->name : t('Navigation'); $block['content'] = ''; } @@ -573,11 +573,6 @@ function theme_user_profile($account, $f foreach ($fields as $category => $value) { $output .= "

    $category

    $value"; } - - if (user_access('administer users')) { - $output .= form_item(t('Administration'), l(t('edit account'), "admin/user/edit/$account->uid")); - } - $output .= "
    \n"; return $output; @@ -588,37 +583,82 @@ function theme_user_list($items, $title } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function user_link($type) { +function user_menu() { global $user; - if ($type == 'system') { - if ($user->uid) { - menu('user', t('my account'), 'user_page', 0); - menu('user/edit', t('edit account'), 'user_page', 0); - menu('logout', t('log out'), 'user_logout', 10); - } - else { - menu('user', t('user'), 'user_page', 0, MENU_HIDE); - menu('user/edit', t('edit account'), MENU_DENIED); - menu('logout', t('log out'), MENU_DENIED); - } - - $access = user_access('administer users'); - menu('admin/user', t('accounts'), $access ? 'user_admin' : MENU_DENIED, 2); - menu('admin/user/create', t('new user'), $access ? 'user_admin' : MENU_DENIED, 1); - menu('admin/user/access', t('access rules'), $access ? 'user_admin' : MENU_DENIED, 3); - menu('admin/user/access/mail', t('e-mail rules'), $access ? 'user_admin' : MENU_DENIED); - menu('admin/user/access/user', t('name rules'), $access ? 'user_admin' : MENU_DENIED); - menu('admin/user/role', t('roles'), $access ? 'user_admin' : MENU_DENIED, 4); - menu('admin/user/permission', t('permissions'), $access ? 'user_admin' : MENU_DENIED, 5); - menu('admin/user/help', t('help'), $access ? 'user_help_page' : MENU_DENIED, 9); - menu('admin/user/edit', t('edit user account'), $access ? 'user_admin' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED); - if (module_exist('search')) { - menu('admin/user/search', t('search'), $access ? 'user_admin' : MENU_DENIED, 8); - } + $items = array(); + + $access = user_access('administer users'); + + if (arg(0) == 'user' && is_numeric(arg(1))) { + $items[] = array('path' => 'user/'. arg(1), 'title' => t('user'), + 'callback' => 'user_page', 'access' => TRUE); + // Add the edit menu: + if ($access) $function = 'user_admin_edit'; + else $function = 'user_edit'; + $items[] = array('path' => 'user/'. arg(1) .'/edit', 'title' => t('edit'), + 'callback' => $function, 'access' => $access || $user->uid == arg(1), + 'type' => MENU_LOCAL_TASK); + } + + if ($user->uid) { + $items[] = array('path' => "user/$user->uid", 'title' => t('my account'), + 'callback' => 'user_page', 'access' => TRUE); + $items[] = array('path' => 'logout', 'title' => t('log out'), + 'access' => TRUE, + 'callback' => 'user_logout', + 'weight' => 10); } + else { + $items[] = array('path' => 'logout', 'title' => t('log out'), + 'callback' => 'user_logout', 'access' => FALSE); + } + + $items[] = array('path' => 'user', 'title' => t('user'), + 'callback' => 'user_page', 'access' => TRUE, + 'type' => MENU_CALLBACK); + $items[] = array('path' => 'user/login', 'title' => t('log in'), + 'type' => MENU_CALLBACK); + + $items[] = array('path' => 'admin/user', 'title' => t('users'), + 'callback' => 'user_admin', 'access' => $access); + + // Tabs: + $items[] = array('path' => 'admin/user/create', 'title' => t('add user'), + 'callback' => 'user_admin', 'access' => $access, + 'type' => MENU_LOCAL_TASK); + $items[] = array('path' => 'admin/user/configure', 'title' => t('configure'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_TASK); + if (module_exist('search')) { + $items[] = array('path' => 'admin/user/search', 'title' => t('search'), + 'callback' => 'user_admin', 'access' => $access, + 'type' => MENU_LOCAL_TASK); + } + + // Sub-tabs: + $items[] = array('path' => 'admin/user/configure/settings', 'title' => t('settings'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/access', 'title' => t('access rules'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/access/mail', 'title' => t('e-mail rules'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/access/user', 'title' => t('name rules'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/role', 'title' => t('roles'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/permission', 'title' => t('permissions'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + + return $items; } /** @@ -720,7 +760,7 @@ function user_login($edit = array(), $ms if (module_invoke($module, 'auth', $name, $pass, $server)) { if (variable_get('user_register', 1) == 1 && !user_load(array('name' => "$name@$server"))) { // Register this new user. $user = user_save('', array('name' => "$name@$server", 'pass' => user_password(), 'init' => "$name@$server", 'status' => 1, "authname_$module" => "$name@$server", 'rid' => array(_user_authenticated_id()))); - watchdog('user', "new user: $name@$server ($module ID)", l(t('edit user'), "admin/user/edit/$user->uid")); + watchdog('user', "new user: $name@$server ($module ID)", l(t('edit user'), "user/$user->uid/edit")); break; } } @@ -1133,7 +1173,7 @@ function user_page() { $op = $_POST['op']; if (empty($op)) { - $op = arg(1); + $op = arg(2); } switch ($op) { @@ -1160,17 +1200,14 @@ function user_page() { case 'edit': $output = user_edit($edit); $GLOBALS['theme'] = init_theme(); - print theme('page', $output, t('Edit account')); - break; - case 'view': - user_view(arg(2)); + print theme('page', $output); break; case t('Logout'): case 'logout': print user_logout(); break; default: - print user_view(); + print user_view(arg(1)); } } @@ -1202,10 +1239,7 @@ function _user_mail_text($messageid, $va } } -/** - * Implementation of hook_settings(). - */ -function user_settings() { +function user_configure_settings() { // User registration settings. $group = form_radios(t('Public registrations'), 'user_register', variable_get('user_register', 1), array(t('Only site administrators can create new user accounts.'), t('Visitors can create accounts and no administrator approval is required.'), t('Visitors can create accounts but administrator approval is required.'))); $group .= form_textarea(t('User registration guidelines'), 'user_registration_help', variable_get('user_registration_help', ''), 70, 4, t('This text is displayed at the top of the user registration form. It\'s useful for helping or instructing your users.')); @@ -1244,6 +1278,7 @@ function user_settings() { } function user_admin_create($edit = array()) { + if ($edit['name'] || $edit['mail']) { if ($error = user_validate_name($edit['name'])) { form_set_error('name', $error); @@ -1459,15 +1494,16 @@ function user_admin_role($edit = array() return $output; } -function user_admin_edit($edit = array()) { +function user_admin_edit() { $op = $_POST['op']; - $id = arg(3); + $edit = $_POST['edit']; + $id = arg(1); if ($account = user_load(array('uid' => $id))) { - if ($op == t('Save account')) { // TODO: This display/edit/validate should be moved to a new profile // module implementing hook_user(). + if ($error = user_validate_name($edit['name'])) { form_set_error('name', $error); } @@ -1523,7 +1559,8 @@ function user_admin_edit($edit = array() db_query('DELETE FROM {authmap} WHERE uid = %d', $account->uid); drupal_set_message(t('the account has been deleted.')); module_invoke_all('user', 'delete', $edit, $account); - return user_admin_account(); + print theme('page', user_admin_account()); + return; } else { drupal_set_message(t('Failed to delete account: the account has to be blocked first.'), 'error'); @@ -1559,12 +1596,12 @@ function user_admin_edit($edit = array() $output .= form_submit(t('Delete account')); $output = form($output, 'post', 0, array('enctype' => 'multipart/form-data')); + + print theme('page', $output, $account->name); } else { - $output = t('No such user'); + print theme('page', t('No such user')); } - - return $output; } function user_admin_account() { @@ -1589,7 +1626,7 @@ function user_admin_account() { $roles[] = $role->name; } - $rows[] = array($account->uid, format_name($account), $status[$account->status], implode(',
    ', $roles), format_date($account->changed, 'small'), l(t('edit account'), "admin/user/edit/$account->uid")); + $rows[] = array($account->uid, format_name($account), $status[$account->status], implode(',
    ', $roles), format_date($account->changed, 'small'), l(t('edit account'), "user/$account->uid/edit")); } $pager = theme('pager', NULL, 50, 0, tablesort_pager()); @@ -1599,43 +1636,55 @@ function user_admin_account() { return theme('table', $header, $rows); } -function user_admin() { +function user_configure() { $op = $_POST['op']; $edit = $_POST['edit']; if (empty($op)) { - $op = arg(2); + $op = arg(3); } switch ($op) { - case 'search': - $output = search_type('user', url('admin/user/search'), $_POST['keys']); - break; case t('Add rule'): case t('Check'): case 'access': - $output .= user_admin_access($edit); + $output = user_admin_access($edit); break; case t('Save permissions'): drupal_set_message(t('user permissions saved.')); case 'permission': - $output .= user_admin_perm($edit); - break; - case t('Create account'): - case 'create': - $output = user_admin_create($edit); + $output = user_admin_perm($edit); break; case t('Add role'): case t('Delete role'): case t('Save role'): drupal_set_message(t('your role changes were saved.')); case 'role': - $output .= user_admin_role($edit); + $output = user_admin_role($edit); break; - case t('Delete account'): - case t('Save account'): - case 'edit': - $output = user_admin_edit($edit); + default: + if ($_POST) system_settings_save(); + $output = system_settings_form(user_configure_settings()); + } + + print theme('page', $output); +} + +function user_admin() { + $op = $_POST['op']; + $edit = $_POST['edit']; + + if (empty($op)) { + $op = arg(2); + } + + switch ($op) { + case 'search': + $output = search_type('user', url('admin/user/search'), $_POST['keys']); + break; + case t('Create account'): + case 'create': + $output = user_admin_create($edit); break; default: $output = user_admin_account(); @@ -1671,9 +1720,9 @@ function user_help($section) { ', array('%permission' => url('admin/user/permission'))); case 'admin/user/search': return t('Enter a simple pattern ("*" may be user as a wildcard match) to search for a username. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda".'); - case 'admin/system/modules#description': + case 'admin/modules#description': return t('Enables the user registration and login system.'); - case 'admin/system/modules/user': + case 'admin/settings/user': return t('In order to use the full power of Drupal a visitor must sign up for an account. This page lets you setup how a user signs up, logs out, the guidelines from the system about user subscriptions, and the e-mails the system will send to the user.'); case 'user/help#user': $site = variable_get('site_name', 'this website'); @@ -1706,8 +1755,7 @@ function user_help($section) {

    One key element of DA is the 'authmap' table, which maps a user's authname (e.g. joe@remote.delphiforums.com) to his local UID (i.e. user identification number). This map is checked whenever a user successfully logs into an external authentication source. Once Drupal knows that the current user is definately joe@remote.delphiforums.com (because Delphi says so), he looks up Joe's UID and logs Joe into that account.

    To disable distributed authentication, simply disable or remove all DA modules. For a virgin install, that means removing/disabling the jabber module and the drupal module.

    Drupal is setup so that it is very easy to add support for any external authentication source. You currently have the following authentication modules installed ...

    - %module-list -", array('%user-role' => url('admin/user/role'), '%user-permission' => url('admin/user/permission'), '%jabber' => 'http://www.jabber.org', '%delphiforums' => 'http://www.delphiforums.com', '%drupal' => 'http://www.drupal.org', '%da-auth' => url('user/help', NULL, 'da'), '%php-sess' => 'http://www.php.net/manual/en/ref.session.php', '%user-prefs' => url('user/edit'), '%admin-user' => url('admin/user'), '%xml' => 'http://www.xmlrpc.org', '%http-post' => 'http://www.w3.org/Protocols/', '%soap' => 'http://www.soapware.org', '%dis-module' => url('admin/system/modules'), '%blogger' => 'http://www.blogger.com', '%blogger-api' => 'http://plant.blogger.com/API', '%drupal-lists' => 'http://drupal.org/mailing-lists', '%drupal-org' => 'http://www.drupal.org', '%registration' => url('user/register'), '%user-acct' => url('user'), '%user-admin' => url('admin/user'))); + %module-list"); foreach (module_list() as $module) { if (module_hook($module, 'auth')) { === modified file 'modules/user/user.module' --- modules/user/user.module 2004-06-14 17:32:51 +0000 +++ modules/user/user.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ $account->name, 'link' => (strstr(request_uri(), 'admin') ? url("admin/user/edit/$account->uid") : url("user/view/$account->uid")), 'user' => $account->name); + $find[] = array('title' => $account->name, 'link' => url("user/$account->uid/view"), 'user' => $account->name); } return array(t('Matching users'), $find); } @@ -484,7 +484,7 @@ function user_block($op = 'list', $delta } return $block; case 1: - if ($menu = menu_tree()) { + if ($menu = theme('menu_tree')) { $block['subject'] = $user->uid ? $user->name : t('Navigation'); $block['content'] = ''; } @@ -573,11 +573,6 @@ function theme_user_profile($account, $f foreach ($fields as $category => $value) { $output .= "

    $category

    $value"; } - - if (user_access('administer users')) { - $output .= form_item(t('Administration'), l(t('edit account'), "admin/user/edit/$account->uid")); - } - $output .= "\n"; return $output; @@ -588,37 +583,82 @@ function theme_user_list($items, $title } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function user_link($type) { +function user_menu() { global $user; - if ($type == 'system') { - if ($user->uid) { - menu('user', t('my account'), 'user_page', 0); - menu('user/edit', t('edit account'), 'user_page', 0); - menu('logout', t('log out'), 'user_logout', 10); - } - else { - menu('user', t('user'), 'user_page', 0, MENU_HIDE); - menu('user/edit', t('edit account'), MENU_DENIED); - menu('logout', t('log out'), MENU_DENIED); - } - - $access = user_access('administer users'); - menu('admin/user', t('accounts'), $access ? 'user_admin' : MENU_DENIED, 2); - menu('admin/user/create', t('new user'), $access ? 'user_admin' : MENU_DENIED, 1); - menu('admin/user/access', t('access rules'), $access ? 'user_admin' : MENU_DENIED, 3); - menu('admin/user/access/mail', t('e-mail rules'), $access ? 'user_admin' : MENU_DENIED); - menu('admin/user/access/user', t('name rules'), $access ? 'user_admin' : MENU_DENIED); - menu('admin/user/role', t('roles'), $access ? 'user_admin' : MENU_DENIED, 4); - menu('admin/user/permission', t('permissions'), $access ? 'user_admin' : MENU_DENIED, 5); - menu('admin/user/help', t('help'), $access ? 'user_help_page' : MENU_DENIED, 9); - menu('admin/user/edit', t('edit user account'), $access ? 'user_admin' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED); - if (module_exist('search')) { - menu('admin/user/search', t('search'), $access ? 'user_admin' : MENU_DENIED, 8); - } + $items = array(); + + $access = user_access('administer users'); + + if (arg(0) == 'user' && is_numeric(arg(1))) { + $items[] = array('path' => 'user/'. arg(1), 'title' => t('user'), + 'callback' => 'user_page', 'access' => TRUE); + // Add the edit menu: + if ($access) $function = 'user_admin_edit'; + else $function = 'user_edit'; + $items[] = array('path' => 'user/'. arg(1) .'/edit', 'title' => t('edit'), + 'callback' => $function, 'access' => $access || $user->uid == arg(1), + 'type' => MENU_LOCAL_TASK); + } + + if ($user->uid) { + $items[] = array('path' => "user/$user->uid", 'title' => t('my account'), + 'callback' => 'user_page', 'access' => TRUE); + $items[] = array('path' => 'logout', 'title' => t('log out'), + 'access' => TRUE, + 'callback' => 'user_logout', + 'weight' => 10); } + else { + $items[] = array('path' => 'logout', 'title' => t('log out'), + 'callback' => 'user_logout', 'access' => FALSE); + } + + $items[] = array('path' => 'user', 'title' => t('user'), + 'callback' => 'user_page', 'access' => TRUE, + 'type' => MENU_CALLBACK); + $items[] = array('path' => 'user/login', 'title' => t('log in'), + 'type' => MENU_CALLBACK); + + $items[] = array('path' => 'admin/user', 'title' => t('users'), + 'callback' => 'user_admin', 'access' => $access); + + // Tabs: + $items[] = array('path' => 'admin/user/create', 'title' => t('add user'), + 'callback' => 'user_admin', 'access' => $access, + 'type' => MENU_LOCAL_TASK); + $items[] = array('path' => 'admin/user/configure', 'title' => t('configure'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_TASK); + if (module_exist('search')) { + $items[] = array('path' => 'admin/user/search', 'title' => t('search'), + 'callback' => 'user_admin', 'access' => $access, + 'type' => MENU_LOCAL_TASK); + } + + // Sub-tabs: + $items[] = array('path' => 'admin/user/configure/settings', 'title' => t('settings'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/access', 'title' => t('access rules'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/access/mail', 'title' => t('e-mail rules'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/access/user', 'title' => t('name rules'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/role', 'title' => t('roles'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + $items[] = array('path' => 'admin/user/configure/permission', 'title' => t('permissions'), + 'callback' => 'user_configure', 'access' => $access, + 'type' => MENU_LOCAL_SUBTASK); + + return $items; } /** @@ -720,7 +760,7 @@ function user_login($edit = array(), $ms if (module_invoke($module, 'auth', $name, $pass, $server)) { if (variable_get('user_register', 1) == 1 && !user_load(array('name' => "$name@$server"))) { // Register this new user. $user = user_save('', array('name' => "$name@$server", 'pass' => user_password(), 'init' => "$name@$server", 'status' => 1, "authname_$module" => "$name@$server", 'rid' => array(_user_authenticated_id()))); - watchdog('user', "new user: $name@$server ($module ID)", l(t('edit user'), "admin/user/edit/$user->uid")); + watchdog('user', "new user: $name@$server ($module ID)", l(t('edit user'), "user/$user->uid/edit")); break; } } @@ -1133,7 +1173,7 @@ function user_page() { $op = $_POST['op']; if (empty($op)) { - $op = arg(1); + $op = arg(2); } switch ($op) { @@ -1160,17 +1200,14 @@ function user_page() { case 'edit': $output = user_edit($edit); $GLOBALS['theme'] = init_theme(); - print theme('page', $output, t('Edit account')); - break; - case 'view': - user_view(arg(2)); + print theme('page', $output); break; case t('Logout'): case 'logout': print user_logout(); break; default: - print user_view(); + print user_view(arg(1)); } } @@ -1202,10 +1239,7 @@ function _user_mail_text($messageid, $va } } -/** - * Implementation of hook_settings(). - */ -function user_settings() { +function user_configure_settings() { // User registration settings. $group = form_radios(t('Public registrations'), 'user_register', variable_get('user_register', 1), array(t('Only site administrators can create new user accounts.'), t('Visitors can create accounts and no administrator approval is required.'), t('Visitors can create accounts but administrator approval is required.'))); $group .= form_textarea(t('User registration guidelines'), 'user_registration_help', variable_get('user_registration_help', ''), 70, 4, t('This text is displayed at the top of the user registration form. It\'s useful for helping or instructing your users.')); @@ -1244,6 +1278,7 @@ function user_settings() { } function user_admin_create($edit = array()) { + if ($edit['name'] || $edit['mail']) { if ($error = user_validate_name($edit['name'])) { form_set_error('name', $error); @@ -1459,15 +1494,16 @@ function user_admin_role($edit = array() return $output; } -function user_admin_edit($edit = array()) { +function user_admin_edit() { $op = $_POST['op']; - $id = arg(3); + $edit = $_POST['edit']; + $id = arg(1); if ($account = user_load(array('uid' => $id))) { - if ($op == t('Save account')) { // TODO: This display/edit/validate should be moved to a new profile // module implementing hook_user(). + if ($error = user_validate_name($edit['name'])) { form_set_error('name', $error); } @@ -1523,7 +1559,8 @@ function user_admin_edit($edit = array() db_query('DELETE FROM {authmap} WHERE uid = %d', $account->uid); drupal_set_message(t('the account has been deleted.')); module_invoke_all('user', 'delete', $edit, $account); - return user_admin_account(); + print theme('page', user_admin_account()); + return; } else { drupal_set_message(t('Failed to delete account: the account has to be blocked first.'), 'error'); @@ -1559,12 +1596,12 @@ function user_admin_edit($edit = array() $output .= form_submit(t('Delete account')); $output = form($output, 'post', 0, array('enctype' => 'multipart/form-data')); + + print theme('page', $output, $account->name); } else { - $output = t('No such user'); + print theme('page', t('No such user')); } - - return $output; } function user_admin_account() { @@ -1589,7 +1626,7 @@ function user_admin_account() { $roles[] = $role->name; } - $rows[] = array($account->uid, format_name($account), $status[$account->status], implode(',
    ', $roles), format_date($account->changed, 'small'), l(t('edit account'), "admin/user/edit/$account->uid")); + $rows[] = array($account->uid, format_name($account), $status[$account->status], implode(',
    ', $roles), format_date($account->changed, 'small'), l(t('edit account'), "user/$account->uid/edit")); } $pager = theme('pager', NULL, 50, 0, tablesort_pager()); @@ -1599,43 +1636,55 @@ function user_admin_account() { return theme('table', $header, $rows); } -function user_admin() { +function user_configure() { $op = $_POST['op']; $edit = $_POST['edit']; if (empty($op)) { - $op = arg(2); + $op = arg(3); } switch ($op) { - case 'search': - $output = search_type('user', url('admin/user/search'), $_POST['keys']); - break; case t('Add rule'): case t('Check'): case 'access': - $output .= user_admin_access($edit); + $output = user_admin_access($edit); break; case t('Save permissions'): drupal_set_message(t('user permissions saved.')); case 'permission': - $output .= user_admin_perm($edit); - break; - case t('Create account'): - case 'create': - $output = user_admin_create($edit); + $output = user_admin_perm($edit); break; case t('Add role'): case t('Delete role'): case t('Save role'): drupal_set_message(t('your role changes were saved.')); case 'role': - $output .= user_admin_role($edit); + $output = user_admin_role($edit); break; - case t('Delete account'): - case t('Save account'): - case 'edit': - $output = user_admin_edit($edit); + default: + if ($_POST) system_settings_save(); + $output = system_settings_form(user_configure_settings()); + } + + print theme('page', $output); +} + +function user_admin() { + $op = $_POST['op']; + $edit = $_POST['edit']; + + if (empty($op)) { + $op = arg(2); + } + + switch ($op) { + case 'search': + $output = search_type('user', url('admin/user/search'), $_POST['keys']); + break; + case t('Create account'): + case 'create': + $output = user_admin_create($edit); break; default: $output = user_admin_account(); @@ -1671,9 +1720,9 @@ function user_help($section) { ', array('%permission' => url('admin/user/permission'))); case 'admin/user/search': return t('Enter a simple pattern ("*" may be user as a wildcard match) to search for a username. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda".'); - case 'admin/system/modules#description': + case 'admin/modules#description': return t('Enables the user registration and login system.'); - case 'admin/system/modules/user': + case 'admin/settings/user': return t('In order to use the full power of Drupal a visitor must sign up for an account. This page lets you setup how a user signs up, logs out, the guidelines from the system about user subscriptions, and the e-mails the system will send to the user.'); case 'user/help#user': $site = variable_get('site_name', 'this website'); @@ -1706,8 +1755,7 @@ function user_help($section) {

    One key element of DA is the 'authmap' table, which maps a user's authname (e.g. joe@remote.delphiforums.com) to his local UID (i.e. user identification number). This map is checked whenever a user successfully logs into an external authentication source. Once Drupal knows that the current user is definately joe@remote.delphiforums.com (because Delphi says so), he looks up Joe's UID and logs Joe into that account.

    To disable distributed authentication, simply disable or remove all DA modules. For a virgin install, that means removing/disabling the jabber module and the drupal module.

    Drupal is setup so that it is very easy to add support for any external authentication source. You currently have the following authentication modules installed ...

    - %module-list -", array('%user-role' => url('admin/user/role'), '%user-permission' => url('admin/user/permission'), '%jabber' => 'http://www.jabber.org', '%delphiforums' => 'http://www.delphiforums.com', '%drupal' => 'http://www.drupal.org', '%da-auth' => url('user/help', NULL, 'da'), '%php-sess' => 'http://www.php.net/manual/en/ref.session.php', '%user-prefs' => url('user/edit'), '%admin-user' => url('admin/user'), '%xml' => 'http://www.xmlrpc.org', '%http-post' => 'http://www.w3.org/Protocols/', '%soap' => 'http://www.soapware.org', '%dis-module' => url('admin/system/modules'), '%blogger' => 'http://www.blogger.com', '%blogger-api' => 'http://plant.blogger.com/API', '%drupal-lists' => 'http://drupal.org/mailing-lists', '%drupal-org' => 'http://www.drupal.org', '%registration' => url('user/register'), '%user-acct' => url('user'), '%user-admin' => url('admin/user'))); + %module-list"); foreach (module_list() as $module) { if (module_hook($module, 'auth')) { === modified file 'modules/watchdog.module' --- modules/watchdog.module 2004-06-01 11:01:26 +0000 +++ modules/watchdog.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ Watchdog module monitors your web site, capturing system events in a log to be reviewed by an authorized individual at a later time. The watchdog log is simply a list of recorded events containing usage data, performance data, errors, warnings and operational information. It is vital to check the watchdog report on a regular basis as it is often the only way to tell what is going on.

    -

    To ease administration, the watchdog will automatically discard old log entries, as configured. Needs "cron.php" to discard the entries.

    ', array('%watchdog' => url('admin/logs'), '%log-entry' => url('admin/system/modules/watchdog'))); +

    To ease administration, the watchdog will automatically discard old log entries, as configured. Needs "cron.php" to discard the entries.

    ', array('%watchdog' => url('admin/logs'), '%log-entry' => url('admin/settings/watchdog'))); case 'admin/logs': return t('The watchdog module monitors your web site, captures system events in a log and records them to be reviewed by an authorized individual at a later time. The watchdog log is simply a list of events recorded during operation and contains usage data, performance data, errors, warnings and operational information. It is vital to check the watchdog report on a regular basis as it is often the only way to tell what is going on.'); case 'admin/logs/user': @@ -26,9 +26,9 @@ function watchdog_help($section = 'admin return t('Watchdog events about PHP and database errors.'); case 'admin/logs/warning': return t('Watchdog warning events. These events don\'t stop Drupal from running, but are things you should know.'); - case 'admin/system/modules#description': + case 'admin/modules#description': return t('Logs and records system events.'); - case 'admin/system/modules/watchdog': + case 'admin/settings/watchdog': return t('Watchdog logs your system events. To see these events go to the logs. Since these logs can grow out of control if kept around forever, below set how long an item should be kept in the log. Note that to discard entries as set below you must run "cron.php" regularly.', array('%watchdog' => url('admin/logs'))); } } @@ -41,29 +41,24 @@ function watchdog_perm() { } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function watchdog_link($type) { - if ($type == 'system') { - menu('admin/logs', t('logs'), user_access('administer watchdog') ? 'watchdog_overview' : MENU_DENIED, 7); - menu('admin/logs/view', t('view details'), user_access('administer watchdog') ? 'watchdog_view' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED); - - if (arg(1) == 'logs') { - foreach (_watchdog_get_message_types() as $type) { - menu("admin/logs/$type", t($type), MENU_FALLTHROUGH, 0, MENU_SHOW, MENU_LOCKED); - } +function watchdog_menu() { + $items = array(); + $items[] = array('path' => 'admin/logs', 'title' => t('logs'), + 'callback' => 'watchdog_overview', + 'access' => user_access('administer watchdog')); + $items[] = array('path' => 'admin/logs/view', 'title' => t('view details'), + 'callback' => 'watchdog_view', + 'access' => user_access('administer watchdog'), + 'type' => MENU_CALLBACK); + if (arg(1) == 'logs') { + foreach (_watchdog_get_message_types() as $type) { + $items[] = array('path' => 'admin/logs/'. $type, 'title' => t($type), + 'type' => MENU_DYNAMIC_ITEM); } } -} - -/** - * Implementation of hook_settings(). - */ -function watchdog_settings() { - $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval'); - $period[1000000000] = t('Never'); - $output .= form_select(t('Discard entries older than'), 'watchdog_clear', variable_get('watchdog_clear', 604800), $period, t('The time watchdog entries should be kept. Older entries will be automatically discarded. Requires crontab.')); - return $output; + return $items; } /** === modified file 'modules/watchdog/watchdog.module' --- modules/watchdog/watchdog.module 2004-06-01 11:01:26 +0000 +++ modules/watchdog/watchdog.module 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ Watchdog module monitors your web site, capturing system events in a log to be reviewed by an authorized individual at a later time. The watchdog log is simply a list of recorded events containing usage data, performance data, errors, warnings and operational information. It is vital to check the watchdog report on a regular basis as it is often the only way to tell what is going on.

    -

    To ease administration, the watchdog will automatically discard old log entries, as configured. Needs "cron.php" to discard the entries.

    ', array('%watchdog' => url('admin/logs'), '%log-entry' => url('admin/system/modules/watchdog'))); +

    To ease administration, the watchdog will automatically discard old log entries, as configured. Needs "cron.php" to discard the entries.

    ', array('%watchdog' => url('admin/logs'), '%log-entry' => url('admin/settings/watchdog'))); case 'admin/logs': return t('The watchdog module monitors your web site, captures system events in a log and records them to be reviewed by an authorized individual at a later time. The watchdog log is simply a list of events recorded during operation and contains usage data, performance data, errors, warnings and operational information. It is vital to check the watchdog report on a regular basis as it is often the only way to tell what is going on.'); case 'admin/logs/user': @@ -26,9 +26,9 @@ function watchdog_help($section = 'admin return t('Watchdog events about PHP and database errors.'); case 'admin/logs/warning': return t('Watchdog warning events. These events don\'t stop Drupal from running, but are things you should know.'); - case 'admin/system/modules#description': + case 'admin/modules#description': return t('Logs and records system events.'); - case 'admin/system/modules/watchdog': + case 'admin/settings/watchdog': return t('Watchdog logs your system events. To see these events go to the logs. Since these logs can grow out of control if kept around forever, below set how long an item should be kept in the log. Note that to discard entries as set below you must run "cron.php" regularly.', array('%watchdog' => url('admin/logs'))); } } @@ -41,29 +41,24 @@ function watchdog_perm() { } /** - * Implementation of hook_link(). + * Implementation of hook_menu(). */ -function watchdog_link($type) { - if ($type == 'system') { - menu('admin/logs', t('logs'), user_access('administer watchdog') ? 'watchdog_overview' : MENU_DENIED, 7); - menu('admin/logs/view', t('view details'), user_access('administer watchdog') ? 'watchdog_view' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED); - - if (arg(1) == 'logs') { - foreach (_watchdog_get_message_types() as $type) { - menu("admin/logs/$type", t($type), MENU_FALLTHROUGH, 0, MENU_SHOW, MENU_LOCKED); - } +function watchdog_menu() { + $items = array(); + $items[] = array('path' => 'admin/logs', 'title' => t('logs'), + 'callback' => 'watchdog_overview', + 'access' => user_access('administer watchdog')); + $items[] = array('path' => 'admin/logs/view', 'title' => t('view details'), + 'callback' => 'watchdog_view', + 'access' => user_access('administer watchdog'), + 'type' => MENU_CALLBACK); + if (arg(1) == 'logs') { + foreach (_watchdog_get_message_types() as $type) { + $items[] = array('path' => 'admin/logs/'. $type, 'title' => t($type), + 'type' => MENU_DYNAMIC_ITEM); } } -} - -/** - * Implementation of hook_settings(). - */ -function watchdog_settings() { - $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval'); - $period[1000000000] = t('Never'); - $output .= form_select(t('Discard entries older than'), 'watchdog_clear', variable_get('watchdog_clear', 604800), $period, t('The time watchdog entries should be kept. Older entries will be automatically discarded. Requires crontab.')); - return $output; + return $items; } /** === modified file 'themes/chameleon/chameleon.theme' --- themes/chameleon/chameleon.theme 2004-05-20 10:23:52 +0000 +++ themes/chameleon/chameleon.theme 2004-06-18 15:04:33 +0000 @@ -1,12 +1,12 @@ $title"; } + if ($tabs = theme('menu_local_tasks')) { + $output .= $tabs; + } + if ($help = menu_get_active_help()) { $output .= "$help
    "; } @@ -106,7 +111,7 @@ function chameleon_node($node, $main = 0 $output = "
    \n"; if (!$page) { - $output .= "

    ". ($main ? l($node->title, "node/view/$node->nid") : $node->title) ."

    \n"; + $output .= "

    ". ($main ? l($node->title, "node/$node->nid") : $node->title) ."

    \n"; } $output .= "
    \n"; === modified file 'themes/chameleon/pure/chameleon.css' --- themes/chameleon/pure/chameleon.css 2004-03-30 22:14:04 +0000 +++ themes/chameleon/pure/chameleon.css 2004-06-18 15:04:33 +0000 @@ -1,4 +1,4 @@ -/* $Id: chameleon.css,v 1.3 2004/03/30 22:14:04 dries Exp $ */ +/* $Id: chameleon.css,v 1.4 2004/06/18 15:04:36 dries Exp $ */ /* ** HTML elements @@ -87,4 +87,4 @@ ul { color: gray; font-style: italic; font-size: 0.9em; -} \ No newline at end of file +} === modified file 'themes/example/example.theme' --- themes/example/example.theme 2003-11-09 23:27:15 +0000 +++ themes/example/example.theme 2004-06-18 15:04:33 +0000 @@ -1,12 +1,12 @@ {breadcrumb}

    {title}

    + +
    {tabs}
    +
    +
    {help}
    @@ -55,7 +59,7 @@ -
    +
    {picture} === modified file 'themes/xtemplate/xtemplate.theme' --- themes/xtemplate/xtemplate.theme 2004-05-20 10:23:52 +0000 +++ themes/xtemplate/xtemplate.theme 2004-06-18 15:04:33 +0000 @@ -1,5 +1,5 @@ "), 70, 4, t('The HTML code for displaying the logo.')); - $group .= form_textarea(t('Primary links'), 'xtemplate_primary_links', variable_get('xtemplate_primary_links', l('edit primary links', 'admin/system/themes/xtemplate')), 70, 8, t('The HTML code for the primary links.')); - $group .= form_textarea(t('Secondary links'), 'xtemplate_secondary_links', variable_get('xtemplate_secondary_links', l('edit secondary links', 'admin/system/themes/xtemplate')), 70, 8, t('The HTML code for the secondary links.')); + $group .= form_textarea(t('Primary links'), 'xtemplate_primary_links', variable_get('xtemplate_primary_links', l('edit primary links', 'admin/themes/xtemplate')), 70, 8, t('The HTML code for the primary links.')); + $group .= form_textarea(t('Secondary links'), 'xtemplate_secondary_links', variable_get('xtemplate_secondary_links', l('edit secondary links', 'admin/themes/xtemplate')), 70, 8, t('The HTML code for the secondary links.')); $group .= form_textarea(t('Message on front page'), 'xtemplate_mission', variable_get('xtemplate_mission', 'edit mission'), 70, 6, t('This text will be displayed on the front page. It can be used to display a mission statement, announcement or site description..')); $group .= form_radios(t('Search box'), 'xtemplate_search_box', variable_get('xtemplate_search_box', 0), array(t('Disabled'), t('Enabled')), t('Show a search box in the upper right corner.')); $output .= form_group(t('Header settings'), $group); @@ -44,7 +44,7 @@ function xtemplate_help($section) { $output = ''; switch ($section) { - case 'admin/system/themes#description': + case 'admin/themes#description': $output = t('A template driven theme'); break; } @@ -59,7 +59,7 @@ function xtemplate_node($node, $main = 0 "submitted" => t("Submitted by %a on %b.", array("%a" => format_name($node), "%b" => format_date($node->created))), - "link" => url("node/view/$node->nid"), + "link" => url("node/$node->nid"), "title" => $node->title, "author" => format_name($node), "date" => format_date($node->created), @@ -144,10 +144,15 @@ function xtemplate_page($content, $title "directory" => "themes/xtemplate/$template_directory", "onload_attributes" => theme_onload_attribute(), "logo" => variable_get('xtemplate_logo', "\"Logo\""), - "primary_links" => variable_get("xtemplate_primary_links", l("edit primary links", "admin/system/themes/xtemplate")), - "secondary_links" => variable_get("xtemplate_secondary_links", l("edit secondary links", "admin/system/themes/xtemplate")) + "primary_links" => variable_get("xtemplate_primary_links", l("edit primary links", "admin/themes/xtemplate")), + "secondary_links" => variable_get("xtemplate_secondary_links", l("edit secondary links", "admin/themes/xtemplate")) )); + if ($tabs = theme('menu_local_tasks')) { + $xtemplate->template->assign("tabs", $tabs); + $xtemplate->template->parse("header.title.tabs"); + } + if ($title = drupal_get_title()) { $xtemplate->template->assign("title", $title); $xtemplate->template->assign("breadcrumb", theme("breadcrumb", drupal_get_breadcrumb()));