86400) { // Find CVS users with newsletter subscriptions but not the CVS newsletter. $result = db_query("SELECT u.uid, u.mail, ss.snid FROM {cvs_accounts} ca INNER JOIN {users} u ON u.uid = ca.uid INNER JOIN {simplenews_subscriptions} ss ON ss.uid = ca.uid WHERE ca.status = %d", CVS_APPROVED); while ($account = db_fetch_object($result)) { if (!db_result(db_query("SELECT snid FROM {simplenews_snid_tid} WHERE snid = %d AND tid = %d", $account->snid, DRUPALORG_CVS_NEWSLETTER))) { module_invoke('simplenews', 'subscribe_user', $account->mail, DRUPALORG_CVS_NEWSLETTER, FALSE); } } // Find CVS users with no newsletter subscriptions at all. $result = db_query("SELECT u.uid, u.mail FROM {cvs_accounts} ca INNER JOIN {users} u ON u.uid = ca.uid LEFT JOIN {simplenews_subscriptions} ss ON ss.uid = ca.uid WHERE ca.status = %d AND ss.uid IS NULL", CVS_APPROVED); while ($account = db_fetch_object($result)) { module_invoke('simplenews', 'subscribe_user', $account->mail, DRUPALORG_CVS_NEWSLETTER, FALSE); } // Store the time of the last run. variable_set('drupalorg_cvs_subscribe_time', time()); } } /** * Pulls issue counts for various issue queues on drupal.org. */ function drupalorg_issue_counts() { $issue_counts['Pending bugs'] = db_result(db_query("SELECT COUNT(*) FROM {project_issues} pi INNER JOIN {node} n ON pi.nid = n.nid WHERE n.status = 1 AND pid = 3060 AND category = 'bug' AND sid = 1 AND priority IN (1,2) AND rid IN (". ISSUE_RIDS .")")); $issue_counts['Critical issues'] = db_result(db_query("SELECT COUNT(*) FROM {project_issues} pi INNER JOIN {node} n ON pi.nid = n.nid WHERE n.status = 1 AND pid = 3060 AND category IN ('bug', 'task') AND sid IN (1,8,13,14) AND priority = 1 AND rid IN (". ISSUE_RIDS .")")); $issue_counts['Patch queue'] = db_result(db_query("SELECT COUNT(*) FROM {project_issues} pi INNER JOIN {node} n ON pi.nid = n.nid WHERE n.status = 1 AND pid = 3060 AND sid IN (8,13,14) AND rid IN (". ISSUE_RIDS .")")); $issue_counts['Patches to review'] = db_result(db_query("SELECT COUNT(*) FROM {project_issues} pi INNER JOIN {node} n ON pi.nid = n.nid WHERE n.status = 1 AND pid = 3060 AND sid IN (8) AND rid IN (". ISSUE_RIDS .")")); variable_set('drupalorg_issue_counts', $issue_counts); } /** * Implementation of hook_form_alter(). */ function drupalorg_form_alter($form_id, &$form) { // List of forms to check for overrides, and the corresponding permissions. $override_forms = array( 'book_node_form' => 'edit book pages', 'forum_node_form' => 'administer nodes', 'page_node_form' => 'administer nodes', 'simplenews_node_form' => 'create newsletter', 'story_node_form' => 'administer nodes', ); // Override the access for attachments if it's a forbidden form, // and the user does not have sufficient permissions. if (in_array($form_id, array_keys($override_forms)) && !user_access($override_forms[$form_id])) { if (isset($form['attachments']['#access'])) { $form['attachments']['#access'] = FALSE; } } // Add a description for the Priority and Status values. if ($form_id == 'project_issue_node_form' || $form_id == 'comment_form' && !empty($form['original_issue']['issue_info'])) { $priority_status_description = array( // The "standard" class adds a clear so the description is positioned // below the floated pull-downs. "fieldset-description" is from // bluebeach to make the font size smaller. '#prefix' => '
', '#value' => t('Descriptions of the Priority and Status values can be found in the Issue queue handbook.', array('!priority_url' => '/node/45111', '!status_url' => '/node/156119', '!issue_queue_url' => '/node/317')), '#suffix' => '
', ); } // Make the "Issue tags" vocabulary not so prominent on issue nodes. if ($form_id == 'project_issue_node_form' || ($form_id == 'comment_form' && !empty($form['original_issue']['issue_info']))) { $form['taxonomy']['#type'] = 'fieldset'; $form['taxonomy']['#title'] = t('Tags'); $form['taxonomy']['#collapsible'] = TRUE; $form['taxonomy']['#collapsed'] = TRUE; // We want this fieldset at the very bottom, just above the buttons, but // we need different weights for that depending on if it's a new issue or // a follow-up comment. if ($form_id == 'project_issue_node_form') { $form['taxonomy']['#weight'] = 35; } else { $form['taxonomy']['#weight'] = 4; } } if ($form_id == 'project_issue_node_form') { $form['issue_info']['description'] = $priority_status_description; } else if ($form_id == 'comment_form' && !empty($form['original_issue']['issue_info'])) { $form['original_issue']['issue_info']['description'] = $priority_status_description; } elseif ($form_id == 'project_release_node_form') { drupalorg_form_project_release_node_form_alter($form_id, $form); } else if ($form_id == 'cvs_user_edit_form') { $submit['drupalorg_cvs_user_edit_submit'] = array(); $form['#submit'] = $form['#submit'] + $submit; } elseif (($form_id == 'user_edit' && isset($form['_category']['#value']) && $form['_category']['#value'] == 'newsletter') || ($form_id == 'simplenews_subscription_manager_form')) { // Alter the newsletter subscription form for CVS account holders only. // An admin may be editing some other user's account. if (isset($form['_account']['#value'])) { $account = $form['_account']['#value']; } else { $account = $GLOBALS['user']; } // Don't allow CVS account holders to unsubscribe from the required newsletter. // Determine if the account being edited is an approved CVS user. if (db_result(db_query("SELECT 1 FROM {cvs_accounts} WHERE uid = %d AND status = %d", $account->uid, CVS_APPROVED))) { $subscribed = is_array($form['subscriptions']['newsletters']['#default_value']) ? in_array(DRUPALORG_CVS_NEWSLETTER, $form['subscriptions']['newsletters']['#default_value']) : FALSE; // Only disable the check box if the user is already subscribed. if ($subscribed) { $title = $form['subscriptions']['newsletters']['#options'][DRUPALORG_CVS_NEWSLETTER]; // Take the required CVs newsletter out of the normal checkboxes. unset($form['subscriptions']['newsletters']['#options'][DRUPALORG_CVS_NEWSLETTER]); // Append a single disabled checkbox below. $form['subscriptions']['cvs_newsletter'] = array( '#type' => 'checkbox', '#title' => $title .' '. t('(mandatory for users with a CVS account)'), '#default_value' => TRUE, '#disabled' => TRUE, ); } } } elseif ($form_id == 'project_project_node_form') { // Deprecate the "license" field, as it must always be GPLv2+ anyway. if (! $form['project']['license']['#default_value']) { $form['project']['license'] = array( '#type' => 'item', '#title' => $form['project']['license']['#title'], '#value' => t('@link_name', array( '@link_url' => CVS_LICENSE_LINK, '@link_name' => CVS_LICENSE, )), ); } } elseif ($form_id == 'search_admin_settings') { unset($form['status']['wipe']); } elseif ($form_id == 'user_register') { $form['#validate']['drupalorg_register_mail_validate'] = array(); } elseif ($form_id == 'user_admin_access_add_form' || $form_id == 'user_admin_access_edit_form') { $form['type']['#options']['homepage'] = t('Homepage'); } elseif ($form_id == 'user_edit') { $form['#validate']['drupalorg_profile_user_edit_validate'] = array(); if (isset($form['Personal information']['profile_languages'])) { $form['Personal information']['profile_languages']['#multiple'] = TRUE; $form['Personal information']['profile_languages']['#default_value'] = explode('; ', $form['Personal information']['profile_languages']['#default_value']); $form['#validate']['drupalorg_profile_fix_languages'] = array(); } } // Force a revision log entry when editing book nodes. elseif ($form_id == 'book_node_form' && isset($form['log']) && arg(1) != 'add') { $form['log']['#required'] = TRUE; } // Remove the news vocabulary on forum forms, if the user is not an admin. // Used to mark news forum topics with tags. if ($form_id == 'forum_node_form' && !user_access('administer nodes')) { unset($form['taxonomy'][DRUPALORG_NEWS_VID]); } } function drupalorg_form_project_release_node_form_alter($form_id, &$form) { if (!empty($form['taxonomy'])) { $vid = drupalorg_get_release_type_vid(); $security_tid = drupalorg_get_security_update_tid(); if (!empty($form['taxonomy'][$vid])) { $form['taxonomy'][$vid]['#weight'] = 10; if (empty($form['nid']['#value'])) { // Adding a new release. if (!empty($form['cvs_tag']['rebuild']['#value'])) { // This is a -dev, don't let anyone mark it a security update. _drupalorg_remove_security_update($form); } else { // Regular release $form['taxonomy'][$vid]['#description'] = t('What is a release type?', array('@handbook_url' => DRUPALORG_RELEASE_TYPE_HANDBOOK_URL)); $form['taxonomy'][$vid]['#prefix'] = '
'; $form['taxonomy'][$vid]['#suffix'] = '
'; $form['#validate']['drupalorg_security_release_form_validate'] = array(); $confirm_class = 'security-update-confirm'; // Hide the confirmation checkbox on page load unless 'Security // update' is already selected. if (empty($form['#post']['taxonomy'][$vid]) || (array_search($security_tid, $form['#post']['taxonomy'][$vid]) === FALSE)) { $confirm_class .= ' js-hide'; } $form['security_update_confirm'] = array( '#type' => 'checkbox', '#title' => t('Are you sure you want to mark this release as a Security update?', array('@security_update_url' => DRUPALORG_SECURITY_UPDATE_HANDBOOK_URL)), '#prefix' => '
', '#suffix' => '
', '#weight' => -2, '#description' => t('If you select %security_update, your release will not be published without the manual intervention of the Drupal Security Team. You should have already contacted the Security Team to coordinate a security advisory (SA) for your release before you committed any security-related patches.', array('%security_update' => t('Security update'), '@security_url' => DRUPALORG_SECURITY_TEAM_URL, '@contact_url' => DRUPALORG_SECURITY_CONTACT_URL)), ); $drupalorg_path = drupal_get_path('module', 'drupalorg'); drupal_add_js($drupalorg_path .'/js/drupalorg.release_node.js'); drupal_add_css($drupalorg_path .'/drupalorg.css'); } } else { // Editing an existing release. if (array_search($security_tid, $form['taxonomy'][$vid]['#default_value']) !== FALSE) { // If this release is already marked as a Security update, don't // let regular users change it any futher. if (!user_access('administer projects')) { $form['taxonomy'][$vid]['#disabled'] = TRUE; } $form['taxonomy'][$vid]['#description'] = t('What is a release type? Since this release is already marked as a %security_update, you can no longer change the release type. If you believe you need to do so for some reason, you should contact the Drupal Security Team.', array('@handbook_url' => DRUPALORG_RELEASE_TYPE_HANDBOOK_URL, '%security_update' => t('Security update'), '@security_url' => DRUPALORG_SECURITY_TEAM_URL, '@contact_url' => DRUPALORG_SECURITY_CONTACT_URL)); } else { // Not a Security update, remove that option entirely if this is // either a -dev snapshot or a non-admin user. if (!empty($form['#node']->rebuild) || !user_access('administer projects')) { _drupalorg_remove_security_update($form); } $form['taxonomy'][$vid]['#description'] = t('What is a release type?', array('@handbook_url' => DRUPALORG_RELEASE_TYPE_HANDBOOK_URL)); } } } } } function _drupalorg_remove_security_update(&$form) { $vid = drupalorg_get_release_type_vid(); $security_tid = drupalorg_get_security_update_tid(); foreach ($form['taxonomy'][$vid]['#options'] as $i => $option) { if (!empty($option->option)) { $tid = key($option->option); if ($tid == $security_tid) { unset($form['taxonomy'][$vid]['#options'][$i]); return; } } } } function drupalorg_get_release_type_vid() { static $vid = 0; if (empty($vid)) { $vid = variable_get('project_release_type_vid', 0); if (empty($vid)) { $vid = db_result(db_query("SELECT v.vid FROM {vocabulary} v INNER JOIN {vocabulary_node_types} n ON v.vid = n.vid WHERE n.type = 'project_release' AND v.name = 'Release type'")); variable_set('project_release_type_vid', $vid); } } return $vid; } function drupalorg_get_security_update_tid() { static $tid = 0; if (empty($tid)) { $tid = variable_get('project_release_type_security_update_tid', 0); if (empty($tid)) { $tid = db_result(db_query("SELECT tid FROM {term_data} WHERE vid = %d AND name = '%s'", drupalorg_get_release_type_vid(), 'Security update')); variable_set('project_release_type_security_update_tid', $tid); } } return $tid; } function drupalorg_security_release_form_validate($form_id, $form_values, $form) { $vid = drupalorg_get_release_type_vid(); $security_tid = drupalorg_get_security_update_tid(); if (!empty($form_values['taxonomy'][$vid][$security_tid]) && empty($form_values['security_update_confirm'])) { form_set_error('security_update_confirm', t('You must confirm you want this release to be a Security update', array('@security_update_url' => DRUPALORG_SECURITY_UPDATE_HANDBOOK_URL))); } } function drupalorg_register_mail_validate($form_id, $form_values) { $hit = preg_match('/(.*)\+(.*)\@(.*)/', $form_values['mail'], $match); if ($hit) { if (db_num_rows(db_query("SELECT uid FROM {users} WHERE LOWER(mail) LIKE LOWER('%s')", $match[1] .'+%%@'. $match[3])) > 0) { form_set_error('mail', t('An e-mail address similar to %email is already registered. Have you forgotten your password?', array('%email' => $form_values['mail'], '@password' => url('user/password')))); } } } /** * Validation handler for the user profile form, to serialize languages to a string. */ function drupalorg_profile_fix_languages($form_id, $form_values, $form) { if (is_array($form_values['profile_languages'])) { form_set_value($form['Personal information']['profile_languages'], join('; ', array_keys($form_values['profile_languages']))); } } /** * Validate all fields in the user_edit form against the list of bad words. */ function drupalorg_profile_user_edit_validate($form_id, $form_values) { $result = db_query("SELECT mask FROM {access} WHERE type = '%s' AND status = %d", 'homepage', 0); $masks = array(); while ($mask = db_fetch_object($result)) { $masks[] = '@'. strtr($mask->mask, array('.' => '\.', '%' => '.*', '_' => '.')) .'@'; } foreach ($form_values as $name => $value) { if (is_string($value) && strlen($value) > 7 && strpos($name, 'homepage') === 0) { // check denied homepages foreach ($masks as $mask) { if (preg_match($mask, $value)){ form_set_error($name, t('Unsuitable homepage detected')); } } if (!user_access('administer users')) { // Override for admins // check for Drupal-ness of website. Try only once. $response = drupal_http_request($value, array(), 'GET', NULL, 1); if ($response->headers['Expires'] != 'Sun, 19 Nov 1978 05:00:00 GMT') { form_set_error($name, t("Your website does not seem to be a Drupal site. If you think we are wrong, please open an issue in the webmasters' queue.")); } } } } } /** * Implementation of hook_comment. */ function drupalorg_comment(&$comment, $op) { switch ($op) { case 'insert': case 'update': $_SESSION['not_slavesafe'] = TRUE; break; } } /** * Implementation of hook_nodeapi. */ function drupalorg_nodeapi(&$node, $op, $teaser, $page) { switch ($op) { case 'insert': case 'update': $_SESSION['not_slavesafe'] = TRUE; } } function drupalorg_cvs_user_edit_submit($form_id, &$form_values) { if (isset($form_values['cvs_status'])) { $account = user_load(array('uid' => $form_values['cvs_uid'])); switch ($form_values['cvs_status']) { case CVS_APPROVED: db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', $form_values['cvs_uid'], DRUPALORG_CVS_USER_ROLE); module_invoke('simplenews', 'subscribe_user', $account->mail, DRUPALORG_CVS_NEWSLETTER, FALSE); break; case CVS_DISABLED: db_query('DELETE FROM {users_roles} WHERE uid = %d AND rid = %d', $form_values['cvs_uid'], DRUPALORG_CVS_USER_ROLE); module_invoke('simplenews', 'unsubscribe_user', $account->mail, DRUPALORG_CVS_NEWSLETTER, FALSE); break; } global $locale; cache_clear_all($form_values['cvs_uid'] .":$locale", 'cache_menu'); } } /** * Implemenation of hook_project_page_link_alter(). */ function drupalorg_project_page_link_alter($node, &$all_links) { // #310446: Alter issue queue links to view issues of all categories if (isset($all_links['support']['links']['pending_support'])) { $prepend = array( 'open_issues' => l(t('View open issues or create one'), 'project/issues/'. $node->uri), 'all_issues' => l(t('View all issues'), 'project/issues/'. $node->uri, NULL, 'states=all'), ); $all_links['support']['links'] = $prepend + $all_links['support']['links']; unset($all_links['support']['links']['pending_support']); unset($all_links['support']['links']['pending_bugs']); unset($all_links['support']['links']['pending_features']); unset($all_links['development']['links']['pending_issues']); } // #310446: Remove issue creation links to avoid duplicate issues. if (isset($all_links['support']['links']['request_support'])) { unset($all_links['support']['links']['request_support']); unset($all_links['support']['links']['report_bug']); unset($all_links['support']['links']['request_feature']); } if (isset($all_links['support']['links']['create_forbidden'])) { unset($all_links['support']['links']['create_forbidden']); } // Link to security handbook page. $all_links['support']['links']['report_security_issue'] = l(t('Report a security issue'), 'security-team'); } /** * Implementation of hook_block(). */ function drupalorg_block($op = 'list', $delta = 0, $edit = array()) { if ($op == 'list') { $blocks[0] = array('info' => t('External/Alternate Search Advice'), 'weight' => 0, 'enabled' => 0, 'region' => 'header'); return $blocks; } else if ($op == 'view') { switch ($delta) { case 0: $block = array('subject' => t('Search Engine'), 'content' => drupalorg_display_block_external_search()); break; } return $block; } } /** * Implementation of hook_search(). * * Add support for searching for users based on the fixed IRC nickname field. */ function drupalorg_search($op = 'search', $keys = NULL) { switch ($op) { case 'name': if (user_access('access user profiles')) { return t('IRC nicks'); } case 'search': if (user_access('access user profiles')) { $find = array(); // Replace wildcards with MySQL/PostgreSQL wildcards. $keys = preg_replace('!\*+!', '%', $keys); $result = pager_query("SELECT u.name, u.uid FROM {profile_values} pv INNER JOIN {users} u ON pv.uid = u.uid WHERE pv.fid = 35 AND LOWER(pv.value) LIKE LOWER('%%%s%%')", 15, 0, NULL, $keys); while ($account = db_fetch_object($result)) { $find[] = array('title' => $account->name, 'link' => url('user/'. $account->uid, NULL, NULL, TRUE)); } return $find; } } } /** * Body for external search block */ function drupalorg_display_block_external_search() { if (!user_access('search content')) { $form = '
'; $message = '

Due to load issues the Drupal.org search occasionally has to be disabled. When this happens, you can use external search engines and a modifier like "site:drupal.org" to refine your results to Drupal. For more information see the infrastructure queue

.'; return $form . $message; } } /** * Implementation of hook_help(). */ function drupalorg_help($section) { switch ($section) { case 'project/usage': return '

'. t('These statistics are incomplete; only Drupal websites using the Update Status module are included in the data. As this module is now included with the download of Drupal since version 6.x, the data is heavily biased toward newer sites. Read more information about how these statistics are calculated.', array('!update_status_url' => url('project/update_status'), '!usage_description_url' => url('node/329620'))) .'

'; case 'project/modules/name': case 'project/Modules/name': return t('You can also view an Alphabetical list of Projects that includes all projects but only their names.', array('@list_url' => url('node/206666'))); case 'project/issues-term/346': return '

'. t('A more detailed overview of the issues can be seen in the Community Initiatives handbook section titled Upgrade Drupal.org from Drupal 5 to 6.') .'

'; } } /** * Implementation of hook_project_issue_assignees(). */ function drupalorg_project_issue_assignees(&$assigned, $node) { global $user; if (empty($user->uid) || empty($node->pid)) { return; } $project = node_load($node->pid); if (!isset($project) || $project->type != 'project_project') { return; } // Determine if the user has CVS access at all. If not, the user can't be a // maintainer of the current project and thus we can skip the next, more // expensive query. if (project_use_cvs($node->pid) && db_result(db_query("SELECT COUNT(*) FROM {cvs_accounts} WHERE uid = %d AND status = %d", $user->uid, CVS_APPROVED))) { // Make an array with all maintainers of the current project. $result = db_query("SELECT cpm.uid, u.name FROM {cvs_project_maintainers} cpm INNER JOIN {users} u ON cpm.uid = u.uid WHERE cpm.nid = %d", $node->pid); $maintainers = array($project->uid => $project->name); while ($row = db_fetch_object($result)) { $maintainers[$row->uid] = $row->name; } // Determine if the current user is one of the maintainers of the project. if (isset($maintainers[$user->uid])) { // Add any maintainers of this project who are not already in the // $assigned array to the array. foreach ($maintainers as $uid => $name) { if (!isset($assigned[$uid])) { $assigned[$uid] = $name; } } } } }