This commit was manufactured as part of Drupal's Great Git Migration to

create tag 'DRUPAL-4-7-0-BETA-5'.

Sprout from master 2006-03-02 19:16:41 UTC Dries Buytaert <dries@buytaert.net> '- Patch #47267 by joshk: made aggregator categorization work.'
Delete:
    modules/aggregator/aggregator.module
    modules/archive/archive.module
    modules/block/block.module
    modules/blog/blog.module
    modules/blogapi/blogapi.module
    modules/book/book.module
    modules/comment/comment.module
    modules/contact/contact.module
    modules/drupal/drupal.module
    modules/filter/filter.module
    modules/forum/forum.module
    modules/help/help.module
    modules/legacy/legacy.module
    modules/locale/locale.module
    modules/menu/menu.module
    modules/node/node.module
    modules/page/page.module
    modules/path/path.module
    modules/ping/ping.module
    modules/poll/poll.module
    modules/profile/profile.module
    modules/search/search.module
    modules/statistics/statistics.module
    modules/story/story.module
    modules/system/system.module
    modules/taxonomy/taxonomy.module
    modules/throttle/throttle.module
    modules/tracker/tracker.module
    modules/upload/upload.module
    modules/user/user.module
    modules/watchdog/watchdog.module
4.7.0-beta-5
The Great Git Migration 2006-03-02 19:16:42 +00:00
parent 1001b7079d
commit 689ff3a775
31 changed files with 0 additions and 22516 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,274 +0,0 @@
<?php
// $Id$
/**
* @file
* Displays a calendar to navigate old content.
*/
/**
* Implementation of hook_help().
*/
function archive_help($section) {
switch ($section) {
case 'admin/help#archive':
$output = '<p>'. t('The archive page allows content to be viewed by date. It also provides a monthly calendar view that users can use to navigate through content.') .'</p>';
$output .= '<p>'. t('To view the archive by date, select the date in the calendar. Administrators can enable the <em>browse archives</em> block in block administration to allow users to browse by calendar. Clicking on a date in the monthly calendar view shows the content for that date. Users can navigate to different months using arrows beside the month\'s name in the calendar display. The current date will be highlighted in the calendar.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>view your <a href="%archive">archive by day</a>.</li>
<li>enable the <em>browse archives</em> block at <a href="%admin-block">administer &gt;&gt; block</a>.</li>
</ul>
', array('%archive' => url('archive'), '%admin-block' => url('admin/block')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%archive">Archive page</a>.', array('%archive' => 'http://drupal.org/handbook/modules/archive/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Displays a calendar for navigating older content.');
}
}
/**
* Generates a monthly calendar, for display in the archive block.
*/
function archive_calendar($original = 0) {
global $user;
$edit = $_POST['edit'];
// Extract today's date:
$start_of_today = mktime(0, 0, 0, date('n', time()), date('d', time()), date('Y', time())) + $user->timezone;
$end_of_today = mktime(23, 59, 59, date('n', time()), date('d', time()), date('Y', time())) + $user->timezone;
// Extract the requested date:
if ($edit['year'] && $edit['month'] && $edit['day']) {
$year = $edit['year'];
$month = $edit['month'];
$day = $edit['day'];
$requested = mktime(0, 0, 0, $month, $day, $year) + $user->timezone;
}
else if (arg(0) == 'archive' && arg(3)) {
$year = arg(1);
$month = arg(2);
$day = arg(3);
$requested = mktime(0, 0, 0, $month, $day, $year) + $user->timezone;
}
else {
$year = date('Y', time());
$month = date('n', time());
$day = date('d', time());
$requested = $end_of_today + $user->timezone;
}
$start_of_month = mktime(0, 0, 0, $month, 1, $year);
// Extract first day of the month:
$first = date('w', $start_of_month);
// Extract last day of the month:
$last = date('t', $start_of_month);
$end_of_month = mktime(23, 59, 59, $month, $last, $year);
$cache = cache_get("archive:calendar:$day-$month-$year");
if (!empty($cache)) {
return $cache->data;
}
// Calculate previous and next months dates and check for shorter months (28/30 days)
$prevmonth = mktime(23, 59, 59, $month - 1, 1, $year);
$prev = mktime(23, 59, 59, $month - 1, min(date('t', $prevmonth), $day), $year);
$nextmonth = mktime(23, 59, 59, $month + 1, 1, $year);
$next = mktime(23, 59, 59, $month + 1, min(date('t', $nextmonth), $day), $year);
$sql = 'SELECT n.nid, n.created FROM {node} n WHERE n.status = 1 AND n.created > %d AND n.created < %d ORDER BY n.created';
$sql = db_rewrite_sql($sql);
$result = db_query($sql, $start_of_month, $end_of_month);
$days_with_posts = array();
while ($day_with_post = db_fetch_object($result)) {
$daynum = date('j', $day_with_post->created + $user->timezone);
if (isset($days_with_posts[$daynum])) {
$days_with_posts[$daynum]++;
}
else {
$days_with_posts[$daynum] = 1;
}
}
// Generate calendar header:
$output .= "\n<!-- calendar -->\n";
$output .= '<div class="calendar">';
$output .= '<table summary="'. t('A calendar to browse the archives') .".\">\n";
$output .= ' <caption>'. l('«', 'archive/'. date('Y/m/d', $prev), array('title' => t('Previous month'))) .' '. format_date($requested, 'custom', 'F') . date(' Y', $requested) .' '. ($nextmonth <= time() ? l('»', 'archive/'. date('Y/m/d', $next), array('title' => t('Next month'))) : ' ') ."</caption>\n";
// First day of week (0 => Sunday, 1 => Monday, ...)
$weekstart = variable_get('date_first_day', 0);
// Last day of week
($weekstart - 1 == -1) ? $lastday = 6 : $lastday = $weekstart - 1;
// Generate the days of the week:
$firstcolumn = mktime(0, 0, 0, 3, 20 + $weekstart, 1994);
$output .= " <tr class=\"header-week\">\n";
$days = array(t('Sunday') => t('Su'), t('Monday') => t('Mo'), t('Tuesday') => t('Tu'), t('Wednesday') => t('We'), t('Thursday') => t('Th'), t('Friday') => t('Fr'), t('Saturday') => t('Sa'));
if ($weekstart) {
$days = array_merge(array_slice($days, $weekstart), array_slice($days, 0, $weekstart));
}
foreach ($days as $fullname => $name) {
$output .= ' <th abbr="'. $fullname .'">'. $name . "</th>\n";
}
$output .= "</tr>\n";
// Initialize temporary variables:
$nday = 1;
$sday = $first;
// Loop through all the days of the month:
while ($nday <= $last) {
// Set up blank days for first week of the month (allowing individual blank day styling):
if ($first != $weekstart) {
$blankdays = ($first - $weekstart + 7) % 7;
$output .= " <tr class=\"row-week\">" . str_repeat("<td class=\"day-blank\">&nbsp;</td>\n", $blankdays);
$first = $weekstart;
}
// Start every week on a new line:
if ($sday == $weekstart) {
$output .= " <tr class=\"row-week\">\n";
}
// Print one cell:
$date = mktime(0, 0, 0, $month, $nday, $year) + $user->timezone;
if (isset($days_with_posts[$nday])) {
$daytext = l($nday, "archive/$year/$month/$nday", array("title" => format_plural($days_with_posts[$nday], "1 post", "%count posts")));
$dayclass = 'day-link';
}
else {
$daytext = $nday;
$dayclass = 'day-normal';
}
if ($date == $requested) {
$output .= " <td class=\"day-selected\">$daytext</td>\n";
}
else if ($date == $start_of_today) {
$output .= " <td class=\"day-today\">$daytext</td>\n";
}
else if ($date > $end_of_today) {
$output .= " <td class=\"day-future\">$daytext</td>\n";
}
else {
$output .= " <td class=\"$dayclass\">$daytext</td>\n";
}
// Start every week on a new line:
if ($sday == $lastday) {
$output .= " </tr>\n";
}
// Update temporary variables:
$sday++;
$sday = $sday % 7;
$nday++;
}
// Complete the calendar (allowing individual blank day styling):
if ($sday != $weekstart) {
$end = (7 - $sday + $weekstart) % 7;
$output .= str_repeat("<td class=\"day-blank\">&nbsp;</td>\n", $end) . "</tr>\n";
}
$output .= "</table></div>\n\n";
cache_set("archive:calendar:$day-$month-$year", $output, CACHE_TEMPORARY);
return $output;
}
/**
* Implementation of hook_block().
*
* Generates a calendar for the current month, with links to the archives
* for each day.
*/
function archive_block($op = 'list', $delta = 0) {
if ($op == 'list') {
$blocks[0]['info'] = t('Calendar to browse archives');
return $blocks;
}
else if ($op == 'view' && user_access('access content')) {
$block['subject'] = t('Browse archives');
$block['content'] = archive_calendar();
return $block;
}
}
/**
* Implementation of hook_menu().
*/
function archive_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'archive', 'title' => t('archives'),
'access' => user_access('access content'),
'callback' => 'archive_page',
'type' => MENU_SUGGESTED_ITEM);
}
return $items;
}
/**
* Menu callback; lists all nodes posted on a given date.
*/
function archive_page($year = 0, $month = 0, $day = 0) {
global $user;
$op = $_POST['op'];
$edit = $_POST['edit'];
if ($op == t('Show')) {
$year = $edit['year'];
$month = $edit['month'];
$day = $edit['day'];
}
$date = mktime(0, 0, 0, $month, $day, $year) - $user->timezone;
$date_end = mktime(0, 0, 0, $month, $day + 1, $year) - $user->timezone;
// Prepare the values of the form fields.
$years = drupal_map_assoc(range(2000, 2010));
$months = array(1 => t('January'), 2 => t('February'), 3 => t('March'), 4 => t('April'), 5 => t('May'), 6 => t('June'), 7 => t('July'), 8 => t('August'), 9 => t('September'), 10 => t('October'), 11 => t('November'), 12 => t('December'));
$days = drupal_map_assoc(range(0, 31));
$form['year'] = array('#type' => 'select', '#default_value' => ($year ? $year : date('Y')), '#options' => $years);
$form['month'] = array('#type' => 'select', '#default_value' => ($month ? $month : date('m')), '#options' => $months);
$form['day'] = array('#type' => 'select', '#default_value' => ($day ? $day : date('d')), '#options' => $days);
$form['show'] = array('#type' => 'submit', '#value' => t('Show'));
$output = drupal_get_form('archive_dates', $form);
if ($year && $month && $day) {
// Fetch nodes for the selected date, if one was specified.
$sql = 'SELECT n.nid, n.created FROM {node} n WHERE n.status = 1 AND n.created > %d AND n.created < %d ORDER BY n.created';
$sql = db_rewrite_sql($sql);
$result = db_query_range($sql, $date, $date_end, 0, 20);
while ($nid = db_fetch_object($result)) {
$output .= node_view(node_load($nid->nid), 1);
}
}
return $output;
}
/**
* Form theme function; displays the archive date navigation form inline.
*/
function theme_archive_dates($form) {
$output = '<div class="container-inline">' . form_render($form) . '</div>';
return $output;
}

View File

@ -1,635 +0,0 @@
<?php
// $Id$
/**
* @file
* Controls the boxes that are displayed around the main content.
*/
/**
* Implementation of hook_help().
*/
function block_help($section) {
switch ($section) {
case 'admin/help#block':
$output = '<p>'. t('Blocks are the boxes of related/grouped data that are visible in the sidebar(s) of your web site. These are usually generated automatically by modules (e.g. recent forum topics), but administrators can also create their own defined blocks.') .'</p>';
$output .= '<p>'. t('The sidebar each block appears in depends on both which theme you are using (some are left-only, some right, some both), and on the settings in block management.') .'</p>';
$output .= '<p>'. t('The block management screen lets you specify the vertical sort-order of the blocks within a sidebar. You do this by assigning a weight to each block. Lighter blocks (smaller weight) "float up" towards the top of the sidebar. Heavier ones "sink down" towards the bottom of it.') .'</p>';
$output .= t('<p>A block\'s visibility depends on:</p>
<ul>
<li>Its enabled checkbox. Disabled blocks are never shown.</li>
<li>Its throttle checkbox. Throttled blocks are hidden during high server loads.</li>
<li>Its path options. Blocks can be configured to only show/hide on certain pages.</li>
<li>User settings. Administrators can choose to let your users decide whether to show/hide certain blocks.</li>
<li>Its function. Dynamic blocks (such as those defined by modules) may be empty on certain pages and will not be shown.</li>
</ul>
');
$output .= '<h3>'. t('Module blocks') .'</h3>';
$output .= '<p>'. t('Module blocks are available when modules are enabled. These blocks can be administered in block administration.') .'</p>';
$output .= '<h3>'. t('Administrator defined blocks') .'</h3>';
$output .= '<p>'. t('An administrator defined block contains content supplied by the administrator. Each admin-defined block consists of a title, a description, and a body which can be as long as you wish. The Drupal engine will render the content of the block.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>enable throttle and configure blocks at <a href="%admin-block">administer &gt;&gt; blocks</a>.</li>
<li>add a block at <a href="%admin-block-add">administer &gt;&gt; blocks &gt;&gt; add block</a>.</li>
</ul>
', array('%admin-block' => url('admin/block'), '%admin-block-add' => url('admin/block/add')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%block">Block page</a>.', array('%block' => 'http://drupal.org/handbook/modules/block/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Controls the boxes that are displayed around the main content.');
case 'admin/block':
return t("
<p>Blocks are content rendered into regions, often boxes in the left and right side bars of the web site. They are made available by modules or created manually.</p>
<p>Only enabled blocks are shown. You can position the blocks by deciding which area of the page they will show up on (e.g., a sidebar) and in which order they appear (weight). Highlighting on this page shows the regions where content will be rendered.</p>
<p>If you want certain blocks to disable themselves temporarily during high server loads, check the 'Throttle' box. You can configure the auto-throttle on the <a href=\"%throttle\">throttle configuration page</a> after having enabled the throttle module.</p>
", array('%throttle' => url('admin/settings/throttle')));
case 'admin/block/add':
return t('<p>Here you can create a new block. Once you have created this block you must make it active and give it a place on the page using <a href="%overview">blocks</a>. The title is used when displaying the block. The description is used in the "block" column on the <a href="%overview">blocks</a> page.</p>', array('%overview' => url('admin/block')));
}
}
/**
* Implementation of hook_perm().
*/
function block_perm() {
return array('administer blocks', 'use PHP for block visibility');
}
/**
* Implementation of hook_menu().
*/
function block_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'admin/block', 'title' => t('blocks'),
'access' => user_access('administer blocks'),
'callback' => 'block_admin');
$items[] = array('path' => 'admin/block/list', 'title' => t('list'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/block/configure', 'title' => t('configure block'),
'access' => user_access('administer blocks'),
'callback' => 'block_admin_configure',
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/block/delete', 'title' => t('delete block'),
'access' => user_access('administer blocks'),
'callback' => 'block_box_delete',
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/block/add', 'title' => t('add block'),
'access' => user_access('administer blocks'),
'callback' => 'block_box_add',
'type' => MENU_LOCAL_TASK);
foreach (list_themes() as $key => $theme) {
if ($theme->status) {
if ($key == variable_get('theme_default', 'bluemarine')) {
$items[] = array('path' => 'admin/block/list/' . $key, 'title' => t('%key settings', array('%key' => $key)),
'access' => user_access('administer blocks'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
}
else {
$items[] = array('path' => 'admin/block/list/' . $key, 'title' => t('%key settings', array('%key' => $key)),
'access' => user_access('administer blocks'), 'type' => MENU_LOCAL_TASK);
}
}
}
}
return $items;
}
/**
* Implementation of hook_block().
*
* Generates the administrator-defined blocks for display.
*/
function block_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$blocks = array();
$result = db_query('SELECT bid, title, info FROM {boxes} ORDER BY title');
while ($block = db_fetch_object($result)) {
$blocks[$block->bid]['info'] = $block->info ? check_plain($block->info) : check_plain($block->title);
}
return $blocks;
case 'configure':
$box = block_box_get($delta);
if (filter_access($box['format'])) {
return block_box_form($box);
}
break;
case 'save':
block_box_save($edit, $delta);
break;
case 'view':
$block = db_fetch_object(db_query('SELECT * FROM {boxes} WHERE bid = %d', $delta));
$data['subject'] = check_plain($block->title);
$data['content'] = check_markup($block->body, $block->format, FALSE);
return $data;
}
}
function block_admin_save($edit) {
foreach ($edit as $module => $blocks) {
foreach ($blocks as $delta => $block) {
db_query("UPDATE {blocks} SET status = %d, weight = %d, region = '%s', throttle = %d WHERE module = '%s' AND delta = '%s' AND theme = '%s'",
$block['status'], $block['weight'], $block['region'], $block['throttle'], $module, $delta, $block['theme']);
}
}
}
/**
* Update the 'blocks' DB table with the blocks currently exported by modules.
*
* @param $order_by php <a
* href="http://www.php.net/manual/en/function.array-multisort.php">array_multisort()</a>
* style sort ordering, eg. "weight", SORT_ASC, SORT_STRING.
*
* @return
* Blocks currently exported by modules, sorted by $order_by.
*/
function _block_rehash($order_by = array('weight')) {
global $theme_key;
init_theme();
$result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $theme_key);
while ($old_block = db_fetch_object($result)) {
$old_blocks[$old_block->module][$old_block->delta] = $old_block;
}
db_query("DELETE FROM {blocks} WHERE theme = '%s'", $theme_key);
foreach (module_list() as $module) {
$module_blocks = module_invoke($module, 'block', 'list');
if ($module_blocks) {
foreach ($module_blocks as $delta => $block) {
$block['module'] = $module;
$block['delta'] = $delta;
// If previously written to database, load values.
if ($old_blocks[$module][$delta]) {
$block['status'] = $old_blocks[$module][$delta]->status;
$block['weight'] = $old_blocks[$module][$delta]->weight;
$block['region'] = $old_blocks[$module][$delta]->region;
$block['visibility'] = $old_blocks[$module][$delta]->visibility;
$block['pages'] = $old_blocks[$module][$delta]->pages;
$block['custom'] = $old_blocks[$module][$delta]->custom;
$block['throttle'] = $old_blocks[$module][$delta]->throttle;
}
// Otherwise, use any set values, or else substitute defaults.
else {
$properties = array ('status' => 0, 'weight' => 0, 'region' => 'left', 'pages' => '', 'custom' => 0);
foreach ($properties as $property => $default) {
if (!isset ($block[$property])) {
$block[$property] = $default;
}
}
}
// reinsert blocks into table
db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d)",
$block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
$blocks[] = $block;
// build array to sort on
$order[$order_by[0]][] = $block[$order_by[0]];
}
}
}
// sort
array_multisort($order[$order_by[0]], $order_by[1] ? $order_by[1] : SORT_ASC, $order_by[2] ? $order_by[2] : SORT_REGULAR, $blocks);
return $blocks;
}
/**
* Prepare the main block administration form.
*/
function block_admin_display() {
global $theme_key, $custom_theme;
$throttle = module_exist('throttle');
// If non-default theme configuration has been selected, set the custom theme.
if (arg(3)) {
$custom_theme = arg(3);
}
else {
$custom_theme = variable_get('theme_default', 'bluemarine');
}
init_theme();
$blocks = _block_rehash();
$block_regions = system_region_list($theme_key);
$form['#action'] = arg(3) ? url('admin/block/list/' . $theme_key) : url('admin/block');
$form['#tree'] = TRUE;
foreach ($blocks as $block) {
$form[$block['module']][$block['delta']]['info'] = array('#type' => 'markup', '#value' => $block['info']);
$form[$block['module']][$block['delta']]['status'] = array('#type' => 'checkbox', '#default_value' => $block['status']);
$form[$block['module']][$block['delta']]['theme'] = array('#type' => 'hidden', '#value' => $theme_key);
$form[$block['module']][$block['delta']]['weight'] = array('#type' => 'weight', '#default_value' => $block['weight']);
$form[$block['module']][$block['delta']]['region'] = array('#type' => 'select', '#default_value' => isset($block['region']) ? $block['region'] : system_default_region(), '#options' => $block_regions);
if ($throttle) {
$form[$block['module']][$block['delta']]['throttle'] = array('#type' => 'checkbox', '#default_value' => $block['throttle']);
}
$form[$block['module']][$block['delta']]['configure'] = array('#type' => 'markup', '#value' => l(t('configure'), 'admin/block/configure/'. $block['module'] .'/'. $block['delta']));
if ($block['module'] == 'block') {
$form[$block['module']][$block['delta']]['delete'] = array('#type' => 'markup', '#value' => l(t('delete'), 'admin/block/delete/'. $block['delta']));
}
}
$form['submit'] = array('#type' => 'submit', '#value' => t('Save blocks'));
return drupal_get_form('block_admin_display', $form);
}
function theme_block_admin_display($form) {
global $theme_key;
$throttle = module_exist('throttle');
$block_regions = system_region_list($theme_key);
// Highlight regions on page, to provide visual reference.
foreach ($block_regions as $key => $value) {
drupal_set_content($key, '<div class="block-region">' . $value . '</div>');
}
$regions = array();
$disabled = array();
foreach (element_children($form) as $module) {
// Don't take form control structures
if (is_array($form[$module])) {
foreach ($form[$module] as $delta => $element) {
// Only take form elements that are blocks
if (is_array($form[$module][$delta]['info'])) {
$block = $form[$module][$delta];
$row = array(array('data' => form_render($block['info']), 'class' => 'block'), form_render($block['status']) . form_render($block['theme']), form_render($block['weight']), form_render($block['region']));
if ($throttle) {
$row[] = form_render($block['throttle']);
}
$row[] = form_render($block['configure']);
$row[] = $block['delete'] ? form_render($block['delete']) : '';
if ($block['status']['#default_value']) {
$regions[$block['region']['#default_value']][] = $row;
}
else if ($block['region']['#default_value'] <= 1) {
$disabled[] = $row;
}
}
}
}
}
$rows = array();
if (count($regions)) {
foreach ($regions as $region => $row) {
$region_title = t('%region', array ('%region' => ucfirst($block_regions[$region])));
$rows[] = array(array('data' => $region_title, 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
$rows = array_merge($rows, $row);
}
}
if (count($disabled)) {
$rows[] = array(array('data' => t('Disabled'), 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
$rows = array_merge($rows, $disabled);
}
$header = array(t('Block'), t('Enabled'), t('Weight'), t('Placement'));
if ($throttle) {
$header[] = t('Throttle');
}
$header[] = array('data' => t('Operations'), 'colspan' => 2);
$output = theme('table', $header, $rows, array('id' => 'blocks'));
$output .= form_render($form['submit']);
return $output;
}
function block_box_get($bid) {
return db_fetch_array(db_query('SELECT * FROM {boxes} WHERE bid = %d', $bid));
}
/**
* Menu callback; displays the block configuration form.
*/
function block_admin_configure($module = NULL, $delta = 0) {
$form['module'] = array('#type' => 'value', '#value' => $module);
$form['delta'] = array('#type' => 'value', '#value' => $delta);
$edit = db_fetch_array(db_query("SELECT pages, visibility, custom FROM {blocks} WHERE module = '%s' AND delta = '%s'", $module, $delta));
// Module-specific block configurations.
if ($settings = module_invoke($module, 'block', 'configure', $delta)) {
$form['block_settings'] = array(
'#type' => 'fieldset',
'#title' => t('Block specific settings'),
'#collapsible' => true,
);
foreach ($settings as $k => $v) {
$form['block_settings'][$k] = $v;
}
}
// Get the block subject for the page title.
$info = module_invoke($module, 'block', 'list');
drupal_set_title(t("'%name' block", array('%name' => $info[$delta]['info'])));
// Standard block configurations.
$form['user_vis_settings'] = array(
'#type' => 'fieldset',
'#title' => t('User specific visibility settings'),
'#collapsible' => true,
);
$form['user_vis_settings']['custom'] = array(
'#type' => 'radios',
'#title' => t('Custom visibility settings'),
'#options' => array(t('Users cannot control whether or not they see this block.'), t('Show this block by default, but let individual users hide it.'), t('Hide this block by default but let individual users show it.')),
'#description' => t('Allow individual users to customize the visibility of this block in their account settings.'),
'#default_value' => $edit['custom'],
);
$form['page_vis_settings'] = array(
'#type' => 'fieldset',
'#title' => t('Page specific visibility settings'),
'#collapsible' => true,
);
$access = user_access('use PHP for block visibility');
if ($edit['visibility'] == 2 && !$access) {
$form['page_vis_settings'] = array();
$form['page_vis_settings']['visibility'] = array('#type' => 'value', '#value' => 2);
$form['page_vis_settings']['pages'] = array('#type' => 'value', '#value' => $edit['pages']);
}
else {
$options = array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.'));
$description = t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are '%blog' for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => theme('placeholder', 'blog'), '%blog-wildcard' => theme('placeholder', 'blog/*'), '%front' => theme('placeholder', '<front>')));
if ($access) {
$options[] = t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).');
$description .= t('If the PHP-mode is chosen, enter PHP code between %php. Note that executing incorrect PHP-code can break your Drupal site.', array('%php' => theme('placeholder', '<?php ?>')));
}
$form['page_vis_settings']['visibility'] = array(
'#type' => 'radios',
'#title' => t('Show block on specific pages'),
'#options' => $options,
'#default_value' => $edit['visibility'],
);
$form['page_vis_settings']['pages'] = array(
'#type' => 'textarea',
'#title' => t('Pages'),
'#default_value' => $edit['pages'],
'#description' => $description,
);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save block'),
);
return drupal_get_form('block_admin_configure', $form);
}
function block_admin_configure_validate($form_id, $form_values) {
if ($form_values['module'] == 'block') {
if (empty($form_values['info']) || db_num_rows(db_query("SELECT bid FROM {boxes} WHERE bid != %d AND info = '%s'", $form_values['delta'], $form_values['info']))) {
form_set_error('info', t('Please ensure that each block description is unique.'));
}
}
}
function block_admin_configure_submit($form_id, $form_values) {
if (!form_get_errors()) {
db_query("UPDATE {blocks} SET visibility = %d, pages = '%s', custom = %d WHERE module = '%s' AND delta = '%s'", $form_values['visibility'], $form_values['pages'], $form_values['custom'], $form_values['module'], $form_values['delta']);
module_invoke($form_values['module'], 'block', 'save', $form_values['delta'], $form_values);
drupal_set_message(t('The block configuration has been saved.'));
cache_clear_all();
return 'admin/block';
}
}
/**
* Menu callback; displays the block creation form.
*/
function block_box_add() {
$form = block_box_form();
$form['submit'] = array('#type' => 'submit', '#value' => t('Save block'));
return drupal_get_form('block_box_add', $form);
}
function block_box_add_validate($form_id, $form_values) {
if (empty($form_values['info']) || db_num_rows(db_query("SELECT info FROM {boxes} WHERE info = '%s'", $form_values['info']))) {
form_set_error('info', t('Please ensure that each block description is unique.'));
}
}
function block_box_add_submit($form_id, $form_values) {
if (!form_get_errors()) {
if (block_box_save($form_values)) {
drupal_set_message(t('The block has been created.'));
return 'admin/block';
}
}
}
/**
* Menu callback; confirm deletion of custom blocks.
*/
function block_box_delete($bid = 0) {
$box = block_box_get($bid);
$form['info'] = array('#type' => 'hidden', '#value' => $box['info'] ? $box['info'] : $box['title']);
$form['bid'] = array('#type' => 'hidden', '#value' => $bid);
return confirm_form('block_box_delete_confirm', $form, t('Are you sure you want to delete the block %name?', array('%name' => theme('placeholder', $info))), 'admin/block', '', t('Delete'), t('Cancel'));
}
/**
* Deletion of custom blocks.
*/
function block_box_delete_confirm_submit($form_id, $form_values) {
db_query('DELETE FROM {boxes} WHERE bid = %d', $form_values['bid']);
drupal_set_message(t('The block %name has been removed.', array('%name' => theme('placeholder', $form_values['info']))));
cache_clear_all();
return 'admin/block';
};
function block_box_form($edit = array()) {
$form['info'] = array(
'#type' => 'textfield',
'#title' => t('Block description'),
'#default_value' => $edit['info'],
'#maxlength' => 64,
'#description' => t('A brief description of your block. Used on the <a href="%overview">block overview page</a>.', array('%overview' => url('admin/block'))),
'#required' => TRUE,
'#weight' => -19,
);
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Block title'),
'#default_value' => $edit['title'],
'#maxlength' => 64,
'#description' => t('The title of the block as shown to the user.'),
'#weight' => -18,
);
$form['body_filter']['#weight'] = -17;
$form['body_filter']['body'] = array(
'#type' => 'textarea',
'#title' => t('Block body'),
'#default_value' => $edit['body'],
'#rows' => 15,
'#description' => t('The content of the block as shown to the user.'),
'#weight' => -17,
);
$form['body_filter']['format'] = filter_form($edit['format'], -16);
return $form;
}
function block_box_save($edit, $delta = NULL) {
if (!filter_access($edit['format'])) {
$edit['format'] = FILTER_FORMAT_DEFAULT;
}
if (isset($delta)) {
db_query("UPDATE {boxes} SET title = '%s', body = '%s', info = '%s', format = %d WHERE bid = %d", $edit['title'], $edit['body'], $edit['info'], $edit['format'], $delta);
}
else {
db_query("INSERT INTO {boxes} (title, body, info, format) VALUES ('%s', '%s', '%s', %d)", $edit['title'], $edit['body'], $edit['info'], $edit['format']);
}
return true;
}
/**
* Menu callback; displays the block overview page.
*/
function block_admin() {
$edit = isset($_POST['edit']) ? $_POST['edit'] : '';
$op = isset($_POST['op']) ? $_POST['op'] : '';
if ($op == t('Save blocks')) {
block_admin_save($edit);
drupal_set_message(t('The blocks have been saved.'));
cache_clear_all();
drupal_goto($_GET['q']);
}
return block_admin_display();
}
/**
* Implementation of hook_user().
*
* Allow users to decide which custom blocks to display when they visit
* the site.
*/
function block_user($type, $edit, &$user, $category = NULL) {
switch ($type) {
case 'form':
if ($category == 'account') {
$result = db_query('SELECT * FROM {blocks} WHERE status = 1 AND custom != 0 ORDER BY weight, module, delta');
$form['block'] = array('#type' => 'fieldset', '#title' => t('Block configuration'), '#weight' => 3, '#collapsible' => TRUE, '#tree' => TRUE);
while ($block = db_fetch_object($result)) {
$data = module_invoke($block->module, 'block', 'list');
if ($data[$block->delta]['info']) {
$return = TRUE;
$form['block'][$block->module][$block->delta] = array('#type' => 'checkbox', '#title' => $data[$block->delta]['info'], '#default_value' => isset($user->block[$block->module][$block->delta]) ? $user->block[$block->module][$block->delta] : ($block->custom == 1));
}
}
if ($return) {
return $form;
}
}
break;
case 'validate':
if (!$edit['block']) {
$edit['block'] = array();
}
return $edit;
}
}
/**
* Return all blocks in the specified region for the current user.
*
* @param $region
* The name of a region.
*
* @return
* An array of block objects, indexed with <i>module</i>_<i>delta</i>.
* If you are displaying your blocks in one or two sidebars, you may check
* whether this array is empty to see how many columns are going to be
* displayed.
*
* @todo
* Add a proper primary key (bid) to the blocks table so we don't have
* to mess around with this <i>module</i>_<i>delta</i> construct.
* Currently, the blocks table has no primary key defined!
*/
function block_list($region) {
global $user, $theme_key;
static $blocks = array();
if (!count($blocks)) {
$result = db_query("SELECT * FROM {blocks} WHERE theme = '%s' AND status = 1 ORDER BY region, weight, module", $theme_key);
while ($block = db_fetch_object($result)) {
if (!isset($blocks[$block->region])) {
$blocks[$block->region] = array();
}
// Use the user's block visibility setting, if necessary
if ($block->custom != 0) {
if ($user->uid && isset($user->block[$block->module][$block->delta])) {
$enabled = $user->block[$block->module][$block->delta];
}
else {
$enabled = ($block->custom == 1);
}
}
else {
$enabled = TRUE;
}
// Match path if necessary
if ($block->pages) {
if ($block->visibility < 2) {
$path = drupal_get_path_alias($_GET['q']);
$regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote($block->pages, '/')) .')$/';
$page_match = !($block->visibility xor preg_match($regexp, $path));
}
else {
$page_match = drupal_eval($block->pages);
}
}
else {
$page_match = TRUE;
}
if ($enabled && $page_match) {
// Check the current throttle status and see if block should be displayed
// based on server load.
if (!($block->throttle && (module_invoke('throttle', 'status') > 0))) {
$array = module_invoke($block->module, 'block', 'view', $block->delta);
if (isset($array) && is_array($array)) {
foreach ($array as $k => $v) {
$block->$k = $v;
}
}
}
if (isset($block->content) && $block->content) {
$blocks[$block->region]["{$block->module}_{$block->delta}"] = $block;
}
}
}
}
// Create an empty array if there were no entries
if (!isset($blocks[$region])) {
$blocks[$region] = array();
}
return $blocks[$region];
}

View File

@ -1,312 +0,0 @@
<?php
// $Id$
/**
* @file
* Enables keeping an easily and regularly updated web page or a blog.
*/
/**
* Implementation of hook_node_info().
*/
function blog_node_info() {
return array('blog' => array('name' => t('blog entry'), 'base' => 'blog'));
}
/**
* Implementation of hook_perm().
*/
function blog_perm() {
return array('edit own blog');
}
/**
* Implementation of hook_access().
*/
function blog_access($op, $node) {
global $user;
if ($op == 'create') {
return user_access('edit own blog') && $user->uid;
}
if ($op == 'update' || $op == 'delete') {
if (user_access('edit own blog') && ($user->uid == $node->uid)) {
return TRUE;
}
}
}
/**
* Implementation of hook_user().
*/
function blog_user($type, &$edit, &$user) {
if ($type == 'view' && user_access('edit own blog', $user)) {
$items[] = array('title' => t('Blog'),
'value' => l(t('view recent blog entries'), "blog/$user->uid", array('title' => t("Read %username's latest blog entries.", array('%username' => $user->name)))),
'class' => 'blog',
);
return array(t('History') => $items);
}
}
/**
* Implementation of hook_help().
*/
function blog_help($section) {
switch ($section) {
case 'admin/help#blog':
$output = '<p>'. t('The blog module allows registered users to maintain an online weblog (commonly known as a blog), often referred to as an online journal or diary. Blogs are made up of individual posts that are time stamped and are typically viewed by date as you would a diary. Blogs often contain links to webpages users have read and/or agree/disagree with.') .'</p>';
$output .= '<p>'. t('The blog module adds a <em>user blogs</em> navigation link to the site, which takes any visitor to a page that displays the most recent blog entries from all the users on the site. The navigation menu has a <em>create a blog entry</em> link (which takes you to a submission form) and a <em>view personal blog</em> link (which displays your blog entries as other people will see them). The blog module also creates a <em>recent blog posts</em> block that can be enabled.') .'</p>';
$output .= '<p>'. t('If a user has the ability to post blogs, then the import module (news aggregator) will display a blog-it link next to each news item in its lists. Clicking on this takes the user to the blog submission form, with the title, a link to the item, and a link to the source into the body text already in the text box, ready for the user to add a comment or explanation. This actively encourages people to add blog entries about things they see and hear elsewhere in the website and from your syndicated partner sites.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>read your blog via your user profile at <a href="%user">my account</a>.</li>
<li>post a blog at <a href="%node-add-blog">create content &gt;&gt; personal blog entry</a>.</li>
<li>administer blog at <a href="%admin-node-configure-types-blog">administer &gt;&gt; content &gt;&gt; configure &gt;&gt; content types &gt;&gt; personal blog entry</a>.</li>
<li>administer blog api at <a href="%admin-settings-blogapi">administer &gt;&gt; settings &gt;&gt; blogapi</a>.</li>
<li>enable the "recent blog posts" block at <a href="%admin-block">administer &gt;&gt; blocks</a> to show the 10 most recent blog posts.</li>
</ul>
', array('%user' => url('user'), '%node-add-blog' => url('node/add/blog'), '%admin-node-configure-types-blog' => url('admin/node/configure/types/blog'), '%admin-settings-blogapi' => url('admin/settings/blogapi'), '%admin-block' => url('admin/block')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%blog">Blog page</a>.', array('%blog' => 'http://drupal.org/handbook/modules/blog/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Enables keeping an easily and regularly updated web page or a blog.');
case 'node/add#blog':
return t("A blog is a regularly updated journal or diary made up of individual posts shown in reversed chronological order. A blog is tightly coupled to the author so each user will have his 'own' blog.");
}
}
/**
* Displays an RSS feed containing recent blog entries of a given user.
*/
function blog_feed_user($uid = 0) {
global $user;
if ($uid) {
$account = user_load(array('uid' => $uid, 'status' => 1));
}
else {
$account = $user;
}
$result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, r.teaser, n.created, u.name, u.uid FROM {node} n INNER JOIN {node_revisions} r ON n.vid = r.vid INNER JOIN {users} u ON n.uid = u.uid WHERE n.type = 'blog' AND u.uid = %d AND n.status = 1 ORDER BY n.created DESC"), $uid, 0, variable_get('feed_default_items', 10));
$channel['title'] = $account->name ."'s blog";
$channel['link'] = url("blog/$uid", NULL, NULL, TRUE);
$channel['description'] = $term->description;
node_feed($result, $channel);
}
/**
* Displays an RSS feed containing recent blog entries of all users.
*/
function blog_feed_last() {
$result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, r.teaser, n.created, u.name, u.uid FROM {node} n INNER JOIN {node_revisions} r ON n.vid = r.vid INNER JOIN {users} u ON n.uid = u.uid WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.created DESC"), 0, variable_get('feed_default_items', 10));
$channel['title'] = variable_get('site_name', 'drupal') .' blogs';
$channel['link'] = url('blog', NULL, NULL, TRUE);
$channel['description'] = $term->description;
node_feed($result, $channel);
}
/**
* Menu callback; displays a Drupal page containing recent blog entries.
*/
function blog_page($a = NULL, $b = NULL) {
if (is_numeric($a)) { // $a is a user ID
if ($b == 'feed') {
return blog_feed_user($a);
}
else {
return blog_page_user($a);
}
}
else if ($a == 'feed') {
return blog_feed_last();
}
else {
return blog_page_last();
}
}
/**
* Displays a Drupal page containing recent blog entries of a given user.
*/
function blog_page_user($uid) {
global $user;
$account = user_load(array((is_numeric($uid) ? 'uid' : 'name') => $uid, 'status' => 1));
if ($account->uid) {
drupal_set_title($title = t("%name's blog", array('%name' => $account->name)));
if (($account->uid == $user->uid) && user_access('edit own blog')) {
$output = '<li>'. l(t('Post new blog entry.'), "node/add/blog") .'</li>';
}
else if ($account->uid == $user->uid) {
$output = '<li>'. t('You are not allowed to post a new blog entry.') .'</li>';
}
if ($output) {
$output = '<ul>'. $output .'</ul>';
}
else {
$output = '';
}
$result = pager_query(db_rewrite_sql("SELECT n.nid, n.sticky, n.created FROM {node} n WHERE type = 'blog' AND n.uid = %d AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10), 0, NULL, $account->uid);
while ($node = db_fetch_object($result)) {
$output .= node_view(node_load($node->nid), 1);
}
$output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
$output .= theme('feed_icon', url("blog/$account->uid/feed"));
drupal_add_link(array('rel' => 'alternate',
'type' => 'application/rss+xml',
'title' => t('RSS - %title', array('%title' => $title)),
'href' => url("blog/$account->uid/feed")));
return $output;
}
else {
drupal_not_found();
}
}
/**
* Displays a Drupal page containing recent blog entries of all users.
*/
function blog_page_last() {
global $user;
$output = '';
$result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.created DESC"), variable_get('default_nodes_main', 10));
while ($node = db_fetch_object($result)) {
$output .= node_view(node_load($node->nid), 1);
}
$output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
$output .= theme('feed_icon', url('blog/feed'));
drupal_add_link(array('rel' => 'alternate',
'type' => 'application/rss+xml',
'title' => t('RSS - blogs'),
'href' => url("blog/feed")));
return $output;
}
/**
* Implementation of hook_validate().
*/
function blog_validate($node) {
node_validate_title($node);
}
/**
* Implementation of hook_form().
*/
function blog_form(&$node) {
global $nid;
$iid = $_GET['iid'];
if (empty($node->body)) {
/*
** If the user clicked a "blog it" link, we load the data from the
** database and quote it in the blog:
*/
if ($nid && $blog = node_load($nid)) {
$node->body = '<em>'. $blog->body .'</em> ['. l($blog->name, "node/$nid") .']';
}
if ($iid && $item = db_fetch_object(db_query('SELECT i.*, f.title as ftitle, f.link as flink FROM {aggregator_item} i, {aggregator_feed} f WHERE i.iid = %d AND i.fid = f.fid', $iid))) {
$node->title = $item->title;
// Note: $item->description has been validated on aggregation.
$node->body = '<a href="'. check_url($item->link) .'">'. check_plain($item->title) .'</a> - <em>'. $item->description .'</em> [<a href="'. check_url($item->flink) .'">'. check_plain($item->ftitle) ."</a>]\n";
}
}
$form['title'] = array('#type' => 'textfield', '#title' => t('Title'), '#required' => TRUE, '#default_value' => $node->title, '#weight' => -5);
$form['body_filter']['body'] = array('#type' => 'textarea', '#title' => t('Body'), '#default_value' => $node->body, '#rows' => 20, '#required' => TRUE);
$form['body_filter']['filter'] = filter_form($node->format);
return $form;
}
/**
* Implementation of hook_view().
*/
function blog_view(&$node, $teaser = FALSE, $page = FALSE) {
if ($page) {
// Breadcrumb navigation
$breadcrumb[] = array('path' => 'blog', 'title' => t('blogs'));
$breadcrumb[] = array('path' => 'blog/'. $node->uid, 'title' => t("%name's blog", array('%name' => $node->name)));
$breadcrumb[] = array('path' => 'node/'. $node->nid);
menu_set_location($breadcrumb);
}
$node = node_prepare($node, $teaser);;
}
/**
* Implementation of hook_link().
*/
function blog_link($type, $node = 0, $main = 0) {
$links = array();
if ($type == 'node' && $node->type == 'blog') {
if (arg(0) != 'blog' || arg(1) != $node->uid) {
$links[] = l(t("%username's blog", array('%username' => $node->name)), "blog/$node->uid", array('title' => t("Read %username's latest blog entries.", array('%username' => $node->name))));
}
}
return $links;
}
/**
* Implementation of hook_menu().
*/
function blog_menu($may_cache) {
global $user;
$items = array();
if ($may_cache) {
$items[] = array('path' => 'node/add/blog', 'title' => t('blog entry'),
'access' => user_access('edit own blog'));
$items[] = array('path' => 'blog', 'title' => t('blogs'),
'callback' => 'blog_page',
'access' => user_access('access content'),
'type' => MENU_SUGGESTED_ITEM);
$items[] = array('path' => 'blog/'. $user->uid, 'title' => t('my blog'),
'access' => user_access('edit own blog'),
'type' => MENU_DYNAMIC_ITEM);
}
return $items;
}
/**
* Implementation of hook_block().
*
* Displays the most recent 10 blog titles.
*/
function blog_block($op = 'list', $delta = 0) {
global $user;
if ($op == 'list') {
$block[0]['info'] = t('Recent blog posts');
return $block;
}
else if ($op == 'view') {
if (user_access('access content')) {
$result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.created DESC"), 0, 10);
if (db_num_rows($result)) {
$block['content'] = node_title_list($result);
$block['content'] .= '<div class="more-link">'. l(t('more'), 'blog', array('title' => t('Read the latest blog entries.'))) .'</div>';
$block['subject'] = t('Recent blog posts');
return $block;
}
}
}
}

View File

@ -1,736 +0,0 @@
<?php
// $Id$
/**
* @file
* Enable users to post using applications that support XML-RPC blog APIs.
*/
/**
* Implementation of hook_help().
*/
function blogapi_help($section) {
switch ($section) {
case 'admin/help#blogapi':
$output = '<p>'. t('The blog API module enables a post to be posted to a site via external GUI applications. Many users perfer to use external tools to improve their ability to read and post responses in a customized way. The blog api provides users the freedom to use the blogging tools they want but still have the blogging server of choice.') .'</p>';
$output .= '<p>'. t('When this module is enabled and configured you can use programs like <a href="%external-http-ecto-kung-foo-tv">Ecto</a> to create and publish posts from your desktop. Blog API module supports several XML-RPC based blogging APIs such as the <a href="%-">Blogger API</a>, <a href="%external-http-www-xmlrpc-com-metaWeblogApi">MetaWeblog API</a>, and most of the <a href="%external-http-www-movabletype-org-docs-mtmanual_programmatic-html">Movable Type API</a>. Any desktop blogging tools or other services (e.g. <a href="%external-http-www-flickr-com">Flickr\'s</a> "post to blog") that support these APIs should work with this site.', array('%external-http-ecto-kung-foo-tv' => 'http://ecto.kung-foo.tv/', '%-' => url('http://www.blogger.com/developers/api/1_docs/'), '%external-http-www-xmlrpc-com-metaWeblogApi' => 'http://www.xmlrpc.com/metaWeblogApi', '%external-http-www-movabletype-org-docs-mtmanual_programmatic-html' => 'http://www.movabletype.org/docs/mtmanual_programmatic.html', '%external-http-www-flickr-com' => 'http://www.flickr.com')) .'</p>';
$output .= '<p>'. t('This module also allows site administrators to configure which content types can be posted via the external applications. So, for instance, users can post forum topics as well as blog posts. Where supported, the external applications will display each content type as a separate "blog".<!--break-->') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>view the XML-RPC page on your site at &gt;&gt; <a href="%file-xmlrpc">xmlrpc.php</a>.</li>
<li><a href="%admin-settings-blogapi">administer &gt;&gt; settings &gt;&gt; blog api</a>.</li>
</ul>
', array('%file-xmlrpc' => 'xmlrpc.php', '%admin-settings-blogapi' => url('admin/settings/blogapi')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%blogapi">BlogApi page</a>.', array('%blogapi' => 'http://drupal.org/handbook/modules/blogapi/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Allows users to post content using applications that support XML-RPC blog APIs.');
}
}
/**
* Implementation of hook_xmlrpc().
*/
function blogapi_xmlrpc() {
return array(
array(
'blogger.getUsersBlogs',
'blogapi_blogger_get_users_blogs',
array('array', 'string', 'string', 'string'),
t('Returns a list of weblogs to which an author has posting privileges.')),
array(
'blogger.getUserInfo',
'blogapi_blogger_get_user_info',
array('struct', 'string', 'string', 'string'),
t('Returns information about an author in the system.')),
array(
'blogger.newPost',
'blogapi_blogger_new_post',
array('string', 'string', 'string', 'string', 'string', 'string', 'boolean'),
t('Creates a new post, and optionally publishes it.')),
array(
'blogger.editPost',
'blogapi_blogger_edit_post',
array('boolean', 'string', 'string', 'string', 'string', 'string', 'boolean'),
t('Updates the information about an existing post.')),
array(
'blogger.getPost',
'blogapi_blogger_get_post',
array('struct', 'string', 'string', 'string', 'string'),
t('Returns information about a specific post.')),
array(
'blogger.deletePost',
'blogapi_blogger_delete_post',
array('boolean', 'string', 'string', 'string', 'string', 'boolean'),
t('Deletes a post.')),
array(
'blogger.getRecentPosts',
'blogapi_blogger_get_recent_posts',
array('array', 'string', 'string', 'string', 'string', 'int'),
t('Returns a list of the most recent posts in the system.')),
array(
'metaWeblog.newPost',
'blogapi_metaweblog_new_post',
array('string', 'string', 'string', 'string', 'struct', 'boolean'),
t('Creates a new post, and optionally publishes it.')),
array(
'metaWeblog.editPost',
'blogapi_metaweblog_edit_post',
array('boolean', 'string', 'string', 'string', 'struct', 'boolean'),
t('Updates information about an existing post.')),
array(
'metaWeblog.getPost',
'blogapi_metaweblog_get_post',
array('struct', 'string', 'string', 'string'),
t('Returns information about a specific post.')),
array(
'metaWeblog.newMediaObject',
'blogapi_metaweblog_new_media_object',
array('string', 'string', 'string', 'string', 'struct'),
t('Uploads a file to your webserver.')),
array(
'metaWeblog.getCategories',
'blogapi_metaweblog_get_category_list',
array('struct', 'string', 'string', 'string'),
t('Returns a list of all categories to which the post is assigned.')),
array(
'metaWeblog.getRecentPosts',
'blogapi_metaweblog_get_recent_posts',
array('array', 'string', 'string', 'string', 'int'),
t('Returns a list of the most recent posts in the system.')),
array(
'mt.getRecentPostTitles',
'blogapi_mt_get_recent_post_titles',
array('array', 'string', 'string', 'string', 'int'),
t('Returns a bandwidth-friendly list of the most recent posts in the system.')),
array(
'mt.getCategoryList',
'blogapi_mt_get_category_list',
array('array', 'string', 'string', 'string'),
t('Returns a list of all categories defined in the weblog.')),
array(
'mt.getPostCategories',
'blogapi_mt_get_post_categories',
array('array', 'string', 'string', 'string'),
t('Returns a list of all categories to which the post is assigned.')),
array(
'mt.setPostCategories',
'blogapi_mt_set_post_categories',
array('boolean', 'string', 'string', 'string', 'array'),
t('Sets the categories for a post.')),
array(
'mt.supportedMethods',
'xmlrpc_server_list_methods',
array('array'),
t('Retrieve information about the XML-RPC methods supported by the server.')),
array(
'mt.supportedTextFilters',
'blogapi_mt_supported_text_filters',
array('array'),
t('Retrieve information about the text formatting plugins supported by the server.')),
array(
'mt.getTrackbackPings',
'blogapi_mt_get_trackback_pings',
array('array', 'string'),
t('Retrieve the list of TrackBack pings posted to a particular entry. This could be used to programmatically retrieve the list of pings for a particular entry, then iterate through each of those pings doing the same, until one has built up a graph of the web of entries referencing one another on a particular topic.')),
array(
'mt.publishPost',
'blogap_mti_publish_post',
array('boolean', 'string', 'string', 'string'),
t('Publish (rebuild) all of the static files related to an entry from your weblog. Equivalent to saving an entry in the system (but without the ping).')));
}
/**
* Blogging API callback. Finds the URL of a user's blog.
*/
function blogapi_blogger_get_users_blogs($appid, $username, $password) {
$user = blogapi_validate_user($username, $password);
if ($user->uid) {
$types = _blogapi_get_node_types();
$structs = array();
foreach ($types as $type) {
$structs[] = array('url' => url('blog/' . $user->uid, NULL, NULL, true), 'blogid' => $type, 'blogName' => $user->name . ": " . $type);
}
return $structs;
}
else {
return blogapi_error($user);
}
}
/**
* Blogging API callback. Returns profile information about a user.
*/
function blogapi_blogger_get_user_info($appkey, $username, $password) {
$user = blogapi_validate_user($username, $password);
if ($user->uid) {
$name = explode(' ', $user->realname ? $user->realname : $user->name, 2);
return array(
'userid' => $user->uid,
'lastname' => $name[1],
'firstname' => $name[0],
'nickname' => $user->name,
'email' => $user->mail,
'url' => url('blog/' . $user->uid, NULL, NULL, true));
}
else {
return blogapi_error($user);
}
}
/**
* Blogging API callback. Inserts a new blog post as a node.
*/
function blogapi_blogger_new_post($appkey, $blogid, $username, $password, $content, $publish) {
$user = blogapi_validate_user($username, $password);
if (!$user->uid) {
return blogapi_error($user);
}
$edit = array();
$edit['type'] = _blogapi_blogid($blogid);
// get the node type defaults
$node_type_default = variable_get('node_options_'. $edit['type'], array('status', 'promote'));
$edit['uid'] = $user->uid;
$edit['name'] = $user->name;
$edit['promote'] = in_array('promote', $node_type_default);
$edit['comment'] = variable_get('comment_'. $edit['type'], 2);
$edit['moderate'] = in_array('moderate', $node_type_default);
$edit['revision'] = in_array('revision', $node_type_default);
$edit['format'] = FILTER_FORMAT_DEFAULT;
$edit['status'] = $publish;
// check for bloggerAPI vs. metaWeblogAPI
if (is_array($content)) {
$edit['title'] = $content['title'];
$edit['body'] = $content['description'];
_blogapi_mt_extra($edit, $content);
}
else {
$edit['title'] = blogapi_blogger_title($content);
$edit['body'] = $content;
}
node_validate($edit);
if ($errors = form_get_errors()) {
return blogapi_error(implode("\n", $errors));
}
if (!node_access('create', $node)) {
return blogapi_error(t('You do not have permission to create the type of post you wanted to create.'));
}
if (user_access('administer nodes') && !isset($edit['date'])) {
$edit['date'] = format_date(time(), 'custom', 'Y-m-d H:i:s O');
}
$node = node_submit($edit);
node_save($node);
if ($node->nid) {
watchdog('content', t('%type: added %title using blog API.', array('%type' => '<em>'. t($node->type) .'</em>', '%title' => theme('placeholder', $node->title))), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid"));
// blogger.newPost returns a string so we cast the nid to a string by putting it in double quotes:
return "$node->nid";
}
return blogapi_error(t('Error storing post.'));
}
/**
* Blogging API callback. Modifies the specified blog node.
*/
function blogapi_blogger_edit_post($appkey, $postid, $username, $password, $content, $publish) {
$user = blogapi_validate_user($username, $password);
if (!$user->uid) {
return blogapi_error($user);
}
$node = node_load($postid);
if (!$node) {
return blogapi_error(message_na());
}
// Let the teaser be re-generated.
unset($node->teaser);
if (!node_access('update', $node)) {
return blogapi_error(t('You do not have permission to update this post.'));
}
$node->status = $publish;
// check for bloggerAPI vs. metaWeblogAPI
if (is_array($content)) {
$node->title = $content['title'];
$node->body = $content['description'];
_blogapi_mt_extra($node, $content);
}
else {
$node->title = blogapi_blogger_title($content);
$node->body = $content;
}
node_validate($node);
if ($errors = form_get_errors()) {
return blogapi_error(implode("\n", $errors));
}
if (user_access('administer nodes') && !isset($edit['date'])) {
$node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O');
}
$node = node_submit($node);
node_save($node);
if ($node->nid) {
watchdog('content', t('%type: updated %title using blog API.', array('%type' => '<em>'. t($node->type) .'</em>', '%title' => theme('placeholder', $node->title))), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid"));
return true;
}
return blogapi_error(t('Error storing post.'));
}
/**
* Blogging API callback. Returns a specified blog node.
*/
function blogapi_blogger_get_post($appkey, $postid, $username, $password) {
$user = blogapi_validate_user($username, $password);
if (!$user->uid) {
return blogapi_error($user);
}
$node = node_load($postid);
return _blogapi_get_post($node, true);
}
/**
* Blogging API callback. Removes the specified blog node.
*/
function blogapi_blogger_delete_post($appkey, $postid, $username, $password, $publish) {
$user = blogapi_validate_user($username, $password);
if (!$user->uid) {
return blogapi_error($user);
}
node_delete($postid);
return true;
}
/**
* Blogging API callback. Returns the latest few postings in a user's blog. $bodies TRUE
* <a href="http://movabletype.org/docs/mtmanual_programmatic.html#item_mt%2EgetRecentPostTitles">
* returns a bandwidth-friendly list</a>.
*/
function blogapi_blogger_get_recent_posts($appkey, $blogid, $username, $password, $number_of_posts, $bodies = TRUE) {
// Remove unused appkey (from bloggerAPI).
$user = blogapi_validate_user($username, $password);
if (!$user->uid) {
return blogapi_error($user);
}
$type = _blogapi_blogid($blogid);
if ($bodies) {
$result = db_query_range("SELECT n.nid, n.title, r.body, n.created, u.name FROM {node} n, {node_revisions} r, {users} u WHERE n.uid = u.uid AND n.vid = r.vid AND n.type = '%s' AND n.uid = %d ORDER BY n.created DESC", $type, $user->uid, 0, $number_of_posts);
}
else {
$result = db_query_range("SELECT n.nid, n.title, n.created, u.name FROM {node} n, {users} u WHERE n.uid = u.uid AND n.type = '%s' AND n.uid = %d ORDER BY n.created DESC", $type, $user->uid, 0, $number_of_posts);
}
$blogs = array ();
while ($blog = db_fetch_object($result)) {
$blogs[] = _blogapi_get_post($blog, $bodies);
}
return $blogs;
}
function blogapi_metaweblog_new_post($blogid, $username, $password, $content, $publish) {
return blogapi_blogger_new_post('0123456789ABCDEF', $blogid, $username, $password, $content, $publish);
}
function blogapi_metaweblog_edit_post($postid, $username, $password, $content, $publish) {
return blogapi_blogger_edit_post('0123456789ABCDEF', $postid, $username, $password, $content, $publish);
}
function blogapi_metaweblog_get_post($postid, $username, $password) {
return blogapi_blogger_get_post('01234567890ABCDEF', $postid, $username, $password);
}
/**
* Blogging API callback. Inserts a file into Drupal.
*/
function blogapi_metaweblog_new_media_object($blogid, $username, $password, $file) {
$user = blogapi_validate_user($username, $password);
if (!$user->uid) {
return blogapi_error($user);
}
$name = basename($file['name']);
$data = $file['bits'];
if (!$data) {
return blogapi_error(t('No file sent.'));
}
if (!$file = file_save_data($data, $name)) {
return blogapi_error(t('Error storing file.'));
}
// Return the successful result.
return array('url' => file_create_url($file), 'struct');
}
/**
* Blogging API callback. Returns a list of the taxonomy terms that can be
* associated with a blog node.
*/
function blogapi_metaweblog_get_category_list($blogid, $username, $password) {
$type = _blogapi_blogid($blogid);
$vocabularies = module_invoke('taxonomy', 'get_vocabularies', $type, 'vid');
$categories = array();
if ($vocabularies) {
foreach ($vocabularies as $vocabulary) {
$terms = module_invoke('taxonomy', 'get_tree', $vocabulary->vid, 0, -1);
foreach ($terms as $term) {
$term_name = $term->name;
foreach (module_invoke('taxonomy', 'get_parents', $term->tid, 'tid') as $parent) {
$term_name = $parent->name . '/' . $term_name;
}
$categories[] = array('categoryName' => $term_name, 'categoryId' => $term->tid);
}
}
}
return $categories;
}
function blogapi_metaweblog_get_recent_posts($blogid, $username, $password, $number_of_posts) {
return blogapi_blogger_get_recent_posts('0123456789ABCDEF', $blogid, $username, $password, $number_of_posts, TRUE);
}
// see above
function blogapi_mt_get_recent_post_titles($blogid, $username, $password, $number_of_posts) {
return blogapi_blogger_get_recent_posts('0123456789ABCDEF', $blogid, $username, $password, $number_of_posts, FALSE);
}
/* **** */
function blogapi_mt_get_category_list($blogid, $username, $password) {
return blogapi_metaweblog_get_category_list($blogid, $username, $password);
}
/**
* Blogging API callback. Returns a list of the taxonomy terms that are
* assigned to a particular node.
*/
function blogapi_mt_get_post_categories($postid, $username, $password) {
$user = blogapi_validate_user($username, $password);
if (!$user->uid) {
return blogapi_error($user);
}
$terms = module_invoke('taxonomy', 'node_get_terms', $postid, 'tid');
$categories = array();
foreach ($terms as $term) {
$term_name = $term->name;
foreach (module_invoke('taxonomy', 'get_parents', $term->tid, 'tid') as $parent) {
$term_name = $parent->name . '/' . $term_name;
}
$categories[] = array('categoryName' => $term_name, 'categoryId' => $term->tid, 'isPrimary' => true);
}
return $categories;
}
/**
* Blogging API callback. Assigns taxonomy terms to a particular node.
*/
function blogapi_mt_set_post_categories($postid, $username, $password, $categories) {
$user = blogapi_validate_user($username, $password);
if (!$user->uid) {
return blogapi_error($user);
}
$node = node_load($postid);
$node->taxonomy = array();
foreach ($categories as $category) {
$node->taxonomy[] = $category['categoryId'];
}
node_save($node);
return TRUE;
}
/**
* Blogging API callback. Sends a list of available input formats.
*/
function blogapi_mt_supported_text_filters() {
// NOTE: we're only using anonymous' formats because the MT spec
// does not allow for per-user formats.
$formats = filter_formats();
$filters = array();
foreach ($formats as $format) {
$filter['key'] = $format->format;
$filter['label'] = $format->name;
$filters[] = $filter;
}
return $filters;
}
/**
* Blogging API callback. Can not be implemented without support from
* trackback module.
*/
function blogapi_mt_get_trackback_pings() {
return blogapi_error(t('Not implemented.'));
}
/**
* Blogging API callback. Publishes the given node
*/
function blogap_mti_publish_post($postid, $username, $password) {
$user = blogapi_validate_user($username, $password);
if (!$user->uid) {
return blogapi_error($user);
}
$node = node_load($postid);
if (!$node) {
return blogapi_error(t('Invalid post.'));
}
$node->status = 1;
if (!node_access('update', $node)) {
return blogapi_error(t('You do not have permission to update this post.'));
}
node_save($node);
return true;
}
/**
* Prepare an error message for returning to the XMLRPC caller.
*/
function blogapi_error($message) {
static $xmlrpcusererr;
if (!is_array($message)) {
$message = array($message);
}
$message = implode(' ', $message);
return xmlrpc_error($xmlrpcusererr + 1, strip_tags($message));
}
/**
* Ensure that the given user has permission to edit a blog.
*/
function blogapi_validate_user($username, $password) {
global $user;
$user = user_authenticate($username, $password);
if ($user->uid) {
if (user_access('edit own blog', $user)) {
return $user;
}
else {
return t("You either tried to edit somebody else's blog or you don't have permission to edit your own blog.");
}
}
else {
return t('Wrong username or password.');
}
}
/**
* For the blogger API, extract the node title from the contents field.
*/
function blogapi_blogger_title(&$contents) {
if (eregi('<title>([^<]*)</title>', $contents, $title)) {
$title = strip_tags($title[0]);
$contents = ereg_replace('<title>[^<]*</title>', '', $contents);
}
else {
list($title, $contents) = explode("\n", $contents, 2);
}
return $title;
}
function blogapi_settings() {
$form['blogapi_engine'] = array(
'#type' => 'select', '#title' => t('XML-RPC Engine'), '#default_value' => variable_get('blogapi_engine', 0),
'#options' => array(0 => 'Blogger', 1 => 'MetaWeblog', 2 => 'Movabletype'),
'#description' => t('RSD or Really-Simple-Discovery is a mechanism which allows external blogger tools to discover the APIs they can use to interact with Drupal. Here you can set the preferred method for blogger tools to interact with your site. The common XML-RPC engines are Blogger, MetaWeblog and Movabletype. If you are not sure which is the correct setting, choose Blogger.')
);
$node_types = node_get_types();
$defaults = isset($node_types['blog']) ? array('blog' => 1) : array();
$form['blogapi_node_types'] = array(
'#type' => 'checkboxes', '#title' => t('Blog types'), '#required' => TRUE,
'#default_value' => variable_get('blogapi_node_types', $defaults), '#options' => $node_types,
'#description' => t('Select the content types for which you wish to enable posting via blogapi. Each type will appear as a different "blog" in the client application (if supported).')
);
return $form;
}
function blogapi_menu($may_cache) {
$items = array();
if (drupal_get_path_alias($_GET['q']) == variable_get('site_frontpage', 'node')) {
drupal_add_link(array('rel' => 'EditURI',
'type' => 'application/rsd+xml',
'title' => t('RSD'),
'href' => url('blogapi/rsd', NULL, NULL, TRUE)));
}
if ($may_cache) {
$items[] = array('path' => 'blogapi', 'title' => t('RSD'), 'callback' => 'blogapi_blogapi', 'access' => user_access('access content'), 'type' => MENU_CALLBACK);
}
return $items;
}
function blogapi_blogapi() {
switch (arg(1)) {
case 'rsd':
blogapi_rsd();
break;
default:
drupal_not_found();
break;
}
}
function blogapi_rsd() {
global $base_url;
$xmlrpc = $base_url .'/'. 'xmlrpc.php';
$base = url('', NULL, NULL, TRUE);
$blogid = 1; # until we figure out how to handle multiple bloggers
drupal_set_header('Content-Type: application/rsd+xml; charset=utf-8');
print <<<__RSD__
<?xml version="1.0"?>
<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">
<service>
<engineName>Drupal</engineName>
<engineLink>http://drupal.org/</engineLink>
<homePageLink>$base</homePageLink>
<apis>
<api name="MetaWeblog" preferred="false" apiLink="$xmlrpc" blogID="$blogid" />
<api name="Blogger" preferred="true" apiLink="$xmlrpc" blogID="$blogid" />
<api name="MovableType" preferred="false" apiLink="$xmlrpc" blogID="$blogid" />
</apis>
</service>
</rsd>
__RSD__;
}
/**
* Handles extra information sent by clients according to MovableType's spec.
*/
function _blogapi_mt_extra(&$node, $struct) {
if (is_array($node)) {
$was_array = true;
$node = (object)$node;
}
// mt_allow_comments
if (array_key_exists('mt_allow_comments', $struct)) {
switch ($struct['mt_allow_comments']) {
case 0:
$node->comment = 0;
break;
case 1:
$node->comment = 2;
break;
case 2:
$node->comment = 1;
break;
}
}
// merge the 3 body sections (description, mt_excerpt, mt_text_more) into
// one body
if ($struct['mt_excerpt']) {
$node->body = $struct['mt_excerpt'] .'<!--break-->'.$node->body;
}
if ($struct['mt_text_more']) {
$node->body = $node->body . '<!--extended-->' . $struct['mt_text_more'];
}
// mt_tb_ping_urls
if (function_exists('trackback_send')) {
if (is_array($struct['mt_tb_ping_urls'])) {
foreach ($struct['mt_tb_ping_urls'] as $tb_ping_url) {
$node->tb_url = $tb_ping_url->getVal();
trackback_send($node);
unset($node->tb_url); // make sure we don't ping twice
}
}
else {
$node->tb_url = $struct['mt_tb_ping_urls'];
}
}
// mt_convert_breaks
if ($struct['mt_convert_breaks']) {
$node->format = $struct['mt_convert_breaks'];
}
// dateCreated
if ($struct['dateCreated']) {
$node->date = format_date(mktime($struct['dateCreated']->hour, $struct['dateCreated']->minute, $struct['dateCreated']->second, $struct['dateCreated']->month, $struct['dateCreated']->day, $struct['dateCreated']->year), 'custom', 'Y-m-d H:i:s O');
}
if ($was_array) {
$node = (array)$node;
}
}
function _blogapi_get_post($node, $bodies = true) {
$xmlrpcval = array (
'userid' => $node->name,
'dateCreated' => xmlrpc_date($node->created),
'title' => $node->title,
'postid' => $node->nid,
'link' => url('node/'.$node->nid, NULL, NULL, true),
'permaLink' => url('node/'.$node->nid, NULL, NULL, true),
);
if ($bodies) {
if ($node->comment = 1) {
$comment = 2;
}
if ($node->comment = 2) {
$comment = 1;
}
$xmlrpcval['content'] = "<title>$node->title</title>$node->body";
$xmlrpcval['description'] = $node->body;
// Add MT specific fields
$xmlrpcval['mt_allow_comments'] = $comment;
$xmlrpcval['mt_convert_breaks'] = $node->format;
}
return $xmlrpcval;
}
function _blogapi_blogid($id) {
if (is_numeric($id)) {
return 'blog';
}
else {
return $id;
}
}
function _blogapi_get_node_types() {
$available_types = array_keys(array_filter(variable_get('blogapi_node_types', array('blog' => 1))));
$types = array();
foreach (node_get_types() as $type => $name) {
if (node_access('create', $type) && in_array($type, $available_types)) {
$types[] = $type;
}
}
return $types;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,572 +0,0 @@
<?php
// $Id$
/**
* @file
* Enables the use of personal and site-wide contact forms.
*/
/**
* Implementation of hook_help().
*/
function contact_help($section) {
switch ($section) {
case 'admin/help#contact':
$output = '<p>'. t('The contact module enables the use of both personal and site-wide contact forms, thereby facilitating easy communication within the community. While personal contact forms allow users to contact each other by e-mail, site-wide forms allow community members to contact the site administration from a central location. Users can specify a subject and message in the contact form, and also request that a copy of the e-mail be sent to their own address.') .'</p>';
$output .= '<p>'. t("Users can activate/deactivate their personal contact forms in their account settings. Upon activation, a contact tab will appear in their user profiles. Privileged users such as site administrators are able to contact users even if they have chosen not to enable this feature.") .'</p>';
$output .= '<p>'. t('If the menu module is enabled, a menu item linking to the site-wide contact page is added to the navigation block. It is disabled by default, but can be enabled via the <a href="%menu-module">menu management</a> page. Links to the contact page may also be added to the primary and secondary links using the same page.', array('%menu-module' => url('admin/menu'))) .'</p>';
$output .= t('Contact module links:') .'<ul>';
$output .= '<li>'. t('Default site-wide <a href="%contact-page">contact page</a>.', array('%contact-page' => url('contact'))) .'</li>';
$output .= '<li>'. t('Site-wide contact form <a href="%configuration-page">category configuration</a>.', array('%configuration-page' => url('admin/contact'))) .'</li>';
$output .= '<li>'. t('Site-wide contact form <a href="%additional-settings">general settings</a>.', array('%additional-settings' => url('admin/contact/settings'))) .'</li>';
$output .= '<li>'. t('Site-wide contact form <a href="%menu-configuration">menu configuration</a>.', array('%menu-configuration' => url('admin/menu'))) .'</li></ul>';
$output .= t('For more information, please read the configuration and customization handbook page for the <a href="%contact">contact module</a>.', array('%contact' => url('http://drupal.org/handbook/modules/contact/', NULL, NULL, TRUE)));
return $output;
case 'admin/modules#description':
return t('Enables the use of both personal and site-wide contact forms.');
case 'admin/contact':
$output = t('This page lets you setup <a href="%form">your site-wide contact form</a>. To do so, add one or more categories. You can associate different recipients with each category to route e-mails to different people. For example, you can route website feedback to the webmaster and direct product information requests to the sales department. On the <a href="%settings">settings page</a>, you can customize the information shown above the contact form. This can be useful to provide additional contact information such as your postal address and telephone number.', array('%settings' => url('admin/contact/settings'), '%form' => url('contact')));
if (!module_exist('menu')) {
$menu_note = t('The menu item can be customized and configured only once the menu module has been <a href="%modules-page">enabled</a>.', array('%modules-page' => url('admin/modules')));
}
else {
$menu_note = '';
}
$output .= '<p>'. t('The contact module also adds a <a href="%menu-settings">menu item</a> (disabled by default) to the navigation block.', array('%menu-settings' => url('admin/menu'))) .' '. $menu_note .'</p>';
return($output);
}
}
/**
* Implementation of hook_menu().
*/
function contact_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'admin/contact',
'title' => t('contact form'),
'callback' => 'contact_admin_categories',
'access' => user_access('administer site configuration'),
);
$items[] = array('path' => 'admin/contact/category',
'title' => t('categories'),
'callback' => 'contact_admin_categories',
'access' => user_access('administer site configuration'),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array('path' => 'admin/contact/category/list',
'title' => t('list'),
'callback' => 'contact_admin_categories',
'access' => user_access('administer site configuration'),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array('path' => 'admin/contact/category/add',
'title' => t('add category'),
'callback' => 'contact_admin_edit',
'access' => user_access('administer site configuration'),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
);
$items[] = array('path' => 'admin/contact/category/edit',
'title' => t('edit contact category'),
'callback' => 'contact_admin_edit',
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
$items[] = array('path' => 'admin/contact/category/delete',
'title' => t('delete contact'),
'callback' => 'contact_admin_delete',
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
$items[] = array('path' => 'admin/contact/settings',
'title' => t('settings'),
'callback' => 'contact_admin_settings',
'access' => user_access('administer site configuration'),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
);
$items[] = array('path' => 'contact',
'title' => t('contact'),
'callback' => 'contact_mail_page',
'access' => user_access('access content'),
'type' => MENU_SUGGESTED_ITEM,
);
}
else {
if (arg(0) == 'user' && is_numeric(arg(1))) {
$items[] = array('path' => "user/". arg(1) ."/contact", 'title' => t('contact'),
'callback' => 'contact_mail_user', 'type' => MENU_LOCAL_TASK, 'weight' => 2);
}
}
return $items;
}
/**
* Implementation of hook_user().
*
* Allows the user the option of enabling/disabling his personal contact form.
*/
function contact_user($type, $edit, &$user, $category = NULL) {
if ($type == 'form' && $category == 'account') {
$form['contact'] = array('#type' => 'fieldset',
'#title' => t('Contact settings'),
'#weight' => 5,
'#collapsible' => TRUE,
);
$form['contact']['contact'] = array('#type' => 'checkbox',
'#title' => t('Personal contact form'),
'#default_value' => $edit['contact'],
'#description' => t('Allow other users to contact you by e-mail via <a href="%url">your personal contact form</a>. Note that while your e-mail address is not made public to other members of the community, privileged users such as site administrators are able to contact you even if you choose not to enable this feature.', array('%url' => url("user/$user->uid/contact"))),
);
return $form;
}
if ($type == 'validate') {
return array('contact' => $edit['contact']);
}
}
/**
* Categories/list tab.
*/
function contact_admin_categories() {
$result = db_query('SELECT cid, category, recipients, selected FROM {contact} ORDER BY weight, category');
$rows = array();
while ($category = db_fetch_object($result)) {
$rows[] = array($category->category, $category->recipients, ($category->selected ? t('Yes') : t('No')), l(t('edit'), 'admin/contact/category/edit/'. $category->cid), l(t('delete'), 'admin/contact/category/delete/'. $category->cid));
}
$header = array(t('Category'), t('Recipients'), t('Selected'), array('data' => t('Operations'), 'colspan' => 2));
return theme('table', $header, $rows);
}
/**
* Category edit page.
*/
function contact_admin_edit($cid = NULL) {
if (arg(3) == "edit" && $cid > 0) {
$category = db_fetch_object(db_query("SELECT * FROM {contact} WHERE cid = %d", $cid));
$edit['cid'] = $category->cid;
$edit['category'] = $category->category;
$edit['recipients'] = $category->recipients;
$edit['reply'] = $category->reply;
$edit['weight'] = $category->weight;
$edit['selected'] = $category->selected;
}
$form['category'] = array('#type' => 'textfield',
'#title' => t('Category'),
'#maxlength' => 255,
'#default_value' => $edit['category'],
'#description' => t("Example: 'website feedback' or 'product information'."),
'#required' => TRUE,
);
$form['recipients'] = array('#type' => 'textarea',
'#title' => t('Recipients'),
'#default_value' => $edit['recipients'],
'#description' => t("Example: 'webmaster@yoursite.com' or 'sales@yoursite.com'. To specify multiple recipients, separate each e-mail address with a comma."),
'#required' => TRUE,
);
$form['reply'] = array('#type' => 'textarea',
'#title' => t('Auto-reply'),
'#default_value' => $edit['reply'],
'#description' => t('Optional auto-reply. Leave empty if you do not want to send the user an auto-reply message.'),
);
$form['weight'] = array('#type' => 'weight',
'#title' => t('Weight'),
'#default_value' => $edit['weight'],
'#description' => t('When listing categories, those with lighter (smaller) weights get listed before categories with heavier (larger) weights. Categories with equal weights are sorted alphabetically.'),
);
$form['selected'] = array('#type' => 'select',
'#title' => t('Selected'),
'#options' => array('0' => t('No'), '1' => t('Yes')),
'#default_value' => $edit['selected'],
'#description' => t('Set this to <em>Yes</em> if you would like this category to be selected by default.'),
);
$form['cid'] = array('#type' => 'hidden',
'#value' => $edit['cid'],
);
$form['submit'] = array('#type' => 'submit',
'#value' => t('Submit'),
);
return drupal_get_form('contact_admin_edit', $form);
}
/**
* Validate the contact category edit page form submission.
*/
function contact_admin_edit_validate($form_id, $form_values) {
if (empty($form_values['category'])) {
form_set_error('category', t('You must enter a category.'));
}
if (empty($form_values['recipients'])) {
form_set_error('recipients', t('You must enter one or more recipients.'));
}
else {
$recipients = explode(',', $form_values['recipients']);
foreach($recipients as $recipient) {
if (!valid_email_address(trim($recipient))) {
form_set_error('recipients',t('%recipient is an invalid e-mail address.', array('%recipient' => theme('placeholder', $recipient))));
}
}
}
}
/**
* Process the contact category edit page form submission.
*/
function contact_admin_edit_submit($form_id, $form_values) {
if ($form_values['selected']) {
// Unselect all other contact categories.
db_query('UPDATE {contact} SET selected = 0');
}
$recipients = explode(',', $form_values['recipients']);
foreach($recipients as $key=>$recipient) {
// E-mail address validation has already been done in _validate.
$recipients[$key] = trim($recipient);
}
$form_values['recipients'] = implode(',', $recipients);
if (arg(3) == 'add') {
db_query("INSERT INTO {contact} (category, recipients, reply, weight, selected) VALUES ('%s', '%s', '%s', %d, %d)", $form_values['category'], $form_values['recipients'], $form_values['reply'], $form_values['weight'], $form_values['selected']);
drupal_set_message(t('Category %category has been added.', array('%category' => theme('placeholder', $form_values['category']))));
watchdog('mail', t('Contact form: category %category added.', array('%category' => theme('placeholder', $form_values['category']))), WATCHDOG_NOTICE, l(t('view'), 'admin/contact'));
}
else {
db_query("UPDATE {contact} SET category = '%s', recipients = '%s', reply = '%s', weight = %d, selected = %d WHERE cid = %d", $form_values['category'], $form_values['recipients'], $form_values['reply'], $form_values['weight'], $form_values['selected'], $form_values['cid']);
drupal_set_message(t('Category %category has been updated.', array('%category' => theme('placeholder', $form_values['category']))));
watchdog('mail', t('Contact form: category %category updated.', array('%category' => theme('placeholder', $form_values['category']))), WATCHDOG_NOTICE, l(t('view'), 'admin/contact'));
}
return 'admin/contact';
}
/**
* Category delete page.
*/
function contact_admin_delete($cid = NULL) {
if ($info = db_fetch_object(db_query("SELECT category FROM {contact} WHERE cid = %d", $cid))) {
$form['category'] = array('#type' => 'hidden',
'#value' => $info->category,
);
return confirm_form('contact_admin_delete', $form, t('Are you sure you want to delete %category?', array('%category' => theme('placeholder', $info->category))), 'admin/contact', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}
else {
drupal_set_message(t('Category not found.'), 'error');
drupal_goto('admin/contact');
}
}
/**
* Process category delete form submission.
*/
function contact_admin_delete_submit($form_id, $form_values) {
db_query("DELETE FROM {contact} WHERE cid = %d", arg(4));
drupal_set_message(t('Category %category has been deleted.', array('%category' => theme('placeholder', $form_values['category']))));
watchdog('mail', t('Contact form: category %category deleted.', array('%category' => theme('placeholder', $form_values['category']))), WATCHDOG_NOTICE);
return 'admin/contact';
}
/**
* Settings tab. Using a form rather than hook_settings().
*/
function contact_admin_settings() {
$form['contact_form_information'] = array('#type' => 'textarea',
'#title' => t('Additional information'),
'#default_value' => variable_get('contact_form_information', t('You can leave a message using the contact form below.')),
'#description' => t('Information to show on the <a href="%form">contact page</a>. Can be anything from submission guidelines to your postal address or telephone number.', array('%form' => url('contact'))),
);
$form['contact_hourly_threshold'] = array('#type' => 'select',
'#title' => t('Hourly threshold'),
'#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50)),
'#default_value' => variable_get('contact_hourly_threshold', 3),
'#description' => t('The maximum number of contact form submissions a user can perform per hour.'),
);
$form['submit'] = array('#type' => 'submit',
'#value' => t('Save configuration'),
);
$form['reset'] = array('#type' => 'submit',
'#value' => t('Reset to defaults'),
);
return drupal_get_form('contact_admin_settings', $form);
}
/**
* Process settings form submission.
*/
function contact_admin_settings_submit($form_id, $form_values) {
$op = isset($_POST['op']) ? $_POST['op'] : '';
if ($op == t('Reset to defaults')) {
foreach ($form_values as $key => $value) {
variable_del($key);
}
drupal_set_message(t('The configuration options have been reset to their default values.'));
}
else {
foreach ($form_values as $key => $value) {
variable_set($key, $value);
}
drupal_set_message(t('The configuration options have been saved.'));
}
}
/**
* Personal contact page.
*/
function contact_mail_user() {
global $user;
if ($account = user_load(array('uid' => arg(1), 'status' => 1))) {
if (!$account->contact && !user_access('administer users')) {
$output = t('%name is not accepting e-mails.', array('%name' => $account->name));
}
else if (!$user->uid) {
$output = t('Please <a href="%login">login</a> or <a href="%register">register</a> to send %name a message.', array('%login' => url('user/login'), '%register' => url('user/register'), '%name' => $account->name));
}
else if (!valid_email_address($user->mail)) {
$output = t('You need to provide a valid e-mail address to contact other users. Please update your <a href="%url">user information</a> and try again.', array('%url' => url("user/$user->uid/edit")));
}
else if (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3))) {
$output = t('You cannot contact more than %number users per hour. Please try again later.', array('%number' => variable_get('contact_hourly_threshold', 3)));
}
else {
drupal_set_title($account->name);
$form['#token'] = $user->name . $user->mail;
$form['from'] = array('#type' => 'item',
'#title' => t('From'),
'#value' => $user->name .' &lt;'. $user->mail .'&gt;',
);
$form['to'] = array('#type' => 'item',
'#title' => t('To'),
'#value' => $account->name,
);
$form['subject'] = array('#type' => 'textfield',
'#title' => t('Subject'),
'#maxlength' => 50,
'#required' => TRUE,
);
$form['message'] = array('#type' => 'textarea',
'#title' => t('Message'),
'#rows' => 15,
'#required' => TRUE,
);
$form['copy'] = array('#type' => 'checkbox',
'#title' => t('Send me a copy.'),
);
$form['submit'] = array('#type' => 'submit',
'#value' => t('Send e-mail'),
);
$output = drupal_get_form('contact_mail_user', $form);
}
return $output;
}
else {
drupal_not_found();
}
}
/**
* Process the personal contact page form submission.
*/
function contact_mail_user_submit($form_id, $edit) {
global $user;
$account = user_load(array('uid' => arg(1), 'status' => 1));
// Compose the body:
$message[] = "$account->name,";
$message[] = t("%name (%name-url) has sent you a message via your contact form (%form-url) at %site.", array('%name' => $user->name, '%name-url' => url("user/$user->uid", NULL, NULL, TRUE), '%form-url' => url($_GET['q'], NULL, NULL, TRUE), '%site' => variable_get('site_name', 'drupal')));
$message[] = t("If you don't want to receive such e-mails, you can change your settings at %url.", array('%url' => url("user/$account->uid", NULL, NULL, TRUE)));
$message[] = t('Message:');
$message[] = $edit['message'];
// Tidy up the body:
foreach ($message as $key => $value) {
$message[$key] = wordwrap($value);
}
// Prepare all fields:
$to = $account->mail;
$from = $user->mail;
// Format the subject:
$subject = '['. variable_get('site_name', 'drupal') .'] '. $edit['subject'];
// Prepare the body:
$body = implode("\n\n", $message);
// Send the e-mail:
user_mail($to, $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
// Send a copy if requested:
if ($edit['copy']) {
user_mail($from, $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
}
// Log the operation:
flood_register_event('contact');
watchdog('mail', t('%name-from sent %name-to an e-mail.', array('%name-from' => theme('placeholder', $user->name), '%name-to' => theme('placeholder', $account->name))));
// Set a status message:
drupal_set_message(t('The message has been sent.'));
// Jump to the user's profile page:
return "user/$account->uid";
}
/**
* Site-wide contact page
*/
function contact_mail_page() {
global $user;
$breadcrumb[] = array('path' => 'contact', 'title' => t('contact'));
menu_set_location($breadcrumb);
if (!flood_is_allowed('contact', variable_get('contact_hourly_threshold', 3))) {
$output = t("You cannot send more than %number messages per hour. Please try again later.", array('%number' => variable_get('contact_hourly_threshold', 3)));
}
else {
if ($user->uid) {
$edit['name'] = $user->name;
$edit['mail'] = $user->mail;
}
$result = db_query('SELECT cid, category, selected FROM {contact} ORDER BY weight, category');
$categories[] = t('--');
while ($category = db_fetch_object($result)) {
$categories[$category->cid] = $category->category;
if ($category->selected) {
$default_category = $category->cid;
}
}
if (count($categories) > 1) {
$form['#token'] = $user->name . $user->mail;
$form['contact_information'] = array('#type' => 'markup',
'#value' => variable_get('contact_form_information', t('You can leave us a message using the contact form below.')),
);
$form['name'] = array('#type' => 'textfield',
'#title' => t('Your name'),
'#maxlength' => 255,
'#default_value' => $edit['name'],
'#required' => TRUE,
);
$form['mail'] = array('#type' => 'textfield',
'#title' => t('Your e-mail address'),
'#maxlength' => 255,
'#default_value' => $edit['mail'],
'#required' => TRUE,
);
$form['subject'] = array('#type' => 'textfield',
'#title' => t('Subject'),
'#maxlength' => 255,
'#default_value' => $edit['subject'],
'#required' => TRUE,
);
if (count($categories) > 2) {
$form['cid'] = array('#type' => 'select',
'#title' => t('Category'),
'#default_value' => $default_category,
'#options' => $categories,
'#required' => TRUE,
);
}
$form['message'] = array('#type' => 'textarea',
'#title' => t('Message'),
'#default_value' => $edit['message'],
'#required' => TRUE,
);
$form['copy'] = array('#type' => 'checkbox',
'#title' => t('Send me a copy.'),
'#default_value' => $edit['copy'],
);
$form['submit'] = array('#type' => 'submit',
'#value' => t('Send e-mail'),
);
$output = drupal_get_form('contact_mail_page', $form);
}
else {
$output = t('The contact form has not been configured.');
}
}
return $output;
}
/**
* Validate the site-wide contact page form submission.
*/
function contact_mail_page_validate($form_id, &$form) {
global $form_values;
if (!$form['cid']) {
// Look if there is only one category
$result = db_query('SELECT cid FROM {contact}');
if (db_num_rows($result) == 1) {
$category = db_fetch_object($result);
$form_values['cid'] = $category->cid;
}
else {
form_set_error('category', t('You must select a valid category.'));
}
if (!valid_email_address($form['mail'])) {
form_set_error('mail', t('You must enter a valid e-mail address.'));
}
}
}
/**
* Process the site-wide contact page form submission.
*/
function contact_mail_page_submit($form_id, $edit) {
// Prepare the sender:
$from = $edit['mail'];
// Compose the body:
$message[] = t("%name sent a message using the contact form at %form.", array('%name' => $edit['name'], '%form' => url($_GET['q'], NULL, NULL, TRUE)));
$message[] = $edit['message'];
// Tidy up the body:
foreach ($message as $key => $value) {
$message[$key] = wordwrap($value);
}
// Load the category information:
$contact = db_fetch_object(db_query("SELECT * FROM {contact} WHERE cid = %d", $edit['cid']));
// Format the category:
$subject = t('[%category] %subject', array('%category' => $contact->category, '%subject' => $edit['subject']));
// Prepare the body:
$body = implode("\n\n", $message);
// Send the e-mail to the recipients:
user_mail($contact->recipients, $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
// If the user requests it, send a copy.
if ($edit['copy']) {
user_mail($from, $subject, $body, "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from");
}
// Send an auto-reply if necessary:
if ($contact->reply) {
user_mail($from, $subject, wordwrap($contact->reply), "From: $contact->recipients\nReply-to: $contact->recipients\nX-Mailer: Drupal\nReturn-path: $contact->recipients\nErrors-to: $contact->recipients");
}
// Log the operation:
flood_register_event('contact');
watchdog('mail', t('%name-from sent an e-mail regarding %category.', array('%name-from' => theme('placeholder', $edit['name'] ." <$from>"), '%category' => theme('placeholder', $contact->category))));
// Update user:
drupal_set_message(t('Your message has been sent.'));
// Jump to home page rather than back to contact page to avoid contradictory messages if flood control has been activated.
return('');
}

View File

@ -1,364 +0,0 @@
<?php
// $Id$
/**
* @file
* Lets users log in using a Drupal ID and can notify a central server about your site.
*/
define('VERSION', '4.7.0');
/**
* Implementation of hook_help().
*/
function drupal_help($section) {
switch ($section) {
case 'admin/help#drupal':
$output = '<p>'. t('The Drupal module uses the XML-RPC network communication protocol to connect your site with a central server that maintains a directory of client sites.') .'</p>';
$output .= t('<p>Enabling the Drupal module will allow you to:</p>
<ul>
<li>register your site with a server, including (optionally) posting information on your installed modules and themes and summary statistics on your number of posts and users, information that can help rank Drupal modules and themes</li>
<li>enable other sites to register with your site</li>
<li>allow members on all sites using the Drupal module to log in to your site without registering using their distributed identification</li>
<li>allow members to log in to any other site that uses the Drupal module, using a login name that looks much like an e-mail address: <em>username@example.com</em></li>
</ul>
');
$output .= '<p>'. t('The Drupal module administration page allows you to set the xml-rpc server page and other related options.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>run your cron job at your site\'s <a href="%file-cron">cron page</a></li>
<li>view your <a href="%file-xmlrpc">XML-RPC page</a>.</li>
<li>administer Drupal <a href="%admin-settings-drupal">administer &gt;&gt; settings &gt;&gt; drupal</a>.</li>
</ul>
', array('%file-cron' => 'cron.php', '%file-xmlrpc' => 'xmlrpc.php', '%admin-settings-drupal' => url('admin/settings/drupal')));
$output .= '<p>'. t('If you maintain a directory of sites, you can list them on a page using the <code>drupal_client_page()</code> function. Sample instructions:
<ul>
<li>Enable the page module. Select create content &gt;&gt; page.</li>
<li>For input format, select PHP code.</li>
<li>Give the page a title. For body, put:
<pre>
&lt;?php
print drupal_client_page();
?&gt;
</pre>
<li>Save the page.</li>
</ul>') . '</p>';
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%drupal">Drupal page</a>.', array('%drupal' => 'http://drupal.org/handbook/modules/drupal/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Lets you register your site with a central server and improve ranking of Drupal projects by posting information on your installed modules and themes; also enables users to log in using a Drupal ID.');
case 'admin/settings/drupal':
return t('<p>Using this your site can "call home" to another Drupal server. By calling home to drupal.org and sending a list of your installed modules and themes, you help rank projects on drupal.org and so assist all Drupal administrators to find the best components for meeting their needs. If you want to register with a different server, you can change the Drupal XML-RPC server setting -- but the server has to be able to handle Drupal XML. Some XML-RPC servers may present directories of all registered sites. To get all your site information listed, go to the <a href="%site-settings">settings page</a> and set the site name, the e-mail address, the slogan, and the mission statement.</p>', array('%site-settings' => url('admin/settings')));
case 'user/help#drupal':
return variable_get('drupal_authentication_service', 0) ? t("<p><a href=\"%Drupal\">Drupal</a> is the name of the software that powers %this-site. There are Drupal web sites all over the world, and many of them share their registration databases so that users may freely log in to any Drupal site using a single <strong>Drupal ID</strong>.</p>
<p>So please feel free to log in to your account here at %this-site with a username from another Drupal site. The format of a Drupal ID is similar to an e-mail address: <strong>username</strong>@<em>server</em>. An example of a valid Drupal ID is <strong>mwlily</strong>@<em>drupal.org</em>.</p>", array('%Drupal' => 'http://drupal.org', '%this-site' => '<em>'. variable_get('site_name', 'this web site') .'</em>')) : NULL;
}
}
/**
* Implementation of hook_settings().
*/
function drupal_settings() {
// Check if all required fields are present
if ((variable_get('site_name', 'drupal') == 'drupal') || (variable_get('site_name', 'drupal') == '')) {
form_set_error('drupal_directory', t('You must set the name of your site on the <a href="%url">administer &raquo; settings</a> page.', array('%url' => url('admin/settings'))));
}
else if (variable_get('site_mail', ini_get('sendmail_from')) == '') {
form_set_error('drupal_directory', t('You must set an e-mail address for your site on the <a href="%url">administer &raquo; settings</a> page.', array('%url' => url('admin/settings'))));
}
else if (variable_get('site_slogan', '') == '') {
form_set_error('drupal_directory', t('You must set your site slogan on the <a href="%url">administer &raquo; settings</a> page.', array('%url' => url('admin/settings'))));
}
else if (variable_get('site_mission', '') == '') {
form_set_error('drupal_directory', t('You must set your site mission on the <a href="%url">administer &raquo; settings</a> page.' , array('%url' => url('admin/settings'))));
}
$options = array('1' => t('Enabled'), '0' => t('Disabled'));
$form['drupal'] = array(
'#type' => 'fieldset',
'#title' => t('Post data to another site'),
'#tree' => FALSE
);
$form['drupal']['drupal_register'] = array(
'#type' => 'radios',
'#title' => t('Register with a Drupal server'),
'#default_value' => variable_get('drupal_register', 0),
'#options' => $options,
'#description' => t("If enabled, your Drupal site will register itself with the specified Drupal XML-RPC server. For this to work properly, you must set your site's name, e-mail address, slogan and mission statement. When the \"Drupal XML-RPC server\" field is set to \"%drupal-xml-rpc\", your web site will register itself with drupal.org. Requires the cron feature to be enabled.", array("%drupal-xml-rpc" => "http://drupal.org/xmlrpc.php", "%drupal-sites" => "http://drupal.org/drupal-sites/"))
);
$form['drupal']['drupal_server'] = array(
'#type' => 'textfield',
'#title' => t('Drupal XML-RPC server'),
'#default_value' => variable_get('drupal_server', 'http://drupal.org/xmlrpc.php'),
'#description' => t('The URL of the Drupal XML-RPC server you wish to register with.')
);
$form['drupal']['drupal_system'] = array(
'#type' => 'radios',
'#title' => t('Send system information'),
'#default_value' => variable_get('drupal_system', 0),
'#options' => $options,
'#description' => t("If enabled, your site will send information on its installed components (modules, themes, and theme engines). This information can help in compiling statistics on usage of Drupal projects.")
);
$form['drupal']['drupal_statistics'] = array(
'#type' => 'radios',
'#title' => t('Send statistics'),
'#default_value' => variable_get('drupal_statistics', 0),
'#options' => $options,
'#description' => t("If enabled, your site will send summary statistics on the number of registered users and the total number of posts. No private information will be sent. These data help to improve the ranking statistics of Drupal projects.")
);
$form['services'] = array(
'#type' => 'fieldset',
'#title' => t('Receive data from other sites'),
'#tree' => FALSE
);
$form['services']['drupal_client_service'] = array(
'#type' => 'radios',
'#title' => t('Allow other Drupal sites to register'),
'#default_value' => variable_get('drupal_client_service', 0),
'#options' => $options,
'#description' => t('If enabled, your Drupal site will allow other sites to register with your site and send information to this site. This functionality can be used to maintain a list of related sites.')
);
$form['services']['drupal_authentication_service'] = array(
'#type' => 'radios',
'#title' => t('Authentication service'),
'#default_value' => variable_get('drupal_authentication_service', 0),
'#options' => $options,
'#description' => t('If enabled, your Drupal site will accept logins with the user names of other Drupal sites, and likewise provide authentication for users logging into other Drupal sites, based on their user accounts here.')
);
return $form;
}
/**
* Implementation of hook_cron(); handles pings to and from the site.
*/
function drupal_cron() {
if (time() - variable_get('cron_last', 0) > 21600) {
// If this site acts as a Drupal XML-RPC server, delete the sites that
// stopped sending "ping" messages.
if (variable_get('drupal_client_service', 0)) {
$result = db_query("SELECT cid FROM {client} WHERE changed < %d", time() - 259200);
while ($client = db_fetch_object($result)) {
db_query("DELETE FROM {client_system} WHERE cid = %d", $client->cid);
db_query("DELETE FROM {client} WHERE cid = %d", $client->cid);
}
}
// If this site acts as a Drupal XML-RPC client, send a message to the
// Drupal XML-RPC server.
if (variable_get('drupal_register', 0) && variable_get('drupal_server', 0)) {
drupal_notify(variable_get('drupal_server', ''));
}
}
}
/**
* Callback function from drupal_xmlrpc() called when another site pings this one.
*/
function drupal_client_ping($client, $system) {
/*
** Parse our parameters:
*/
foreach (array('link', 'name', 'mail', 'slogan', 'mission') as $key) {
$client[$key] = strip_tags($client[$key]);
}
/*
** Update the data in our database and send back a reply:
*/
if ($client['link'] && $client['name'] && $client['mail'] && $client['slogan'] && $client['mission']) {
$result = db_query(db_rewrite_sql("SELECT cid FROM {client} WHERE link = '%s'"), $client['link']);
if (db_num_rows($result)) {
$record = db_fetch_object($result);
$client['cid'] = $record->cid;
// We have an existing record.
db_query("UPDATE {client} SET link = '%s', name = '%s', mail = '%s', slogan = '%s', mission = '%s', users = %d, nodes = %d, version = '%s', changed = '%s' WHERE cid = %d", $client['uid'], $client['link'], $client['name'], $client['mail'], $client['slogan'], $client['mission'], $client['users'], $client['nodes'], $client['version'], time(), $client['cid']);
}
else {
$client['cid'] = db_next_id('{client}_cid');
db_query("INSERT INTO {client} (cid, link, name, mail, slogan, mission, users, nodes, version, created, changed) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", $client['cid'], $client['link'], $client['name'], $client['mail'], $client['slogan'], $client['mission'], $client['users'], $client['nodes'], $client['version'], time(), time());
}
if (is_array($system)) {
db_query("DELETE FROM {client_system} WHERE cid = %d", $client['cid']);
foreach ($system as $item) {
db_query("INSERT INTO {client_system} (cid, name, type) VALUES (%d, '%s', '%s')", $client['cid'], $item['name'], $item['type']);
}
}
watchdog('client ping', t('Ping from %name (%link).', array('%name' => theme('placeholder', $client['name']), '%link' => theme('placeholder', $client['link']))), WATCHDOG_NOTICE, '<a href="'. check_url($client['link']) .'">view</a>');
return TRUE;
}
else {
return 0;
}
}
/**
* Formats a list of all clients.
*
* This function may be called from a custom page on sites that are
* Drupal directory servers.
*/
function drupal_client_page($sort = 'name') {
$result = db_query('SELECT * FROM {client} ORDER BY %s', $sort);
$clients = array();
while ($client = db_fetch_object($result)) {
$clients[] = $client;
}
return theme('client_list', $clients);
}
/**
* Theme a client list.
*/
function theme_client_list($clients) {
// Note: All fields except the mission are treated as plain-text.
// The mission is stripped of any HTML tags to keep the output simple and consistent.
$output = "\n<dl>\n";
foreach ($clients as $client) {
$output .= ' <dt><a href="' . check_url($client->link) . '">' . check_plain($client->name) . '</a> - ' . check_plain($client->slogan) . "</dt>\n";
$output .= ' <dd>' . strip_tags($client->mission) . "</dd>\n";
}
$output .= "</dl>\n";
return $output;
}
/**
* Implementation of hook_xmlrpc().
*/
function drupal_xmlrpc() {
$xmlrpc = array();
if (variable_get('drupal_client_service', 0)) {
$xmlrpc[] = array(
'drupal.client.ping',
'drupal_client_ping',
array('array', 'array', 'array'),
t('Handling ping request')
);
}
if (variable_get('drupal_authentication_service', 0)) {
$xmlrpc[] = array(
'drupal.login',
'drupal_login',
array('int', 'string', 'string'),
t('Logging into a Drupal site')
);
}
return $xmlrpc;
}
/**
* Sends a ping to the Drupal directory server.
*/
function drupal_notify($server) {
global $base_url;
$client = array(
'link' => $base_url,
'name' => variable_get('site_name', ''),
'mail' => variable_get('site_mail', ''),
'slogan' => variable_get('site_slogan', ''),
'mission' => variable_get('site_mission', ''),
'version' => VERSION
);
if (variable_get('drupal_system', 0)) {
$system = array();
$result = db_query("SELECT name, type FROM {system} WHERE status = 1");
while ($item = db_fetch_array($result)) {
$system[] = $item;
}
}
if (variable_get('drupal_statistics', 0)) {
$users = db_fetch_object(db_query("SELECT COUNT(uid) AS count FROM {users}"));
$client['users'] = $users->count;
$nodes = db_fetch_object(db_query("SELECT COUNT(nid) AS count FROM {node}"));
$client['nodes'] = $nodes->count;
}
$result = xmlrpc($server, 'drupal.client.ping', $client, $system);
if ($result === FALSE) {
watchdog('server ping', t('Failed to notify %server; error code: %errno; error message: %error_msg.', array('%server' => theme('placeholder', $server), '%errno' => theme('placeholder', xmlrpc_errno()), '%error_msg' => theme('placeholder', xmlrpc_error_msg()))), WATCHDOG_WARNING);
}
}
/**
* Implementation of hook_info().
*/
function drupal_info($field = 0) {
$info['name'] = 'Drupal';
$info['protocol'] = 'XML-RPC';
if ($field) {
return $info[$field];
}
else {
return $info;
}
}
/**
* Implementation of hook_auth().
*/
function drupal_auth($username, $password, $server) {
if (variable_get('drupal_authentication_service', 0)) {
$result = xmlrpc("http://$server/xmlrpc.php", 'drupal.login', $username, $password);
if ($result === FALSE) {
drupal_set_message(t('Error %code : %message', array('%code' => theme('placeholder', xmlrpc_errno()), '%message' => theme('placeholder', xmlrpc_error_msg()))), 'error');
}
else {
return $result;
}
}
}
/**
* Implementation of hook_menu().
*/
function drupal_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'drupal', 'title' => t('Drupal'),
'callback' => 'drupal_page_help', 'access' => TRUE,
'type' => MENU_SUGGESTED_ITEM
);
}
return $items;
}
/**
* Menu callback; print Drupal-authentication-specific information from user/help.
*/
function drupal_page_help() {
return drupal_help('user/help#drupal');
}
/**
* Callback function from drupal_xmlrpc() for authenticating remote clients.
*
* Remote clients are usually other Drupal instances.
*/
function drupal_login($username, $password) {
if (variable_get('drupal_authentication_service', 0)) {
if ($user = user_load(array('name' => $username, 'pass' => $password, 'status' => 1))) {
return $user->uid;
}
else {
return 0;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
<?php
// $Id$
/**
* @file
* Manages displaying online help.
*/
/**
* Implementation of hook_menu().
*/
function help_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'admin/help', 'title' => t('help'),
'callback' => 'help_main',
'access' => user_access('access administration pages'),
'weight' => 9);
foreach (module_list() as $name) {
if (module_hook($name, 'help')) {
$items[] = array('path' => 'admin/help/' . $name,
'title' => t($name),
'callback' => 'help_page',
'type' => MENU_CALLBACK,
'access' => user_access('access administration pages'));
}
}
}
return $items;
}
/**
* Menu callback; prints a page listing a glossary of Drupal terminology.
*/
function help_main() {
$output = t("
<p>This guide explains what the various modules in <a href=\"%Drupal\">Drupal</a> do and how to configure them.</p>
<p>It is not a substitute for the <a href=\"%handbook\">Drupal handbook</a> available online and should be used in conjunction with it. The online reference handbook might be more up-to-date and has helpful user-contributed comments. It is your definitive reference point for all Drupal documentation.</p>
<h2>Help topics</h2>
<p>Help is available on the following items:</p>
%help_pages
<h2>Glossary of Drupal terminology</h2>
<dl>
<dt>Block</dt><dd>A small box containing information or content placed in the left-hand or right-hand sidebar of a web page.</dd>
<dt>Comment</dt><dd>A note attached to a node. Usually intended to clarify, explain, criticize, or express an opinion on the original material.</dd>
<dt>Moderation</dt>
<dd>The activity of making sure a post to a Drupal site fits in with what is expected for that Drupal site.
<dl>
<dt>Approved</dt><dd>A moderated post which has been accepted by the moderators for publication. (See published).</dd>
<dt>Waiting</dt><dd>A moderated post which is still being voted on to be accepted for publication. (See published.)</dd>
</dl>
</dd>
<dt>Node</dt><dd>The basic data unit in Drupal. Everything is a node or an extension of a node.</dd>
<dt>Public</dt><dd>See published.</dd>
<dt>Published</dt><dd>A node that is viewable by everyone. (See unpublished.)</dd>
<dt>Role</dt><dd>A classification users are placed into for the purpose of setting users' permissions.</dd>
<dt>Taxonomy</dt><dd>A division of a collection of things into ordered, classified groups. (See <a href=\"%taxonomy\">taxonomy help</a>.)</dd>
<dt>Unpublished</dt><dd>A node that is only viewable by administrators and moderators.</dd>
<dt>User</dt><dd>A person who has an account at your Drupal site, and is logged in with that account.</dd>
<dt>Visitor</dt><dd>A person who does not have an account at your Drupal site or a person who has an account at your Drupal site but is <strong>not</strong> logged in with that account. Also termed \"anonymous user\".</dd>
</dl>", array('%Drupal' => 'http://drupal.org', '%handbook' => 'http://drupal.org/handbook', '%help_pages' => help_links_as_list(), '%taxonomy' => url('admin/help/taxonomy')));
return $output;
}
function help_links_as_list() {
$output = '<ul>';
foreach (module_list() as $name) {
if (module_hook($name, 'help')) {
if (module_invoke($name, 'help', "admin/help#$name")) {
$output .= '<li><a href="' . url("admin/help/$name") . '">' . t($name) . '</a></li>';
}
}
}
$output .= '</ul>';
return $output;
}
/**
* Implementation of hook_help().
*/
function help_help($section) {
switch ($section) {
case 'admin/help#help':
$output = '<p>'. t('The help module displays context sensitive help information. Users can learn how to use modules and accomplish tasks quicker with less errors by clicking on links in provided by the help module.') .'</p>';
$output .= t('<p>Modules can make documentation available to other modules with this module. All user help should be presented using this module. Some examples of help: </p>
<ul>
<li>The name of a module (unused, but there).</li>
<li>The description found on the admin/system/modules page.</li>
<li>The module\'s help text, displayed on the admin/help page and through the module\'s individual help link.</li>
<li>The help for a distributed authorization module (if applicable).</li>
<li>The description of a post type (if applicable).</li>
</ul>
');
$output .= '<p>'. t('You can not administer the help system.') .'</p>';
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%help">Help page</a>.', array('%help' => 'http://drupal.org/handbook/modules/help/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Manages the display of online help.');
}
}
/**
* Menu callback; prints a page listing general help for all modules.
*/
function help_page() {
$name = arg(2);
if (module_hook($name, 'help')) {
$temp = module_invoke($name, 'help', "admin/help#$name");
if (empty($temp)) {
$output .= t("No help is available for module %module.", array('%module' => $name));
}
else {
$output .= $temp;
}
}
return $output;
}

View File

@ -1,202 +0,0 @@
<?php
// $Id$
/**
* @file
* Provides legacy handlers for upgrades from older Drupal installations.
*/
/**
* Implementation of hook_help().
*/
function legacy_help($section) {
switch ($section) {
case 'admin/help#legacy':
$output = '<p>'. t('The legacy module provides legacy handlers for upgrades from older installations. These handlers help automatically redirect references to pages from old installations and prevent <em>page not found</em> errors for your site.') .'</p>';
$output .= '<p>'. t('The legacy module handles legacy style taxonomy page, taxonomy feed, and blog feed paths. It also handles URL upgrades from Drupal 4.1. It rewrites old-style URLs to new-style URLs (clean URLs). ') .'</p>';
$output .= t('<p>Example Mappings:</p>
<ul>
<li><em>taxonomy/page/or/52,97</em> to <em>taxonomy/term/52+97</em>.</li>
<li><em>taxonomy/feed/or/52,97</em> to <em>taxonomy/term/52+97/0/feed</em>.</li>
<li><em>blog/feed/52</em> to <em>blog/52/feed</em>.</li>
<li><em>node/view/52</em> to <em>node/52</em>.</li>
<li><em>book/view/52</em> to <em>node/52</em>.</li>
<li><em>user/view/52</em> to <em>user/52</em>.</li>
</ul>
');
$output .= '<p>'. t('Legacy module has no configurable options.') .'</p>';
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%legacy">Legacy page</a>.', array('%legacy' => 'http://drupal.org/handbook/modules/legacy/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Provides legacy handlers for upgrades from older Drupal installations.');
}
}
/**
* Implementation of hook_menu().
*
* Registers menu paths used in earlier Drupal versions.
*/
function legacy_menu($may_cache) {
$items = array();
if ($may_cache) {
// Map "taxonomy/page/or/52,97" to "taxonomy/term/52+97".
$items[] = array('path' => 'taxonomy/page', 'title' => t('taxonomy'),
'callback' => 'legacy_taxonomy_page',
'access' => TRUE, 'type' => MENU_CALLBACK);
// Map "taxonomy/feed/or/52,97" to "taxonomy/term/52+97/0/feed".
$items[] = array('path' => 'taxonomy/feed', 'title' => t('taxonomy'),
'callback' => 'legacy_taxonomy_feed',
'access' => TRUE, 'type' => MENU_CALLBACK);
// Map "blog/feed/52" to "blog/52/feed".
$items[] = array('path' => 'blog/feed', 'title' => t('blog'),
'callback' => 'legacy_blog_feed',
'access' => TRUE, 'type' => MENU_CALLBACK);
}
else {
// Map "node/view/52" to "node/52".
$items[] = array('path' => 'node/view', 'title' => t('view'),
'callback' => 'drupal_goto',
'callback arguments' => array('node/'. arg(2), NULL, NULL),
'access' => TRUE, 'type' => MENU_CALLBACK);
// Map "book/view/52" to "node/52".
$items[] = array('path' => 'book/view', 'title' => t('view'),
'callback' => 'drupal_goto',
'callback arguments' => array('node/'. arg(2), NULL, NULL),
'access' => TRUE, 'type' => MENU_CALLBACK);
// Map "user/view/52" to "user/52".
$items[] = array('path' => 'user/view', 'title' => t('view'),
'callback' => 'drupal_goto',
'callback arguments' => array('user/'. arg(2), NULL, NULL),
'access' => TRUE, 'type' => MENU_CALLBACK);
}
return $items;
}
/**
* Menu callback; redirects users to new taxonomy page paths.
*/
function legacy_taxonomy_page($operation = 'or', $str_tids = '') {
if ($operation == 'or') {
$str_tids = str_replace(',', '+', $str_tids);
}
drupal_goto('taxonomy/term/'. $str_tids);
}
/**
* Menu callback; redirects users to new taxonomy feed paths.
*/
function legacy_taxonomy_feed($operation = 'or', $str_tids = '') {
if ($operation == 'or') {
$str_tids = str_replace(',', '+', $str_tids);
}
drupal_goto('taxonomy/term/'. $str_tids .'/0/feed');
}
/**
* Menu callback; redirects users to new blog feed paths.
*/
function legacy_blog_feed($str_uid = '') {
// if URL is of form blog/feed/52 redirect
// if URL is of form blog/feed we have to call blog_feed_last().
if (is_numeric($str_uid)) {
drupal_goto('blog/'. $str_uid .'/feed');
}
else {
module_invoke('blog', 'feed_last');
}
}
/**
* Implementation of hook_filter(). Handles URL upgrades from Drupal 4.1.
*/
function legacy_filter($op, $delta = 0, $format = -1, $text = '') {
switch ($op) {
case 'list':
return array(t('Legacy filter'));
case 'description':
return t('Replaces URLs from Drupal 4.1 (and lower) with updated equivalents.');
case 'process':
return _legacy_filter_old_urls($text, $format);
case 'settings':
return;
default:
return $text;
}
}
/**
* Rewrite legacy URLs.
*
* This is a *temporary* filter to rewrite old-style URLs to new-style
* URLs (clean URLs). Currently, URLs are being rewritten dynamically
* (ie. "on output"), however when these rewrite rules have been tested
* enough, we will use them to permanently rewrite the links in node
* and comment bodies.
*/
function _legacy_filter_old_urls($text) {
if (!variable_get('rewrite_old_urls', 0)) {
return $text;
}
global $base_url;
$end = substr($base_url, 12);
if (variable_get('clean_url', '0') == '0') {
// Relative URLs:
// rewrite 'node.php?id=<number>[&cid=<number>]' style URLs:
$text = eregi_replace("\"(node)\.php\?id=([[:digit:]]+)(&cid=)?([[:digit:]]*)", "\"?q=\\1/view/\\2/\\4", $text);
// rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
$text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "\"?q=\\2/\\4/\\6" , $text);
$text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "\"?q=\\2/\\4", $text);
$text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))", "\"?q=\\2", $text);
// Absolute URLs:
// rewrite 'node.php?id=<number>[&cid=<number>]' style URLs:
$text = eregi_replace("$end/(node)\.php\?id=([[:digit:]]+)(&cid=)?([[:digit:]]*)", "$end/?q=\\1/view/\\2/\\4", $text);
// rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
$text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/?q=\\2/\\4/\\6" , $text);
$text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/?q=\\2/\\4", $text);
$text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))", "\"$end/?q=\\2", $text);
}
else {
// Relative URLs:
// Rewrite 'node.php?id=<number>[&cid=<number>]' style URLs:
$text = eregi_replace("\"(node)\.php\?id=([[:digit:]]+)(&cid=)?([[:digit:]]*)", "\"\\1/view/\\2/\\4", $text);
// Rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
$text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "\"\\2/\\4/\\6", $text);
$text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "\"\\2/\\4", $text);
$text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))", "\"\\2", $text);
// Absolute URLs:
// Rewrite 'node.php?id=<number>[&cid=<number>]' style URLs:
$text = eregi_replace("$end/(node)\.php\?id=([[:digit:]]+)(&cid=)?([[:digit:]]*)", "$end/\\1/view/\\2/\\4", $text);
// Rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
$text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/\\2/\\4/\\6", $text);
$text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/\\2/\\4", $text);
$text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/\\2", $text);
}
return $text;
}

View File

@ -1,463 +0,0 @@
<?php
// $Id$
/**
* @file
* Enables administrators to manage the site interface languages.
*
* When enabled, the site interface can be displayed in different
* languages. The setup of languages and translations is completely
* web based. Gettext portable object files are supported.
*/
// ---------------------------------------------------------------------------------
// Hook implementations (needed on all page loads)
/**
* Implementation of hook_help().
*/
function locale_help($section) {
switch ($section) {
case 'admin/help#locale':
$output = '<p>'. t('The locale module allows you to present your Drupal site in a language other than the default English. You can use it to set up a multi-lingual web site or replace given <em>built-in</em> text with text which has been customized for your site. Whenever the locale module encounters text which needs to be displayed, it tries to translate it into the currently selected language. If a translation is not available, then the string is remembered, so you can look up untranslated strings easily.') .'</p>';
$output .= '<p>'. t('The locale module provides two options for providing translations. The first is the integrated web interface, via which you can search for untranslated strings, and specify their translations. An easier and less time-consuming method is to import existing translations for your language. These translations are available as <em>GNU gettext Portable Object files</em> (<em>.po</em> files for short). Translations for many languages are available for download from the translation page.') .'</p>';
$output .= '<p>'. t('If an existing translation does not meet your needs, the <em>.po</em> files are easily edited with special editing tools. The locale module\'s import feature allows you to add strings from such files into your site\'s database. The export functionality enables you to share your translations with others, generating Portable Object files from your site strings.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>administer localization at <a href="%admin-locale">administer &gt;&gt; localization</a>.</li>
<li>manage strings for the localization: <a href="%admin-locale-string-search">administer &gt;&gt; localization &gt;&gt; manage strings</a>.</li>
<li>add a locale language: <a href="%admin-locale-language-add">administer &gt;&gt; localization &gt;&gt; add language</a>.</li>
<li>download translation files from the <a href="%external-http-drupal-org-project-Translations">Drupal translations page</a>.
</li>
</ul>
', array('%admin-locale' => url('admin/locale'), '%admin-locale-string-search' => url('admin/locale/string/search'), '%admin-locale-language-add' => url('admin/locale/language/add'), '%external-http-drupal-org-project-Translations' => 'http://drupal.org/project/Translations'));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%locale">Locale page</a>.', array('%locale' => 'http://drupal.org/handbook/modules/locale/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Enables the translation of the user interface to languages other than English.');
case 'admin/locale':
case 'admin/locale/language/overview':
return t("<p>Drupal provides support for the translation of its interface text into different languages. This page provides an overview of the installed languages. You can add a language on the <a href=\"%add-language\">add language page</a>, or directly by <a href=\"%import\">importing a translation</a>. If multiple languages are enabled, registered users will be able to set their preferred language. The site default will be used for anonymous visitors and for users without their own settings.</p><p>Drupal interface translations may be added or extended by several courses: by <a href=\"%import\">importing</a> an existing translation, by <a href=\"%search\">translating everything</a> from scratch, or by a combination of these approaches.</p>", array("%search" => url("admin/locale/string/search"), "%import" => url("admin/locale/language/import"), "%add-language" => url("admin/locale/language/add")));
case 'admin/locale/language/add':
return t("<p>You need to add all languages in which you would like to display the site interface. If you can't find the desired language in the quick-add dropdown, then you will need to provide the proper language code yourself. The language code may be used to negotiate with browsers and to present flags, etc., so it is important to pick a code that is standardised for the desired language. You can also add a language by <a href=\"%import\">importing a translation</a>.</p>", array("%import" => url("admin/locale/language/import")));
case 'admin/locale/language/import':
return t("<p>This page allows you to import a translation provided in the gettext Portable Object (.po) format. The easiest way to get your site translated is to obtain an existing Drupal translation and to import it. You can find existing translations on the <a href=\"%url\">Drupal translation page</a>. Note that importing a translation file might take a while.</p>", array('%url' => 'http://drupal.org/project/translations'));
case 'admin/locale/language/export':
return t("<p>This page allows you to export Drupal strings. The first option is to export a translation so it can be shared. The second option generates a translation template, which contains all Drupal strings, but without their translations. You can use this template to start a new translation using various software packages designed for this task.</p>");
case 'admin/locale/string/search':
return t("<p>It is often convenient to get the strings from your setup on the <a href=\"%export\">export page</a>, and use a desktop Gettext translation editor to edit the translations. On this page you can search in the translated and untranslated strings, and the default English texts provided by Drupal.</p>", array("%export" => url("admin/locale/language/export")));
}
}
/**
* Implementation of hook_menu().
*/
function locale_menu($may_cache) {
$items = array();
if ($may_cache) {
$access = user_access('administer locales');
// Main admin menu item
$items[] = array('path' => 'admin/locale', 'title' => t('localization'),
'callback' => 'locale_admin_manage', 'access' => $access);
// Top level tabs
$items[] = array('path' => 'admin/locale/language', 'title' => t('manage languages'),
'access' => $access, 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK);
$items[] = array('path' => 'admin/locale/string/search', 'title' => t('manage strings'),
'callback' => 'locale_admin_string', 'access' => $access, 'weight' => 10,
'type' => MENU_LOCAL_TASK);
// Manage languages subtabs
$items[] = array('path' => 'admin/locale/language/overview', 'title' => t('list'),
'callback' => 'locale_admin_manage', 'access' => $access, "weight" => 0,
'type' => MENU_DEFAULT_LOCAL_TASK);
$items[] = array('path' => 'admin/locale/language/add', 'title' => t('add language'),
'callback' => 'locale_admin_manage_add', 'access' => $access, "weight" => 5,
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'admin/locale/language/import', 'title' => t('import'),
'callback' => 'locale_admin_import', 'access' => $access, 'weight' => 10,
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'admin/locale/language/export', 'title' => t('export'),
'callback' => 'locale_admin_export', 'access' => $access, 'weight' => 20,
'type' => MENU_LOCAL_TASK);
// Language related callbacks
$items[] = array('path' => 'admin/locale/language/delete', 'title' => t('confirm'),
'callback' => 'locale_admin_manage_delete_screen', 'access' => $access,
'type' => MENU_CALLBACK);
// String related callbacks
$items[] = array('path' => 'admin/locale/string/edit', 'title' => t('edit'),
'callback' => 'locale_admin_string', 'access' => $access, 'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/locale/string/delete', 'title' => t('delete'),
'callback' => 'locale_admin_string', 'access' => $access, 'type' => MENU_CALLBACK);
}
return $items;
}
/**
* Implementation of hook_perm().
*/
function locale_perm() {
return array('administer locales');
}
/**
* Implementation of hook_user().
*/
function locale_user($type, $edit, &$user, $category = NULL) {
$languages = locale_supported_languages();
if ($type == 'form' && $category == 'account' && count($languages['name']) > 1) {
if ($user->language == '') {
$user->language = key($languages['name']);
}
$languages['name'] = array_map('check_plain', $languages['name']);
$form['locale'] = array('#title' => t('Interface language settings'), '#type' => 'fieldset', '#weight' => 1);
$form['locale']['language'] = array('#type' => 'radios', '#title' => t('Language'), '#default_value' => $user->language, '#options' => $languages['name'], '#description' => t('Selecting a different locale will change the interface language of the site.'));
return $form;
}
}
// ---------------------------------------------------------------------------------
// Locale core functionality (needed on all page loads)
/**
* Provides interface translation services
*
* This function is called from t() to translate a string if needed.
*/
function locale($string) {
global $locale;
static $locale_t;
// Store database cached translations in a static var
if (!isset($locale_t)) {
$cache = cache_get("locale:$locale");
if ($cache == 0) {
locale_refresh_cache();
$cache = cache_get("locale:$locale");
}
$locale_t = unserialize($cache->data);
}
// We have the translation cached (if it is TRUE, then there is no
// translation, so there is no point in checking the database)
if (isset($locale_t[$string])) {
$string = ($locale_t[$string] === TRUE ? $string : $locale_t[$string]);
}
// We don't have this translation cached, so get it from the DB
else {
$result = db_query("SELECT s.lid, t.translation FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid WHERE s.source = '%s' AND t.locale = '%s'", $string, $locale);
// Translation found
if ($trans = db_fetch_object($result)) {
if (!empty($trans->translation)) {
$locale_t[$string] = $trans->translation;
$string = $trans->translation;
}
}
// Either we have no such source string, or no translation
else {
$result = db_query("SELECT lid, source FROM {locales_source} WHERE source = '%s'", $string);
// We have no such translation
if ($obj = db_fetch_object($result)) {
if ($locale) {
db_query("INSERT INTO {locales_target} (lid, locale) VALUES (%d, '%s')", $obj->lid, $locale);
}
}
// We have no such source string
else {
db_query("INSERT INTO {locales_source} (location, source) VALUES ('%s', '%s')", request_uri(), $string);
if ($locale) {
$lid = db_fetch_object(db_query("SELECT lid FROM {locales_source} WHERE source = '%s'", $string));
db_query("INSERT INTO {locales_target} (lid, locale) VALUES (%d, '%s')", $lid->lid, $locale);
}
}
// Clear locale cache in DB
cache_clear_all("locale:$locale");
}
}
return $string;
}
/**
* Refreshes database stored cache of translations
*
* We only store short strings to improve performance and consume less memory.
*/
function locale_refresh_cache() {
$languages = locale_supported_languages();
foreach (array_keys($languages['name']) as $locale) {
$result = db_query("SELECT s.source, t.translation, t.locale FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid WHERE t.locale = '%s' AND LENGTH(s.source) < 75", $locale);
$t = array();
while ($data = db_fetch_object($result)) {
$t[$data->source] = (empty($data->translation) ? TRUE : $data->translation);
}
cache_set("locale:$locale", serialize($t));
}
}
/**
* Returns list of languages supported on this site
*
* @param $reset Refresh cached language list
* @param $getall Return all languages (even disabled ones)
*/
function locale_supported_languages($reset = FALSE, $getall = FALSE) {
static $enabled = NULL;
static $all = NULL;
if ($reset) {
unset($enabled); unset($all);
}
if (is_null($enabled)) {
$enabled = $all = array();
$all['name'] = $all['formula'] = $enabled['name'] = $enabled['formula'] = array();
$result = db_query('SELECT locale, name, formula, enabled FROM {locales_meta} ORDER BY isdefault DESC, enabled DESC, name ASC');
while ($row = db_fetch_object($result)) {
$all['name'][$row->locale] = $row->name;
$all['formula'][$row->locale] = $row->formula;
if ($row->enabled) {
$enabled['name'][$row->locale] = $row->name;
$enabled['formula'][$row->locale] = $row->formula;
}
}
}
return $getall ? $all : $enabled;
}
/**
* Returns plural form index for a specific number
*
* The index is computed from the formula of this language
*/
function locale_get_plural($count) {
global $locale;
static $locale_formula, $plurals = array();
if (!isset($plurals[$count])) {
if (!isset($locale_formula)) {
$languages = locale_supported_languages();
$locale_formula = $languages['formula'][$locale];
}
if ($locale_formula) {
$n = $count;
$plurals[$count] = @eval("return intval($locale_formula);");
return $plurals[$count];
}
else {
$plurals[$count] = -1;
return -1;
}
}
return $plurals[$count];
}
// ---------------------------------------------------------------------------------
// Language management functionality (administration only)
/**
* Page handler for the language management screen
*/
function locale_admin_manage() {
include_once './includes/locale.inc';
$edit = &$_POST['edit'];
if ($_POST['op'] == t('Save configuration')) {
// Save changes to existing languages
$languages = locale_supported_languages(FALSE, TRUE);
foreach($languages['name'] as $key => $value) {
if ($edit['sitedefault'] == $key) {
$edit['enabled'][$key] = 1; // autoenable the default language
}
if ($key == 'en') {
// Disallow name change for English locale
db_query("UPDATE {locales_meta} SET isdefault = %d, enabled = %d WHERE locale = 'en'", ($edit['sitedefault'] == $key), isset($edit['enabled'][$key]));
}
else {
db_query("UPDATE {locales_meta} SET name = '%s', isdefault = %d, enabled = %d WHERE locale = '%s'", $edit['name'][$key], ($edit['sitedefault'] == $key), isset($edit['enabled'][$key]), $key);
}
}
// Changing the locale settings impacts the interface:
cache_clear_all();
drupal_goto('admin/locale/language/overview');
}
return _locale_admin_manage_screen();
}
/**
* User interface for the language deletion confirmation screen
*/
function locale_admin_manage_delete_screen() {
include_once './includes/locale.inc';
$langcode = arg(4);
$edit = $_POST['edit'];
// Check confirmation and if so, delete language
if ($edit['confirm']) {
$languages = locale_supported_languages(FALSE, TRUE);
if (isset($languages['name'][$edit['langcode']])) {
db_query("DELETE FROM {locales_meta} WHERE locale = '%s'", $edit['langcode']);
db_query("DELETE FROM {locales_target} WHERE locale = '%s'", $edit['langcode']);
$message = t('The language %locale has been removed.', array('%locale' => theme('placeholder', t($languages['name'][$edit['langcode']]))));
drupal_set_message($message);
watchdog('locale', $message);
}
// Changing the locale settings impacts the interface:
cache_clear_all();
drupal_goto('admin/locale/language/overview');
}
// Do not allow deletion of English locale
if ($langcode == 'en') {
drupal_goto('admin/locale/language/overview');
return;
}
// For other locales, warn user that data loss is ahead
$languages = locale_supported_languages(FALSE, TRUE);
$form['langcode'] = array('#type' => 'hidden', '#value' => $langcode);
return confirm_form('locale_admin_manage_delete_screen', $form,
t('Are you sure you want to delete the language %name?', array('%name' => theme('placeholder', t($languages['name'][$langcode])))),
'admin/locale/language/overview',
t('Deleting a language will remove all data associated with it. This action cannot be undone.'),
t('Delete'), t('Cancel'));
}
/**
* Page handler for the language addition screen
*/
function locale_admin_manage_add() {
include_once './includes/locale.inc';
$edit = &$_POST['edit'];
$isocodes = _locale_get_iso639_list();
// Check for duplicates
if ($duplicate = db_num_rows(db_query("SELECT locale FROM {locales_meta} WHERE locale = '%s'", $edit['langcode'])) == 0) {
switch ($_POST['op']) {
// Try to add new language
case t('Add language'):
// Set language name from the available list if needed
if ($edit['langcode'] && !$edit['langname'] && isset($isocodes[$edit['langcode']])) {
_locale_add_language($edit['langcode'], $isocodes[$edit['langcode']][0]);
drupal_goto('admin/locale');
}
break;
case t('Add custom language'):
// Add language, if we have the details
if ($edit['langcode'] && $edit['langname']) {
_locale_add_language($edit['langcode'], $edit['langname']);
drupal_goto('admin/locale');
}
// Seems like we have not received some data
drupal_set_message(t('The language code and the English name of the new language must be specified.'), 'error');
break;
default:
break;
}
}
else {
drupal_set_message(t('The language %language (%code) already exists.', array('%language' => theme('placeholder', check_plain($edit['langname'])), '%code' => theme('placeholder', $edit['langcode']))), 'error');
}
return _locale_admin_manage_add_screen();
}
// ---------------------------------------------------------------------------------
// Gettext Portable Object import functionality (administration only)
/**
* Page handler for the translation import screen
*/
function locale_admin_import() {
include_once './includes/locale.inc';
$edit = &$_POST['edit'];
switch ($_POST['op']) {
case t('Import'):
// Add language, if not yet supported
$languages = locale_supported_languages(TRUE, TRUE);
if (!isset($languages['name'][$edit['langcode']])) {
$isocodes = _locale_get_iso639_list();
_locale_add_language($edit['langcode'], $isocodes[$edit['langcode']][0], FALSE);
}
// Now import strings into the language
$file = file_check_upload('file');
if ($ret = _locale_import_po($file, $edit['langcode'], $edit['mode']) == FALSE) {
$message = t('The translation import of %filename failed.', array('%filename' => theme('placeholder', $file->filename)));
drupal_set_message($message, 'error');
watchdog('locale', $message, WATCHDOG_ERROR);
}
drupal_goto('admin/locale');
break;
}
return _locale_admin_import_screen();
}
// ---------------------------------------------------------------------------------
// Gettext Portable Object export functionality (administration only)
/**
* Page handler for the translation export screen
*/
function locale_admin_export() {
include_once './includes/locale.inc';
switch ($_POST['op']) {
case t('Export'):
_locale_export_po($_POST['edit']['langcode']);
break;
}
return _locale_admin_export_screen();
}
// ---------------------------------------------------------------------------------
// String search and editing functionality (administration only)
/**
* Page handler for the string search and administration screen
*/
function locale_admin_string() {
include_once './includes/locale.inc';
$op = ($_POST['op'] ? $_POST['op'] : arg(3));
$edit =& $_POST['edit'];
switch ($op) {
case 'delete':
$output .= _locale_string_delete(arg(4));
$output .= _locale_string_seek();
break;
case 'edit':
$output .= _locale_string_edit(arg(4));
$output .= _locale_string_seek();
break;
case t('Search'):
case 'search':
$output = _locale_string_seek();
$output .= _locale_string_seek_form();
break;
case t('Save translations'):
$output .= _locale_string_save(arg(4));
drupal_goto('admin/locale/string/search');
break;
default:
}
return $output;
}

View File

@ -1,786 +0,0 @@
<?php
// $Id$
/**
* @file
* Allows administrators to customize the site navigation menu.
*/
/**
* Implementation of hook_menu().
*/
function menu_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'admin/menu', 'title' => t('menus'),
'callback' => 'menu_overview',
'access' => user_access('administer menu'));
$items[] = array('path' => 'admin/menu/item/edit', 'title' => t('edit menu item'),
'callback' => 'menu_edit_item',
'access' => user_access('administer menu'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/menu/item/reset', 'title' => t('reset menu item'),
'callback' => 'menu_reset_item',
'access' => user_access('administer menu'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/menu/item/disable', 'title' => t('disable menu item'),
'callback' => 'menu_disable_item',
'access' => user_access('administer menu'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/menu/item/delete', 'title' => t('delete menu item'),
'callback' => 'menu_edit_item_delete',
'access' => user_access('administer menu'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/menu/list', 'title' => t('list'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/menu/menu/add', 'title' => t('add menu'),
'callback' => 'menu_add_menu',
'access' => user_access('administer menu'),
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'admin/menu/item/add', 'title' => t('add menu item'),
'callback' => 'menu_edit_item',
'access' => user_access('administer menu'),
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'admin/menu/reset', 'title' => t('reset menus'),
'callback' => 'menu_reset',
'access' => user_access('administer menu'),
'type' => MENU_LOCAL_TASK);
$items[] = array('path' => 'admin/settings/menu',
'title' => t('menus'),
'callback' => 'menu_configure');
}
return $items;
}
/**
* Implementation of hook_help().
*/
function menu_help($section) {
switch ($section) {
case 'admin/help#menu':
$output = t('<p>The menu module allows for customization of the menus. Menus are useful for providing navigation in your site. The main menu for navigation is the navigation menu. Menus appear in blocks on your site.</p>
<ul>
<li>On the administer menu page administrators can \"edit\" to change the title, description, parent or weight of the menu item. Under the \"operations\" column, click on \"enable/disable\" to toggle the menu item on or off. Menu items which are disabled are not deleted; they are merely not available for navigating the site in the sidebar menu block. Note that the default menu items generated by the menu module cannot be deleted, only disabled.</li>
<li>Using the \"add menu\" tab submit a title for a new custom menu. Once submitted, the new menu will appear in a list toward the bottom of the administer menu page underneath the main navigation menu.</li>
<li>Use the \"add menu item\" tab to create new links in either the navigation or a custom menu. Select the parent item to place the new link within an existing menu structure. For top level menu items, choose the name of the menu in which the link is to be added.</li>
<li>To turn off the navigation menu block, administer the block page.</li>
</ul>
');
$output .= t('<p>You can</p>
<ul>
<li>administer menus at <a href="%admin-menu">administer &gt;&gt; menus</a>.</li>
<li>turn menus blocks on and off in the <a href="%admin-block">administer &gt;&gt; blocks</a>.</li>
<li>add a menu at <a href="%admin-menu-menu-add">administer &gt;&gt; menus &gt;&gt; add menu</a>.</li>
<li>add a menu item at <a href="%admin-menu-item-add">administer &gt;&gt; menus &gt;&gt; add menu item</a>.</li>
</ul>
', array('%admin-menu' => url('admin/menu'), '%admin-block' => url('admin/block'), '%admin-menu-menu-add' => url('admin/menu/menu/add'), '%admin-menu-item-add' => url('admin/menu/item/add')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%menu">Menu page</a>.', array('%menu' => 'http://drupal.org/handbook/modules/menu/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Allows administrators to customize the site navigation menu.');
case 'admin/menu':
return t('<p>Select an operation from the list to move, change, or delete a menu item.</p>');
case 'admin/menu/menu/add':
return t('<p>Enter the name for your new menu. Remember to enable the newly created block in the <a href="%blocks">blocks administration page</a>.</p>', array('%blocks' => url('admin/block')));
case 'admin/menu/item/add':
return t('<p>Enter the title, path, position and the weight for your new menu item.</p>');
case 'admin/settings/menu':
return t('<p>Customize the menu settings.</p>');
}
}
/**
* Menu callback; presents menu configuration options.
*/
function menu_configure() {
$menu = menu_get_menu();
$root_menus = menu_get_root_menus();
$primary_options = $root_menus;
$primary_options[0] = t('No primary links');
$form['settings_links'] = array(
'#type' => 'fieldset',
'#title' => t('Primary links settings'),
);
$form['settings_links']['intro'] = array(
'#type' => 'item',
'#value' => t('Primary links is a navigation system which usually (depending on your theme) appears at the top-right of the browser window. There are usually two rows of links, primary and secondary. You may control which links appear in this area by choosing a menu from which the links will be generated and then placing your links into the menu using the <a href="%menu">menu administration</a> or the menu settings pane on each post authoring form.', array('%menu' => url('admin/menu'))),
);
$form['settings_links']['menu_primary_menu'] = array(
'#type' => 'select',
'#title' => t('Menu containing primary links'),
'#default_value' => variable_get('menu_primary_menu', 0),
'#options' => $primary_options,
);
$secondary_options = $root_menus;
$secondary_options[0] = t('No secondary links');
$form['settings_links']['menu_secondary_menu'] = array(
'#type' => 'select',
'#title' => t('Menu containing secondary links'),
'#default_value' => variable_get('menu_secondary_menu', 0),
'#options' => $secondary_options,
'#description' => t('If you select the same menu as primary links then secondary links will display the appropriate second level of your navigation hierarchy.'),
);
$form['settings_authoring'] = array(
'#type' => 'fieldset',
'#title' => t('Post authoring form settings'),
);
$form['settings_authoring']['intro'] = array(
'#type' => 'item',
'#value' => t('On each post authoring form there is a menu settings pane. This setting allows you to limit what is displayed in the parent item drop-down menu of that pane. This can be used to force new menu items to be created in the primary links menu or to hide admin menu items.'),
);
$authoring_options = $root_menus;
$authoring_options[0] = t('Show all menus');
$form['settings_authoring']['menu_parent_items'] = array(
'#type' => 'select',
'#title' => t('Restrict parent items to'),
'#default_value' => variable_get('menu_parent_items', 0),
'#options' => $authoring_options,
'#description' => t('Choose the menu from which parent items will be made available. Only this menu item and its children will be shown.'),
);
return system_settings_form('menu_configure', $form);
}
/**
* Implementation of hook_block().
*/
function menu_block($op = 'list', $delta = 0) {
if ($op == 'list') {
$blocks = array();
$root_menus = menu_get_root_menus();
foreach ($root_menus as $mid => $title) {
// Default "Navigation" block is handled by user.module.
if ($mid != 1) {
$blocks[$mid]['info'] = $title;
}
}
return $blocks;
}
else if ($op == 'view') {
$item = menu_get_item($delta);
$data['subject'] = $item['title'];
$data['content'] = theme('menu_tree', $delta);
return $data;
}
}
/**
* Implementation of hook_nodeapi().
*/
function menu_nodeapi(&$node, $op) {
if (user_access('administer menu')) {
switch ($op) {
case 'insert':
case 'update':
if ($node->menu['delete']) {
menu_node_form_delete($node);
menu_rebuild();
}
elseif ($node->menu['title']) {
$node->menu['path'] = ($node->menu['path']) ? $node->menu['path'] : "node/$node->nid";
menu_edit_item_save($node->menu);
menu_rebuild();
}
break;
case 'delete':
menu_node_form_delete($node);
menu_rebuild();
break;
}
}
}
/**
* Implementation of hook_perm().
*/
function menu_perm() {
return array('administer menu');
}
/**
* Menu callback; present the main menu management page.
*/
function menu_overview() {
menu_rebuild();
return menu_overview_tree();
}
/**
* Menu callback; clear the database, resetting the menu to factory defaults.
*/
function menu_reset() {
$op = isset($_POST['op']) ? $_POST['op'] : '';
switch ($op) {
case t('Reset all'):
db_query('DELETE FROM {menu}');
$mid = menu_edit_item_save(array('title' => t('Primary menu links'), 'pid' => 0, 'type' => MENU_CUSTOM_MENU));
variable_set('menu_primary_menu', $mid);
variable_set('menu_secondary_menu', $mid);
drupal_set_message(t('The menu items have been reset to their default settings.'));
drupal_goto('admin/menu');
break;
default:
return confirm_form('menu_confirm_reset', array(),
t('Are you sure you want to reset all menu items to their default settings?'),
'admin/menu', t('Any custom additions or changes to the menu will be lost.'),
t('Reset all'));
}
}
/**
* Menu callback; handle the adding of a new menu.
*/
function menu_add_menu() {
$op = isset($_POST['op']) ? $_POST['op'] : '';
$edit = isset($_POST['edit']) ? $_POST['edit'] : '';
$output = '';
switch ($op) {
case t('Submit'):
menu_edit_item_validate($edit);
if (!form_get_errors()) {
menu_edit_item_save($edit);
drupal_goto('admin/menu');
}
// Fall through.
default:
$edit['pid'] = 0;
$edit['type'] = MENU_CUSTOM_MENU;
$output .= menu_edit_item_form($edit);
}
return $output;
}
/**
* Menu callback; reset a single modified item.
*/
function menu_reset_item($mid) {
$op = isset($_POST['op']) ? $_POST['op'] : '';
switch ($op) {
case t('Reset'):
menu_delete_item($mid);
drupal_set_message(t("The menu item was reset to its default settings."));
drupal_goto('admin/menu');
break;
default:
$title = db_result(db_query('SELECT title FROM {menu} WHERE mid = %d', $mid));
return confirm_form('menu_item_confirm_reset', array(),
t('Are you sure you want to reset the item %item to its default values?', array('%item' => theme('placeholder', $title))),
'admin/menu', t('Any customizations will be lost. This action cannot be undone.'),
t('Reset'));
}
}
/**
* Menu callback; delete a single custom item.
*/
function menu_edit_item_delete($mid) {
$op = isset($_POST['op']) ? $_POST['op'] : '';
$result = db_query('SELECT type, title FROM {menu} WHERE mid = %d', $mid);
$menu = db_fetch_object($result);
if (!$menu) {
drupal_goto('admin/menu');
}
switch ($op) {
case t('Delete'):
menu_delete_item($mid);
if ($menu->type & MENU_IS_ROOT) {
drupal_set_message(t('The menu has been removed.'));
}
else {
drupal_set_message(t('The menu item has been removed.'));
}
drupal_goto('admin/menu');
break;
default:
if ($menu->type & MENU_IS_ROOT) {
$message = t('Are you sure you want to delete the menu %item?', array('%item' => theme('placeholder', $menu->title)));
}
else {
$message = t('Are you sure you want to delete the custom menu item %item?', array('%item' => theme('placeholder', $menu->title)));
}
return confirm_form('menu_confirm_delete', $form, $message, 'admin/menu', t('This action cannot be undone.'), t('Delete'));
}
}
/**
* Menu callback; hide a menu item.
*/
function menu_disable_item($mid) {
$item = menu_get_item($mid);
$type = $item['type'];
$type &= ~MENU_VISIBLE_IN_TREE;
$type &= ~MENU_VISIBLE_IN_BREADCRUMB;
$type |= MENU_MODIFIED_BY_ADMIN;
db_query('UPDATE {menu} SET type = %d WHERE mid = %d', $type, $mid);
drupal_set_message(t('The menu item has been disabled.'));
drupal_goto('admin/menu');
}
/**
* Menu callback; dispatch to the appropriate menu item edit function.
*/
function menu_edit_item($mid = 0) {
$op = isset($_POST['op']) ? $_POST['op'] : '';
$edit = isset($_POST['edit']) ? $_POST['edit'] : '';
$output = '';
switch ($op) {
case t('Submit'):
menu_edit_item_validate($edit);
if (!form_get_errors()) {
menu_edit_item_save($edit);
drupal_goto('admin/menu');
}
$output .= menu_edit_item_form($edit);
break;
default:
if ($mid > 0) {
$item = db_fetch_object(db_query('SELECT * FROM {menu} WHERE mid = %d', $mid));
$edit['mid'] = $item->mid;
$edit['pid'] = $item->pid;
$edit['path'] = $item->path;
$edit['title'] = $item->title;
$edit['description'] = $item->description;
$edit['weight'] = $item->weight;
$edit['type'] = $item->type;
}
else {
$edit['mid'] = 0; // In case a negative ID was passed in.
$edit['pid'] = 1; // default to "Navigation" menu.
$edit['type'] = MENU_CUSTOM_ITEM;
}
$output .= menu_edit_item_form($edit);
}
return $output;
}
/**
* Present the menu item editing form.
*/
function menu_edit_item_form($edit) {
if ($edit['pid'] == 0) {
// Display a limited set of fields for menus (not items).
$form['title'] = array('#type' => 'textfield', '#title' => t('Title'), '#default_value' => $edit['title'], '#description' => t('The name of the menu.'), '#required' => TRUE);
$form['path'] = array('#type' => 'hidden', '#value' => '');
$form['pid'] = array('#type' => 'hidden', '#value' => 0);
$form['weight'] = array('#type' => 'hidden', '#value' => 0);
}
else {
$form['title'] = array('#type' => 'textfield', '#title' => t('Title'), '#default_value' => $edit['title'], '#description' => t('The name of the menu item.'), '#required' => TRUE);
$form['description'] = array('#type' => 'textfield', '#title' => t('Description'), '#default_value' => $edit['description'], '#description' => t('The description displayed when hovering over a menu item.'));
$path_description = t('The Drupal path this menu item links to. Enter %front to link to the front page.', array('%front' => theme('placeholder', '<front>')));
if ($edit['type'] & MENU_CREATED_BY_ADMIN) {
$form['path'] = array('#type' => 'textfield', '#title' => t('Path'), '#default_value' => $edit['path'], '#description' => $path_description, '#required' => TRUE);
}
else {
$form['_path'] = array('#type' => 'item', '#title' => t('Path'), '#description' => l($edit['path'], $edit['path']));
$form['path'] = array('#type' => 'hidden', '#value' => $edit['path']);
}
$expanded = $edit['type'] & MENU_EXPANDED ? 1 : 0;
$form['expanded'] = array('#type' => 'checkbox', '#title' => t('Expanded'), '#default_value' => $expanded, '#description' => t('If selected and this menu item has children, the menu will always appear expanded.'));
// Generate a list of possible parents (not including this item or descendants).
$options = menu_parent_options($edit['mid']);
$form['pid'] = array('#type' => 'select', '#title' => t('Parent item'), '#default_value' => $edit['pid'], '#options' => $options);
$form['weight'] = array('#type' => 'weight', '#title' => t('Weight'), '#default_value' => $edit['weight'], '#description' => t('Optional. In the menu, the heavier items will sink and the lighter items will be positioned nearer the top.'));
}
$form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
$form['mid'] = array('#type' => 'hidden', '#value' => $edit['mid']);
// Always enable menu items (but not menus) when editing them.
if (!($edit['type'] & MENU_IS_ROOT)) {
$edit['type'] |= MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB;
}
$form['type'] = array('#type' => 'hidden', '#value' => $edit['type']);
return drupal_get_form('menu_edit_item_form', $form);
}
/**
* Confirm that an edited menu item has fields properly filled in.
*/
function menu_edit_item_validate($edit) {
if (empty($edit['title'])) {
form_set_error('title', t('You must specify a title.'));
}
if ($edit['pid'] != 0) {
if (empty($edit['path'])) {
form_set_error('path', t('You must specify a path.'));
}
}
}
/**
* Save changes to a menu item into the database.
*
* @return mid
*/
function menu_edit_item_save($edit) {
if ($edit['expanded']) {
$edit['type'] |= MENU_EXPANDED;
}
else {
$edit['type'] &= ~MENU_EXPANDED;
}
$edit['type'] = $edit['type'] | MENU_MODIFIED_BY_ADMIN;
$status = menu_save_item($edit);
if ($status == SAVED_UPDATED) {
drupal_set_message(t('The menu item %title has been updated.', array('%title' => theme('placeholder', $edit['title']))));
}
elseif ($status == SAVED_NEW) {
drupal_set_message(t('The menu item %title has been created.', array('%title' => theme('placeholder', $edit['title']))));
}
return $edit['mid'];
}
/**
* Save a menu item to the database.
*
* @param $item
* The menu item to be saved. This is passed by reference, so that the newly
* generated $item['mid'] can be accessed after an insert takes place.
*
* @return $status
* The operation that was performed in saving. Either SAVED_NEW (if a new
* menu item was created), or SAVED_UPDATED (if an existing menu item was
* updated).
*/
function menu_save_item(&$item) {
$existing_item = NULL;
// Check that the item already exists in the menu tree, if $item['mid'] is
// specified.
if (isset($item['mid'])) {
$existing_item = menu_get_item($item['mid']);
}
if ($item['mid'] && !empty($existing_item)) {
db_query("UPDATE {menu} SET pid = %d, path = '%s', title = '%s', description = '%s', weight = %d, type = %d WHERE mid = %d", $item['pid'], $item['path'], $item['title'], $item['description'], $item['weight'], $item['type'], $item['mid']);
return SAVED_UPDATED;
}
else {
$item['mid'] = db_next_id('{menu}_mid');
// Check explicitly for mid <= 2. If the database was improperly prefixed,
// this would cause a nasty infinite loop or duplicate mid errors.
// TODO: have automatic prefixing through an installer to prevent this.
while ($item['mid'] <= 2) {
$item['mid'] = db_next_id('{menu}_mid');
}
db_query("INSERT INTO {menu} (mid, pid, path, title, description, weight, type) VALUES (%d, %d, '%s', '%s', '%s', %d, %d)", $item['mid'], $item['pid'], $item['path'], $item['title'], $item['description'], $item['weight'], $item['type']);
return SAVED_NEW;
}
}
/**
* Delete a menu item from the database. If $item['mid'] is specified, then
* this is used to find the existing item; otherwise, $item['path'] is used.
*
* @param $item
* The menu item to be deleted.
*/
function menu_delete_item($item) {
if (!is_array($item)) {
$item = array('mid' => $item);
}
if ($item['mid']) {
db_query('DELETE FROM {menu} WHERE mid = %d', $item['mid']);
}
elseif ($item['path']) {
db_query("DELETE FROM {menu} WHERE path = '%s'", $item['path']);
}
}
/**
* Present the menu tree, rendered along with links to edit menu items.
*/
function menu_overview_tree() {
$menu = menu_get_menu();
$root_menus = menu_get_root_menus();
$header = array(t('Menu item'), t('Expanded'), array('data' => t('Operations'), 'colspan' => '3'));
$output = '';
foreach ($root_menus as $mid => $title) {
$operations = array();
if ($menu['items'][$mid]['type'] & MENU_MODIFIABLE_BY_ADMIN) {
$operations[] = l(t('edit'), 'admin/menu/item/edit/'. $mid);
}
if ($menu['items'][$mid]['type'] & MENU_CREATED_BY_ADMIN) {
$operations[] = l(t('delete'), 'admin/menu/item/delete/'. $mid);
}
$table = theme('item_list', $operations);
$table .= theme('table', $header, menu_overview_tree_rows($mid));
$output .= theme('box', $title, $table);
}
return $output;
}
function menu_overview_tree_rows($pid = 0, $depth = 0) {
$parent_item = menu_get_item($pid);
$rows = array();
if (isset($parent_item) && isset($parent_item['children'])) {
usort($parent_item['children'], '_menu_sort');
foreach ($parent_item['children'] as $mid) {
$item = menu_get_item($mid);
// Populate the title field.
$title = '';
if ($pid == 0) {
// Top-level items are menu names, and don't have an associated path.
$title .= $item['title'];
}
else {
$title .= l($item['title'], $item['path']);
}
if ($depth > 0) {
$title = '-&nbsp;'. $title;
}
for ($i = 1; $i < $depth; $i++) {
$title = '&nbsp;&nbsp;'. $title;
}
// Populate the operations field.
$operations = array();
if (!($item['type'] & MENU_MODIFIABLE_BY_ADMIN)) {
$operations[] = array('data' => t('locked'), 'colspan' => '3', 'align' => 'center');
}
else {
// Set the edit column.
if ($item['type'] & (MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IF_HAS_CHILDREN)) {
$operations[] = array('data' => l(t('edit'), 'admin/menu/item/edit/'. $mid));
}
else {
$operations[] = array('data' => '');
}
// Set the disable column.
if ($item['type'] & (MENU_IS_ROOT | MENU_VISIBLE_IF_HAS_CHILDREN)) {
// Disabling entire menus is done from block admin page.
// MENU_VISIBLE_IF_HAS_CHILDREN menus are always enabled so hide this operation.
$operations[] = array('data' => '');
}
else if ($item['type'] & MENU_VISIBLE_IN_TREE) {
$operations[] = array('data' => l(t('disable'), 'admin/menu/item/disable/'. $mid));
}
else {
$operations[] = array('data' => l(t('enable'), 'admin/menu/item/edit/'. $mid));
}
// Set the reset column.
if ($item['type'] & MENU_CREATED_BY_ADMIN) {
$operations[] = array('data' => l(t('delete'), 'admin/menu/item/delete/'. $mid));
}
else if ($item['type'] & MENU_MODIFIED_BY_ADMIN) {
$operations[] = array('data' => l(t('reset'), 'admin/menu/item/reset/'. $mid));
}
else {
$operations[] = array('data' => '');
}
}
// Call out disabled items.
if ($item['type'] & (MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IF_HAS_CHILDREN)) {
$class = 'menu-enabled';
}
else {
$title .= ' ('. t('disabled') .')';
$class = 'menu-disabled';
}
if ($item['type'] & (MENU_MODIFIABLE_BY_ADMIN | MENU_VISIBLE_IN_TREE)) {
$row = array(array('data' => $title, 'class' => $class), array('data' => ($item['children'] ? (($item['type'] & MENU_EXPANDED) ? t('Yes') : t('No')) : ''), 'class' => $class));
foreach ($operations as $operation) {
$operation['class'] = $class;
$row[] = $operation;
}
$rows[] = $row;
$rows = array_merge($rows, menu_overview_tree_rows($mid, $depth + 1));
}
else {
// Skip items that are hidden and locked; admins will never care about them.
$rows = array_merge($rows, menu_overview_tree_rows($mid, $depth));
}
}
}
return $rows;
}
/**
* Return a list of menu items that are valid possible parents for the
* given menu item. The list excludes the given item and its children.
*
* @param $mid
* The menu item id for which to generate a list of parents.
* If $mid == 0 then the complete tree is returned.
* @param $pid
* The menu item id of the menu item at which to start the tree.
* If $pid > 0 then this item will be included in the tree.
* @param $depth
* The current depth in the tree - used when recursing to indent the tree.
* @return
* An array of menu titles keyed on the mid.
*/
function menu_parent_options($mid, $pid = 0, $depth = 0) {
$options = array();
if (!($parent_item = menu_get_item($pid))) {
return $options;
}
// Exclude $mid and its children from the list unless $mid is 0.
if ($mid && $mid == $pid) {
return $options;
}
// Add the current $pid to the list.
if ($pid > 0 && ($parent_item['type'] & (MENU_MODIFIABLE_BY_ADMIN | MENU_IS_ROOT))) {
$title = ' '. $parent_item['title'];
for ($i = 0; $i < $depth; $i++) {
$title = '--'. $title;
}
if (!($parent_item['type'] & MENU_VISIBLE_IN_TREE)) {
$title .= ' ('. t('disabled') .')';
}
$options[$pid] = $title;
$depth ++;
}
// Add children of $pid to the list recursively.
if ($parent_item['children']) {
usort($parent_item['children'], '_menu_sort');
foreach ($parent_item['children'] as $child) {
$options += menu_parent_options($mid, $child, $depth);
}
}
return $options;
}
/**
* Add menu item fields to the node form.
*/
function menu_form_alter($form_id, &$form) {
if (user_access('administer menu') && isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
$edit = isset($_POST['edit']) ? $_POST['edit'] : '';
$edit['nid'] = $form['nid']['#value'];
$item = array();
if ($edit['nid'] > 0) {
$item = db_fetch_array(db_query("SELECT * FROM {menu} WHERE path = 'node/%d'", $edit['nid']));
if (is_array($edit['menu'])) {
$item = !is_array($item) ? $edit['menu'] : (($_POST['op'] == t('Preview')) ? array_merge($item, $edit['menu']) : array_merge($edit['menu'], $item));
}
}
$form['menu'] = array(
'#type' => 'fieldset',
'#title' => t('Menu settings'),
'#collapsible' => TRUE,
'#collapsed' => empty($item['title']),
'#tree' => TRUE,
'#weight' => 30,
);
$form['menu']['title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $item['title'],
'#description' => t('The name to display for this link.'),
);
$form['menu']['description'] = array(
'#type' => 'textfield',
'#title' => t('Description'),
'#default_value' => $item['description'],
'#description' => t('The description displayed when hovering over a menu item.'),
);
// Generate a list of possible parents.
$options = menu_parent_options($item['mid'], variable_get('menu_parent_items', 0));
$form['menu']['pid'] = array(
'#type' => 'select',
'#title' => t('Parent item'),
'#default_value' => $item['pid'],
'#options' => $options,
);
$form['menu']['path'] = array(
'#type' => 'hidden',
'#value' => $item['path'],
);
$form['menu']['weight'] = array(
'#type' => 'weight',
'#title' => t('Weight'),
'#default_value' => $item['weight'],
'#delta' => 10,
'#description' => t('Optional. In the menu, the heavier items will sink and the lighter items will be positioned nearer the top.'),
);
$form['menu']['mid'] = array(
'#type' => 'hidden',
'#value' => $item['mid'] ? $item['mid'] : 0,
);
$form['menu']['type'] = array(
'#type' => 'hidden',
'#value' => $item['type'] ? $item['type'] : MENU_CUSTOM_ITEM,
);
if ($item['mid'] > 0) {
$form['menu']['delete'] = array(
'#type' => 'checkbox',
'#title' => t('Check to delete this menu item.'),
'#default_value' => $item['delete'],
);
$form['menu']['advanced'] = array(
'#type' => 'item',
'#value' => t('You may also <a href="%edit">edit the advanced settings</a> for this menu item.', array('%edit' => url("admin/menu/item/edit/{$item['mid']}"))),
);
}
}
}
/**
* Remove the menu item.
*/
function menu_node_form_delete($node) {
menu_delete_item(array('path' => 'node/'. $node->nid));
}

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +0,0 @@
<?php
// $Id$
/**
* @file
* Enables the creation of pages that can be added to the navigation system.
*/
/**
* Implementation of hook_help().
*/
function page_help($section) {
switch ($section) {
case 'admin/help#page':
$output = '<p>'. t('The page module allows users to create static pages, which are the most basic type of content. Pages are commonly collected in books via the book module. Users should create a page if the information on the page is static. An example would be an "about" page. ') .'</p>';
$output .= '<p>'. t('When a page is created, a user can set authoring information, configure publishing options, whether readers will be able to post comments. They can also select the content type of the page (e.g., full HTML, filtered HTML). ') .'</p>';
$output .= '<p>'. t('As an administrator, you can set the publishing default for a page (in its workflow): you can specify whether a page is by default published, sent to moderation, promoted to the front page, sticky at the top of lists, and whether revisions are enabled by default. You can set the permissions that different user roles have to view, create, and edit pages.') .'</p>';
$output .= '<p>'. t('If the location module is enabled, then location specific information can be added. If the trackback module is enabled trackbacks can be configured.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>read the node administration help at <a href="%admin-help-node">administer &gt;&gt; help &gt;&gt; node</a>.</li>
<li>read the page administration help at <a href="%admin-help-page">administer &gt;&gt; help &gt;&gt; page</a>.</li>
<li>read the story administration help at <a href="%admin-help-story">administer &gt;&gt; help &gt;&gt; story</a>.</li>
<li>create a page at <a href="%node-add-page">create content &gt;&gt; page</a>.</li>
<li>administer page content type at <a href="%admin-settings-content-types-page">administer &gt;&gt; settings &gt;&gt; content types &gt;&gt; configure page</a>.</li>
</ul>
', array('%admin-help-node' => url('admin/help/node'), '%admin-help-page' => url('admin/help/page'), '%admin-help-story' => url('admin/help/story'), '%node-add-page' => url('node/add/page'), '%admin-settings-content-types-page' => url('admin/settings/content-types/page')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%page">Page page</a>.', array('%page' => 'http://drupal.org/handbook/modules/page/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Enables the creation of pages that can be added to the navigation system.');
case 'node/add#page':
return t('If you want to add a static page, like a contact page or an about page, use a page.');
}
}
/**
* Implementation of hook_perm().
*/
function page_perm() {
return array('create pages', 'edit own pages');
}
/**
* Implementation of hook_node_info().
*/
function page_node_info() {
return array('page' => array('name' => t('page'), 'base' => 'page'));
}
/**
* Implementation of hook_access().
*/
function page_access($op, $node) {
global $user;
if ($op == 'create') {
return user_access('create pages');
}
if ($op == 'update' || $op == 'delete') {
if (user_access('edit own pages') && ($user->uid == $node->uid)) {
return TRUE;
}
}
}
/**
* Implementation of hook_menu().
*/
function page_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'node/add/page', 'title' => t('page'),
'access' => user_access('create pages'));
}
return $items;
}
/**
* Implementation of hook_validate().
*/
function page_validate($node) {
node_validate_title($node);
}
/**
* Implementation of hook_form().
*/
function page_form(&$node) {
$form['title'] = array('#type' => 'textfield', '#title' => t('Title'), '#required' => TRUE, '#default_value' => $node->title, '#weight' => -5);
$form['body_filter']['body'] = array('#type' => 'textarea', '#title' => t('Body'), '#default_value' => $node->body, '#rows' => 20, '#required' => TRUE);
$form['body_filter']['format'] = filter_form($node->format);
$form['log'] = array(
'#type' => 'textarea', '#title' => t('Log message'), '#default_value' => $node->log, '#weight' => 5,
'#description' => t('An explanation of the additions or updates being made to help other authors understand your motivations.')
);
return $form;
}

View File

@ -1,349 +0,0 @@
<?php
// $Id$
/**
* @file
* Enables users to rename URLs.
*/
/**
* Implementation of hook_help().
*/
function path_help($section) {
switch ($section) {
case 'admin/help#path':
$output = '<p>'. t('The path module allows you to specify aliases for Drupal URLs. Such aliases improve readability of URLs for your users and may help internet search engines to index your content more effectively. More than one alias may be created for a given page.') .'</p>';
$output .= t('<p>Some examples of URL aliases are:</p>
<ul>
<li>user/login =&gt; login</li>
<li>image/tid/16 =&gt; store</li>
<li>taxonomy/term/7+19+20+21 =&gt; store/products/whirlygigs</li>
<li>node/3 =&gt; contact</li>
</ul>
');
$output .= '<p>'. t('The path module enables an extra field for aliases in all node input and editing forms (when users have the appropriate permissions). It also provides an interface to view and edit all URL aliases. The two permissions are related to URL aliasing are "administer a list of URL aliases" and "add url aliases". ') .'</p>';
$output .= '<p>'. t('This module also comes with user-defined mass URL aliasing capabilities, which is useful if you wish to uniformly use URLs different from the default. For example, you may want to have your URLs presented in a different language. Access to the Drupal source code on the web server is required to set up these kinds of aliases. ') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>set the path for a post with the path module.</li>
<li>add a URL alias: <a href="%admin-path-add">administer &gt;&gt; url aliases &gt;&gt; add alias</a>.</li>
<li>administer the list of URL aliases: <a href="%admin-path">administer &gt;&gt; url aliases</a>.</li>
<li>read how to <a href="%external-http-drupal-org-node-15365">configure clean URLs</a> for your webserver.
<li>enable clean url\'s to remove the =? at <a href="%admin-settings">administer &gt;&gt; settings</a>.</li>
</ul>
', array('%admin-path-add' => url('admin/path/add'), '%admin-path' => url('admin/path'), '%external-http-drupal-org-node-15365' => 'http://drupal.org/node/15365', '%admin-settings' => url('admin/settings')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%path">Path page</a>.', array('%path' => 'http://drupal.org/handbook/modules/path/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Allows users to rename URLs.');
case 'admin/path':
return t("<p>Drupal provides users complete control over URLs through aliasing. This feature is typically used to make URLs human-readable or easy to remember. For example, one could map the relative URL 'node/1' onto 'about'. Each system path can have multiple aliases.</p>");
case 'admin/path/add':
return t('<p>Enter the path you wish to create the alias for, followed by the name of the new alias.</p>');
}
}
/**
* Implementation of hook_menu().
*/
function path_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'admin/path', 'title' => t('url aliases'),
'callback' => 'path_admin',
'access' => user_access('administer url aliases'));
$items[] = array('path' => 'admin/path/edit', 'title' => t('edit alias'),
'callback' => 'path_admin_edit',
'access' => user_access('administer url aliases'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/path/delete', 'title' => t('delete alias'),
'callback' => 'path_admin_delete_confirm',
'access' => user_access('administer url aliases'),
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/path/list', 'title' => t('list'),
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
$items[] = array('path' => 'admin/path/add', 'title' => t('add alias'),
'callback' => 'path_admin_edit',
'access' => user_access('administer url aliases'),
'type' => MENU_LOCAL_TASK);
}
return $items;
}
/**
* Menu callback; presents an overview of all URL aliases.
*/
function path_admin() {
return path_overview();
}
/**
* Menu callback; handles pages for creating and editing URL aliases.
*/
function path_admin_edit($pid = 0) {
if ($pid) {
$alias = path_load($pid);
drupal_set_title($alias['dst']);
$output = path_form(path_load($pid));
}
else {
$output = path_form();
}
return $output;
}
/**
* Menu callback; confirms deleting an URL alias
**/
function path_admin_delete_confirm($pid) {
$path = path_load($pid);
if (user_access('administer url aliases')) {
$form['pid'] = array('#type' => 'value', '#value' => $pid);
$output = confirm_form('path_admin_delete_confirm', $form,
t('Are you sure you want to delete path alias %title?', array('%title' => theme('placeholder', $path['dst']))),
$_GET['destination'] ? $_GET['destination'] : 'admin/path', t('This action cannot be undone.'),
t('Delete'), t('Cancel') );
}
return $output;
}
/**
* Execute URL alias deletion
**/
function path_admin_delete_confirm_submit($form_id, $form_values) {
if ($form_values['confirm']) {
path_admin_delete($form_values['pid']);
return 'admin/path';
}
}
/**
* Post-confirmation; delete an URL alias.
*/
function path_admin_delete($pid = 0) {
db_query('DELETE FROM {url_alias} WHERE pid = %d', $pid);
drupal_set_message(t('The alias has been deleted.'));
}
/**
* Set an aliased path for a given Drupal path, preventing duplicates.
*/
function path_set_alias($path = NULL, $alias = NULL, $pid = NULL) {
if ($path && !$alias) {
db_query("DELETE FROM {url_alias} WHERE src = '%s'", $path);
drupal_clear_path_cache();
}
else if (!$path && $alias) {
db_query("DELETE FROM {url_alias} WHERE dst = '%s'", $alias);
drupal_clear_path_cache();
}
else if ($path && $alias) {
$path_count = db_result(db_query("SELECT COUNT(src) FROM {url_alias} WHERE src = '%s'", $path));
$alias_count = db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE dst = '%s'", $alias));
// We have an insert:
if ($path_count == 0 && $alias_count == 0) {
db_query("INSERT INTO {url_alias} (src, dst) VALUES ('%s', '%s')", $path, $alias);
drupal_clear_path_cache();
}
else if ($path_count >= 1 && $alias_count == 0) {
if ($pid) {
db_query("UPDATE {url_alias} SET dst = '%s', src = '%s' WHERE pid = %d", $alias, $path, $pid);
}
else {
db_query("INSERT INTO {url_alias} (src, dst) VALUES ('%s', '%s')", $path, $alias);
}
drupal_clear_path_cache();
}
else if ($path_count == 0 && $alias_count == 1) {
db_query("UPDATE {url_alias} SET src = '%s' WHERE dst = '%s'", $path, $alias);
drupal_clear_path_cache();
}
else if ($path_count == 1 && $alias_count == 1) {
// This will delete the path that alias was originally pointing to:
path_set_alias(NULL, $alias);
path_set_alias($path);
path_set_alias($path, $alias);
}
}
}
/**
* Return a form for editing or creating an individual URL alias.
*/
function path_form($edit = '') {
$form['src'] = array('#type' => 'textfield', '#title' => t('Existing system path'), '#default_value' => $edit['src'], '#maxlength' => 64, '#description' => t('Specify the existing path you wish to alias. For example: node/28, forum/1, taxonomy/term/1+2.'));
$form['dst'] = array('#type' => 'textfield', '#default_value' => $edit['dst'], '#maxlength' => 64, '#description' => t('Specify an alternative path by which this data can be accessed. For example, type "about" when writing an about page. Use a relative path and don\'t add a trailing slash or the URL alias won\'t work.'));
if ($edit['pid']) {
$form['pid'] = array('#type' => 'hidden', '#value' => $edit['pid']);
$form['submit'] = array('#type' => 'submit', '#value' => t('Update alias'));
}
else {
$form['submit'] = array('#type' => 'submit', '#value' => t('Create new alias'));
}
return drupal_get_form('path_form', $form);
}
/**
* Implementation of hook_nodeapi().
*
* Allows URL aliases for nodes to be specified at node edit time rather
* than through the administrative interface.
*/
function path_nodeapi(&$node, $op, $arg) {
if (user_access('create url aliases') || user_access('administer url aliases')) {
switch ($op) {
case 'validate':
$node->path = trim($node->path);
if ($node->path && !valid_url($node->path)) {
form_set_error('path', t('The path is invalid.'));
}
else if (db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE dst = '%s' AND src != '%s'", $node->path, "node/$node->nid"))) {
form_set_error('path', t('The path is already in use.'));
}
break;
case 'load':
$path = "node/$node->nid";
$alias = drupal_get_path_alias($path);
if ($alias != $path) {
$node->path = $alias;
}
break;
case 'insert':
// Don't try to insert if path is NULL. We may have already set
// the alias ahead of time.
if ($node->path) {
path_set_alias("node/$node->nid", $node->path);
}
break;
case 'update':
path_set_alias("node/$node->nid", $node->path, $node->pid);
break;
case 'delete':
$path = "node/$node->nid";
if (drupal_get_path_alias($path) != $path) {
path_set_alias($path);
}
break;
}
}
}
/**
* Implementation of hook_form_alter().
*/
function path_form_alter($form_id, &$form) {
if (user_access('create url aliases') && isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
$path = $form['#node']->path;
$form['path'] = array(
'#type' => 'fieldset',
'#title' => t('URL path settings'),
'#collapsible' => TRUE,
'#collapsed' => empty($path),
'#weight' => 30,
);
$form['path']['path'] = array(
'#type' => 'textfield',
'#default_value' => $path,
'#maxlength' => 250,
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#description' => t('Optionally specify an alternative URL by which this node can be accessed. For example, type "about" when writing an about page. Use a relative path and don\'t add a trailing slash or the URL alias won\'t work.'),
);
if ($node->path) {
$form['path']['pid'] = array(
'#type' => 'value',
'#value' => db_result(db_query("SELECT pid FROM {url_alias} WHERE dst = '%s'", $path))
);
}
}
}
/**
* Implementation of hook_perm().
*/
function path_perm() {
return array('create url aliases', 'administer url aliases');
}
/**
* Return a listing of all defined URL aliases.
*/
function path_overview() {
$sql = 'SELECT * FROM {url_alias}';
$header = array(
array('data' => t('Alias'), 'field' => 'dst', 'sort' => 'asc'),
array('data' => t('System'), 'field' => 'src'),
array('data' => t('Operations'), 'colspan' => '2')
);
$sql .= tablesort_sql($header);
$result = pager_query($sql, 50);
$destination = drupal_get_destination();
while ($data = db_fetch_object($result)) {
$rows[] = array($data->dst, $data->src, l(t('edit'), "admin/path/edit/$data->pid", array(), $destination), l(t('delete'), "admin/path/delete/$data->pid", array(), $destination));
}
if (!$rows) {
$rows[] = array(array('data' => t('No URL aliases available.'), 'colspan' => '4'));
}
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 50, 0, tablesort_pager());
return $output;
}
/**
* Fetch a specific URL alias from the database.
*/
function path_load($pid) {
return db_fetch_array(db_query('SELECT * FROM {url_alias} WHERE pid = %d', $pid));
}
/**
* Verify that a new URL alias is valid, and save it to the database.
*/
function path_form_submit() {
$edit = $GLOBALS['form_values'];
$src = $edit['src'];
$dst = $edit['dst'];
$pid = $edit['pid'];
if (!valid_url($src)) {
form_set_error('src', t('The system path %path is invalid.', array('%path' => theme('placeholder', $src))));
}
if (!valid_url($dst)) {
form_set_error('dst', t('The alias %alias is invalid.', array('%alias' => theme('placeholder', $dst))));
}
if (db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE pid != %d AND dst = '%s'", $pid, $dst))) {
form_set_error('dst', t('The alias %alias is already in use.', array('%alias' => theme('placeholder', $dst))));
}
if (form_get_errors()) {
return path_form($edit);
}
else {
path_set_alias($src, $dst, $pid);
drupal_set_message(t('The alias has been saved.'));
return 'admin/path';
}
}

View File

@ -1,68 +0,0 @@
<?php
// $Id$
/**
* @file
* Alerts other sites that your site has been updated.
*/
/**
* Implementation of hook_help().
*/
function ping_help($section) {
switch ($section) {
case 'admin/help#ping':
$output = '<p>'. t('The ping module is useful for notifying interested sites that your site has changed. It automatically sends notifications (called "pings") to the <a href="%external-http-pingomatic-com">pingomatic</a> service to tell it that your site has changed. In turn pingomatic will ping other services such as weblogs.com, Technorati, blo.gs, BlogRolling, Feedster.com, Moreover, etc.', array('%external-http-pingomatic-com' => 'http://pingomatic.com/')) .'</p>';
$output .= '<p>'. t('The ping module requires <code>cron</code> or a similar periodic job scheduler to be enabled.') .'</p>';
$output .= t('<p>You can:</p>
<ul>
<li> enable or disable the ping module at <a href="%admin-modules">administer &gt;&gt; modules</a>.</li>
<li>run your cron job at your sites <a href="%file-cron">cron page</a>.</li>
<li>read about <a href="%external-http-drupal-org-node-23714">configuring cron jobs</a>.</li>
</ul></p>
', array('%admin-modules' => url('admin/modules'), '%file-cron' => 'cron.php', '%external-http-drupal-org-node-23714' => 'http://drupal.org/node/23714'));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%ping">Ping page</a>.', array('%ping' => 'http://drupal.org/handbook/modules/ping/')) .'</p>';
return $output;
case 'admin/modules#description':
return('Alerts other sites when your site has been updated.');
}
}
/**
* Implementation of hook_cron().
*
* Fire off notifications of updates to remote sites.
*/
function ping_cron() {
global $base_url;
if (variable_get('site_name', 0) && variable_get('site_slogan', 0)) {
if (db_num_rows(db_query("SELECT nid FROM {node} WHERE status = 1 AND moderate = 0 AND (created > '". variable_get('cron_last', time()) ."' OR changed > '". variable_get('cron_last', time()) ."')"), 1)) {
_ping_notify(variable_get('site_name', '') .' - '. variable_get('site_slogan', ''), $base_url);
}
}
}
/**
* Call hook_ping() in all modules to notify remote sites that there is
* new content at this one.
*/
function _ping_notify($name, $url) {
module_invoke_all('ping', $name, $url);
}
/**
* Implementation of hook_ping().
*
* Notifies pingomatic.com, blo.gs, and technorati.com of changes at this site.
*/
function ping_ping($name = '', $url = '') {
$result = xmlrpc('http://rpc.pingomatic.com', 'weblogUpdates.ping', $name, $url);
if ($result === FALSE) {
watchdog('directory ping', t('Failed to notify pingomatic.com (site).'), WATCHDOG_WARNING);
}
}

View File

@ -1,494 +0,0 @@
<?php
// $Id$
/**
* @file
* Enables your site to capture votes on different topics in the form of multiple
* choice questions.
*/
/**
* Implementation of hook_help().
*/
function poll_help($section) {
switch ($section) {
case 'admin/help#poll':
$output = '<p>'. t('The poll module can be used to create simple polls for site users. A poll is a simple multiple choice questionnaire which displays the cummulative results of the answers to the poll. Having polls on the site is a good way to get instant feedback from community members.') .'</p>';
$output .= '<p>'. t('Users can create a poll. 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 <a href="%poll">poll</a> item in the navigation menu 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('%poll' => url('poll'))) .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>view the <a href="%poll">polls page</a>.</li>
<li><a href="%admin-node-configure-types-poll">administer &gt;&gt; content &gt;&gt; configure &gt;&gt; poll</a>.</li>
</ul>
', array('%poll' => url('poll'), '%admin-node-configure-types-poll' => url('admin/node/configure/types/poll')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%poll">Poll page</a>.', array('%poll' => 'http://drupal.org/handbook/modules/poll/')) .'</p>';
return $output;
case 'admin/modules#description':
return t("Allows 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.");
}
}
/**
* Implementation of hook_access().
*/
function poll_access($op, $node) {
if ($op == 'create') {
return user_access('create polls');
}
}
/**
* Implementation of hook_block().
*
* Generates a block containing the latest poll.
*/
function poll_block($op = 'list', $delta = 0) {
if (user_access('access content')) {
if ($op == 'list') {
$blocks[0]['info'] = t('Most recent poll');
return $blocks;
}
else if ($op == 'view') {
// Retrieve the latest poll.
$sql = db_rewrite_sql("SELECT MAX(n.created) FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1 AND n.moderate = 0");
$timestamp = db_result(db_query($sql));
if ($timestamp) {
$poll = node_load(array('type' => 'poll', 'created' => $timestamp, 'moderate' => 0, 'status' => 1));
if ($poll->nid) {
// poll_view() dumps the output into $poll->body.
poll_view($poll, 1, 0, 1);
}
}
$block['subject'] = t('Poll');
$block['content'] = $poll->body;
return $block;
}
}
}
/**
* Implementation of hook_cron().
*
* Closes polls that have exceeded their allowed runtime.
*/
function poll_cron() {
$result = db_query('SELECT p.nid FROM {poll} p INNER JOIN {node} n ON p.nid = n.nid WHERE (n.created + p.runtime) < '. time() .' AND p.active = 1 AND p.runtime != 0');
while ($poll = db_fetch_object($result)) {
db_query("UPDATE {poll} SET active = 0 WHERE nid = %d", $poll->nid);
}
}
/**
* Implementation of hook_delete().
*/
function poll_delete($node) {
db_query("DELETE FROM {poll} WHERE nid = %d", $node->nid);
db_query("DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
db_query("DELETE FROM {poll_votes} WHERE nid = %d", $node->nid);
}
/**
* Implementation of hook_submit().
*/
function poll_submit(&$node) {
// Renumber fields
$node->choice = array_values($node->choice);
$node->teaser = poll_teaser($node);
}
/**
* Implementation of hook_validate().
*/
function poll_validate($node) {
node_validate_title($node, t('You have to specify a question.'));
if (isset($node->title)) {
// Check for at least two options and validate amount of votes:
$realchoices = 0;
// Renumber fields
$node->choice = array_values($node->choice);
foreach ($node->choice as $i => $choice) {
if ($choice['chtext'] != '') {
$realchoices++;
}
if ($choice['chvotes'] < 0) {
form_set_error("choice][$i][chvotes", t('Negative values are not allowed.'));
}
}
if ($realchoices < 2) {
form_set_error("choice][$realchoices][chtext", t('You must fill in at least two choices.'));
}
}
}
/**
* Implementation of hook_form().
*/
function poll_form(&$node) {
$admin = user_access('administer nodes');
$form['title'] = array('#type' => 'textfield', '#title' => t('Question'), '#required' => TRUE, '#default_value' => $node->title, '#weight' => -1);
$form['choice']['choices'] = array('#type' => 'hidden', '#default_value' => max(2, count($node->choice) ? count($node->choice) : 5));
$form['choice']['morechoices'] = array('#type' => 'checkbox', '#title' => t('Need more choices'), '#default_value' => 0, '#description' => t("If the amount of boxes above isn't enough, check this box and click the Preview button below to add some more."), '#weight' => 1);
$form['choice'] = form_builder('poll_node_form', $form['choice']);
if ($form['choice']['morechoices']['#value']) {
$form['choice']['morechoices']['#value'] = 0;
$form['choice']['choices']['#value'] *= 2;
}
// if the value was changed in a previous iteration, retain it.
$node->choices = $form['choice']['choices']['#value'];
// Poll choices
$form['choice'] += array('#type' => 'fieldset', '#title' => t('Choices'), '#prefix' => '<div class="poll-form">', '#suffix' => '</div>', '#tree' => TRUE);
for ($a = 0; $a < $node->choices; $a++) {
$form['choice'][$a]['chtext'] = array('#type' => 'textfield', '#title' => t('Choice %n', array('%n' => ($a + 1))), '#default_value' => $node->choice[$a]['chtext']);
if ($admin) {
$form['choice'][$a]['chvotes'] = array('#type' => 'textfield', '#title' => t('Votes for choice %n', array('%n' => ($a + 1))), '#default_value' => (int)$node->choice[$a]['chvotes'], '#size' => 5, '#maxlength' => 7);
}
}
// Poll attributes
$_duration = array(0 => t('Unlimited')) + drupal_map_assoc(array(86400, 172800, 345600, 604800, 1209600, 2419200, 4838400, 9676800, 31536000), "format_interval");
$_active = array(0 => t('Closed'), 1 => t('Active'));
if ($admin) {
$form['settings'] = array('#type' => 'fieldset', '#title' => t('Settings'), '#suffix' => '</div>');
$form['settings']['active'] = array('#type' => 'radios', '#title' => t('Poll status'), '#default_value' => isset($node->active) ? $node->active : 1, '#options' => $_active, '#description' => t('When a poll is closed, visitors can no longer vote for it.'));
}
$form['settings']['runtime'] = array('#type' => 'select', '#title' => t('Poll duration'), '#default_value' => $node->runtime ? $node->runtime : 0, '#options' => $_duration, '#description' => t('After this period, the poll will be closed automatically.'));
return $form;
}
function poll_insert($node) {
if (!user_access('administer nodes')) {
// Make sure all votes are 0 initially
foreach ($node->choice as $i => $choice) {
$node->choice[$i]['chvotes'] = 0;
}
$node->active = 1;
}
db_query("INSERT INTO {poll} (nid, runtime, active) VALUES (%d, %d, %d)", $node->nid, $node->runtime, $node->active);
foreach ($node->choice as $choice) {
if ($choice['chtext'] != '') {
db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $choice['chtext'], $choice['chvotes'], $i++);
}
}
}
/**
* Implementation of hook_menu().
*/
function poll_menu($may_cache) {
$items = array();
if ($may_cache) {
$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);
$items[] = array('path' => 'poll/vote',
'title' => t('vote'),
'callback' => 'poll_vote',
'access' => user_access('vote on polls'),
'type' => MENU_CALLBACK);
}
else {
if (arg(0) == 'node' && is_numeric(arg(1))) {
$node = node_load(arg(1));
if ($node->type == 'poll' && $node->allowvotes) {
$items[] = array('path' => 'node/'. arg(1) .'/results',
'title' => t('results'),
'callback' => 'poll_results',
'access' => user_access('access content'),
'weight' => 3,
'type' => MENU_LOCAL_TASK);
}
}
}
return $items;
}
/**
* Implementation of hook_load().
*/
function poll_load($node) {
global $user;
// Load the appropriate choices into the $node object
$poll = db_fetch_object(db_query("SELECT runtime, active FROM {poll} WHERE nid = %d", $node->nid));
$result = db_query("SELECT chtext, chvotes, chorder FROM {poll_choices} WHERE nid = %d ORDER BY chorder", $node->nid);
while ($choice = db_fetch_array($result)) {
$poll->choice[$choice['chorder']] = $choice;
}
// Determine whether or not this user is allowed to vote
$poll->allowvotes = FALSE;
if (user_access('vote on polls') && $poll->active) {
if ($user->uid && db_num_rows(db_query('SELECT uid FROM {poll_votes} WHERE nid = %d AND uid = %d', $node->nid, $user->uid)) == 0) {
$poll->allowvotes = TRUE;
}
else if ($user->uid == 0 && db_num_rows(db_query("SELECT hostname FROM {poll_votes} WHERE nid = %d AND hostname = '%s'", $node->nid, $_SERVER['REMOTE_ADDR'])) == 0) {
$poll->allowvotes = TRUE;
}
}
return $poll;
}
/**
* Implementation of hook_node_info().
*/
function poll_node_info() {
return array('poll' => array('name' => t("poll"), 'base' => 'poll'));
}
function poll_page() {
// List all polls
$sql = "SELECT n.nid, n.title, p.active, n.created, 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 n.status = 1 AND n.moderate = 0 GROUP BY n.nid, n.title, p.active, n.created ORDER BY n.created DESC";
$sql = db_rewrite_sql($sql);
$result = pager_query($sql, 15);
$output = '<ul>';
while ($node = db_fetch_object($result)) {
$output .= '<li>'. l($node->title, "node/$node->nid") .' - '. format_plural($node->votes, '1 vote', '%count votes') .' - '. ($node->active ? t('open') : t('closed')) .'</li>';
}
$output .= '</ul>';
$output .= theme("pager", NULL, 15);
return $output;
}
/**
* Implementation of hook_perm().
*/
function poll_perm() {
return array('create polls', 'vote on polls');
}
/**
* Creates a simple teaser that lists all the choices.
*/
function poll_teaser($node) {
$teaser = NULL;
if (is_array($node->choice)) {
foreach ($node->choice as $k => $choice) {
$teaser .= '* '. $choice['chtext'] .'\n';
}
}
return $teaser;
}
/**
* Generates the voting form for a poll.
*/
function poll_view_voting(&$node, $teaser, $page, $block) {
if ($_POST['op'] == t('Vote')) {
poll_vote($node);
}
if ($node->choice) {
$list = array();
foreach ($node->choice as $i => $choice) {
$list[$i] = check_plain($choice['chtext']);
}
$form['choice'] = array('#type' => 'radios', '#title' => $page ? '' : check_plain($node->title), '#default_value' => -1, '#options' => $list);
}
$form['nid'] = array('#type' => 'hidden', '#value' => $node->nid);
$form['vote'] = array('#type' => 'submit', '#value' => t('Vote'));
$form['#action'] = url('node/'. $node->nid);
return drupal_get_form('poll_view_voting', $form);
}
/**
* Themes the voting form for a poll.
*/
function theme_poll_view_voting($form) {
$output .= '<div class="poll">';
$output .= ' <div class="vote-form">';
$output .= ' <div class="choices">';
$output .= form_render($form['choice']);
$output .= ' </div>';
$output .= form_render($form['nid']);
$output .= form_render($form['vote']);
$output .= ' </div>';
$output .= form_render($form);
$output .= '</div>';
return $output;
}
/**
* Generates a graphical representation of the results of a poll.
*/
function poll_view_results(&$node, $teaser, $page, $block) {
// Count the votes and find the maximum
foreach ($node->choice as $choice) {
$total_votes += $choice['chvotes'];
$max_votes = max($max_votes, $choice['chvotes']);
}
foreach ($node->choice as $i => $choice) {
if ($choice['chtext'] != '') {
$poll_results .= theme('poll_bar', check_plain($choice['chtext']), round($choice['chvotes'] * 100 / max($total_votes, 1)), format_plural($choice['chvotes'], '1 vote', '%count votes'), $block);
}
}
$output .= theme('poll_results', check_plain($node->title), $poll_results, $total_votes, $node->links, $block);
return $output;
}
function theme_poll_results($title, $results, $votes, $links, $block) {
if ($block) {
$output .= '<div class="poll">';
$output .= '<div class="title">'. $title .'</div>';
$output .= $results;
$output .= '<div class="total">'. t('Total votes: %votes', array('%votes' => $votes)) .'</div>';
$output .= '</div>';
$output .= '<div class="links">'. theme('links', $links) .'</div>';
}
else {
$output .= '<div class="poll">';
$output .= $results;
$output .= '<div class="total">'. t('Total votes: %votes', array('%votes' => $votes)) .'</div>';
$output .= '</div>';
}
return $output;
}
function theme_poll_bar($title, $percentage, $votes, $block) {
if ($block) {
$output = '<div class="text">'. $title .'</div>';
$output .= '<div class="bar"><div style="width: '. $percentage .'%;" class="foreground"></div></div>';
$output .= '<div class="percent">'. $percentage .'%</div>';
}
else {
$output = '<div class="text">'. $title .'</div>';
$output .= '<div class="bar"><div style="width: '. $percentage .'%;" class="foreground"></div></div>';
$output .= '<div class="percent">'. $percentage .'% ('. $votes .')</div>';
}
return $output;
}
/**
* Callback for the 'results' tab for polls you can vote on
*/
function poll_results() {
if ($node = node_load(arg(1))) {
drupal_set_title(check_plain($node->title));
return node_show($node, 0);
}
else {
drupal_not_found();
}
}
/**
* Callback for processing a vote
*/
function poll_vote(&$node) {
global $user;
$nid = arg(1);
if ($node = node_load($nid)) {
$edit = $_POST['edit'];
$choice = $edit['choice'];
$vote = $_POST['vote'];
if (isset($choice) && isset($node->choice[$choice])) {
if ($node->allowvotes) {
// Mark the user or host as having voted.
if ($user->uid) {
db_query('INSERT INTO {poll_votes} (nid, uid) VALUES (%d, %d)', $node->nid, $user->uid);
}
else {
db_query("INSERT INTO {poll_votes} (nid, hostname) VALUES (%d, '%s')", $node->nid, $_SERVER['REMOTE_ADDR']);
}
// Add one to the votes.
db_query("UPDATE {poll_choices} SET chvotes = chvotes + 1 WHERE nid = %d AND chorder = %d", $node->nid, $choice);
$node->allowvotes = FALSE;
$node->choice[$choice]['chvotes']++;
drupal_set_message(t('Your vote was recorded.'));
}
else {
drupal_set_message(t("You're not allowed to vote on this poll."), 'error');
}
}
else {
drupal_set_message(t("You didn't specify a valid poll choice."), 'error');
}
drupal_goto('node/'. $nid);
}
else {
drupal_not_found();
}
}
/**
* Implementation of hook_view().
*
* @param $block
* An extra parameter that adapts the hook to display a block-ready
* rendering of the poll.
*/
function poll_view(&$node, $teaser = FALSE, $page = FALSE, $block = FALSE) {
global $user;
$output = '';
// Special display for side-block
if ($block) {
// No 'read more' link
$node->body = $node->teaser = '';
$links = module_invoke_all('link', 'node', $node, 1);
$links[] = l(t('older polls'), 'poll', array('title' => t('View the list of polls on this site.')));
if ($node->allowvotes && $block) {
$links[] = l(t('results'), 'node/'. $node->nid .'/results', array('title' => t('View the current poll results.')));
}
$node->links = $links;
}
if ($node->allowvotes && ($block || arg(2) != 'results')) {
$output .= poll_view_voting($node, $teaser, $page, $block);
}
else {
$output .= poll_view_results($node, $teaser, $page, $block);
}
$node->body = $node->teaser = $output;
}
/**
* Implementation of hook_update().
*/
function poll_update($node) {
db_query('UPDATE {poll} SET runtime = %d, active = %d WHERE nid = %d', $node->runtime, $node->active, $node->nid);
db_query('DELETE FROM {poll_choices} WHERE nid = %d', $node->nid);
db_query('DELETE FROM {poll_votes} WHERE nid = %d', $node->nid);
foreach ($node->choice as $choice) {
$chvotes = (int)$choice['chvotes'];
$chtext = $choice['chtext'];
if ($chtext != '') {
db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $chtext, $chvotes, $i++);
}
}
}

View File

@ -1,763 +0,0 @@
<?php
// $Id$
/**
* @file
* Support for configurable user profiles.
*/
/**
* Flags to define the visibility of a profile field.
*/
define('PROFILE_PRIVATE', 1);
define('PROFILE_PUBLIC', 2);
define('PROFILE_PUBLIC_LISTINGS', 3);
define('PROFILE_HIDDEN', 4);
/**
* Implementation of hook_help().
*/
function profile_help($section) {
switch ($section) {
case 'admin/help#profile':
$output = '<p>'. t('The profile module allows you to define custom fields (such as country, real name, age, ...) in the user profile. This permits users of a site to share more information about themselves, and can help community-based sites to organize users around profile fields.') .'</p>';
$output .= t('<p>The following types of fields can be added to the user profile:</p>
<ul>
<li>single-line textfield</li>
<li>multi-line textfield</li>
<li>checkbox</li>
<li>list selection</li>
<li>freeform list</li>
<li>URL</li>
<li>date</li>
</ul>
');
$output .= t('<p>You can</p>
<ul>
<li>view user <a href="%profile">profiles</a>.</li>
<li>administer profile settings: <a href="%admin-settings-profile">administer &gt;&gt; settings &gt;&gt; profiles</a>.</li>
</ul>
', array('%profile' => url('profile'), '%admin-settings-profile' => url('admin/settings/profile')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%profile">Profile page</a>.', array('%profile' => 'http://drupal.org/handbook/modules/profile/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Supports configurable user profiles.');
case 'admin/settings/profile':
return t('<p>Here you can define custom fields that users can fill in in their user profile (such as <em>country</em>, <em>real name</em>, <em>age</em>, ...).</p>');
}
}
/**
* Implementation of hook_block().
*/
function profile_block($op = 'list', $delta = 0, $edit = array()) {
if ($op == 'list') {
$blocks[0]['info'] = t('Author information');
return $blocks;
}
else if ($op == 'configure' && $delta == 0) {
// Compile a list of fields to show
$fields = array();
$result = db_query('SELECT name, title, weight FROM {profile_fields} ORDER BY weight');
while ($record = db_fetch_object($result)) {
$fields[$record->name] = $record->title;
}
$fields['user_profile'] = t('Link to full user profile');
$form['profile_block_author_fields'] = array('#type' => 'checkboxes', '#title' => t('Profile fields to display'), '#default_value' => variable_get('profile_block_author_fields', NULL), '#options' => $fields, '#description' => t('Select which profile fields you wish to display in the block. Only fields designated as public in the <a href="%profile-admin">profile field configuration</a> are available.', array('%profile-admin' => url('admin/settings/profile'))));
return $form;
}
else if ($op == 'save' && $delta == 0) {
variable_set('profile_block_author_fields', $edit['profile_block_author_fields']);
}
else if ($op == 'view') {
if (user_access('access user profiles')) {
if ((arg(0) == 'node') && is_numeric(arg(1)) && (arg(2) == NULL)) {
$node = node_load(arg(1));
$account = user_load(array('uid' => $node->uid));
if ($use_fields = variable_get('profile_block_author_fields', array())) {
// Compile a list of fields to show
$fields = array();
$result = db_query('SELECT name, title, type, visibility, weight FROM {profile_fields} WHERE visibility IN (%d, %d) ORDER BY weight', PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS);
while ($record = db_fetch_object($result)) {
// Ensure that field is displayed only if it is among the defined block fields and, if it is private, the user has appropriate permissions.
if (in_array($record->name, $use_fields)) {
$fields[] = $record;
}
}
}
if ($fields) {
$fields = _profile_update_user_fields($fields, $account);
$output .= theme('profile_block', $account, $fields, true);
}
if (in_array('user_profile', $use_fields)) {
$output .= '<div>' . l(t('View full user profile'), 'user/' . $account->uid) . '</div>';
}
}
if ($output) {
$block['subject'] = t('About %name', array('%name' => $account->name));
$block['content'] = $output;
return $block;
}
}
}
}
/**
* Implementation of hook_menu().
*/
function profile_menu($may_cache) {
global $user;
$items = array();
if ($may_cache) {
$items[] = array('path' => 'profile', 'title' => t('user list'),
'callback' => 'profile_browse',
'access' => user_access('access user profiles'),
'type' => MENU_SUGGESTED_ITEM);
$items[] = array('path' => 'admin/settings/profile', 'title' => t('profiles'),
'callback' => 'profile_admin_overview');
$items[] = array('path' => 'admin/settings/profile/add', 'title' => t('add field'),
'callback' => 'profile_admin_add',
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/settings/profile/edit', 'title' => t('edit field'),
'callback' => 'profile_admin_edit',
'type' => MENU_CALLBACK);
$items[] = array('path' => 'admin/settings/profile/delete', 'title' => t('delete field'),
'callback' => 'profile_admin_delete',
'type' => MENU_CALLBACK);
}
return $items;
}
/**
* Menu callback; display a list of user information.
*/
function profile_browse() {
$name = arg(1);
list(,,$value) = explode('/', $_GET['q'], 3);
$field = db_fetch_object(db_query("SELECT DISTINCT(fid), type, title, page, visibility FROM {profile_fields} WHERE name = '%s'", $name));
if ($name && $field->fid) {
// Do not allow browsing of private fields by non-admins
if (!user_access('administer users') && $field->visibility == PROFILE_PRIVATE) {
drupal_access_denied();
return;
}
// Compile a list of fields to show
$fields = array();
$result = db_query('SELECT name, title, type, weight FROM {profile_fields} WHERE fid != %d AND visibility = %d ORDER BY weight', $field->fid, PROFILE_PUBLIC_LISTINGS);
while ($record = db_fetch_object($result)) {
$fields[] = $record;
}
// Determine what query to use:
$arguments = array($field->fid);
switch ($field->type) {
case 'checkbox':
$query = 'v.value = 1';
break;
case 'selection':
$query = "v.value = '%s'";
$arguments[] = $value;
break;
case 'list':
$query = "v.value LIKE '%%%s%%'";
$arguments[] = $value;
break;
default:
drupal_not_found();
return;
}
// Extract the affected users:
$result = pager_query("SELECT u.uid, u.access FROM {users} u INNER JOIN {profile_values} v ON u.uid = v.uid WHERE v.fid = %d AND $query ORDER BY u.access DESC", 20, 0, NULL, $arguments);
$output = '<div id="profile">';
while ($account = db_fetch_object($result)) {
$account = user_load(array('uid' => $account->uid));
$fields = _profile_update_user_fields($fields, $account);
$output .= theme('profile_listing', $account, $fields);
}
$output .= theme('pager', NULL, 20);
if ($field->type == 'selection' || $field->type == 'list') {
$title = strtr($field->page, array('%value' => theme('placeholder', $value)));
}
else {
$title = $field->page;
}
$output .= '</div>';
drupal_set_title($title);
return $output;
}
else if ($name && !$field->fid) {
drupal_not_found();
}
else {
// Compile a list of fields to show
$fields = array();
$result = db_query('SELECT name, title, type, weight FROM {profile_fields} WHERE visibility = %d ORDER BY category, weight', PROFILE_PUBLIC_LISTINGS);
while ($record = db_fetch_object($result)) {
$fields[] = $record;
}
// Extract the affected users:
$result = pager_query("SELECT uid, access FROM {users} WHERE uid > 0 AND status != 0 ORDER BY access DESC", 20, 0, NULL);
$output = '<div id="profile">';
while ($account = db_fetch_object($result)) {
$account = user_load(array('uid' => $account->uid));
$profile = _profile_update_user_fields($fields, $account);
$output .= theme('profile_listing', $account, $profile);
}
$output .= '</div>';
$output .= theme('pager', NULL, 20);
drupal_set_title(t('user list'));
return $output;
}
}
function profile_load_profile(&$user) {
$result = db_query('SELECT f.name, f.type, v.value FROM {profile_fields} f INNER JOIN {profile_values} v ON f.fid = v.fid WHERE uid = %d', $user->uid);
while ($field = db_fetch_object($result)) {
if (empty($user->{$field->name})) {
$user->{$field->name} = _profile_field_serialize($field->type) ? unserialize($field->value) : $field->value;
}
}
}
function profile_save_profile(&$edit, &$user, $category) {
if ($_GET['q'] == 'user/register' || $_GET['q'] == 'admin/user/create') {
$result = db_query('SELECT fid, name, type FROM {profile_fields} WHERE register = 1 AND visibility != %d ORDER BY category, weight', PROFILE_HIDDEN);
}
else {
$result = db_query("SELECT fid, name, type FROM {profile_fields} WHERE LOWER(category) = LOWER('%s') AND visibility != %d", $category, PROFILE_HIDDEN);
// We use LOWER('%s') instead of PHP's strtolower() to avoid UTF-8 conversion issues.
}
while ($field = db_fetch_object($result)) {
if (_profile_field_serialize($field->type)) {
$edit[$field->name] = serialize($edit[$field->name]);
}
db_query("DELETE FROM {profile_values} WHERE fid = %d AND uid = %d", $field->fid, $user->uid);
db_query("INSERT INTO {profile_values} (fid, uid, value) VALUES (%d, %d, '%s')", $field->fid, $user->uid, $edit[$field->name]);
// Mark field as handled (prevents saving to user->data).
$edit[$field->name] = NULL;
}
}
function profile_view_field($user, $field) {
// Only allow browsing of private fields for admins
$browse = user_access('administer users') || $field->visibility != PROFILE_PRIVATE;
if ($value = $user->{$field->name}) {
switch ($field->type) {
case 'textfield':
return check_plain($value);
case 'textarea':
return check_markup($value);
case 'selection':
return $browse ? l($value, 'profile/'. $field->name .'/'. $value) : check_plain($value);
case 'checkbox':
return $browse ? l($field->title, 'profile/'. $field->name) : check_plain($field->title);
case 'url':
return '<a href="'. check_url($value) .'">'. check_plain($value) .'</a>';
case 'date':
list($format) = explode(' - ', variable_get('date_format_short', 'm/d/Y - H:i'), 2);
// Note: we avoid PHP's date() because it does not handle dates before
// 1970 on Windows. This would make the date field useless for e.g.
// birthdays.
$replace = array('d' => sprintf('%02d', $value['day']),
'j' => $value['day'],
'm' => sprintf('%02d', $value['month']),
'M' => map_month($value['month']),
'Y' => $value['year'],
'H:i' => null,
'g:ia' => null);
return strtr($format, $replace);
case 'list':
$values = split("[,\n\r]", $value);
$fields = array();
foreach ($values as $value) {
if ($value = trim($value)) {
$fields[] = $browse ? l($value, "profile/". drupal_urlencode($field->name) ."/". drupal_urlencode($value)) : check_plain($value);
}
}
return implode(', ', $fields);
}
}
}
function profile_view_profile($user) {
profile_load_profile($user);
// Show private fields to administrators and people viewing their own account.
if (user_access('administer users') || $GLOBALS['user']->uid == $user->uid) {
$result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d ORDER BY category, weight', PROFILE_HIDDEN);
}
else {
$result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d AND visibility != %d ORDER BY category, weight', PROFILE_PRIVATE, PROFILE_HIDDEN);
}
while ($field = db_fetch_object($result)) {
if ($value = profile_view_field($user, $field)) {
$description = ($field->visibility == PROFILE_PRIVATE) ? t('The content of this field is private and only visible to yourself.') : '';
$title = ($field->type != 'checkbox') ? check_plain($field->title) : NULL;
$item = array('title' => $title,
'value' => $value,
'class' => $field->name,
);
$fields[$field->category][] = $item;
}
}
return $fields;
}
function _profile_form_explanation($field) {
$output = $field->explanation;
if ($field->type == 'list') {
$output .= ' '. t('Put each item on a separate line or separate them by commas. No HTML allowed.');
}
if ($field->visibility == PROFILE_PRIVATE) {
$output .= ' '. t('The content of this field is kept private and will not be shown publicly.');
}
return $output;
}
function profile_form_profile($edit, $user, $category) {
if ($_GET['q'] == 'user/register') {
$result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d AND register = 1 ORDER BY category, weight', PROFILE_HIDDEN);
}
elseif ($_GET['q'] == 'admin/user/create') {
$result = db_query('SELECT * FROM {profile_fields} WHERE register = 1 ORDER BY category, weight');
}
elseif (user_access('administer users')) {
$result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = LOWER('%s') ORDER BY weight", $category);
}
else {
$result = db_query("SELECT * FROM {profile_fields} WHERE visibility != %d AND LOWER(category) = LOWER('%s') ORDER BY weight", PROFILE_HIDDEN, $category);
// We use LOWER('%s') instead of PHP's strtolower() to avoid UTF-8 conversion issues.
}
while ($field = db_fetch_object($result)) {
$category = $field->category;
if (!isset($fields[$category])) {
$fields[$category] = array('#type' => 'fieldset', '#title' => $category, '#weight' => $w++);
}
switch ($field->type) {
case 'textfield':
case 'url':
$fields[$category][$field->name] = array(
'#type' => 'textfield',
'#title' => check_plain($field->title),
'#default_value' => $edit[$field->name],
'#maxlength' => 255,
'#description' => _profile_form_explanation($field),
'#required' => $field->required
);
break;
case 'textarea':
$fields[$category][$field->name] = array(
'#type' => 'textarea',
'#title' => check_plain($field->title),
'#default_value' => $edit[$field->name],
'#description' => _profile_form_explanation($field),
'#required' => $field->required
);
break;
case 'list':
$fields[$category][$field->name] = array(
'#type' => 'textarea',
'#title' => check_plain($field->title),
'#default_value' => $edit[$field->name],
'#description' => _profile_form_explanation($field),
'#required' => $field->required
);
break;
case 'checkbox':
$fields[$category][$field->name] = array(
'#type' => 'checkbox',
'#title' => check_plain($field->title),
'#default_value' => $edit[$field->name],
'#description' => _profile_form_explanation($field),
'#required' => $field->required
);
break;
case 'selection':
$options = array('--');
$lines = split("[,\n\r]", $field->options);
foreach ($lines as $line) {
if ($line = trim($line)) {
$options[$line] = $line;
}
}
$fields[$category][$field->name] = array(
'#type' => 'select',
'#title' => check_plain($field->title),
'#default_value' => $edit[$field->name],
'#options' => $options,
'#description' => _profile_form_explanation($field),
'#required' => $field->required
);
break;
case 'date':
$fields[$category][$field->name] = array(
'#type' => 'date',
'#title' => check_plain($field->title),
'#default_value' => $edit[$field->name],
'#description' => _profile_form_explanation($field),
'#required' => $field->required
);
break;
}
}
return $fields;
}
/**
* Helper function: update an array of user fields by calling profile_view_field
*/
function _profile_update_user_fields($fields, $account) {
foreach ($fields as $key => $field) {
if ($value = profile_view_field($account, $field)) {
$fields[$key]->value = $value;
}
}
return $fields;
}
function profile_validate_profile($edit, $category) {
if ($_GET['q'] == 'user/register') {
$result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d AND register = 1 ORDER BY category, weight', PROFILE_HIDDEN);
}
elseif ($_GET['q'] == 'admin/user/create') {
$result = db_query('SELECT * FROM {profile_fields} WHERE register = 1 ORDER BY category, weight');
}
elseif (user_access('administer users')) {
$result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = LOWER('%s') ORDER BY weight", $category);
}
else {
$result = db_query("SELECT * FROM {profile_fields} WHERE visibility != %d AND LOWER(category) = LOWER('%s') ORDER BY weight", PROFILE_HIDDEN, $category);
// We use LOWER('%s') instead of PHP's strtolower() to avoid UTF-8 conversion issues.
}
while ($field = db_fetch_object($result)) {
if ($edit[$field->name]) {
if ($field->type == 'url') {
if (!valid_url($edit[$field->name], true)) {
form_set_error($field->name, t('The value provided for %field is not a valid URL.', array('%field' => theme('placeholder', $field->title))));
}
}
}
else if ($field->required && !user_access('administer users')) {
form_set_error($field->name, t('The field %field is required.', array('%field' => theme('placeholder', $field->title))));
}
}
return $edit;
}
function profile_categories() {
$result = db_query("SELECT DISTINCT(category) FROM {profile_fields}");
while ($category = db_fetch_object($result)) {
$data[] = array('name' => check_plain($category->category), 'title' => $category->category, 'weight' => 3);
}
return $data;
}
/**
* Implementation of hook_user().
*/
function profile_user($type, &$edit, &$user, $category = NULL) {
switch ($type) {
case 'load':
return profile_load_profile($user);
case 'register':
return profile_form_profile($edit, $user, $category);
case 'update':
case 'insert':
return profile_save_profile($edit, $user, $category);
case 'view':
return profile_view_profile($user);
case 'form':
return profile_form_profile($edit, $user, $category);
case 'validate':
return profile_validate_profile($edit, $category);
case 'categories':
return profile_categories();
}
}
function profile_validate_form($edit) {
// Validate the title:
if (!$edit['title']) {
form_set_error('title', t('You must enter a title.'));
}
// Validate the 'form name':
if (eregi('[^a-z0-9_-]', $edit['name'])) {
form_set_error('name', t('The specified form name contains one or more illegal characters. Spaces or any other special characters expect dash (-) and underscore (_) are not allowed.'));
}
if (in_array($edit['name'], user_fields())) {
form_set_error('name', t('The specified form name is reserved for use by Drupal.'));
}
// Validate the category:
if (!$edit['category']) {
form_set_error('category', t('You must enter a category.'));
}
if ($edit['category'] == 'account') {
form_set_error('category', t('The specified category name is reserved for use by Drupal.'));
}
}
/**
* Menu callback; adds a new field to all user profiles.
*/
function profile_admin_add($type) {
if ($_POST['op']) {
$data = $_POST['edit'];
// Validate the form:
profile_validate_form($data);
if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE title = '%s' AND category = '%s'", $data['title'], $data['category']))) {
form_set_error('title', t('The specified title is already in use.'));
}
if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE name = '%s'", $data['name']))) {
form_set_error('name', t('The specified name is already in use.'));
}
if (!form_get_errors()) {
db_query("INSERT INTO {profile_fields} (title, name, explanation, category, type, weight, required, register, visibility, options, page) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s')", $data['title'], $data['name'], $data['explanation'], $data['category'], $type, $data['weight'], $data['required'], $data['register'], $data['visibility'], $data['options'], $data['page']);
cache_clear_all();
drupal_set_message(t('The field has been created.'));
drupal_goto('admin/settings/profile');
}
}
else {
$data = array('name' => 'profile_');
}
drupal_set_title(t('Add new %type', array('%type' => _profile_field_types($type))));
return _profile_field_form($type, $data);
}
/**
* Menu callback; displays the profile field editing form.
*/
function profile_admin_edit($fid) {
if ($_POST['op']) {
$data = $_POST['edit'];
// Validate form:
profile_validate_form($data);
if (!form_get_errors()) {
db_query("UPDATE {profile_fields} SET title = '%s', name = '%s', explanation = '%s', category = '%s', weight = %d, required = %d, register = %d, visibility = %d, options = '%s', page = '%s' WHERE fid = %d", $data['title'], $data['name'], $data['explanation'], $data['category'], $data['weight'], $data['required'], $data['register'], $data['visibility'], $data['options'], $data['page'], $fid);
cache_clear_all();
drupal_set_message(t('The field has been updated.'));
drupal_goto('admin/settings/profile');
}
}
else {
$data = db_fetch_array(db_query('SELECT * FROM {profile_fields} WHERE fid = %d', $fid));
}
drupal_set_title(t('Edit %type', array('%type' => $data['type'])));
return _profile_field_form($data['type'], $data);
}
/**
* Menu callback; deletes a field from all user profiles.
*/
function profile_admin_delete($fid) {
$field = db_fetch_object(db_query("SELECT title FROM {profile_fields} WHERE fid = %d", $fid));
if ($_POST['edit']['confirm']) {
db_query('DELETE FROM {profile_fields} WHERE fid = %d', $fid);
db_query('DELETE FROM {profile_values} WHERE fid = %d', $fid);
cache_clear_all();
drupal_set_message(t('The field %field has been deleted.', array('%field' => theme('placeholder', $field->title))));
drupal_goto('admin/settings/profile');
}
else {
return confirm_form('profile_confirm_delete', $form,
t('Are you sure you want to delete the field %field?', array('%field' => theme('placeholder', $field->title))),
'admin/settings/profile',
t('This action cannot be undone. If users have entered values into this field in their profile, these entries will also be deleted. If you want to keep the user-entered data, instead of deleting the field you may wish to <a href="%edit-field">edit this field</a> and change it to a \'hidden profile field\' so that it may only be accessed by administrators.', array('%edit-field' => url('admin/settings/profile/edit/' . $fid))),
t('Delete'),
t('Cancel'));
}
}
function _profile_field_form($type, $edit = array()) {
$form['fields'] = array('#type' => 'fieldset',
'#title' => t('Field settings'),
);
$form['fields']['category'] = array('#type' => 'textfield',
'#title' => t('Category'),
'#default_value' => $edit['category'],
'#description' => t('The category the new field should be part of. Categories are used to group fields logically. An example category is "Personal information".'),
'#required' => TRUE,
);
$form['fields']['title'] = array('#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $edit['title'],
'#description' => t('The title of the new field. The title will be shown to the user. An example title is "Favorite color".'),
'#required' => TRUE,
);
$form['fields']['name'] = array('#type' => 'textfield',
'#title' => t('Form name'),
'#default_value' => $edit['name'],
'#description' => 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 <code>profile_</code> 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".'),
'#required' => TRUE,
);
$form['fields']['explanation'] = array('#type' => 'textarea',
'#title' => t('Explanation'),
'#default_value' => $edit['explanation'],
'#description' => t('An optional explanation to go with the new field. The explanation will be shown to the user.'),
);
if ($type == 'selection') {
$form['fields']['options'] = array('#type' => 'textarea',
'#title' => t('Selection options'),
'#default_value' => $edit['options'],
'#description' => t('A list of all options. Put each option on a separate line. Example options are "red", "blue", "green", etc.'),
);
}
$form['fields']['weight'] = array('#type' => 'weight',
'#title' => t('Weight'),
'#default_value' => $edit['weight'],
'#delta' => 5,
'#description' => t('The weights define the order in which the form fields are shown. Lighter fields "float up" towards the top of the category.'),
);
$form['fields']['visibility'] = array('#type' => 'radios',
'#title' => t('Visibility'),
'#default_value' => isset($edit['visibility']) ? $edit['visibility'] : PROFILE_PUBLIC,
'#options' => array(PROFILE_HIDDEN => t('Hidden profile field, only accessible by administrators, modules and themes.'), PROFILE_PRIVATE => t('Private field, content only available to privileged users.'), PROFILE_PUBLIC => t('Public field, content shown on profile page but not used on member list pages.'), PROFILE_PUBLIC_LISTINGS => t('Public field, content shown on profile page and on member list pages.')),
);
if ($type == 'selection' || $type == 'list') {
$form['fields']['page'] = array('#type' => 'textfield',
'#title' => t('Page title'),
'#default_value' => $edit['page'],
'#description' => t('The title of the page showing all users with the specified field. The word <code>%value</code> will be substituted with the corresponding value. An example page title is "People whose favorite color is %value". Only applicable if the field is configured to be shown on member list pages.'),
);
}
else {
$form['fields']['page'] = array('#type' => 'textfield',
'#title' => t('Page title'),
'#default_value' => $edit['page'],
'#description' => t('The title of the page showing all users with the specified field. Only applicable if the field is configured to be shown on member listings.'),
);
}
$form['fields']['required'] = array('#type' => 'checkbox',
'#title' => t('The user must enter a value.'),
'#default_value' => $edit['required'],
);
$form['fields']['register'] = array('#type' => 'checkbox',
'#title' => t('Visible in user registration form.'),
'#default_value' => $edit['register'],
);
$form['submit'] = array('#type' => 'submit',
'#value' => t('Save field'),
);
return drupal_get_form('_profile_field_form', $form);
}
/**
* 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');
$rows = array();
while ($field = db_fetch_object($result)) {
$rows[] = array(check_plain($field->title), $field->name, _profile_field_types($field->type), $field->category, l(t('edit'), "admin/settings/profile/edit/$field->fid"), l(t('delete'), "admin/settings/profile/delete/$field->fid"));
}
if (count($rows) == 0) {
$rows[] = array(array('data' => t('No fields defined.'), 'colspan' => '6'));
}
$header = array(t('Title'), t('Name'), t('Type'), t('Category'), array('data' => t('Operations'), 'colspan' => '2'));
$output = theme('table', $header, $rows);
$output .= '<h2>'. t('Add new field') .'</h2>';
$output .= '<ul>';
foreach (_profile_field_types() as $key => $value) {
$output .= '<li>'. l($value, "admin/settings/profile/add/$key") .'</li>';
}
$output .= '</ul>';
return $output;
}
function theme_profile_block($account, $fields = array()) {
$output .= theme('user_picture', $account);
foreach ($fields as $field) {
if ($field->value) {
$output .= "<p><strong>$field->title:</strong><br />$field->value</p>\n";
}
}
return $output;
}
function theme_profile_listing($account, $fields = array()) {
$output = "<div class=\"profile\">\n";
$output .= theme('user_picture', $account);
$output .= ' <div class="name">'. theme('username', $account) ."</div>\n";
foreach ($fields as $field) {
if ($field->value) {
$output .= " <div class=\"field\">$field->value</div>\n";
}
}
$output .= "</div>\n";
return $output;
}
function _profile_field_types($type = NULL) {
$types = array('textfield' => t('single-line textfield'),
'textarea' => t('multi-line textfield'),
'checkbox' => t('checkbox'),
'selection' => t('list selection'),
'list' => t('freeform list'),
'url' => t('URL'),
'date' => t('date'));
return isset($type) ? $types[$type] : $types;
}
function _profile_field_serialize($type = NULL) {
return $type == 'date';
}

File diff suppressed because it is too large Load Diff

View File

@ -1,484 +0,0 @@
<?php
// $Id$
/**
* @file
* Logs access statistics for your site.
*/
/**
* Implementation of hook_help().
*/
function statistics_help($section) {
switch ($section) {
case 'admin/help#statistics':
$output = '<p>'. t('The statistics module keeps track of numerous statistics of site usage. It counts how many times, and from where each of your posts is viewed. The statistics module can be used to learn many useful things about how users are interacting with each other and with your site.') .'</p>';
$output .= t('<p>Statistics module features</p>
<ul>
<li>Logs show statistics for how many times your site and specific content on your site has been accessed.</li>
<li>Referrers tells you from where visitors came from (referrer URL).</li>
<li>Top pages shows you what\'s hot, what is the most popular content on your site.</li>
<li>Top users shows you the most active users for your site.</li>
<li>Recent hits displays information about the latest activity on your site.</li>
<li>Node count displays the number of times a node has been accessed in the node\'s link section next to <em># comments</em>.</li>
<li>Popular content block creates a block that can display the day\'s top viewed content, the all time top viewed content, and the last content viewed.</li>
</ul>
');
$output .= t('<p>Configuring the statistics module</p>
<ul>
<li>Enable access log allows you to turn the access log on and off. This log is used to store data about every page accessed, such as the remote host\'s IP address, where they came from (referrer), what node they\'ve viewed, and their user name. Enabling the log adds one database call per page displayed by Drupal.</li>
<li>Discard access logs older than allows you to configure how long an access log entry is saved, after which time it is deleted from the database table. To use this you need to run <em>cron.php</em></li>
<li>Enable node view counter allows you to turn on and off the node-counting functionality of this module. If it is turned on, an extra database query is added for each node displayed, which increments a counter.</li>
</ul>
');
$output .= t('<p>You can</p>
<ul>
<li>administer statistics <a href="%admin-settings-statistics">administer &gt;&gt; setttings &gt;&gt; statistics</a>.</li>
<li>access statistics logs <a href="%admin-logs">administer &gt;&gt; logs</a>.</li>
<li>view recent hits <a href="%admin-logs-hits">administer &gt;&gt; logs &gt;&gt; recent hits</a>.</li>
<li>enable \'popular content\' block in block administration <a href="%admin-block">administer &gt;&gt; blocks </a> but only after you have enabled \'Count content views\' in settings.</li>
</ul>
', array('%admin-settings-statistics' => url('admin/settings/statistics'), '%admin-logs' => url('admin/logs'), '%admin-logs-hits' => url('admin/logs/hits'), '%admin-block' => url('admin/block')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%statistics">Statistics page</a>.', array('%statistics' => 'http://drupal.org/handbook/modules/statistics/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Logs access statistics for your site.');
case 'admin/settings/statistics':
return t('<p>Settings for the statistical information that Drupal will keep about the site. See <a href="%statistics">site statistics</a> for the actual information.</p>', array('%statistics' => url('admin/logs/hits')));
case 'admin/logs/hits':
return t('<p>This page shows you the most recent hits.</p>');
case 'admin/logs/referrers':
return t('<p>This page shows you all external referrers. These are links pointing to your web site from outside your web site.</p>');
case 'admin/logs/visitors':
return t('<p>When you ban a visitor, you prevent his IP address from accessing your site. Unlike blocking a user, banning a visitor works even for anonymous users. The most common use for this is to block bots/web crawlers that are consuming too many resources.</p>');
}
}
/**
* Implementation of hook_exit().
*
* This is where statistics are gathered on page accesses.
*/
function statistics_exit() {
global $user, $recent_activity;
drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH);
if (variable_get('statistics_count_content_views', 0)) {
// We are counting content views.
if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') {
// A node has been viewed, so update the node's counters.
db_query('UPDATE {node_counter} SET daycount = daycount + 1, totalcount = totalcount + 1, timestamp = %d WHERE nid = %d', time(), arg(1));
// If we affected 0 rows, this is the first time viewing the node.
if (!db_affected_rows()) {
// We must create a new row to store counters for the new node.
db_query('INSERT INTO {node_counter} (nid, daycount, totalcount, timestamp) VALUES (%d, 1, 1, %d)', arg(1), time());
}
}
}
if ((variable_get('statistics_enable_access_log', 0)) && (module_invoke('throttle', 'status') == 0)) {
// Log this page access.
db_query("INSERT INTO {accesslog} (title, path, url, hostname, uid, sid, timer, timestamp) values('%s', '%s', '%s', '%s', %d, '%s', %d, %d)", strip_tags(drupal_get_title()), $_GET['q'], referer_uri(), $_SERVER['REMOTE_ADDR'], $user->uid, session_id(), timer_read('page'), time());
}
}
/**
* Implementation of hook_perm().
*/
function statistics_perm() {
return array('access statistics', 'view post access counter');
}
/**
* Implementation of hook_link().
*/
function statistics_link($type, $node = 0, $main = 0) {
global $id;
$links = array();
if ($type != 'comment' && user_access('view post access counter')) {
$statistics = statistics_get($node->nid);
if ($statistics) {
$links[] = format_plural($statistics['totalcount'], '1 read', '%count reads');
}
}
return $links;
}
/**
* Implementation of hook_menu().
*/
function statistics_menu($may_cache) {
$items = array();
$access = user_access('access statistics');
if ($may_cache) {
$items[] = array('path' => 'admin/logs/hits', 'title' => t('recent hits'),
'callback' => 'statistics_recent_hits', 'access' => $access,
'weight' => 3);
$items[] = array('path' => 'admin/logs/pages', 'title' => t('top pages'),
'callback' => 'statistics_top_pages', 'access' => $access,
'weight' => 1);
$items[] = array('path' => 'admin/logs/visitors', 'title' => t('top visitors'),
'callback' => 'statistics_top_visitors', 'access' => $access,
'weight' => 2);
$items[] = array('path' => 'admin/logs/referrers', 'title' => t('referrers'),
'callback' => 'statistics_top_referrers', 'access' => $access);
$items[] = array('path' => 'admin/logs/access', 'title' => t('details'),
'callback' => 'statistics_access_log', 'access' => $access,
'type' => MENU_CALLBACK);
}
else {
if (arg(0) == 'user' && is_numeric(arg(1))) {
$items[] = array('path' => 'user/'. arg(1) .'/track/navigation', 'title' => t('track page visits'),
'callback' => 'statistics_user_tracker', 'access' => $access,
'type' => MENU_LOCAL_TASK, 'weight' => 2);
}
if (arg(0) == 'node' && is_numeric(arg(1))) {
$items[] = array('path' => 'node/'. arg(1) .'/track', 'title' => t('track'),
'callback' => 'statistics_node_tracker', 'access' => $access,
'type' => MENU_LOCAL_TASK, 'weight' => 2);
}
}
return $items;
}
function statistics_access_log($aid) {
$result = db_query('SELECT a.*, u.name FROM {accesslog} a LEFT JOIN {users} u ON a.uid = u.uid WHERE aid = %d', $aid);
if ($access = db_fetch_object($result)) {
$output = '<table border="1" cellpadding="2" cellspacing="2">';
$output .= ' <tr><th>'. t('URL') ."</th><td>". l(url($access->path, NULL, NULL, TRUE), $access->path) ."</td></tr>";
$output .= ' <tr><th>'. t('Title') .'</th><td>'. $access->title .'</td></tr>'; // safe because it comes from drupal_get_title()
$output .= ' <tr><th>'. t('Referrer') ."</th><td>". ($access->url ? l($access->url, $access->url) : '') ."</td></tr>";
$output .= ' <tr><th>'. t('Date') .'</th><td>'. format_date($access->timestamp, 'large') .'</td></tr>';
$output .= ' <tr><th>'. t('User') .'</th><td>'. theme('username', $access) .'</td></tr>';
$output .= ' <tr><th>'. t('Hostname') .'</th><td>'. check_plain($access->hostname) .'</td></tr>';
$output .= '</table>';
return $output;
}
else {
drupal_not_found();
}
}
function statistics_node_tracker() {
if ($node = node_load(arg(1))) {
$header = array(
array('data' => t('Time'), 'field' => 'a.timestamp', 'sort' => 'desc'),
array('data' => t('Referrer'), 'field' => 'a.url'),
array('data' => t('User'), 'field' => 'u.name'),
array('data' => t('Operations')));
$result = pager_query('SELECT a.aid, a.timestamp, a.url, a.uid, u.name FROM {accesslog} a LEFT JOIN {users} u ON a.uid = u.uid WHERE a.path LIKE \'node/%d%%\'' . tablesort_sql($header), 30, 0, NULL, $node->nid);
while ($log = db_fetch_object($result)) {
$rows[] = array(
array('data' => format_date($log->timestamp, 'small'), 'class' => 'nowrap'),
l(_statistics_column_width($log->url), $log->url),
theme('username', $log),
l(t('details'), "admin/logs/access/$log->aid"));
}
drupal_set_title(check_plain($node->title));
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 30, 0, tablesort_pager());
return $output;
}
else {
drupal_not_found();
}
}
function statistics_user_tracker() {
if ($account = user_load(array('uid' => arg(1)))) {
$header = array(
array('data' => t('Timestamp'), 'field' => 'timestamp', 'sort' => 'desc'),
array('data' => t('Page'), 'field' => 'path'),
array('data' => t('Operations')));
$result = pager_query('SELECT aid, timestamp, path, title FROM {accesslog} WHERE uid = %d' . tablesort_sql($header), 30, 0, NULL, $account->uid);
while ($log = db_fetch_object($result)) {
$rows[] = array(
array('data' => format_date($log->timestamp, 'small'), 'class' => 'nowrap'),
_statistics_format_item($log->title, $log->path),
l(t('details'), "admin/logs/access/$log->aid"));
}
drupal_set_title($account->name);
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 30, 0, tablesort_pager());
return $output;
}
else {
drupal_not_found();
}
}
/**
* Menu callback; presents the "recent hits" page.
*/
function statistics_recent_hits() {
$header = array(
array('data' => t('Timestamp'), 'field' => 'a.timestamp', 'sort' => 'desc'),
array('data' => t('Page'), 'field' => 'a.path'),
array('data' => t('User'), 'field' => 'u.name'),
array('data' => t('Operations'))
);
$sql = 'SELECT a.aid, a.path, a.title, a.uid, u.name, a.timestamp FROM {accesslog} a LEFT JOIN {users} u ON u.uid = a.uid' . tablesort_sql($header);
$result = pager_query($sql, 30);
while ($log = db_fetch_object($result)) {
$rows[] = array(
array('data' => format_date($log->timestamp, 'small'), 'class' => 'nowrap'),
_statistics_format_item($log->title, $log->path),
theme('username', $log),
l(t('details'), "admin/logs/access/$log->aid"));
}
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 30, 0, tablesort_pager());
return $output;
}
/**
* Menu callback; presents the "top pages" page.
*/
function statistics_top_pages() {
$sql = "SELECT COUNT(path) AS hits, path, title, AVG(timer) AS average_time, SUM(timer) AS total_time FROM {accesslog} GROUP BY path, title";
$sql_cnt = "SELECT COUNT(DISTINCT(path)) FROM {accesslog}";
$header = array(
array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
array('data' => t('Page'), 'field' => 'path'),
array('data' => t('Average page generation time'), 'field' => 'average_time'),
array('data' => t('Total page generation time'), 'field' => 'total_time')
);
$sql .= tablesort_sql($header);
$result = pager_query($sql, 30, 0, $sql_cnt);
while ($page = db_fetch_object($result)) {
$rows[] = array($page->hits, _statistics_format_item($page->title, $page->path), t('%time ms', array('%time' => round($page->average_time))), format_interval(round($page->total_time / 1000)));
}
drupal_set_title(t('Top pages in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 30, 0, tablesort_pager());
return $output;
}
/**
* Menu callback; presents the "top visitors" page.
*/
function statistics_top_visitors() {
$header = array(
array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
array('data' => t('Visitor'), 'field' => 'u.name'),
array('data' => t('Total page generation time'), 'field' => 'total'),
array('data' => t('Operations'))
);
$sql = "SELECT COUNT(a.uid) AS hits, a.uid, u.name, a.hostname, SUM(a.timer) AS total, ac.aid FROM {accesslog} a LEFT JOIN {access} ac ON ac.type = 'host' AND LOWER(a.hostname) LIKE (ac.mask) LEFT JOIN {users} u ON a.uid = u.uid GROUP BY a.hostname, a.uid, u.name, ac.aid". tablesort_sql($header);
$sql_cnt = "SELECT COUNT(DISTINCT(uid)) FROM {accesslog}";
$result = pager_query($sql, 30, 0, $sql_cnt);
while ($account = db_fetch_object($result)) {
$qs = drupal_get_destination();
$ban_link = $account->aid ? l(t('unban'), "admin/access/rules/delete/$account->aid", array(), $qs) : l(t('ban'), "admin/access/rules/add/$account->hostname/host", array(), $qs);
$rows[] = array($account->hits, ($account->uid ? theme('username', $account) : $account->hostname), format_interval(round($account->total / 1000)), $ban_link);
}
drupal_set_title(t('Top visitors in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 30, 0, tablesort_pager());
return $output;
}
/**
* Menu callback; presents the "referrer" page.
*/
function statistics_top_referrers() {
$query = "SELECT url, COUNT(url) AS hits, MAX(timestamp) AS last FROM {accesslog} WHERE url NOT LIKE '%%%s%%' AND url <> '' GROUP BY url";
$query_cnt = "SELECT COUNT(DISTINCT(url)) FROM {accesslog} WHERE url <> '' AND url NOT LIKE '%%%s%%'";
drupal_set_title(t('Top referrers in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
$header = array(
array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
array('data' => t('Url'), 'field' => 'url'),
array('data' => t('Last visit'), 'field' => 'last'),
);
$query .= tablesort_sql($header);
$result = pager_query($query, 30, 0, $query_cnt, $_SERVER['HTTP_HOST']);
while ($referrer = db_fetch_object($result)) {
$rows[] = array($referrer->hits, '<a href="'. check_url($referrer->url) .'">'. check_plain(_statistics_column_width($referrer->url)) .'</a>', t('%time ago', array('%time' => format_interval(time() - $referrer->last))));
}
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 30, 0, tablesort_pager());
return $output;
}
/**
* Implementation of hook_settings().
*/
function statistics_settings() {
// access log settings:
$options = array('1' => t('Enabled'), '0' => t('Disabled'));
$form['access'] = array('#type' => 'fieldset', '#title' => t('Access log settings'));
$form['access']['statistics_enable_access_log'] = array('#type' => 'radios', '#title' => t('Enable access log'), '#default_value' => variable_get('statistics_enable_access_log', 0), '#options' => $options, '#description' => t('Log each page access. Required for referrer statistics.'));
$period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
$form['access']['statistics_flush_accesslog_timer'] = array('#type' => 'select', '#title' => t('Discard access logs older than'), '#default_value' => variable_get('statistics_flush_accesslog_timer', 259200), '#options' => $period, '#description' => t('Older access log entries (including referrer statistics) will be automatically discarded. Requires crontab.'));
// count content views settings
$form['content'] = array('#type' => 'fieldset', '#title' => t('Content viewing counter settings'));
$form['content']['statistics_count_content_views'] = array('#type' => 'radios', '#title' => t('Count content views'), '#default_value' => variable_get('statistics_count_content_views', 0), '#options' => $options, '#description' => t('Increment a counter each time content is viewed.'));
return $form;
}
/**
* Implementation of hook_cron().
*/
function statistics_cron() {
$statistics_timestamp = variable_get('statistics_day_timestamp', '');
if ((time() - $statistics_timestamp) >= 86400) {
/* reset day counts */
db_query('UPDATE {node_counter} SET daycount = 0');
variable_set('statistics_day_timestamp', time());
}
/* clean expired access logs */
db_query('DELETE FROM {accesslog} WHERE timestamp < %d', time() - variable_get('statistics_flush_accesslog_timer', 259200));
}
/**
* Returns all time or today top or last viewed node(s).
*
* @param $dbfield
* one of
* - 'totalcount': top viewed content of all time.
* - 'daycount': top viewed content for today.
* - 'timestamp': last viewed node.
*
* @param $dbrows
* number of rows to be returned.
*
* @return
* A query result containing n.nid, n.title, u.uid, u.name of the selected node(s)
* or FALSE if the query could not be executed correctly.
*/
function statistics_title_list($dbfield, $dbrows) {
return db_query_range(db_rewrite_sql("SELECT n.nid, n.title, u.uid, u.name FROM {node} n INNER JOIN {node_counter} s ON n.nid = s.nid INNER JOIN {users} u ON n.uid = u.uid WHERE %s <> '0' AND n.status = 1 ORDER BY %s DESC"), 's.'. $dbfield, 's.'. $dbfield, 0, $dbrows);
}
/**
* Retrieves a node's "view statistics".
*
* @param $nid
* node ID
*
* @return
* An array with three entries: [0]=totalcount, [1]=daycount, [2]=timestamp
* - totalcount: count of the total number of times that node has been viewed.
* - daycount: count of the total number of times that node has been viewed "today".
* For the daycount to be reset, cron must be enabled.
* - timestamp: timestamp of when that node was last viewed.
*/
function statistics_get($nid) {
if ($nid > 0) {
/* retrieves an array with both totalcount and daycount */
$statistics = db_fetch_array(db_query('SELECT totalcount, daycount, timestamp FROM {node_counter} WHERE nid = %d', $nid));
}
return $statistics;
}
/**
* Implementation of hook_block().
*/
function statistics_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
if (variable_get('statistics_count_content_views', 0)) {
$blocks[0]['info'] = t('Popular content');
}
return $blocks;
case 'configure':
// Popular content block settings
$numbers = array('0' => t('Disabled')) + drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40));
$form['statistics_block_top_day_num'] = array('#type' => 'select', '#title' => t("Number of day's top views to display"), '#default_value' => variable_get('statistics_block_top_day_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "day" list.'));
$form['statistics_block_top_all_num'] = array('#type' => 'select', '#title' => t('Number of all time views to display'), '#default_value' => variable_get('statistics_block_top_all_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "all time" list.'));
$form['statistics_block_top_last_num'] = array('#type' => 'select', '#title' => t('Number of most recent views to display'), '#default_value' => variable_get('statistics_block_top_last_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "recently viewed" list.'));
return $form;
case 'save':
variable_set('statistics_block_top_day_num', $edit['statistics_block_top_day_num']);
variable_set('statistics_block_top_all_num', $edit['statistics_block_top_all_num']);
variable_set('statistics_block_top_last_num', $edit['statistics_block_top_last_num']);
break;
case 'view':
if (user_access('access content')) {
$content = array();
$daytop = variable_get('statistics_block_top_day_num', 0);
if ($daytop && ($result = statistics_title_list('daycount', $daytop)) && db_num_rows($result)) {
$content[] = node_title_list($result, t("Today's:"));
}
$alltimetop = variable_get('statistics_block_top_all_num', 0);
if ($alltimetop && ($result = statistics_title_list('totalcount', $alltimetop)) && db_num_rows($result)) {
$content[] = node_title_list($result, t('All time:'));
}
$lasttop = variable_get('statistics_block_top_last_num', 0);
if ($lasttop && ($result = statistics_title_list('timestamp', $lasttop)) && db_num_rows($result)) {
$content[] = node_title_list($result, t('Last viewed:'));
}
if (count($content)) {
$block['content'] = implode('<br />', $content);
$block['subject'] = t('Popular content');
return $block;
}
}
}
}
/**
* It is possible to adjust the width of columns generated by the
* statistics module.
*/
function _statistics_column_width($column, $width = 35) {
return (strlen($column) > $width ? substr($column, 0, $width) . '...' : $column);
}
function _statistics_format_item($title, $link) {
$link = ($link ? $link : '/');
$output = ($title ? "$title<br />" : '');
$output .= l(_statistics_column_width($link), $link);
return $output;
}
/**
* Implementation of hook_nodeapi().
*/
function statistics_nodeapi(&$node, $op, $arg = 0) {
switch ($op) {
case 'delete':
// clean up statistics table when node is deleted
db_query('DELETE FROM {node_counter} WHERE nid = %d', $node->nid);
}
}

View File

@ -1,93 +0,0 @@
<?php
// $Id$
/**
* @file
* Enables users to submit stories, articles or similar content.
*/
/**
* Implementation of hook_help().
*/
function story_help($section) {
switch ($section) {
case 'admin/help#story':
$output = '<p>'. t('The story module is used to create a content post type called <em>stories.</em> Stories are articles in their simplest form: they have a title, a teaser and a body. Stories are typically used to post news articles or as a group blog. ') .'</p>';
$output .= '<p>'. t('The story administration interface allows for complex configuration. It provides a submission form, workflow, default view permission, default edit permission, permissions for permission, and attachments. Trackbacks can also be enabled.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>post a story at <a href="%node-add-story">create content &gt;&gt; story</a>.</li>
<li>configure story at <a href="%admin-settings-content-types-story">administer &gt;&gt; settings &gt;&gt; content types &gt;&gt; configure story</a>.</li>
</ul>
', array('%node-add-story' => url('node/add/story'), '%admin-settings-content-types-story' => url('admin/settings/content-types/story')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%story">Story page</a>.', array('%story' => 'http://drupal.org/handbook/modules/story/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Allows users to submit stories, articles or similar content.');
case 'node/add#story':
return t('Stories are articles in their simplest form: they have a title, a teaser and a body, but can be extended by other modules. The teaser is part of the body too. Stories may be used as a personal blog or for news articles.');
}
}
/**
* Implementation of hook_node_info().
*/
function story_node_info() {
return array('story' => array('name' => t('story'), 'base' => 'story'));
}
/**
* Implementation of hook_perm().
*/
function story_perm() {
return array('create stories', 'edit own stories');
}
/**
* Implementation of hook_access().
*/
function story_access($op, $node) {
global $user;
if ($op == 'create') {
return user_access('create stories');
}
if ($op == 'update' || $op == 'delete') {
if (user_access('edit own stories') && ($user->uid == $node->uid)) {
return TRUE;
}
}
}
/**
* Implementation of hook_menu().
*/
function story_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'node/add/story', 'title' => t('story'),
'access' => user_access('create stories'));
}
return $items;
}
/**
* Implementation of hook_validate().
*/
function story_validate($node) {
node_validate_title($node);
}
/**
* Implementation of hook_form().
*/
function story_form(&$node) {
$form['title'] = array('#type' => 'textfield', '#title' => t('Title'), '#required' => TRUE, '#default_value' => $node->title, '#weight' => -5);
$form['body_filter']['body'] = array('#type' => 'textarea', '#title' => t('Body'), '#default_value' => $node->body, '#rows' => 20, '#required' => TRUE);
$form['body_filter']['format'] = filter_form($node->format);
return $form;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,158 +0,0 @@
<?php
// $Id$
/**
* @file
* Allows configuration of congestion control auto-throttle mechanism.
*/
/**
* Determine the current load on the site.
*
* Call the throttle_status() function from your own modules, themes, blocks,
* etc. to determine the current throttle status. For example, in your theme
* you might choose to disable pictures when your site is too busy (reducing
* bandwidth), or in your modules you might choose to disable some complicated
* logic when your site is too busy (reducing CPU utilization).
*
* @return
* 0 or 1. 0 means that the throttle is currently disabled. 1 means that
* the throttle is currently enabled. When the throttle is enabled, CPU
* and bandwidth intensive functionality should be disabled.
*/
function throttle_status() {
return variable_get('throttle_level', 0);
}
/**
* Implementation of hook_exit().
*
* Changes the current throttle level based on page hits.
*/
function throttle_exit() {
// The following logic determines what the current throttle level should
// be, and can be disabled by the admin. If enabled, the mt_rand() function
// returns a number between 0 and N, N being specified by the admin. If
// 0 is returned, the throttle logic is run, adding two additional database
// queries. Otherwise, the following logic is skipped. This mechanism is
// referred to in the admin page as the 'probability limiter', roughly
// limiting throttle related database calls to 1 in N.
if (!mt_rand(0, variable_get('throttle_probability_limiter', 9))) {
// Count users with activity in the past n seconds, defined in user module
$time_period = variable_get('user_block_seconds_online', 2700);
$throttle = module_invoke('throttle', 'status');
if ($max_guests = variable_get('throttle_anonymous', 0)) {
$guests = db_result(db_query('SELECT COUNT(sid) AS count FROM {sessions} WHERE timestamp >= %d AND uid = 0', time() - $time_period));
}
else {
$guests = 0;
}
if ($max_users = variable_get('throttle_user', 0)) {
$users = db_result(db_query('SELECT COUNT(DISTINCT(uid)) AS count FROM {sessions} WHERE timestamp >= %d AND uid != 0', time() - $time_period));
}
else {
$users = 0;
}
// update the throttle status
$message = '';
if ($max_users && $users > $max_users) {
if (!$throttle) {
variable_set('throttle_level', 1);
$message = format_plural($users,
'1 user accessing site; throttle enabled.',
'%count users accessing site; throttle enabled.');
}
}
elseif ($max_guests && $guests > $max_guests) {
if (!$throttle) {
variable_set('throttle_level', 1);
$message = format_plural($guests,
'1 guest accessing site; throttle enabled.',
'%count guests accessing site; throttle enabled.');
}
}
else {
if ($throttle) {
variable_set('throttle_level', 0);
// Note: unorthodox format_plural() usage due to Gettext plural limitations.
$message = format_plural($users, '1 user', '%count users') .', ';
$message .= format_plural($guests, '1 guest accessing site; throttle disabled', '%count guests accessing site; throttle disabled');
}
}
if ($message) {
cache_clear_all();
watchdog('throttle', t('Throttle') .': '. $message);
}
}
}
function _throttle_validate($value, $form) {
if ($value != NULL) {
if (!is_numeric($value) || $value < 0) {
form_set_error($form, t("'%value' is not a valid auto-throttle setting. Please enter a positive numeric value.", array('%value' => theme('placeholder', $value))));
}
}
}
/**
* Implementation of hook_help().
*/
function throttle_help($section) {
switch ($section) {
case 'admin/help#throttle':
$output = '<p>'. t('The throttle module provides a congestion control throttling mechanism for automatically detecting a surge in incoming traffic. If the site gets linked to by a popular website, or otherwise comes under a "Denial of Service" (DoS) attack, your webserver might become overwhelmed. This mechanism is utilized by other modules to automatically optimize their performance by temporarily disabling CPU-intensive functionality. For example, in the site theme, you might choose to disable pictures when the site is too busy (reducing bandwidth), or in modules, you might choose to disable some complicated logic (reducing CPU utilization).') .'</p>';
$output .= '<p>'. t('The congestion control throttle can be automatically enabled when the number of anonymous or authenticated users currently visiting the site exceeds the specified threshold. ') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>enable throttle for modules at <a href="%admin-modules">administer &gt;&gt; module</a>.</li>
<li>enable throttle for blocks at <a href="%admin-block">administer &gt;&gt; block</a>.</li>
<li>administer throttle at <a href="%admin-settings-throttle">administer &gt;&gt; settings &gt;&gt; throttle</a>.</li>
</ul>
', array('%admin-modules' => url('admin/modules'), '%admin-block' => url('admin/block'), '%admin-settings-throttle' => url('admin/settings/throttle')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%throttle">Throttle page</a>.', array('%throttle' => 'http://drupal.org/handbook/modules/throttle/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Handles the auto-throttling mechanism, to control site congestion.');
case 'admin/settings/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 congestion control throttling mechanism for automatically detecting a surge in incoming traffic. This mechanism is utilized by other Drupal modules to automatically optimize their performance by temporarily disabling CPU-intensive functionality.');
}
}
/**
* Implementation of hook_settings().
*/
function throttle_settings() {
_throttle_validate(variable_get('throttle_anonymous', ''), 'throttle_anonymous');
_throttle_validate(variable_get('throttle_user', ''), 'throttle_user');
$probabilities = array(0 => '100%', 1 => '50%', 2 => '33.3%', 3 => '25%', 4 => '20%', 5 => '16.6%', 7 => '12.5%', 9 => '10%', 19 => '5%', 99 => '1%', 199 => '.5%', 399 => '.25%', 989 => '.1%');
$form['throttle_anonymous'] = array(
'#type' => 'textfield',
'#title' => t('Auto-throttle on anonymous users'),
'#default_value' => variable_get('throttle_anonymous', 0),
'#size' => 5,
'#maxlength' => 6,
'#description' => t('The congestion control throttle can be automatically enabled when the number of anonymous users currently visiting your site exceeds the specified threshold. For example, to start the throttle when your site has 250 anonymous users online at once, enter \'250\' in this field. Leave this value blank or set to "0" if you do not wish to auto-throttle on anonymous users. You can inspect the current number of anonymous users using the "Who\'s online" block.')
);
$form['throttle_user'] = array(
'#type' => 'textfield',
'#title' => t('Auto-throttle on authenticated users'),
'#default_value' => variable_get('throttle_user', 0),
'#size' => 5,
'#maxlength' => 6,
'#description' => t('The congestion control throttle can be automatically enabled when the number of authenticated users currently visiting your site exceeds the specified threshold. For example, to start the throttle when your site has 50 registered users online at once, enter \'50\' in this field. Leave this value blank or set to "0" if you do not wish to auto-throttle on authenticated users. You can inspect the current number of authenticated users using the "Who\'s online" block.')
);
$form['throttle_probability_limiter'] = array(
'#type' => 'select',
'#title' => t('Auto-throttle probability limiter'),
'#default_value' => variable_get('throttle_probability_limiter', 9),
'#options' => $probabilities,
'#description' => t('The auto-throttle probability limiter is an efficiency mechanism to statistically reduce the overhead of the auto-throttle. The limiter is expressed as a percentage of page views, so for example if set to the default of 10% we only perform the extra database queries to update the throttle status 1 out of every 10 page views. The busier your site, the lower you should set the limiter value.')
);
return $form;
}

View File

@ -1,121 +0,0 @@
<?php
// $Id$
/**
* @file
* Enables tracking of recent posts for users.
*/
/**
* Implementation of hook_help().
*/
function tracker_help($section) {
switch ($section) {
case 'admin/help#tracker':
$output = '<p>'. t('The tracker module displays the most recently added or updated content to the website allowing users to see the most recent contributions. The tracker module provides user level tracking for those who like to follow the contributions of particular authors.') .'</p>';
$output .= '<p>'. t('The &quot;recent posts&quot; page is available via a link in the navigation menu block and contains a reverse chronological list of new and recently-updated content. The table displays the content type, the title, the author\'s name, how many comments that item has received, and when it was last updated. Updates include any changes to the text, either by the original author or someone else, as well as any new comments added to an item. To use the tracker module to <em>watch</em> for a user\'s updated content, click on that user\'s profile, then the <em>track</em> tab.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>view the <a href="%tracker">most recent posts</a>.</li>
<li>view <a href="%profile">user profiles</a> and select the track tab.</li>
<li>not administer this module.</li>
</ul>
', array('%tracker' => url('tracker'), '%profile' => url('profile')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%tracker">Tracker page</a>.', array('%tracker' => 'http://drupal.org/handbook/modules/tracker/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Enables tracking of recent posts for users.');
}
}
/**
* Implementation of hook_menu().
*/
function tracker_menu($may_cache) {
global $user;
$items = array();
if ($may_cache) {
$items[] = array('path' => 'tracker', 'title' => t('recent posts'),
'callback' => 'tracker_page', 'access' => user_access('access content'),
'weight' => 1);
if ($user->uid) {
$items[] = array('path' => 'tracker/all', 'title' => t('all recent posts'),
'type' => MENU_DEFAULT_LOCAL_TASK);
$items[] = array('path' => 'tracker/'. $user->uid, 'title' => t('my recent posts'),
'type' => MENU_LOCAL_TASK);
}
}
else {
if (arg(0) == 'user' && is_numeric(arg(1))) {
$items[] = array('path' => 'user/'. arg(1) .'/track', 'title' => t('track'),
'callback' => 'tracker_track_user', 'access' => user_access('access content'),
'type' => MENU_IS_LOCAL_TASK);
$items[] = array('path' => 'user/'. arg(1) .'/track/posts', 'title' => t('track posts'),
'type' => MENU_DEFAULT_LOCAL_TASK);
}
}
return $items;
}
/**
* Menu callback. Prints a listing of active nodes on the site.
*/
function tracker_track_user() {
if ($account = user_load(array('uid' => arg(1)))) {
drupal_set_title($account->name);
return tracker_page($account->uid);
}
}
/**
* Menu callback. Prints a listing of active nodes on the site.
*/
function tracker_page($uid = 0) {
if ($uid) {
$sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, l.last_comment_timestamp AS last_post, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {users} u ON n.uid = u.uid LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d) ORDER BY last_post DESC';
$sql = db_rewrite_sql($sql);
$sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d)';
$sql_count = db_rewrite_sql($sql_count);
$result = pager_query($sql, 25, 0, $sql_count, COMMENT_PUBLISHED, $uid, $uid);
}
else {
$sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, l.last_comment_timestamp AS last_post, l.comment_count FROM {node} n INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 ORDER BY last_post DESC';
$sql = db_rewrite_sql($sql);
$sql_count = 'SELECT COUNT(n.nid) FROM {node} n WHERE n.status = 1';
$sql_count = db_rewrite_sql($sql_count);
$result = pager_query($sql, 25, 0, $sql_count);
}
while ($node = db_fetch_object($result)) {
// Determine the number of comments:
$comments = 0;
if (module_exist('comment') && $node->comment_count) {
$comments = $node->comment_count;
if ($new = comment_num_new($node->nid)) {
$comments .= '<br />';
$comments .= l(format_plural($new, '1 new', '%count new'), "node/$node->nid", NULL, NULL, 'new');
}
}
$rows[] = array(
node_get_name($node->type),
l($node->title, "node/$node->nid") .' '. theme('mark', node_mark($node->nid, $node->changed)),
theme('username', $node),
array('class' => 'replies', 'data' => $comments),
t('%time ago', array('%time' => format_interval(time() - $node->last_post)))
);
}
$header = array(t('Type'), t('Post'), t('Author'), t('Replies'), t('Last post'));
$output = '<div id="tracker">';
$output .= theme('table', $header, $rows);
$output .= theme('pager', NULL, 25, 0);
$output .= '</div>';
return $output;
}

View File

@ -1,581 +0,0 @@
<?php
// $Id$
/**
* @file
* File-handling and attaching files to nodes.
*/
/**
* Implementation of hook_help().
*/
function upload_help($section) {
switch ($section) {
case 'admin/help#upload':
$output = '<p>'. t('The upload module allows users to upload files to the site. The ability to upload files to a site is important for members of a community who want to share work. It is also useful to administrators who want to keep uploaded files connected to a node or page.') .'</p>';
$output .= '<p>'. t('Users with the upload files permission can upload attachments. You can choose which post types can take attachments on the content types settings page. Each user role can be customized for the file size of uploads, and the dimension of image files.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>administer user permissions at <a href="%admin-user-configure">administer &gt;&gt; user &gt;&gt; configure &gt;&gt; permissions</a>.</li>
<li>administer content at <a href="%admin-node-configure">administer &gt;&gt; content types</a>.</li>
<li>administer upload at <a href="%admin-settings">administer &gt;&gt; settings</a>.</li>
</ul>
', array('%admin-user-configure' => url('admin/user/configure'), '%admin-node-configure' => url('admin/node/configure'), '%admin-settings' => url('admin/settings')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%upload">Upload page</a>.', array('%upload' => 'http://drupal.org/handbook/modules/upload/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Allows users to upload and attach files to content.');
case 'admin/settings/upload':
return t('<p>Users with the <a href="%permissions">upload files permission</a> can upload attachments. You can choose which post types can take attachments on the <a href="%types">content types settings</a> page.</p>', array('%permissions' => url('admin/access'), '%types' => url('admin/settings/content-types')));
}
}
/**
* Implementation of hook_perm().
*/
function upload_perm() {
return array('upload files', 'view uploaded files');
}
/**
* Implementation of hook_link().
*/
function upload_link($type, $node = 0, $main = 0) {
$links = array();
// Display a link with the number of attachments
if ($main && $type == 'node' && $node->files && user_access('view uploaded files')) {
$num_files = 0;
foreach ($node->files as $file) {
if ($file->list) {
$num_files++;
}
}
if ($num_files) {
$links[] = l(format_plural($num_files, '1 attachment', '%count attachments'), "node/$node->nid", array('title' => t('Read full article to view attachments.')), NULL, 'attachments');
}
}
return $links;
}
/**
* Implementation of hook_menu().
*/
function upload_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'upload/js',
'callback' => 'upload_js',
'access' => user_access('upload files'),
'type' => MENU_CALLBACK
);
}
else {
// Add handlers for previewing new uploads.
if ($_SESSION['file_uploads']) {
foreach ($_SESSION['file_uploads'] as $key => $file) {
$filename = file_create_filename($file->filename, file_create_path());
$items[] = array(
'path' => $filename, 'title' => t('file download'),
'callback' => 'upload_download',
'access' => user_access('view uploaded files'),
'type' => MENU_CALLBACK
);
$_SESSION['file_uploads'][$key]->_filename = $filename;
}
}
}
return $items;
}
function upload_settings() {
$form['settings_general'] = array('#type' => 'fieldset', '#title' => t('General settings'));
$form['settings_general']['upload_max_resolution'] = array(
'#type' => 'textfield', '#title' => t('Maximum resolution for uploaded images'), '#default_value' => variable_get('upload_max_resolution', 0),
'#size' => 15, '#maxlength' => 10, '#description' => t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.')
);
$roles = user_roles(0, 'upload files');
foreach ($roles as $rid => $role) {
$form["settings_role_$rid"] = array('#type' => 'fieldset', '#title' => t('Settings for %role', array('%role' => theme('placeholder', $role))), '#collapsible' => TRUE, '#collapsed' => TRUE);
$form["settings_role_$rid"]["upload_extensions_$rid"] = array(
'#type' => 'textfield', '#title' => t('Permitted file extensions'), '#default_value' => variable_get("upload_extensions_$rid", "jpg jpeg gif png txt html doc xls pdf ppt pps"),
'#maxlength' => 255, '#description' => t('Extensions that users in this role can upload. Separate extensions with a space and do not include the leading dot.')
);
$form["settings_role_$rid"]["upload_uploadsize_$rid"] = array(
'#type' => 'textfield', '#title' => t('Maximum file size per upload'), '#default_value' => variable_get("upload_uploadsize_$rid", 1),
'#size' => 5, '#maxlength' => 5, '#description' => t('The maximum size of a file a user can upload (in megabytes).')
);
$form["settings_role_$rid"]["upload_usersize_$rid"] = array(
'#type' => 'textfield', '#title' => t('Total file size per user'), '#default_value' => variable_get("upload_usersize_$rid", 10),
'#size' => 5, '#maxlength' => 5, '#description' => t('The maximum size of all files a user can have on the site (in megabytes).')
);
}
return $form;
}
function upload_download() {
foreach ($_SESSION['file_uploads'] as $file) {
if ($file->_filename == $_GET['q']) {
file_transfer($file->filepath, array('Content-Type: '. mime_header_encode($file->filemime), 'Content-Length: '. $file->filesize));
}
}
}
function upload_file_download($file) {
if (user_access('view uploaded files')) {
$file = file_create_path($file);
$result = db_query("SELECT f.* FROM {files} f WHERE filepath = '%s'", $file);
if ($file = db_fetch_object($result)) {
$node = node_load($file->nid);
if (node_access('view', $node)) {
$name = mime_header_encode($file->filename);
$type = mime_header_encode($file->filemime);
// Serve images and text inline for the browser to display rather than download.
$disposition = ereg('^(text/|image/)', $file->filemime) ? 'inline' : 'attachment';
return array('Content-Type: '. $type .'; name='. $name,
'Content-Length: '. $file->filesize,
'Content-Disposition: '. $disposition .'; filename='. $name);
}
}
}
}
function upload_form_alter($form_id, &$form) {
if (isset($form['type'])) {
if ($form['type']['#value'] .'_node_settings' == $form_id) {
$form['workflow']['upload_'. $form['type']['#value']] = array(
'#type' => 'radios', '#title' => t('Attachments'), '#default_value' => variable_get('upload_'. $form['type']['#value'], 1),
'#options' => array(t('Disabled'), t('Enabled')),
);
}
$node = $form['#node'];
if ($form['type']['#value'] .'_node_form' == $form_id && variable_get("upload_$node->type", TRUE) && user_access('upload files')) {
drupal_add_js('misc/progress.js');
drupal_add_js('misc/upload.js');
// Clears our files in session when you enter the edit view the first time.
// This is so files don't linger around if you happen to leave the node
// and come back into it.
if(count($_POST) == 0) {
unset($_SESSION['file_uploads']);
}
upload_nodeapi($node, 'validate', NULL);
$form['attachments'] = array(
'#type' => 'fieldset',
'#title' => t('File attachments'),
'#collapsible' => TRUE,
'#collapsed' => empty($node->files),
'#description' => t('Changes made to the attachments are not permanent until you save this post. The first "listed" file will be included in RSS feeds.'),
'#prefix' => '<div class="attachments">',
'#suffix' => '</div>',
'#weight' => 30,
);
$form['attachments'] += _upload_form($node);
$form['#attributes'] = array('enctype' => 'multipart/form-data');
}
}
}
/**
* Implementation of hook_nodeapi().
*/
function upload_nodeapi(&$node, $op, $arg) {
switch ($op) {
case 'validate':
$node->files = upload_load($node);
// Double check existing files:
if (is_array($node->list)) {
foreach ($node->list as $key => $value) {
// Ensure file is valid and retrieve contents of $_FILES array
if ($file = file_check_upload($key)) {
$node->files[$file->source] = $file;
$node->files[$key]->list = $node->list[$key];
$node->files[$key]->remove = $node->remove[$key];
$node->files[$key]->description = $node->description[$key];
if ($file->source) {
$filesize += $file->filesize;
}
}
}
}
else {
foreach ($node->files as $key => $file) {
$node->list[$key] = $file->list;
}
}
if (($file = file_check_upload('upload')) && user_access('upload files')) {
global $user;
$file = _upload_image($file);
// Don't do any checks for uid #1.
if ($user->uid != 1) {
// Validate file against all users roles. Only denies an upload when
// all roles prevent it.
$total_usersize = upload_space_used($user->uid) + $filesize;
foreach ($user->roles as $rid => $name) {
$extensions = variable_get("upload_extensions_$rid", 'jpg jpeg gif png txt html doc xls pdf ppt pps');
$uploadsize = variable_get("upload_uploadsize_$rid", 1) * 1024 * 1024;
$usersize = variable_get("upload_usersize_$rid", 1) * 1024 * 1024;
$regex = '/\.('. ereg_replace(' +', '|', preg_quote($extensions)) .')$/i';
if (!preg_match($regex, $file->filename)) {
$error['extension']++;
}
if ($uploadsize && $file->filesize > $uploadsize) {
$error['uploadsize']++;
}
if ($usersize && $total_usersize + $file->filesize > $usersize) {
$error['usersize']++;
}
}
}
if ($error['extension'] == count($user->roles) && $user->uid != 1) {
form_set_error('upload', t('The selected file %name can not be attached to this post, because it is only possible to attach files with the following extensions: %files-allowed.', array('%name' => theme('placeholder', $file->filename), '%files-allowed' => theme('placeholder', $extensions))));
}
elseif ($error['uploadsize'] == count($user->roles) && $user->uid != 1) {
form_set_error('upload', t('The selected file %name can not be attached to this post, because it exceeded the maximum filesize of %maxsize.', array('%name' => theme('placeholder', $file->filename), '%maxsize' => theme('placeholder', format_size($uploadsize)))));
}
elseif ($error['usersize'] == count($user->roles) && $user->uid != 1) {
form_set_error('upload', t('The selected file %name can not be attached to this post, because the disk quota of %quota has been reached.', array('%name' => theme('placeholder', $file->filename), '%quota' => theme('placeholder', format_size($usersize)))));
}
else {
$key = 'upload_'. count($_SESSION['file_uploads']);
$file->source = $key;
$file->list = 1;
$file = file_save_upload($file);
$node->files[$key] = $file;
}
}
for ($x = 0; $x < count($_SESSION['file_uploads']); $x++) {
$key = 'upload_' . $x;
if ($file = file_check_upload($key)) {
$node->files[$key] = $file;
}
}
break;
case 'load':
if (variable_get("upload_$node->type", 1) == 1) {
$output['files'] = upload_load($node);
}
break;
case 'view':
if ($node->files && user_access('view uploaded files')) {
$header = array(t('Attachment'), t('Size'));
$rows = array();
$previews = array();
// Build list of attached files
foreach ($node->files as $key => $file) {
if ($file->list && !$node->remove[$key]) {
$rows[] = array(
'<a href="'. check_url(($file->fid ? file_create_url($file->filepath) : url(file_create_filename($file->filename, file_create_path())))) .'">'. check_plain($file->description ? $file->description : $file->filename) .'</a>',
format_size($file->filesize)
);
// We save the list of files still in preview for later
if (!$file->fid) {
$previews[] = $file;
}
}
}
// URLs to files being previewed are actually Drupal paths. When Clean
// URLs are disabled, the two do not match. We perform an automatic
// replacement from temporary to permanent URLs. That way, the author
// can use the final URL in the body before having actually saved (to
// place inline images for example).
if (!variable_get('clean_url', 0)) {
foreach ($previews as $file) {
$old = file_create_filename($file->filename, file_create_path());
$new = url($old);
$node->body = str_replace($old, $new, $node->body);
$node->teaser = str_replace($old, $new, $node->teaser);
}
}
$teaser = $arg;
// Add the attachments list
if (count($rows) && !$teaser) {
$node->body .= theme('table', $header, $rows, array('id' => 'attachments'));
}
}
break;
case 'insert':
case 'update':
if (user_access('upload files')) {
upload_save($node);
}
break;
case 'delete':
upload_delete($node);
break;
case 'delete revision':
upload_delete_revision($node);
break;
case 'search result':
return $node->files ? format_plural(count($node->files), '1 attachment', '%count attachments') : null;
case 'rss item':
if ($node->files) {
$files = array();
foreach ($node->files as $file) {
if ($file->list) {
$files[] = $file;
}
}
if (count($files) > 0) {
// RSS only allows one enclosure per item
$file = array_shift($files);
return array(array('key' => 'enclosure',
'attributes' => array('url' => file_create_url($file->filepath),
'length' => $file->filesize,
'type' => $file->filemime)));
}
}
return array();
}
return $output;
}
/**
* Determine how much disk space is occupied by a user's uploaded files.
*
* @param $uid
* The integer user id of a user.
* @return
* The amount of disk space used by the user in bytes.
*/
function upload_space_used($uid) {
return db_result(db_query('SELECT SUM(filesize) FROM {files} f INNER JOIN {node} n ON f.nid = n.nid WHERE n.uid = %d', $uid));
}
/**
* Determine how much disk space is occupied by uploaded files.
*
* @return
* The amount of disk space used by uploaded files in bytes.
*/
function upload_total_space_used() {
return db_result(db_query('SELECT SUM(filesize) FROM {files}'));
}
function upload_save($node) {
$node->old_files = isset($node->files) ? $node->files : array();
upload_nodeapi($node, 'validate', NULL);
$node->files = $node->old_files + $node->files;
foreach ((array)$node->files as $key => $file) {
// New file upload
if ($file->source) {
// Only add a file if it's not marked for removal
if (!$node->remove[$key]) {
if ($file = file_save_upload($file, $file->filename)) {
$fid = db_next_id('{files}_fid');
db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', %d)", $fid, $node->nid, $file->filename, $file->filepath, $file->filemime, $file->filesize);
db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $fid, $node->vid, $node->list[$key], $node->description[$key]);
}
}
// Clean up the session
unset($_SESSION['file_uploads'][$file->source]);
}
// Update existing file
else {
// Remove existing file, as needed
if ($node->remove[$key]) {
db_query('DELETE FROM {file_revisions} WHERE fid = %d AND vid = %d', $key, $node->vid);
// Only delete a file if it isn't used by any revision
$count = db_result(db_query('SELECT COUNT(fid) FROM {file_revisions} WHERE fid = %d', $key));
if ($count < 1) {
db_query('DELETE FROM {files} WHERE fid = %d', $key);
file_delete($file->filepath);
}
}
else {
// Create a new revision, as needed
if ($node->old_vid && is_numeric($key)) {
// new revision
if (isset($node->list)) {
db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $key, $node->vid, $node->list[$key], $node->description[$key]);
}
// copy of old revision
else {
db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $key, $node->vid, $file->list, $file->description);
}
}
// Update existing revision
else {
db_query("UPDATE {file_revisions} SET list = %d, description = '%s' WHERE fid = %d AND vid = %d", $node->list[$key], $node->description[$key], $key, $node->vid);
}
}
}
}
return;
}
function upload_delete($node) {
$files = array();
$result = db_query('SELECT * FROM {files} WHERE nid = %d', $node->nid);
while ($file = db_fetch_object($result)) {
$files[$file->fid] = $file;
}
foreach ($files as $fid => $file) {
// delete all file revision information associated with the node
db_query('DELETE FROM {file_revisions} WHERE fid = %d', $fid);
file_delete($file->filepath);
}
// delete all files associated with the node
db_query('DELETE FROM {files} WHERE nid = %d', $node->nid);
}
function upload_delete_revision($node) {
$files = upload_load($node);
foreach ($files as $file) {
// check if the file will be used after this revision is deleted
$count = db_result(db_query('SELECT COUNT(fid) FROM {file_revisions} WHERE fid = %d', $file->fid));
// if the file won't be used, delete it
if ($count < 2) {
db_query('DELETE FROM {files} WHERE fid = %d', $file->fid);
file_delete($file->filepath);
}
}
// delete the revision
db_query('DELETE FROM {file_revisions} WHERE vid = %d', $node->vid);
}
function _upload_form($node) {
$header = array(t('Delete'), t('List'), t('Description'), t('Size'));
$rows = array();
$output = '';
$form['#theme'] = 'upload_form_new';
if (is_array($node->files) && count($node->files)) {
$form['current']['#theme'] = 'upload_form_current';
$form['current']['description']['#tree'] = TRUE;
foreach ($node->files as $key => $file) {
$options[$key] = '';
if ($file->remove || $node->remove[$key]) {
$remove[] = $key;
}
if ($file->list || $node->list[$key]) {
$list[] = $key;
}
$description = "<small>". file_create_url(($file->fid ? $file->filepath : file_create_filename($file->filename, file_create_path()))) ."</small>";
$form['current']['description'][$key] = array('#type' => 'textfield', '#default_value' => $file->description ? $file->description : $file->filename, '#maxlength' => 256, '#description' => $description );
$form['current']['size'][$key] = array('#type' => 'markup', '#value' => format_size($file->filesize));
}
$form['current']['remove'] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => $remove);
$form['current']['list'] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => $list);
$form['files'][$key] = array('#type' => 'hidden', '#value' => 1);
}
if (user_access('upload files')) {
$form['new']['upload'] = array('#type' => 'file', '#title' => t('Attach new file'), '#size' => 40);
$form['new']['fileop'] = array('#type' => 'button', '#value' => t('Attach'), '#name'=> 'fileop', '#attributes' => array('id' => 'fileop'));
// The class triggers the js upload behaviour.
$form['fileop'] = array('#type' => 'hidden', '#value' => url('upload/js', NULL, NULL, TRUE), '#attributes' => array('class' => 'upload'));
}
// Needed for JS
$form['current']['vid'] = array('#type' => 'hidden', '#value' => $node->vid);
return $form;
}
function theme_upload_form_new($form) {
$output .= '<div id="fileop-wrapper">' . "\n";
$output .= '<div id="fileop-hide">' . "\n";
$output .= form_render($form) . "\n";
$output .= "</div>\n";
$output .= "</div>\n";
return $output;
}
function theme_upload_form_current(&$form) {
$header = array(t('Delete'), t('List'), t('Description'), t('Size'));
foreach (element_children($form['description']) as $key) {
$row = array();
$row[] = form_render($form['remove'][$key]);
$row[] = form_render($form['list'][$key]);
$row[] = form_render($form['description'][$key]);
$row[] = form_render($form['size'][$key]);
$rows[] = $row;
}
$output = theme('table', $header, $rows);
$output .= form_render($form);
return $output;
}
function upload_load($node) {
$files = array();
if ($node->vid) {
$result = db_query('SELECT * FROM {files} f INNER JOIN {file_revisions} r ON f.fid = r.fid WHERE r.vid = %d', $node->vid);
while ($file = db_fetch_object($result)) {
$files[$file->fid] = $file;
}
}
return $files;
}
/**
* Check an upload, if it is an image, make sure it fits within the
* maximum dimensions allowed.
*/
function _upload_image($file) {
$info = image_get_info($file->filepath);
if ($info) {
list($width, $height) = explode('x', variable_get('upload_max_resolution', 0));
if ($width && $height) {
$result = image_scale($file->filepath, $file->filepath, $width, $height);
if ($result) {
$file->filesize = filesize($file->filepath);
drupal_set_message(t('The image was resized to fit within the maximum allowed resolution of %resolution pixels.', array('%resolution' => theme('placeholder', variable_get('upload_max_resolution', 0)))));
}
}
}
return $file;
}
/**
* Menu-callback for JavaScript-based uploads.
*/
function upload_js() {
// We only do the upload.module part of the node validation process.
$node = (object)$_POST['edit'];
upload_nodeapi($node, 'validate', NULL);
$form = _upload_form($node);
$form = form_builder('upload_js', $form);
$output = theme('status_messages') . form_render($form);
// We send the updated file attachments form.
print drupal_to_js(array('status' => TRUE, 'data' => $output));
exit;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,185 +0,0 @@
<?php
// $Id$
/**
* @file
* System monitoring and logging for administrators.
*
* The watchdog module monitors your site and keeps a list of
* recorded events containing usage and performance data, errors,
* warnings, and similar operational information.
*
* @see watchdog().
*/
/**
* Implementation of hook_help().
*/
function watchdog_help($section) {
switch ($section) {
case 'admin/help#watchdog':
$output = '<p>'. t('The watchdog module monitors your system, capturing system events in a log to be reviewed by an authorized individual at a later time. This is useful for site administrators who want a quick overview of activities on their site. The logs also record the sequence of events, so it can be useful for debugging site errors.') .'</p>';
$output .= '<p>'. t('The watchdog log is simply a list of recorded events containing usage data, performance data, errors, warnings and operational information. Administrators should check the watchdog report on a regular basis to ensure their site is working properly.') .'</p>';
$output .= t('<p>You can</p>
<ul>
<li>view watchdog logs at <a href="%admin-watchdog">administer &gt;&gt; watchdog</a>.</li>
<li>view watchdog event logs at <a href="%admin-watchdog-events">administer &gt;&gt; watchdog &gt;&gt; events</a>.</li>
</ul>
', array('%admin-watchdog' => url('admin/watchdog'), '%admin-watchdog-events' => url('admin/watchdog/events')));
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%watchdog">Watchdog page</a>.', array('%watchdog' => 'http://drupal.org/handbook/modules/watchdog/')) .'</p>';
return $output;
case 'admin/modules#description':
return t('Logs and records system events.');
case 'admin/logs':
return t('<p>The 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.</p>');
}
}
/**
* Implementation of hook_menu().
*/
function watchdog_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'admin/logs', 'title' => t('logs'),
'callback' => 'watchdog_overview');
$items[] = array('path' => 'admin/logs/event', 'title' => t('details'),
'callback' => 'watchdog_event',
'type' => MENU_CALLBACK);
}
return $items;
}
/**
* Implementation of hook_cron().
*
* Remove expired log messages and flood control events.
*/
function watchdog_cron() {
db_query('DELETE FROM {watchdog} WHERE timestamp < %d', time() - variable_get('watchdog_clear', 604800));
db_query('DELETE FROM {flood} WHERE timestamp < %d', time() - 3600);
}
/**
* Menu callback; displays a listing of log messages.
*/
function watchdog_overview() {
$icons = array(WATCHDOG_NOTICE => '',
WATCHDOG_WARNING => theme('image', 'misc/watchdog-warning.png', t('warning'), t('warning')),
WATCHDOG_ERROR => theme('image', 'misc/watchdog-error.png', t('error'), t('error')));
$classes = array(WATCHDOG_NOTICE => 'watchdog-notice', WATCHDOG_WARNING => 'watchdog-warning', WATCHDOG_ERROR => 'watchdog-error');
$names['all'] = t('all messages');
foreach (_watchdog_get_message_types() as $type) {
$names[$type] = t('%type messages', array('%type' => t($type)));
}
if (empty($_SESSION['watchdog_overview_filter'])) {
$_SESSION['watchdog_overview_filter'] = 'all';
}
$form['filter'] = array(
'#type' => 'select',
'#title' => t('Filter by message type'),
'#options' => $names,
'#default_value' => $_SESSION['watchdog_overview_filter']
);
$form['#action'] = url('admin/logs');
$form['submit'] = array('#type' => 'submit', '#value' =>t('Filter'));
$output = drupal_get_form('watchdog_form_overview', $form);
$header = array(
' ',
array('data' => t('Type'), 'field' => 'w.type'),
array('data' => t('Date'), 'field' => 'w.wid', 'sort' => 'desc'),
array('data' => t('Message'), 'field' => 'w.message'),
array('data' => t('User'), 'field' => 'u.name'),
array('data' => t('Operations'))
);
$sql = "SELECT w.*, u.name, u.uid FROM {watchdog} w INNER JOIN {users} u ON w.uid = u.uid";
$tablesort = tablesort_sql($header);
$type = $_SESSION['watchdog_overview_filter'];
if ($type != 'all') {
$result = pager_query($sql ." WHERE w.type = '%s'". $tablesort, 50, 0, NULL, $type);
}
else {
$result = pager_query($sql . $tablesort, 50);
}
while ($watchdog = db_fetch_object($result)) {
$rows[] = array('data' =>
array(
// Cells
$icons[$watchdog->severity],
t($watchdog->type),
format_date($watchdog->timestamp, 'small'),
l(truncate_utf8($watchdog->message, 56, TRUE, TRUE), 'admin/logs/event/'. $watchdog->wid, array(), NULL, NULL, FALSE, TRUE),
theme('username', $watchdog),
$watchdog->link,
),
// Attributes for tr
'class' => "watchdog-". preg_replace('/[^a-z]/i', '-', $watchdog->type) .' '. $classes[$watchdog->severity]
);
}
if (!$rows) {
$rows[] = array(array('data' => t('No log messages available.'), 'colspan' => 6));
}
$output .= theme('table', $header, $rows);
$output .= theme('pager', NULL, 50, 0, tablesort_pager());
return $output;
}
function theme_watchdog_form_overview($form) {
return '<div class="container-inline">'. form_render($form) .'</div>';
}
function watchdog_form_overview_submit($form_id, $form) {
global $form_values;
$_SESSION['watchdog_overview_filter'] = $form_values['filter'];
}
/**
* Menu callback; displays details about a log message.
*/
function watchdog_event($id) {
$severity = array(WATCHDOG_NOTICE => t('notice'), WATCHDOG_WARNING => t('warning'), WATCHDOG_ERROR => t('error'));
$output = '';
$result = db_query('SELECT w.*, u.name, u.uid FROM {watchdog} w INNER JOIN {users} u ON w.uid = u.uid WHERE w.wid = %d', $id);
if ($watchdog = db_fetch_object($result)) {
$header = array(t('Type'), t('Date'), t('User'), t('Location'), t('Referrer'), t('Message'), t('Severity'), t('Hostname'));
$data = array(t($watchdog->type), format_date($watchdog->timestamp, 'large'), theme('username', $watchdog), l($watchdog->location, $watchdog->location), l($watchdog->referer, $watchdog->referer), $watchdog->message, $severity[$watchdog->severity], $watchdog->hostname);
$output = theme('watchdog_event', $header, $data);
}
return $output;
}
function theme_watchdog_event($header, $data) {
$output = '';
$output .= '<table class="watchdog-event">';
$n = count($header);
for ($i = 0; $i < $n; $i++) {
$output .= '<tr class="' . ($i % 2 == 0 ? 'even' : 'odd') . '"><th>' . $header[$i] . '</th><td>' . $data[$i] . '</td></tr>';
}
$output .= '</table>';
return $output;
}
function _watchdog_get_message_types() {
$types = array();
$result = db_query('SELECT DISTINCT(type) FROM {watchdog} ORDER BY type');
while ($object = db_fetch_object($result)) {
$types[] = $object->type;
}
return $types;
}