'textfield', '#title' => t('E-mail address'), '#default_value' => variable_get('versioncontrol_email_address', 'versioncontrol@example.com'), '#description' => t('The e-mail address of the VCS administrator.'), '#weight' => -10, ); $form['versioncontrol_allow_unauthorized_access'] = array( '#type' => 'checkbox', '#title' => 'Allow repository access to unknown or unauthorized committers', '#description' => 'If this is enabled, VCS users that are not registered or approved can nevertheless commit to repositories, assuming that no other commit restrictions apply. If it is disabled, only authorized users may commit. In any case, this setting only works if the appropriate pre-commit/pre-branch/pre-tag hook script is in place for the respective repository.', '#default_value' => variable_get('versioncontrol_allow_unauthorized_access', 0), '#weight' => -1, ); $form['versioncontrol_register_form'] = array( '#type' => 'fieldset', '#title' => t('Account registration form strings'), '#description' => t('The following messages are shown on the !repository-selection-page that leads to the account registration form.', array('!repository-selection-page' => l(t('repository selection page'), 'versioncontrol/register/demo'))), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => 0, ); $form['versioncontrol_register_form']['versioncontrol_registration_message_unauthorized'] = array( '#type' => 'textarea', '#title' => t('Message to unauthorized users'), '#description' => t('Message to show to anonymous users and to users without the \'use version control systems\' permission.'), '#default_value' => variable_get( 'versioncontrol_registration_message_unauthorized', $presets['versioncontrol_registration_message_unauthorized'] ), ); $form['versioncontrol_register_form']['versioncontrol_registration_message_authorized'] = array( '#type' => 'textarea', '#title' => t('Message to registering users'), '#description' => t('Message to show to users who are in the process of selecting a repository in order to create a VCS account. If there\'s only one repository on this site, users will never get to see this message.'), '#default_value' => variable_get( 'versioncontrol_registration_message_authorized', $presets['versioncontrol_registration_message_authorized'] ), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save configuration'), '#weight' => 100, ); return $form; } /** * Submit handler for the authorization settings form. * system_settings_form() is left out because it's nasty for modules that * hook into this form and don't want to use automatic variable saving. */ function versioncontrol_admin_settings_submit($form_id, $form_values) { $value_names = array( 'versioncontrol_email_address', 'versioncontrol_allow_unauthorized_access', 'versioncontrol_registration_message_unauthorized', 'versioncontrol_registration_message_authorized', ); foreach ($value_names as $name) { variable_set($name, $form_values[$name]); } } /** * Form callback for "admin/project/versioncontrol-accounts": * A list of accounts with filtering possibilities. */ function versioncontrol_admin_account_list_page() { $users = array(); $accounts = versioncontrol_get_accounts(array(), TRUE); // Retrieve all repositories that users are listed in. $repo_ids = array(); foreach ($accounts as $uid => $usernames_by_repository) { foreach ($usernames_by_repository as $repo_id => $username) { $repo_ids[] = $repo_id; } } $repo_ids = array_unique($repo_ids); $repositories = versioncontrol_get_repositories(array('repo_ids' => $repo_ids)); $filter_form = drupal_get_form('versioncontrol_admin_account_list_filter_form', $repositories); // Filter the list of accounts. foreach (module_implements('versioncontrol_filter_accounts') as $module) { $function = $module .'_versioncontrol_filter_accounts'; $function($accounts); } $accounts = versioncontrol_admin_get_paged_accounts($accounts); // Retrieve more info for the accounts that survived filtering. foreach ($accounts as $uid => $usernames_by_repository) { $user = user_load(array('uid' => $uid)); if (!$user) { unset($accounts[$uid]); continue; } $users[$uid] = $user; } if (empty($users)) { return $filter_form .'
'. t('No accounts could be found with the current filter settings.') .'
'; } $placeholders = array(); $params = array(); foreach ($users as $uid => $user) { $placeholders[] = "'%d'"; $params[] = $uid; } // Retrieve total, first and last commits of each user. $result = db_query("SELECT uid, COUNT(commit_id) AS number_commits, MIN(date) AS first_commit_date, MAX(date) AS last_commit_date, MIN(commit_id) AS first_commit_id, MAX(commit_id) AS last_commit_id FROM {versioncontrol_commits} WHERE uid IN (". implode(',', $placeholders) .") GROUP BY uid", $params); $number_commits = array(); $first_commits = array(); $last_commits = array(); while ($statistics = db_fetch_object($result)) { $number_commits[$statistics->uid] = $statistics->number_commits; $first_commits[$statistics->uid] = t('!time ago', array( '!time' => format_interval(time() - $statistics->first_commit_date, 1)) ); $last_commits[$statistics->uid] = t('!time ago', array( '!time' => format_interval(time() - $statistics->last_commit_date, 1)) ); if (module_exists('commitlog')) { $number_commits[$statistics->uid] = l($number_commits[$statistics->uid], 'user/'. $statistics->uid .'/track/code'); $first_commits[$statistics->uid] = theme('commitlog_commit_id', $statistics->first_commit_id, $first_commits[$statistics->uid]); $last_commits[$statistics->uid] = theme('commitlog_commit_id', $statistics->last_commit_id, $last_commits[$statistics->uid]); } } // Construct the user account table. $header = array(t('User'), t('Accounts'), t('Commits'), t('First commit'), t('Last commit')); $rows_by_uid = array(); foreach ($accounts as $uid => $usernames_by_repository) { $user = $users[$uid]; // Present a list of all VCS usernames and the repository where they're in. $repo_usernames = array(); foreach ($usernames_by_repository as $repo_id => $username) { if (!isset($repositories[$repo_id])) { // happens if the backend isn't loaded continue; } if (module_exists('commitlog')) { $username = commitlog_account_username( $uid, $username, $repositories[$repo_id], FALSE ); $repo_name = theme('commitlog_repository', $repositories[$repo_id]); } else { $username = check_plain($username); $repo_name = check_plain($repositories[$repo_id]['name']); } $repo_usernames[] = t('!username in !repository (!edit)', array( '!username' => $username, '!repository' => $repo_name, '!edit' => l(t('edit'), 'user/'. $uid .'/edit/versioncontrol/'. $repo_id), )); } $vcs_usernames = empty($repo_usernames) ? t('VCS backend is currently disabled') : theme('item_list', $repo_usernames); $rows_by_uid[$uid] = array( theme('username', $user), $vcs_usernames, isset($number_commits[$uid]) ? $number_commits[$uid] : 0, isset($first_commits[$uid]) ? $first_commits[$uid] : t('n/a'), isset($last_commits[$uid]) ? $last_commits[$uid] : t('n/a'), ); } // Provide a possibility for backends and other modules to modify the list. foreach (module_implements('versioncontrol_alter_account_list') as $module) { $function = $module .'_versioncontrol_alter_account_list'; $function($accounts, $repositories, $header, $rows_by_uid); } // We don't want the uids in the final $rows array. $rows = array_values($rows_by_uid); // The finished user account list with account filter. $output .= $filter_form . theme('table', $header, $rows); if ($pager = theme('pager', NULL, variable_get('versioncontrol_admin_account_pager', 20), 0)) { $output .= $pager; } return $output; } /** * Return a subset of the given accounts (10 Drupal users by default, and all * of their VCS usernames). Paging is also used by emulating pager_query(). */ function versioncontrol_admin_get_paged_accounts($accounts, $element = 0) { global $pager_page_array, $pager_total, $pager_total_items; $page = isset($_GET['page']) ? $_GET['page'] : ''; $pager_page_array = explode(',', $page); $page = empty($pager_page_array[$element]) ? 0 : $pager_page_array[$element]; $limit = variable_get('versioncontrol_admin_account_pager', 20); $i = 0; $paged_accounts = array(); foreach ($accounts as $uid => $usernames_by_repository) { if ($i >= ($page * $limit) && $i < (($page+1) * $limit)) { $paged_accounts[$uid] = $usernames_by_repository; } ++$i; } // Emulate pager_query() in order to get a proper theme('pager'). $pager_total_items[$element] = count($accounts); $pager_total[$element] = ceil($pager_total_items[$element] / $limit); $pager_page_array[$element] = max(0, min((int)$pager_page_array[$element], ((int)$pager_total[$element]) - 1)); return $paged_accounts; } /** * A form for filtering accounts which is embedded in the account list page. */ function versioncontrol_admin_account_list_filter_form($repositories) { $form = array(); $repository_names = array(0 => t('All')); foreach ($repositories as $repo_id => $repository) { $repository_names[$repo_id] = check_plain($repository['name']); } if (!isset($_SESSION['versioncontrol_filter_repo_id'])) { $_SESSION['versioncontrol_filter_repo_id'] = 0; } $form['#id'] = 'versioncontrol-account-filter-form'; $form['fieldset'] = array( '#type' => 'fieldset', '#title' => t('Filter'), '#collapsible' => TRUE, '#collapsed' => FALSE, ); $form['fieldset']['filters'] = array( '#value' => '', '#prefix' => '', '#suffix' => '
', ); return $form; } $repository_names = array(); foreach ($repositories as $repo_id => $repository) { if (!isset($first_repo_id)) { $first_repo_id = $repo_id; } $repository_names[$repo_id] = check_plain($repository['name']); } $form['repo_id'] = array( '#type' => 'select', '#title' => t('Import accounts into'), '#options' => $repository_names, '#default_value' => $first_repo_id, ); $form['data'] = array( '#type' => 'textarea', '#title' => t('Account data'), '#description' => t('The contents of the config file that contains the accounts that shall be imported. Existing accounts will be updated, new accounts will be created, and all others will be left untouched.'), '#cols' => 70, '#rows' => 24, '#required' => TRUE, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Import accounts'), '#weight' => 100, ); return $form; } /** * Submit handler for the "select repository to import" form from above: * Call the [vcs_backend]_admin_import_accounts() with the given data. */ function versioncontrol_admin_account_import_form_submit($form_id, $form_values) { $repository = versioncontrol_get_repository($form_values['repo_id']); if (!isset($repository)) { drupal_set_message(t('The selected repository could not be found.'), 'error'); return; } _versioncontrol_call_backend($repository['vcs'], 'import_accounts', array($repository, $form_values['data'])); } /** * Callback for "admin/project/versioncontrol-accounts/export": * Export a repository's authenticated accounts to the version control system's * password file format. */ function versioncontrol_admin_account_export_page() { $repo_id = arg(4); if (is_numeric($repo_id)) { $repository = versioncontrol_get_repository($repo_id); } if (!isset($repository)) { // When the repository is not given, show the redirection page. return drupal_get_form('versioncontrol_admin_account_export_form'); } if (!versioncontrol_backend_implements($repository['vcs'], 'export_accounts')) { drupal_not_found(); return; } // The repository has already been selected, export the accounts. $data = versioncontrol_export_accounts($repository); if (arg(5) == 'plaintext') { drupal_set_header('Content-Type: text/plain; charset=utf-8'); print $data; } else { return drupal_get_form('versioncontrol_admin_account_export_display_form', $repository, $data); } } /** * Form callback for "admin/project/versioncontrol-accounts/export": * Select the repository from which to extract data, and show the exported * data on submitting the form. */ function versioncontrol_admin_account_export_form() { $backends = versioncontrol_get_backends(); $selected_backends = array(); foreach ($backends as $vcs => $backend) { if (versioncontrol_backend_implements($vcs, 'export_accounts')) { $selected_backends[] = $vcs; } } $repositories = versioncontrol_get_repositories(array('vcs' => $selected_backends)); $form = array(); if (empty($repositories)) { $form['no_repositories'] = array( '#type' => 'markup', '#value' => t('There are no repositories for which the accounts can be exported.'), '#prefix' => '', '#suffix' => '
', ); return $form; } $repository_names = array(); foreach ($repositories as $repo_id => $repository) { if (!isset($first_repo_id)) { $first_repo_id = $repo_id; } $repository_names[$repo_id] = check_plain($repository['name']); } $form['repository'] = array( '#type' => 'fieldset', '#title' => t('Select repository'), '#weight' => 10, ); $form['repository']['repo_id'] = array( '#type' => 'select', '#title' => t('Export accounts from'), '#options' => $repository_names, '#default_value' => $first_repo_id, ); $form['repository']['buttons'] = array(); $form['repository']['buttons']['export_to_form'] = array( '#type' => 'submit', '#value' => t('Export to page'), ); $form['repository']['buttons']['export_to_plaintext'] = array( '#type' => 'submit', '#value' => t('Export to plaintext'), ); return $form; } /** * Submit handler for the "select repository to export" form from above: * Redirect to the export form for the specific repository. */ function versioncontrol_admin_account_export_form_submit($form_id, $form_values) { $target_path = 'admin/project/versioncontrol-accounts/export/'. $form_values['repo_id']; if ($form_values['op'] == t('Export to plaintext')) { $target_path .= '/plaintext'; } return $target_path; } /** * Form callback for "admin/project/versioncontrol-accounts/export/$repo_id": * Show the exported account data in a form as text area. * * @param $repository * The repository for which accounts have been exported. * @param $data * The exported account data - the text that is supposed to be copied * to the version control system's accounts file. */ function versioncontrol_admin_account_export_display_form($repository, $data) { $backends = versioncontrol_get_backends(); $vcs_name = $backends[$repository['vcs']]['name']; $form['#vcs'] = $vcs_name; $form['#repository'] = $repository; $form['data'] = array( '#type' => 'textarea', '#title' => t('@vcs account data', array('@vcs' => $vcs_name)), '#description' => t('The exported account data. You can copy this to the config file that contains the @vcs accounts.', array('@vcs' => $vcs_name)), '#default_value' => $data, '#cols' => 70, '#rows' => 30, ); return $form; } /** * Form callback for "admin/project/versioncontrol-repositories": * A simple list of repositories, sorted by version control system. */ function versioncontrol_admin_repository_list() { $form = array(); $backends = versioncontrol_get_backends(); $repositories = versioncontrol_get_repositories(); if (empty($repositories)) { $form['empty'] = array( '#value' => ''. t('No repositories are currently known. Please add one or more repositories in order to be able to use version control features on the site.') .'
' ); return $form; } // The header may be modified separately for each VCS, // so this is only a template and still missing the Actions column. $header_template = array(t('Name'), t('Root')); // Sort repositories by backend. $repositories_by_backend = array(); foreach ($repositories as $repo_id => $repository) { if (!isset($repositories_by_backend[$repository['vcs']])) { $repositories_by_backend[$repository['vcs']] = array(); } $repositories_by_backend[$repository['vcs']][$repo_id] = $repository; } // Construct the form elements for each VCS separately. foreach ($repositories_by_backend as $vcs => $vcs_repositories) { $header = $header_template; $form[$vcs] = array( '#value' => '