diff --git a/election-candidate-details.tpl.php b/election-candidate-details.tpl.php deleted file mode 100644 index 0134efa5cce2c7be8fd5f0504babbc9af40bc9b8..0000000000000000000000000000000000000000 --- a/election-candidate-details.tpl.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -/** - * @file - * Default theme implementation to display an election candidate's full details. - */ - -?> -<div id="election-<?php print $election->election_id; ?>-candidate-details-<?php print $candidate->candidate_id; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>> - - <div class="content"<?php print $content_attributes; ?>> - <?php print render($content); ?> - </div> - -</div> diff --git a/election-candidate.admin.inc b/election-candidate.admin.inc deleted file mode 100644 index 2fa82a4c53dd925fa083acf0048ef42521971264..0000000000000000000000000000000000000000 --- a/election-candidate.admin.inc +++ /dev/null @@ -1,403 +0,0 @@ -<?php -/** - * @file - * Administrative page callbacks for election candidates and nominations - * (Election module). - */ - -/** - * Form builder function for the main administrative election candidate list. - * - * @param array $form - * @param array $form_state - * @param stdClass $election - * - * @return array - * Render array. - */ -function election_candidate_list_form($form, $form_state, $election) { - - // @todo this should not be necessary - drupal_set_title(t('Candidates'), PASS_THROUGH); - drupal_set_breadcrumb( - _election_build_breadcrumb($election) - ); - - $post_name = _election_get_posts_name($election->type); - - // Build the sortable table header. - $header = array( - 'created' => array('data' => t('Nominated'), 'field' => 'ec.created', 'sort' => 'desc'), - 'post_title' => array('data' => drupal_ucfirst($post_name), 'field' => 'ep.title'), - 'first_name' => array('data' => t('First name'), 'field' => 'ec.first_name'), - 'last_name' => array('data' => t('Last name'), 'field' => 'ec.last_name'), - 'username' => array('data' => t('Username'), 'field' => 'ec.username'), - 'cstatus' => array('data' => t('Status'), 'field' => 'ec.cstatus'), - 'operations' => array('data' => t('Operations')), - ); - - // Build the query, adding a pager and sorter. - $query = db_select('election_candidate', 'ec') - ->extend('PagerDefault') - ->extend('TableSort') - ->fields('ec', array('candidate_id')); - $query->leftJoin('election_post', 'ep', 'ec.post_id=ep.post_id'); - $query->condition('ec.election_id', $election->election_id) - ->limit(50) - ->orderByHeader($header); - $result = $query->execute(); - - // Get array of candidates - $candidate_ids = $result->fetchCol(); - $candidates = election_candidate_load_multiple($candidate_ids); - - $destination = drupal_get_destination(); - - $default_post_title = '<em class="deleted-post">' . t('Deleted?') . '</em>'; - - $options = array(); - foreach ($candidates as $id => $candidate) { - - $post_title = $default_post_title; - if (!empty($candidate->post_id)) { - $post = election_post_load($candidate->post_id); - $post_title = check_plain($post->title); - } - - $account = user_load($candidate->uid); - - $options[$candidate->candidate_id] = array( - 'created' => format_date($candidate->created, 'short'), - 'post_title' => $post_title, - 'first_name' => check_plain($candidate->first_name), - 'last_name' => check_plain($candidate->last_name), - 'username' => $account? theme('username', array('account' => $account)) : t('Anonymous'), - 'cstatus' => _election_candidate_format_status($candidate), - ); - - $operations = array(); - $candidate_uri_path = election_candidate_uri_path($candidate); - - if (election_candidate_access('view', $candidate)) { - $operations['view'] = l( - t('view'), - $candidate_uri_path - ); - } - - if (election_candidate_access('view details', $candidate)) { - $operations['view_details'] = l( - t('details'), - $candidate_uri_path . '/details' - ); - } - - if (election_candidate_access('update', $candidate)) { - $operations['edit'] = l( - t('edit'), - $candidate_uri_path . '/edit', - array('query' => $destination) - ); - } - - if (count($operations)) { - // Render an unordered list of operations links. - $options[$candidate->candidate_id]['operations'] = array( - 'data' => array( - '#theme' => 'item_list', - '#items' => $operations, - '#attributes' => array('class' => array('operations')), - ), - ); - } - - } - - $form['election_candidates'] = array( - '#theme' => 'table', - '#header' => $header, - '#rows' => $options, - '#empty' => t('No candidates available.'), - ); - - $form['pager'] = array('#markup' => theme('pager')); - - return $form; -} - -/** - * Display total numbers of candidates per post. - */ -function election_candidate_totals_page(stdClass $election) { - - drupal_set_title(t('Candidate totals')); - - $result = db_query('SELECT COUNT(DISTINCT candidate_id) AS num_candidates, COUNT(DISTINCT IF (cstatus=0, candidate_id, NULL)) AS num_pending, COUNT(DISTINCT IF (cstatus=1, candidate_id, NULL)) AS num_approved, COUNT(DISTINCT IF (cstatus=-1, candidate_id, NULL)) AS num_withdrawn, COUNT(DISTINCT IF (cstatus=-2, candidate_id, NULL)) AS num_rejected FROM {election_candidate} WHERE election_id = :election_id', array( - ':election_id' => $election->election_id)); - $totalAll = $result->fetch(); - - $output = array( - 'total' => array( - '#markup' => '<p>' . t('Total number of candidates: !totalAll', array('!totalAll' => $totalAll->num_candidates)) . '</p>', - ), - ); - - if ($totalAll->num_candidates > 0) { - $result = db_query( - 'SELECT ep.title, COUNT(DISTINCT ec.candidate_id) AS num_candidates, COUNT(DISTINCT IF (ec.cstatus=0, ec.candidate_id, NULL)) AS num_pending, COUNT(DISTINCT IF (ec.cstatus=1, ec.candidate_id, NULL)) AS num_approved, COUNT(DISTINCT IF (ec.cstatus=-1, ec.candidate_id, NULL)) AS num_withdrawn, COUNT(DISTINCT IF (ec.cstatus=-2, ec.candidate_id, NULL)) AS num_rejected FROM {election_post} ep LEFT JOIN {election_candidate} ec USING (post_id) WHERE ep.election_id = :election_id GROUP BY ep.post_id ORDER BY ep.title', - array( - ':election_id' => $election->election_id, - ) - ); - $totals = $result->fetchAll(); - $header = array(t('Position'), t('Pending'), t('Approved'), t('Rejected'), t('Withdrawn')); - $rows = array(); - $rows[] = array(t('TOTAL'), $totalAll->num_pending, $totalAll->num_approved, $totalAll->num_withdrawn, $totalAll->num_rejected); - foreach ($totals as $total) { - $rows[] = array(check_plain($total->title), $total->num_pending, $total->num_approved, $total->num_withdrawn, $total->num_rejected); - } - $output['by_position'] = array( - '#theme' => 'table', - '#header' => $header, - '#rows' => $rows, - ); - } - - return $output; -} - -/** - * Form builder function for the form at "election/%election/candidates/download". - * - * @param array $form - * @param array $form_state - * @param stdClass $election - */ -function election_candidate_download_form($form, &$form_state, stdClass $election) { - - drupal_set_title(t('Download candidate data')); - - // @todo allow new candidate bundles. - $candidate_field_instances = field_info_instances('election_candidate', 'election_candidate'); - - $post_name = _election_get_posts_name($election->type); - - $properties = array( - 'election_id' => t('Election ID'), - 'election_title' => array( - 'label' => t('Election title'), - 'default' => TRUE, - ), - 'candidate_id' => t('Candidate ID'), - 'first_name' => array( - 'label' => t('First name'), - 'default' => TRUE, - ), - 'last_name' => array( - 'label' => t('Last name'), - 'default' => TRUE, - ), - 'post_id' => t('@post_name ID', array('@post_name' => drupal_ucfirst($post_name))), - 'post_title' => array( - 'label' => t('@post_name title', array('@post_name' => drupal_ucfirst($post_name))), - 'default' => TRUE, - ), - 'cstatus' => array( - 'label' => t('Candidate status'), - 'default' => TRUE, - ), - 'mail' => array( - 'label' => t('Email address'), - 'default' => TRUE, - ), - 'phone' => array( - 'label' => t('Phone number'), - 'default' => TRUE, - ), - 'uid' => t('User ID'), - 'username' => array( - 'label' => t('Username'), - 'default' => TRUE, - ), - 'created' => array( - 'label' => t('Created date'), - 'default' => TRUE, - 'type' => 'timestamp', - ), - 'changed' => array( - 'label' => t('Last modified date'), - 'default' => TRUE, - 'type' => 'timestamp', - ), - 'profile_link' => array( - 'label' => t('Profile link'), - 'default' => TRUE, - ), - ); - foreach ($candidate_field_instances as $field_name => $cfi) { - $field = field_info_field($field_name); - $properties[$field_name] = array( - 'label' => $cfi['label'], - 'type' => $field['type'], - 'default' => FALSE, - ); - } - - $property_options = array(); - $default_properties = array(); - foreach ($properties as $property_key => $property) { - $label = is_string($property)? $property : $property['label']; - $property_options[$property_key] = $label; - if (isset($property['default']) && $property['default'] === TRUE) { - $default_properties[] = $property_key; - } - } - - $form_state['#election'] = $election; - $form_state['#properties'] = $properties; - $form_state['#property_options'] = $property_options; - - $form['include_properties'] = array( - '#type' => 'checkboxes', - '#title' => t('Properties to include'), - '#options' => $property_options, - '#default_value' => $default_properties, - ); - - $form['buttons'] = array( - '#type' => 'actions', - '#weight' => 100, - ); - $form['buttons']['download'] = array( - '#type' => 'submit', - '#value' => t('Download candidate spreadsheet'), - ); - - return $form; - -} - -/** - * Submit callback for the form election_candidate_download_form. - * - * @param array $form - * @param array $form_state - */ -function election_candidate_download_form_submit($form, &$form_state) { - - $election = $form_state['#election']; - - $fileName = 'candidates_election' . $election->election_id . '_' . date('Y-m-d_His', REQUEST_TIME) . '.csv'; - - $include_properties = $form_state['values']['include_properties']; - foreach ($include_properties as $key => $value) { - if ($value === 0) { - unset($include_properties[$key]); - } - } - - $properties = array_intersect_key($form_state['#properties'], $include_properties); - - $separator = ','; - $enclosure = '"'; - $empty = ''; - - $outstream = fopen('php://output', 'w'); - - $candidate_ids = db_select('election_candidate') - ->fields('election_candidate', array('candidate_id')) - ->condition('election_id', $election->election_id) - ->orderBy('created', 'DESC') - ->execute() - ->fetchCol(); - $candidates = election_candidate_load_multiple($candidate_ids); - - drupal_add_http_header('Content-Type', 'text/csv; charset=UTF-8'); - drupal_add_http_header('Cache-Control', 'no-store, max-age=0, must-revalidate'); - drupal_add_http_header('Pragma', FALSE); - drupal_add_http_header('Content-Description', 'File Transfer'); - drupal_add_http_header('Content-Disposition', 'attachment; filename="' . $fileName . '"'); - - $property_headers = array(); - foreach ($properties as $property) { - $property_headers[] = is_string($property)? $property : $property['label']; - } - - fputcsv($outstream, $property_headers, $separator, $enclosure); - - foreach ($candidates as $candidate) { - - $row = array(); - foreach ($properties as $property_key => $property) { - $value = _election_candidate_download_format_property($candidate, $property_key, $property); - $row[$property_key] = strlen($value)? $value : $empty; - } - - fputcsv($outstream, $row, $separator, $enclosure); - fpassthru($outstream); - } - - fpassthru($outstream); - fclose($outstream); - - exit(); - -} - -/** - * Format a candidate property. - * - * @param stdClass $candidate - */ -function _election_candidate_download_format_property(stdClass $candidate, $property_key, $property) { - $value = isset($candidate->{$property_key})? $candidate->{$property_key} : NULL; - switch ($property_key) { - case 'profile_link': - return url(election_candidate_uri_path($candidate), array('absolute' => TRUE)); - return $election->title; - break; - case 'election_title': - $election = election_load($candidate->election_id); - return $election->title; - break; - case 'post_title': - if (empty($candidate->post_id)) { - return; - } - $post = election_post_load($candidate->post_id); - return $post->title; - break; - case 'cstatus': - return _election_candidate_format_status($candidate); - break; - } - $type = 'string'; - if (is_array($property) && !empty($property['type'])) { - $type = $property['type']; - } - switch ($type) { - case 'timestamp': - return date('Y-m-d H:i:s', $value); - break; - case 'string': - if (is_string($value)) { - return check_plain($value); - } - break; - case 'file': - case 'image': - if (is_array($value) && isset($value['und'][0]['uri'])) { - return file_create_url($value['und'][0]['uri']); - } - break; - default: - if (is_array($value)) { - if (isset($value['und'][0]['safe_value'])) { - return $value['und'][0]['safe_value']; - } - else if (isset($value['und'][0]['value'])) { - return check_plain($value['und'][0]['value']); - } - } - } -} \ No newline at end of file diff --git a/election-candidate.pages.inc b/election-candidate.pages.inc deleted file mode 100644 index b42b7ce219013f1593d98a8959ef5afcc116369c..0000000000000000000000000000000000000000 --- a/election-candidate.pages.inc +++ /dev/null @@ -1,715 +0,0 @@ -<?php -/** - * @file - * Page callbacks and form functions for election candidates and nominations - * (Election module). - */ - -/** - * Page callback for election/%election/candidate/%election_candidate - * - * @param stdClass $election - * @param stdClass $candidate - */ -function election_candidate_page_view(stdClass $election, stdClass $candidate, $view_mode = 'full') { - - drupal_set_title( - t( - 'Candidate: @first-name @last-name', - array( - '@first-name' => $candidate->first_name, - '@last-name' => $candidate->last_name, - ) - ), - PASS_THROUGH - ); - - drupal_set_breadcrumb( - _election_build_breadcrumb($election, '_CANDIDATES_') - ); - - $uri = entity_uri('election_candidate', $candidate, $election); - // Set the candidate path as the canonical URL to prevent duplicate content. - drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url($uri['path'], $uri['options'])), TRUE); - // Set the non-aliased path as a default shortlink. - drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE); - - return election_candidate_view($candidate, $election, $view_mode); - -} - -/** - * Page callback for election/%election/candidate/%election_candidate/details - * - * @param stdClass $election - * @param stdClass $candidate - */ -function election_candidate_details_page_view(stdClass $election, stdClass $candidate) { - - drupal_set_title( - t( - 'Candidate: @first-name @last-name', - array( - '@first-name' => $candidate->first_name, - '@last-name' => $candidate->last_name, - ) - ), - PASS_THROUGH - ); - - drupal_set_breadcrumb( - _election_build_breadcrumb($election, '_CANDIDATES_') - ); - - $post = election_post_load($candidate->post_id); - - return array( - '#theme' => 'election_candidate_details', - '#candidate' => $candidate, - '#election' => $election, - '#post' => $post, - ); - -} - - -/** - * Generate a table of a user's previous nominations in an election. - * - * @param stdClass $election - * @param array $previous_nominations - */ -function election_candidate_display_previous_nominations(stdClass $election, array $previous_nominations) { - if (empty($previous_nominations)) { - return; - } - $caption = t('Your previous nominations in this election'); - $header = array( - t('Nomination date'), - drupal_ucfirst(_election_get_posts_name($election->type)), - t('Candidate name'), - t('Status'), - ); - $rows = array(); - foreach ($previous_nominations as $nomination) { - $post = election_post_load($nomination->post_id); - $post_title = empty($post)? '?' : check_plain($post->title); - $rows[] = array( - format_date($nomination->created, 'short'), - $post_title, - check_plain($nomination->first_name . ' ' . $nomination->last_name), - _election_candidate_format_status($nomination) - ); - } - return array( - '#theme' => 'table', - '#header' => $header, - '#rows' => $rows, - '#caption' => $caption, - ); -} - -/** - * Page callback for election/%election/nomination-form - */ -function election_page_nomination_form(stdClass $election) { - - // @todo this should not be necessary - drupal_set_title(t('Nomination form'), PASS_THROUGH); - drupal_set_breadcrumb(_election_build_breadcrumb($election)); - - if ($election->type == 'referendum') { - return MENU_NOT_FOUND; - } - - $nopen = _election_is_open($election->nstatus, $election->nopen_time, $election->nclose_time); - if (!$nopen && !user_access('bypass nomination schedule')) { - return array( - '#markup' => t('Nominations are currently closed.'), - ); - } - - $previous_nominations = (array) election_candidate_get_user_nominations($election); - - $available_post_ids = (array) election_candidate_get_available_posts($election, $previous_nominations); - - // End with an error message if there are no available posts. - if (empty($available_post_ids)) { - $posts_name = _election_get_posts_name($election->type, TRUE); - return array( - election_candidate_display_previous_nominations($election, $previous_nominations), - array( - '#markup' => t( - 'There are no more @posts-name available for nomination in this election.', - array('@posts-name' => $posts_name) - ), - ), - ); - } - $available_posts = (array) election_post_load_multiple($available_post_ids); - - return drupal_get_form('election_candidate_nomination_form', $election, $previous_nominations, $available_posts); - -} - -/* - * Election nominations form function. This creates election_candidate entities. - * - * @param array $form - * @param array $form_state - * @param stdClass $election - * @param array $previous_nominations - * @param array $available_posts - */ -function election_candidate_nomination_form($form, &$form_state, stdClass $election, array $previous_nominations, array $available_posts) { - - global $user; - - $candidate = entity_get_controller('election_candidate')->create(); - $candidate->is_new = TRUE; - - $form['#id'] = 'election-nomination-form'; - - if (!isset($form_state['seconder_count'])) { - $form_state['seconder_count'] = 1; - } - - $form_state['candidate'] = $candidate; - $form_state['election'] = $election; - - if (count($previous_nominations)) { - $form['previous_nominations'] = array( - '#type' => 'fieldset', - '#title' => t('Your previous nominations'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#weight' => -50, - ); - $previous_nominations_display = election_candidate_display_previous_nominations($election, $previous_nominations); - unset($previous_nominations_display['#caption']); - $form['previous_nominations']['display'] = $previous_nominations_display; - } - - $bypass = user_access('bypass nomination access control'); - $post_options = array(); - foreach ($available_posts as $post) { - if ($bypass || $post->nstatus_inheritance == ELECTION_POST_STATUS_INHERIT) { - // @todo make this alterable - $post_options[$post->post_id] = truncate_utf8($post->title, 100, TRUE, TRUE, 80); - } - } - drupal_alter('election_candidate_post_options', $post_options); - $post_name = _election_get_posts_name($election->type); - $form['post_id'] = array( - '#type' => 'select', - '#options' => $post_options, - '#title' => check_plain(drupal_ucfirst($post_name)), - '#empty_option' => t('- Select @post_name -', array('@post_name' => $post_name)), - '#required' => TRUE, - ); - - $form['first_name'] = array( - '#type' => 'textfield', - '#title' => t('First name(s)'), - '#max_length' => 100, - '#size' => 50, - '#required' => TRUE, - ); - - $form['last_name'] = array( - '#type' => 'textfield', - '#title' => t('Last name(s)'), - '#max_length' => 100, - '#size' => 50, - '#required' => TRUE, - ); - - $form['mail'] = array( - '#type' => 'textfield', - '#title' => t('Email address'), - '#size' => 30, - '#required' => TRUE, - '#default_value' => empty($user->mail)? NULL: $user->mail, - ); - - $form['phone'] = array( - '#type' => 'textfield', - '#title' => t('Contact telephone number'), - '#size' => 12, - '#required' => TRUE, // @todo make this alterable - ); - - // Add custom fields from the Field system. - field_attach_form('election_candidate', $candidate, $form, $form_state); - - $form['#validate'][] = 'election_candidate_form_validate'; - $form['#validate'][] = 'election_candidate_nomination_form_validate'; - - $form['buttons'] = array( - '#type' => 'actions', - '#weight' => 100, - ); - $form['buttons']['submit'] = array( - '#type' => 'submit', - '#value' => t('Submit nomination'), - '#submit' => array('election_candidate_nomination_form_submit'), - ); - - return $form; -} - - -/** - * Validation function for both the candidate edit form and the nomination form. - * - * @param array $form - * @param array $form_state - */ -function election_candidate_form_validate($form, &$form_state) { - - if (!empty($form_state['values']['mail']) && !filter_var($form_state['values']['mail'], FILTER_VALIDATE_EMAIL)) { - form_set_error('mail', t('Please enter a valid email address')); - } - - if (!empty($form_state['values']['phone']) && !preg_match('/\b\+?([0-9]+[\s-\+]?)+\b/', $form_state['values']['phone'])) { - form_set_error('phone', t('Please enter a valid phone number.')); - } - - field_attach_form_validate('election_candidate', $form_state['candidate'], $form, $form_state); - -} - -/** - * Validation function for just the nomination form. - * - * @param array $form - * @param array $form_state - */ -function election_candidate_nomination_form_validate($form, &$form_state) { - // @todo validate post again -} - -/** - * Validation function for just the edit form. - * - * @param array $form - * @param array $form_state - */ -function election_candidate_edit_form_validate($form, &$form_state) { - if (!empty($form_state['values']['new_user'])) { - if (!$account = user_load_by_name($form_state['values']['new_user'])) { - form_set_error('new_user', t('The username %name does not exist', array('%name' => $form_state['values']['new_user']))); - } - } -} - - -/** - * Submit callback for the nomination form. - * - * @param array $form - * @param array $form_state - */ -function election_candidate_nomination_form_submit($form, &$form_state) { - - $candidate = &$form_state['candidate']; - - $values = $form_state['values']; - - // election object won't be changed, no need to pass by reference - $election = $form_state['election']; - $post = election_post_load($values['post_id']); - - $candidate->election_id = $election->election_id; - - $candidate->post_id = $values['post_id']; - - $candidate->first_name = $values['first_name']; - $candidate->last_name = $values['last_name']; - $candidate->mail = $values['mail']; - $candidate->phone = $values['phone']; - $candidate->cstatus = ELECTION_CANDIDATE_PENDING; - - // @todo set up manifesto, summary, photo fields - - field_attach_submit('election_candidate', $candidate, $form, $form_state); - - global $user; - if (!empty($user->uid)) { - $candidate->uid = $user->uid; - $candidate->username = $user->name; - } - - // Save the nomination. - election_candidate_save($candidate); - - // Trigger a Rules action. - if (function_exists('rules_invoke_event')) { - rules_invoke_event('election_candidate_nomination_submitted', $candidate, $post, $election); - } - - // Notify the user that the nomination was saved. - drupal_set_message(t( - 'The nomination for the @posts_name %title (name %first_name %last_name) was successfully submitted.', - array( - '@posts_name' => _election_get_posts_name($election->type), - '%title' => $post->title, - '%first_name' => $candidate->first_name, - '%last_name' => $candidate->last_name, - ) - )); - - if (empty($_GET['destination'])) { - $form_state['redirect'] = election_uri_path($election); - } - -} - -/** - * Generate an array for rendering the given candidate. - * - * @param $candidate - * @param $election - * @param $view_mode - * View mode, e.g. 'full', 'teaser'... - * - * @return - * An array as expected by drupal_render(). - */ -function election_candidate_view($candidate, $election, $view_mode = 'full') { - - // Remove previously built content, if it exists. - $candidate->content = array(); - - $title = t('Candidate: @first-name @last-name', array('@first-name' => $candidate->first_name, '@last-name' => $candidate->last_name)); - - if ($view_mode == 'teaser') { - $candidate->content['title'] = array( - '#markup' => $title, - '#weight' => -5, - ); - } - - // Build fields content. - // In case of a multiple view, node_view_multiple() already ran the - // 'prepare_view' step. An internal flag prevents the operation from running - // twice. - field_attach_prepare_view('election_candidate', array($candidate->candidate_id => $candidate), $view_mode); - entity_prepare_view('election_candidate', array($candidate->candidate_id => $candidate)); - $candidate->content += field_attach_view('election_candidate', $candidate, $view_mode); - - $build = $candidate->content; - // We don't need duplicate rendering info in election->content. - unset($candidate->content); - - $post = election_post_load($candidate->post_id); - - $build += array( - '#theme' => 'election_candidate', - '#candidate' => $candidate, - '#election' => $election, - '#post' => $post, - '#view_mode' => $view_mode, - ); - - // Add contextual links for this election, except when the election is already being - // displayed on its own page. Modules may alter this behavior (for example, - // to restrict contextual links to certain view modes) by implementing - // hook_election_candidate_view_alter(). - if (!empty($candidate->candidate_id) && $view_mode != 'full') { - $build['#contextual_links']['election_candidate'] = array('election_candidate', array($candidate->candidate_id)); - } - - // Allow modules to modify the structured election. - $type = 'election_candidate'; // $type is passed by reference to drupal_alter() so it must be a variable. - drupal_alter(array('election_candidate_view', 'entity_view'), $build, $type); - - return $build; - -} - -/* - * Form builder function for editing a single candidate. - * - * @param array $form - * @param array $form_state - * @param stdClass $election - * @param stdClass $candidate - * - * @return array - * Render array. - */ -function election_candidate_edit_form($form, $form_state, stdClass $election, stdClass $candidate) { - - // @todo this should not be necessary - drupal_set_title(t('Edit candidate: %first-name %last-name', array('%first-name' => $candidate->first_name, '%last-name' => $candidate->last_name)), PASS_THROUGH); - drupal_set_breadcrumb( - _election_build_breadcrumb($election, '_CANDIDATES_') - ); - - $form['#id'] = 'election-candidate-edit-form'; - $form['#candidate'] = $candidate; - - $form_state['election'] = $election; - $form_state['candidate'] = $candidate; - - $candidate_account = NULL; - if (!empty($candidate->uid)) { - $candidate_account = user_load($candidate->uid); - } - - $form['cstatus'] = array( - '#type' => 'select', - '#options' => array( - ELECTION_CANDIDATE_PENDING => t('Pending approval'), - ELECTION_CANDIDATE_APPROVED => t('Approved'), - ELECTION_CANDIDATE_WITHDRAWN => t('Withdrawn'), - ELECTION_CANDIDATE_REJECTED => t('Rejected'), - ), - '#title' => t('Candidate status'), - '#required' => TRUE, - '#default_value' => $candidate->cstatus, - '#empty_option' => t('- Select status -'), - '#description' => t( - 'If the status is set to !approved, the candidate will be visible to all those who have permission to view the election.', - array('!approved' => t('Approved')) - ), - '#weight' => 0, - ); - - $form['user_info']['current_user'] = array( - '#title' => t('Associated user account'), - '#type' => 'item', - '#default_value' => empty($candidate_account)? NULL : $candidate_account->name, - '#weight' => 1, - ); - if (empty($account)) { - $form['user_info']['current_user']['#markup'] = t('No user account associated.'); - } - else { - $form['user_info']['current_user']['#markup'] = theme( - 'username', - array('account' => $candidate_account, 'link_options' => array('target' => '_blank')) - ); - $form['user_info']['current_user']['#description'] = t('The account that submitted the nomination.'); - } - - $post_ids = election_candidate_get_available_posts($election, NULL, FALSE); - $available_posts = election_post_load_multiple($post_ids); - $post_options = array(); - foreach ($available_posts as $post) { - $post_options[$post->post_id] = truncate_utf8($post->title, 100, TRUE, TRUE, 80); - } - $post_name = _election_get_posts_name($election->type); - $form['post'] = array( - '#type' => 'select', - '#options' => $post_options, - '#title' => check_plain(drupal_ucfirst($post_name)), - '#empty_option' => t('- Select @post_name -', array('@post_name' => $post_name)), - '#required' => TRUE, - '#default_value' => $candidate->post_id, - ); - - $form['first_name'] = array( - '#type' => 'textfield', - '#title' => t('First name(s)'), - '#max_length' => 100, - '#default_value' => $candidate->first_name, - '#size' => 50, - '#required' => TRUE, - ); - - $form['last_name'] = array( - '#type' => 'textfield', - '#title' => t('Last name(s)'), - '#max_length' => 100, - '#default_value' => $candidate->last_name, - '#size' => 50, - '#required' => TRUE, - ); - - $form['mail'] = array( - '#type' => 'textfield', - '#title' => t('Email address'), - '#size' => 30, - '#required' => FALSE, - '#default_value' => $candidate->mail, - ); - - $form['phone'] = array( - '#type' => 'textfield', - '#title' => t('Contact telephone number'), - '#size' => 12, - '#required' => FALSE, - '#default_value' => $candidate->phone, - ); - - field_attach_form('election_candidate', $candidate, $form, $form_state); - - foreach ($form as $key => &$field) { - if (strpos($key, 'field_') === 0 && isset($field['#required'])) { - $field['#required'] = FALSE; - } - } - - $form['buttons'] = array( - '#type' => 'actions', - '#weight' => 100, - ); - $form['buttons']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save'), - '#submit' => array('election_candidate_edit_form_submit'), - ); - $form['buttons']['delete'] = array( - '#type' => 'submit', - '#value' => t('Delete'), - '#submit' => array('election_candidate_edit_form_delete_submit'), - '#access' => entity_access('delete', 'election_candidate', $candidate), - '#limit_validation_errors' => array(), // No need to validate on deletion - ); - - $form['#validate'][] = 'election_candidate_form_validate'; - $form['#validate'][] = 'election_candidate_edit_form_validate'; - - return $form; - -} - -/** - * Form submit function for the Save button in the form election_candidate_edit_form(). - * - * @param array $form - * @param array &$form_state - * @return void - */ -function election_candidate_edit_form_submit($form, &$form_state) { - - $candidate = &$form_state['candidate']; - - foreach ($candidate as $property => $value) { - if (isset($form_state['values'][$property])) { - $candidate->$property = $form_state['values'][$property]; - } - } - - $candidate->post_id = $form_state['values']['post']; - - if (!empty($form_state['values']['new_user'])) { - if ($account = user_load_by_name($form_state['values']['new_user'])) { - $candidate->uid = $account->uid; - $candidate->username = $account->username; - } - } - - field_attach_submit('election_candidate', $candidate, $form, $form_state); - - election_candidate_save($candidate); - - drupal_set_message( - t( - 'The candidate %first_name %last_name was saved.', - array( - '%first_name' => $candidate->first_name, - '%last_name' => $candidate->last_name, - ) - ) - ); - -} - -/** - * Form submit function for the Delete button in the form election_candidate_edit_form. - * - * @param array $form - * @param array &$form_state - * @return void - */ -function election_candidate_edit_form_delete_submit($form, &$form_state) { - $destination = array(); - if (isset($_GET['destination'])) { - $destination = drupal_get_destination(); - unset($_GET['destination']); - } - $candidate = $form['#candidate']; - $form_state['redirect'] = array( - election_candidate_uri_path($candidate) . '/delete', - array('query' => $destination), - ); -} - -/** - * Form builder function to confirm the delete action for a candidate. - * See http://api.drupal.org/api/drupal/modules--system--system.module/function/confirm_form. - * - * @param array $form - * @param array &$form_state - * @param stdClass $election - * - * @return array - * Render array. - */ -function election_candidate_edit_form_delete_confirm($form, &$form_state, $election, $candidate) { - - drupal_set_breadcrumb( - _election_build_breadcrumb($election, '_CANDIDATES_') - ); - - $form['candidate_id'] = array( - '#type' => 'value', - '#value' => $candidate->candidate_id, - ); - - return confirm_form( - $form, - t('Are you sure you want to delete the candidate %title?', array('%title' => $candidate->first_name . ' ' . $candidate->last_name)), - election_candidate_uri_path($candidate), - t('Deleting a candidate also deletes ALL associated data, for example votes. This action cannot be undone.'), - t('Delete'), - t('Cancel') - ); -} - -/** - * Form submit function for the Delete button in the form election_candidate_edit_form_delete_confirm. - * - * @param array $form - * @param array &$form_state - * @return void - */ -function election_candidate_edit_form_delete_confirm_submit($form, &$form_state) { - if ($form_state['values']['confirm']) { - - $candidate = election_candidate_load($form_state['values']['candidate_id']); - $election = election_load($candidate->election_id); - - $info = array( - '%first_name' => $candidate->first_name, - '%last_name' => $candidate->last_name, - '%election_title' => !empty($election)? $election->title : t('unknown'), - ); - - // Delete the candidate - $delete = election_candidate_delete($form_state['values']['candidate_id']); - if ($delete) { - watchdog('election', 'Deleted candidate "%first_name %last_name".', $info); - } - - if ($delete) { - drupal_set_message( - t('The candidate %first_name %last_name has been deleted from the election %election_title.', $info) - ); - } - else { - drupal_set_message( - t('Failed to delete the candidate %first_name %last_name from the election %election_title.', $info) - ); - } - - } - - if (empty($_GET['destination']) && $election) { - $form_state['redirect'] = election_uri_path($election) . '/candidates'; - } - -} diff --git a/election-candidate.tpl.php b/election-candidate.tpl.php deleted file mode 100644 index 8e984a56001fd53d0a7f6c463b422ba728bc4a71..0000000000000000000000000000000000000000 --- a/election-candidate.tpl.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/** - * @file - * Default theme implementation to display an election candidate. - */ - -?> -<div id="election-<?php print $election->election_id; ?>-candidate-<?php print $candidate->candidate_id; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>> - - <?php if (!$page): ?> - <h2<?php print $title_attributes; ?>><a href="<?php print $url; ?>"><?php print $full_name; ?></a></h2> - <?php endif; ?> - - <div class="pseudo-field candidate-election"> - <span class="label">Election: </span><span class="item"><?php print $election_link; ?></span> - </div> - - <div class="pseudo-field candidate-post"> - <span class="label">Standing for: </span><span class="item"><?php print $post_link; ?></span> - </div> - - <div class="content"<?php print $content_attributes; ?>> - <?php print render($content); ?> - </div> - -</div> diff --git a/election.info b/election.info index ef49b5f00cd46e19165a3e77de8fa69a0817071a..b53f55d65df124d26e7c4558b5b29503b32f4f86 100644 --- a/election.info +++ b/election.info @@ -5,11 +5,9 @@ core = 7.x php = 5.3 dependencies[] = entity dependencies[] = views -dependencies[] = election_candidate files[] = includes/election-default.controller.inc files[] = includes/election.controller.inc files[] = includes/election-post.controller.inc -files[] = includes/election-candidate.controller.inc files[] = views/handlers/views_handler_field_election.inc files[] = views/handlers/views_handler_field_election_link.inc files[] = views/handlers/views_handler_field_election_link_delete.inc diff --git a/election.module b/election.module index b11cdfb5d01e84e905ef8d8b5baa14f4e0605063..5c4f7dd7f26dd6570dbabbc68910a4d8311b5e03 100644 --- a/election.module +++ b/election.module @@ -1013,241 +1013,6 @@ function election_page_title($election) { return $election->title; } -/** - * Implements hook_token_info(). - * See http://api.drupal.org/api/drupal/modules--system--system.api.php/function/hook_token_info/7. - */ -function election_token_info() { - $info = array(); - $info['types'] = array( - 'election' => array( - 'name' => t('Elections'), - 'description' => t('Tokens related to elections.'), - 'needs-data' => 'election', - ), - 'election_candidate' => array( - 'name' => t('Candidates'), - 'description' => t('Tokens related to election candidates.'), - 'needs-data' => 'election_candidate', - ), - ); - $info['tokens'] = array( - 'election' => array( - 'id' => array( - 'name' => t('Election ID'), - 'description' => t('The unique ID of the election.'), - ), - 'type' => array( - 'name' => t('Election type'), - 'description' => t('The machine-readable name of the election type.'), - ), - 'type_name' => array( - 'name' => t('Election type name'), - 'description' => t('The human-readable name of the election type.'), - ), - 'title' => array( - 'name' => t('Title'), - 'description' => t('The title of the election.'), - ), - 'created' => array( - 'name' => t('Date created'), - 'description' => t('The date the election was created.'), - 'type' => 'date', - ), - ), - 'election_candidate' => array( - 'id' => array( - 'name' => t('Election candidate ID'), - 'description' => t('The unique ID of the candidate.'), - ), - 'mail' => array( - 'name' => t('Email address'), - 'description' => t('The email address of the candidate.'), - ), - ), - ); - return $info; -} - -/** - * Implements hook_tokens(). - */ -function election_tokens($type, array $tokens, array $data = array(), array $options = array()) { - $sanitize = !empty($options['sanitize']); - $replacements = array(); - if ($type == 'election' && !empty($data['election'])) { - $election = $data['election']; - foreach ($tokens as $name => $original) { - switch ($name) { - case 'id': - $replacements[$original] = $election->election_id; - break; - case 'type': - $replacements[$original] = $sanitize ? check_plain($election->type) : $election->type; - break; - case 'type_name': - $type = _election_type_get_info($election->type); - $type_name = $type['name']; - $replacements[$original] = $sanitize ? check_plain($type_name) : $type_name; - break; - case 'title': - $replacements[$original] = $sanitize ? check_plain($election->title) : $election->title; - break; - case 'created': - $replacements[$original] = format_date($election->created, 'medium'); - break; - } - } - } - else if ($type == 'election_candidate' && !empty($data['election_candidate'])) { - $candidate = $data['election_candidate']; - foreach ($tokens as $name => $original) { - switch ($name) { - case 'id': - $replacements[$original] = $candidate->candidate_id; - break; - case 'mail': - $replacements[$original] = $sanitize ? check_plain($candidate->mail) : $candidate->mail; - break; - } - } - } - return $replacements; -} - -/** - * Implements hook_pathauto(). See the Pathauto module. - * - * @param string $op - * @return stdClass - */ -function election_pathauto($op) { - switch ($op) { - case 'settings': - $settings = array(); - $settings['module'] = 'election'; - $settings['token_type'] = 'election'; - $settings['groupheader'] = t('Election paths'); - $settings['patterndescr'] = t('Default path pattern (applies to all election types with blank patterns below)'); - $settings['patterndefault'] = 'election/[election:title]'; - $settings['batch_update_callback'] = 'election_pathauto_bulk_update_batch_process'; - $settings['batch_file'] = drupal_get_path('module', 'election') . '/election.module'; - foreach (election_types() as $type_mn => $type) { - $settings['patternitems'][$type_mn] = t('Pattern for all %type paths', array('%type' => $type['name'])); - } - return (object) $settings; - default: - break; - } -} - -/** - * Allow bulk updating of paths. See the Pathauto module. - * - * @see election_pathauto() - * @param array &$context - * @return void - */ -function election_pathauto_bulk_update_batch_process(&$context) { - if (!isset($context['sandbox']['current'])) { - $context['sandbox']['count'] = 0; - $context['sandbox']['current'] = 0; - } - $query = db_select('election', 'e'); - $query->leftJoin('url_alias', 'ua', "CONCAT('election/', e.election_id) = ua.source"); - $query->addField('e', 'election_id'); - $query->isNull('ua.source'); - $query->condition('e.election_id', $context['sandbox']['current'], '>'); - $query->orderBy('e.election_id'); - $query->addTag('pathauto_bulk_update'); - $query->addMetaData('entity', 'election'); - // Get the total amount of items to process. - if (!isset($context['sandbox']['total'])) { - $context['sandbox']['total'] = $query->countQuery()->execute()->fetchField(); - // If there are no elections to update, then stop immediately. - if (!$context['sandbox']['total']) { - $context['finished'] = 1; - return; - } - } - $query->range(0, 25); - $ids = $query->execute()->fetchCol(); - pathauto_election_update_alias_multiple($ids, 'bulkupdate'); - $context['sandbox']['count'] += count($ids); - $context['sandbox']['current'] = max($ids); - $context['message'] = t('Updated alias for election @id.', array('@id' => end($ids))); - if ($context['sandbox']['count'] != $context['sandbox']['total']) { - $context['finished'] = $context['sandbox']['count'] / $context['sandbox']['total']; - } -} - -/** - * Update the URL aliases for an individual election. - * - * @param $election - * A election object. - * @param $op - * Operation being performed on the election ('insert', 'update' or 'bulkupdate'). - * @param $options - * An optional array of additional options. - */ -function pathauto_election_update_alias(stdClass $election, $op, array $options = array()) { - // Skip processing if the user has disabled pathauto for the election. - if (isset($election->path['pathauto']) && empty($election->path['pathauto'])) { - return; - } - $options += array( - 'language' => isset($election->language) ? $election->language : LANGUAGE_NONE, - ); - // Skip processing if the election has no pattern. - if (!pathauto_pattern_load_by_entity('election', $election->type, $options['language'])) { - return; - } - module_load_include('inc', 'pathauto'); - pathauto_create_alias( - 'election', - $op, - election_uri_path($election), - array('election' => $election), - $election->type, - $options['language'] - ); -} - -/** - * Update the URL aliases for multiple elections. - * - * @param $election_ids - * An array of election IDs. - * @param $op - * Operation being performed on the elections ('insert', 'update' or - * 'bulkupdate'). - * @param $options - * An optional array of additional options. - */ -function pathauto_election_update_alias_multiple(array $election_ids, $op, array $options = array()) { - $options += array('message' => FALSE); - $elections = election_load_multiple($election_ids); - foreach ($elections as $election) { - pathauto_election_update_alias($election, $op, $options); - } - if (!empty($options['message'])) { - drupal_set_message(format_plural(count($election_ids), 'Updated URL alias for 1 election.', 'Updated URL aliases for @count elections.')); - } -} - -/** - * Implements hook_path_alias_types(). See Pathauto module. - * - * Used primarily by the bulk delete form. - */ -function election_path_alias_types() { - $objects = array( - 'election/' => t('Elections') - ); - return $objects; -} - /** * Implements hook_theme(). */ @@ -1261,14 +1026,6 @@ function election_theme() { 'render element' => 'elements', 'template' => 'election-post', ), - 'election_candidate' => array( - 'render element' => 'elements', - 'template' => 'election-candidate', - ), - 'election_candidate_details' => array( - 'render element' => 'elements', - 'template' => 'election-candidate-details', - ), ); } @@ -1488,188 +1245,6 @@ function template_preprocess_election_post(&$variables) { } -/** - * Process variables for election-candidate.tpl.php - * - * The $variables array contains the following arguments: - * - $candidate - * - $election - * - $view_mode - * - $page - * - * @see election-candidate.tpl.php - */ -function template_preprocess_election_candidate(&$variables) { - $variables['view_mode'] = $variables['elements']['#view_mode']; - - // $teaser boolean - $variables['teaser'] = $variables['view_mode'] == 'teaser'; - // $details boolean - $variables['details'] = $variables['view_mode'] == 'details'; - // $page boolean - $variables['page'] = ($variables['view_mode'] == 'full' || $variables['view_mode'] == 'details'); - - $variables['election'] = $variables['elements']['#election']; - $variables['candidate'] = $variables['elements']['#candidate']; - $variables['post'] = $variables['elements']['#post']; - - $election = $variables['election']; - $candidate = $variables['candidate']; - $post = $variables['post']; - $election_type = _election_type_get_info($election->type); - - if (empty($post)) { - // Handle gracefully when the candidate's post is deleted prematurely. - $post = entity_get_controller('election_post')->create(array( - 'type' => $election_type['post key'], - )); - } - - $uri = entity_uri('election_candidate', $candidate, $election); - $variables['url'] = url($uri['path'], $uri['options']); - - $election_uri = entity_uri('election', $election); - $variables['election_url'] = url($election_uri['path'], $election_uri['options']); - $variables['election_title'] = check_plain($election->title); - $variables['election_link'] = l($election->title, $election_uri['path'], $election_uri['options']); - $variables['election_type'] = check_plain($election_type['name']); - - $post_uri = entity_uri('election_post', $post); - $variables['post_url'] = url($post_uri['path'], $post_uri['options']); - $variables['post_title'] = check_plain($post->title); - $variables['post_link'] = l($post->title, $post_uri['path'], $post_uri['options']); - $variables['post_name'] = check_plain($election_type['post name']); - - $variables['full_name'] = t('@first_name @last_name', array('@first_name' => $candidate->first_name, '@last_name' => $candidate->last_name)); - - $variables += array('content' => array()); - foreach (element_children($variables['elements']) as $key) { - $variables['content'][$key] = $variables['elements'][$key]; - } - - // Make the field variables available with the appropriate language. - field_attach_preprocess('election_candidate', $candidate, $variables['content'], $variables); - - $variables['classes_array'][] = drupal_html_class('election-' . $election->type . '-candidate'); - - $variables['theme_hook_suggestions'][] = 'election_candidate__' . $candidate->candidate_id; - $variables['theme_hook_suggestions'][] = 'election__' . $election->type . '__candidate'; - $variables['theme_hook_suggestions'][] = 'election__' . $election->election_id . '__candidate'; - -} - -/** - * Process variables for election-candidate-details.tpl.php - * - * The $variables array contains the following arguments: - * - $candidate - * - $election - * - $page - * - * @see election-candidate.tpl.php - */ -function template_preprocess_election_candidate_details(&$variables) { - - $variables['election'] = $variables['elements']['#election']; - $variables['candidate'] = $variables['elements']['#candidate']; - $variables['post'] = $variables['elements']['#post']; - - $election = $variables['election']; - $candidate = $variables['candidate']; - $post = $variables['post']; - $election_type = _election_type_get_info($election->type); - - if (empty($post)) { - // Handle gracefully when the candidate's post is deleted prematurely. - $post = entity_get_controller('election_post')->create(array( - 'type' => $election_type['post key'], - )); - } - - $uri = entity_uri('election_candidate', $candidate, $election); - $variables['url'] = url($uri['path'], $uri['options']); - - $election_uri = entity_uri('election', $election); - $variables['election_url'] = url($election_uri['path'], $election_uri['options']); - $variables['election_link'] = l($election->title, $election_uri['path'], $election_uri['options']); - - $post_uri = entity_uri('election_post', $post); - $variables['post_url'] = url($post_uri['path'], $post_uri['options']); - $variables['post_link'] = l($post->title, $post_uri['path'], $post_uri['options']); - - $variables['full_name'] = t('@first_name @last_name', array('@first_name' => $candidate->first_name, '@last_name' => $candidate->last_name)); - - $variables['content']['election'] = array( - '#theme' => 'container', - '#attributes' => array( - 'class' => array('pseudo-field', 'candidate-election'), - ), - '#markup' => '<span class="label">' . t('Election:') . '</span>' - . ' <span class="item">' . $variables['election_link'] . '</span>', - ); - - $variables['content']['post'] = array( - '#theme' => 'container', - '#attributes' => array( - 'class' => array('pseudo-field', 'candidate-post'), - ), - '#markup' => '<span class="label">' . drupal_ucfirst($election_type['post name'] . ':') . '</span>' - . ' <span class="item">' . $variables['post_link'] . '</span>', - ); - - $variables['content']['full-name'] = array( - '#theme' => 'container', - '#attributes' => array( - 'class' => array('pseudo-field', 'candidate-full-name'), - ), - '#markup' => '<span class="label">' . t('Name:') . '</span>' - . ' <span class="item">' . $variables['full_name'] . '</span>', - ); - - $variables['username'] = theme('username', array('#account' => $candidate->uid? user_load($candidate->uid) : NULL)); - $variables['phone'] = check_plain($candidate->phone); - $variables['mail'] = l($candidate->mail, 'mailto:' . $candidate->mail, array('absolute' => TRUE)); - - $variables['content']['mail'] = array( - '#theme' => 'container', - '#attributes' => array( - 'class' => array('pseudo-field', 'candidate-email-address') - ), - '#markup' => '<span class="label">' . t('Email address:') . '</span>' - . ' <span class="item">' . $variables['mail'] . '</span>', - ); - - $variables['content']['phone'] = array( - '#theme' => 'container', - '#attributes' => array( - 'class' => array('pseudo-field', 'candidate-phone'), - ), - '#markup' => '<span class="label">' . t('Phone number:') . '</span>' - . ' <span class="item">' . $variables['phone'] . '</span>', - ); - - $variables['content']['candidate-username'] = array( - '#theme' => 'container', - '#attributes' => array( - 'class' => array('pseudo-field', 'candidate-username'), - ), - '#markup' => '<span class="label">' . t('Username:') . '</span>' - . ' <span class="item">' . $variables['username'] . '</span>', - ); - - $variables += array('content' => array()); - foreach (element_children($variables['elements']) as $key) { - $variables['content'][$key] = $variables['elements'][$key]; - } - - $variables['classes_array'][] = drupal_html_class('election-' . $election->type . '-candidate', 'election-candidate-details'); - - $variables['theme_hook_suggestions'][] = 'election_candidate_details__' . $candidate->candidate_id; - $variables['theme_hook_suggestions'][] = 'election__' . $election->type . '__candidate_details'; - $variables['theme_hook_suggestions'][] = 'election__' . $election->election_id . '__candidate_details'; - -} - /** * Internal function that determines whether voting/nominating in an election is 'open', * based on the status, opening time and closing time. @@ -1763,33 +1338,6 @@ function _election_post_format_status(stdClass $election, stdClass $post, $statu return t('!status_formatted (overridden)', array('!status_formatted' => $status_formatted)); } -/** - * Internal function to format the status field of an election candidate for display. - * - * @todo make this themeable - * - * @param stdClass $candidate - * - * @return string - */ -function _election_candidate_format_status(stdClass $candidate) { - switch ($candidate->cstatus) { - case ELECTION_CANDIDATE_APPROVED: - return t('Approved'); - break; - case ELECTION_CANDIDATE_REJECTED: - return t('Nomination rejected'); - break; - case ELECTION_CANDIDATE_WITHDRAWN: - return t('Withdrawn'); - break; - case ELECTION_CANDIDATE_PENDING: - default: - return t('Pending approval'); - break; - } -} - /** * General function for creating breadcrumbs. Accepts any number of parameters, * each corresponding to the breadcrumb link. Output must be sanitized before @@ -1933,3 +1481,58 @@ function election_menu_position_rule_plugins() { ), ); } + +/** + * Update the URL aliases for an individual election. + * + * @param $election + * A election object. + * @param $op + * Operation being performed on the election ('insert', 'update' or 'bulkupdate'). + * @param $options + * An optional array of additional options. + */ +function pathauto_election_update_alias(stdClass $election, $op, array $options = array()) { + // Skip processing if the user has disabled pathauto for the election. + if (isset($election->path['pathauto']) && empty($election->path['pathauto'])) { + return; + } + $options += array( + 'language' => isset($election->language) ? $election->language : LANGUAGE_NONE, + ); + // Skip processing if the election has no pattern. + if (!pathauto_pattern_load_by_entity('election', $election->type, $options['language'])) { + return; + } + module_load_include('inc', 'pathauto'); + pathauto_create_alias( + 'election', + $op, + election_uri_path($election), + array('election' => $election), + $election->type, + $options['language'] + ); +} + +/** + * Update the URL aliases for multiple elections. + * + * @param $election_ids + * An array of election IDs. + * @param $op + * Operation being performed on the elections ('insert', 'update' or + * 'bulkupdate'). + * @param $options + * An optional array of additional options. + */ +function pathauto_election_update_alias_multiple(array $election_ids, $op, array $options = array()) { + $options += array('message' => FALSE); + $elections = election_load_multiple($election_ids); + foreach ($elections as $election) { + pathauto_election_update_alias($election, $op, $options); + } + if (!empty($options['message'])) { + drupal_set_message(format_plural(count($election_ids), 'Updated URL alias for 1 election.', 'Updated URL aliases for @count elections.')); + } +} \ No newline at end of file diff --git a/election.pathauto.inc b/election.pathauto.inc new file mode 100644 index 0000000000000000000000000000000000000000..74e3d3e9f0a690338e86fcaaa3c787c0d269843a --- /dev/null +++ b/election.pathauto.inc @@ -0,0 +1,83 @@ +<?php +/** + * @file + * Pathauto hooks for the Election module. + */ + +/** + * Implements hook_pathauto(). See the Pathauto module. + * + * @param string $op + * @return stdClass + */ +function election_pathauto($op) { + switch ($op) { + case 'settings': + $settings = array(); + $settings['module'] = 'election'; + $settings['token_type'] = 'election'; + $settings['groupheader'] = t('Election paths'); + $settings['patterndescr'] = t('Default path pattern (applies to all election types with blank patterns below)'); + $settings['patterndefault'] = 'election/[election:title]'; + $settings['batch_update_callback'] = 'election_pathauto_bulk_update_batch_process'; + $settings['batch_file'] = drupal_get_path('module', 'election') . '/election.module'; + foreach (election_types() as $type_mn => $type) { + $settings['patternitems'][$type_mn] = t('Pattern for all %type paths', array('%type' => $type['name'])); + } + return (object) $settings; + default: + break; + } +} + +/** + * Allow bulk updating of paths. See the Pathauto module. + * + * @see election_pathauto() + * @param array &$context + * @return void + */ +function election_pathauto_bulk_update_batch_process(&$context) { + if (!isset($context['sandbox']['current'])) { + $context['sandbox']['count'] = 0; + $context['sandbox']['current'] = 0; + } + $query = db_select('election', 'e'); + $query->leftJoin('url_alias', 'ua', "CONCAT('election/', e.election_id) = ua.source"); + $query->addField('e', 'election_id'); + $query->isNull('ua.source'); + $query->condition('e.election_id', $context['sandbox']['current'], '>'); + $query->orderBy('e.election_id'); + $query->addTag('pathauto_bulk_update'); + $query->addMetaData('entity', 'election'); + // Get the total amount of items to process. + if (!isset($context['sandbox']['total'])) { + $context['sandbox']['total'] = $query->countQuery()->execute()->fetchField(); + // If there are no elections to update, then stop immediately. + if (!$context['sandbox']['total']) { + $context['finished'] = 1; + return; + } + } + $query->range(0, 25); + $ids = $query->execute()->fetchCol(); + pathauto_election_update_alias_multiple($ids, 'bulkupdate'); + $context['sandbox']['count'] += count($ids); + $context['sandbox']['current'] = max($ids); + $context['message'] = t('Updated alias for election @id.', array('@id' => end($ids))); + if ($context['sandbox']['count'] != $context['sandbox']['total']) { + $context['finished'] = $context['sandbox']['count'] / $context['sandbox']['total']; + } +} + +/** + * Implements hook_path_alias_types(). See Pathauto module. + * + * Used primarily by the bulk delete form. + */ +function election_path_alias_types() { + $objects = array( + 'election/' => t('Elections') + ); + return $objects; +} \ No newline at end of file diff --git a/election.tokens.inc b/election.tokens.inc new file mode 100644 index 0000000000000000000000000000000000000000..6fad0985a1ae3bacc84b12633f282f135b6e6143 --- /dev/null +++ b/election.tokens.inc @@ -0,0 +1,79 @@ +<?php +/** + * @file + * Token integration for the Election module. + */ + +/** + * Implements hook_token_info(). + * See http://api.drupal.org/api/drupal/modules--system--system.api.php/function/hook_token_info/7. + */ +function election_token_info() { + $info = array(); + $info['types'] = array( + 'election' => array( + 'name' => t('Elections'), + 'description' => t('Tokens related to elections.'), + 'needs-data' => 'election', + ), + ); + $info['tokens'] = array( + 'election' => array( + 'id' => array( + 'name' => t('Election ID'), + 'description' => t('The unique ID of the election.'), + ), + 'type' => array( + 'name' => t('Election type'), + 'description' => t('The machine-readable name of the election type.'), + ), + 'type_name' => array( + 'name' => t('Election type name'), + 'description' => t('The human-readable name of the election type.'), + ), + 'title' => array( + 'name' => t('Title'), + 'description' => t('The title of the election.'), + ), + 'created' => array( + 'name' => t('Date created'), + 'description' => t('The date the election was created.'), + 'type' => 'date', + ), + ), + ); + return $info; +} + +/** + * Implements hook_tokens(). + */ +function election_tokens($type, array $tokens, array $data = array(), array $options = array()) { + $sanitize = !empty($options['sanitize']); + $replacements = array(); + if ($type == 'election' && !empty($data['election'])) { + $election = $data['election']; + foreach ($tokens as $name => $original) { + switch ($name) { + case 'id': + $replacements[$original] = $election->election_id; + break; + case 'type': + $replacements[$original] = $sanitize ? check_plain($election->type) : $election->type; + break; + case 'type_name': + $type = _election_type_get_info($election->type); + $type_name = $type['name']; + $replacements[$original] = $sanitize ? check_plain($type_name) : $type_name; + break; + case 'title': + $replacements[$original] = $sanitize ? check_plain($election->title) : $election->title; + break; + case 'created': + $replacements[$original] = format_date($election->created, 'medium'); + break; + } + } + } + return $replacements; +} diff --git a/includes/election-candidate.controller.inc b/includes/election-candidate.controller.inc deleted file mode 100644 index 42fad0f2a4ca43b9ccd80a5e9d7e7b6e18b92ba5..0000000000000000000000000000000000000000 --- a/includes/election-candidate.controller.inc +++ /dev/null @@ -1,41 +0,0 @@ -<?php -/** - * @file - * Entity controller for candidates (in the Election module). - * - * @class - * ElectionCandidateController - * @extends - * ElectionDefaultController - */ -class ElectionCandidateController extends ElectionDefaultController { - - /** - * Overrides EntityAPIController::create(), allowing defaults to be defined. - */ - public function create(array $values = array()) { - $default_values = array( - 'candidate_id' => '', - 'election_id' => '', - 'post_id' => '', - 'cstatus' => ELECTION_CANDIDATE_PENDING, - 'uid' => '', - 'username' => '', - 'first_name' => '', - 'last_name' => '', - 'phone' => '', - 'mail' => '', - 'summary' => '', - 'manifesto' => '', - 'photo' => '', - 'proposer' => new stdClass(), - 'seconders' => array(), - 'created' => 0, - 'changed' => 0, - ); - // Overwrite default values with supplied values. - $values = array_merge($default_values, $values); - return parent::create($values); - } - -} diff --git a/includes/election.controller-old.inc b/includes/election.controller-old.inc deleted file mode 100644 index c2c6037e826740daa1f80e5783372e937ff99805..0000000000000000000000000000000000000000 --- a/includes/election.controller-old.inc +++ /dev/null @@ -1,124 +0,0 @@ -<?php -/** - * @file - * Entity controller for the Election module. - * - * @class - * ElectionController - * @extends - * DrupalDefaultEntityController - */ -class ElectionController extends DrupalDefaultEntityController { - - public function create($type = 0) { - - return (object) array( - 'election_id' => '', - 'type' => $type, - 'title' => '', - 'vstatus' => ELECTION_STATUS_CLOSED, - 'vopen_time' => NULL, - 'vclose_time' => NULL, - 'nstatus' => ELECTION_STATUS_CLOSED, - 'nopen_time' => NULL, - 'nclose_time' => NULL, - ); - - } - - public function save($election) { - - $transaction = db_transaction(); - - try { - - global $user; - - // Determine whether the election is new. - $election->is_new = empty($election->election_id); - - // Set timestamp fields. - if (empty($election->created)) { - $election->created = REQUEST_TIME; - } - - $election->changed = REQUEST_TIME; - $update_election = TRUE; - - field_attach_presave('election', $election); - - if ($election->is_new) { - drupal_write_record('election', $election); - $op = 'insert'; - } - else { - drupal_write_record('election', $election, 'election_id'); - $op = 'update'; - } - - $function = 'field_attach_' . $op; - $function('election', $election); - - module_invoke_all('entity_' . $op, $election, 'election'); - - if (function_exists('pathauto_election_update_alias')) { - pathauto_election_update_alias($election, $op); - } - - unset($election->is_new); - - // Skip the slave server for this user temporarily. - db_ignore_slave(); - - return $election; - - } - catch (Exception $e) { - - $transaction->rollback(); - watchdog_exception('election', $e, NULL, WATCHDOG_ERROR); - return FALSE; - - } - - } - - public function delete($ids) { - - if (!empty($ids)) { - $elections = $this->load($ids, array()); - $transaction = db_transaction(); - - try { - db_delete('election') - ->condition('election_id', $ids, 'IN') - ->execute(); - foreach ($elections as $election_id => $election) { - - field_attach_delete('election', $election); - - module_invoke_all('entity_delete', $election, 'election'); - - if (function_exists('pathauto_entity_path_delete_all')) { - pathauto_entity_path_delete_all('election', $election); - } - - } - db_ignore_slave(); - } - catch (Exception $e) { - $transaction->rollback(); - watchdog_exception('election', $e, NULL, WATCHDOG_ERROR); - return FALSE; - } - - cache_clear_all(); - $this->resetCache(); - - } - - return TRUE; - - } - -} \ No newline at end of file diff --git a/submodules/election_candidate/election_candidate.constants.inc b/submodules/election_candidate/election_candidate.constants.inc deleted file mode 100644 index a7d610df424db8c35c81346969be027835a1b997..0000000000000000000000000000000000000000 --- a/submodules/election_candidate/election_candidate.constants.inc +++ /dev/null @@ -1,14 +0,0 @@ -<?php -/** - * @file - * Constants for the Election Candidate module. - */ - -// Constants for the {election_candidate} table. -define('ELECTION_CANDIDATE_APPROVED', 1); -define('ELECTION_CANDIDATE_PENDING', 0); -define('ELECTION_CANDIDATE_WITHDRAWN', -1); -define('ELECTION_CANDIDATE_REJECTED', -2); - -// Cardinality of the nomination form's "seconder" field (instance of "endorser"). -define('ELECTION_CANDIDATE_MAX_SECONDERS', 10); diff --git a/submodules/election_candidate/election_candidate.info b/submodules/election_candidate/election_candidate.info deleted file mode 100644 index 60ca28554ab55ab278a973044c63ec35e6344d31..0000000000000000000000000000000000000000 --- a/submodules/election_candidate/election_candidate.info +++ /dev/null @@ -1,6 +0,0 @@ -name = Election Candidate -description = "Allows elections to have candidates." -package = Election -core = 7.x -php = 5.3 -dependencies[] = election diff --git a/submodules/election_candidate/election_candidate.install b/submodules/election_candidate/election_candidate.install deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/submodules/election_candidate/election_candidate.module b/submodules/election_candidate/election_candidate.module deleted file mode 100644 index ab803581736982da8fe25e837729652eedfb3d57..0000000000000000000000000000000000000000 --- a/submodules/election_candidate/election_candidate.module +++ /dev/null @@ -1,513 +0,0 @@ -<?php -/** - * @file - * Election Candidate: primary module file. - */ - -// Required files. -require_once 'election_candidate.constants.inc'; - - -/** - * Implements hook_entity_info(). - */ -function election_candidate_entity_info() { - - $entities = array(); - - $entities['election_candidate'] = array( - 'label' => t('Election candidate'), - 'access callback' => 'election_candidate_access', - 'uri callback' => 'election_candidate_uri', - 'controller class' => 'ElectionCandidateController', - 'base table' => 'election_candidate', - 'label callback' => 'election_candidate_label', - 'entity keys' => array( - 'id' => 'candidate_id', - ), - 'static cache' => TRUE, - 'fieldable' => TRUE, - 'module' => 'election', - 'bundles' => array( - // Single bundles are named after the entity type (see entity_extract_ids()). - 'election_candidate' => array( - 'label' => t('Election candidate'), - 'admin' => array( - 'path' => 'admin/election/candidate', - 'access arguments' => array('administer elections'), - ), - ), - ), - 'view modes' => array( - 'teaser' => array( - 'label' => t('Teaser'), - 'custom settings' => TRUE, - ), - ), - 'redirect' => FALSE, // for the Redirect module - ); - - return $entities; - -} - -/** - * Implements hook_permission(). - */ -function election_candidate_permission() { - $permissions = array( - 'bypass nomination schedule' => array( - 'title' => t('Bypass nomination schedule'), - 'description' => t('This allows the user to submit a nomination at any time, regardless of whether or not nominations are open.'), - ), - 'bypass nomination exclusivity' => array( - 'title' => t('Bypass nomination exclusivity'), - 'description' => t('This allows the user to submit a nomination for more than one exclusive position.'), - ), - 'allow duplicate nominations' => array( - 'title' => t('Allow duplicate nominations'), - 'description' => t('This allows the user to submit more than one nomination for the same position.'), - ), - 'submit nominations' => array( - 'title' => t('Submit nominations'), - 'description' => t('This allows the user to submit a nomination, only when nominations are open.'), - ), - 'edit own nominations' => array( - 'title' => t('Edit own nominations'), - 'description' => t('This allows the user to edit his/her own nominations.'), - ), - ); - return $permissions; -} - -/** - * Determines whether the given user has access to a given election candidate. - * - * @param $op - * The operation being performed. One of 'view', 'update', 'create', 'delete' - * or just 'edit' (being the same as 'create' or 'update'). - * @param $candidate - * Optionally a candidate to check access for. If nothing is - * given, access for all candidates is determined. - * @param $account - * The user to check for. Leave it to NULL to check for the global user. - * @return boolean - * Whether access is allowed or not. - */ -function election_candidate_access($op, $candidate = NULL, $account = NULL) { - if ($account === NULL) { - global $user; - $account = $user; - } - switch ($op) { - case 'view': - if (user_access('edit any election', $account)) { - return TRUE; - } - if ($candidate && $candidate->cstatus == ELECTION_CANDIDATE_APPROVED && user_access('view any election', $account)) { - return TRUE; - } - break; - case 'edit': - case 'update': - case 'delete': - case 'view details': - if (user_access('edit any election', $account)) { - return TRUE; - } - break; - case 'create': - // Creating must happen through the nomination form, not via entity_access. - return FALSE; - break; - } - if ($candidate === NULL || empty($candidate->uid) || $candidate->uid !== $account->uid) { - // This is not the account's nomination, and global checks have failed. - return FALSE; - } - // This is the $acccount's nomination. - switch ($op) { - case 'view': - case 'view details': - return TRUE; - break; - case 'edit': - case 'update': - return (bool) user_access('edit own nominations', $account); - break; - default: - return FALSE; - break; - } -} - -/** - * Implements hook_menu(). - */ -function election_candidate_menu() { - $items = array(); - - $items['admin/election/candidate'] = array( - 'title' => 'Candidate settings', - 'description' => 'Manage fields and display settings for election candidates (not applicable to referendums).', - 'title callback' => 'check_plain', - 'page callback' => 'system_admin_menu_block_page', - 'file' => 'system.admin.inc', - 'file path' => drupal_get_path('module', 'system'), - 'access arguments' => array('administer elections'), - ); - - $items['admin/election/candidate/settings'] = array( - 'title' => 'Settings', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => 0, - ); - - $items['election/%election/nomination-form'] = array( - 'title' => 'Nomination form', - 'page callback' => 'election_page_nomination_form', - 'page arguments' => array(1), - 'access callback' => 'election_access', - 'access arguments' => array('nomination', 1), - 'file' => 'election-candidate.pages.inc', - 'type' => MENU_LOCAL_TASK, - 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, - 'weight' => 2, - ); - - $items['election/%election/candidates'] = array( - 'title' => 'Candidates', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('election_candidate_list_form', 1), - 'access callback' => 'election_access', - 'access arguments' => array('edit candidates', 1), - 'file' => 'election-candidate.admin.inc', - 'type' => MENU_LOCAL_TASK, - 'weight' => 4, - 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, - ); - - $items['election/%election/candidates/list'] = array( - 'title' => 'List candidates', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => 0, - ); - - $items['election/%election/candidates/totals'] = array( - 'title' => 'View totals', - 'page callback' => 'election_candidate_totals_page', - 'page arguments' => array(1), - 'access callback' => 'election_access', - 'access arguments' => array('edit candidates', 1), - 'file' => 'election-candidate.admin.inc', - 'type' => MENU_LOCAL_TASK, - 'weight' => 1, - 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, - ); - - $items['election/%election/candidates/download'] = array( - 'title' => 'Download data', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('election_candidate_download_form', 1), - 'access callback' => 'election_access', - 'access arguments' => array('edit candidates', 1), - 'file' => 'election-candidate.admin.inc', - 'type' => MENU_LOCAL_TASK, - 'weight' => 2, - 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, - ); - - - $items['election/%election/candidate/%election_candidate'] = array( - 'title callback' => 'election_candidate_page_title', - 'title arguments' => array(1, 3), - 'page callback' => 'election_candidate_page_view', - 'page arguments' => array(1, 3), - 'file' => 'election-candidate.pages.inc', - 'access callback' => 'election_candidate_access', - 'access arguments' => array('view', 3), - 'type' => MENU_CALLBACK, - ); - - $items['election/%election/candidate/%election_candidate/view'] = array( - 'title' => 'View', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => 0, - ); - - $items['election/%election/candidate/%election_candidate/details'] = array( - 'title' => 'Details', - 'page callback' => 'election_candidate_details_page_view', - 'page arguments' => array(1, 3), - 'file' => 'election-candidate.pages.inc', - 'access callback' => 'election_candidate_access', - 'access arguments' => array('view details', 3), - 'type' => MENU_LOCAL_TASK, - 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, - 'weight' => 1, - ); - - $items['election/%election/candidate/%election_candidate/edit'] = array( - 'title' => 'Edit', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('election_candidate_edit_form', 1, 3), - 'file' => 'election-candidate.pages.inc', - 'access callback' => 'election_candidate_access', - 'access arguments' => array('update', 3), - 'type' => MENU_LOCAL_TASK, - 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, - 'weight' => 2, - ); - - $items['election/%election/candidate/%election_candidate/delete'] = array( - 'title' => 'Delete', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('election_candidate_edit_form_delete_confirm', 1, 3), - 'access callback' => 'election_candidate_access', - 'access arguments' => array('delete', 3), - 'file' => 'election-candidate.pages.inc', - 'weight' => 3, - 'type' => MENU_LOCAL_TASK, - 'context' => MENU_CONTEXT_INLINE, - ); - - return $items; -} - -/** - * Implements hook_menu_alter(). - */ -function election_candidate_menu_alter(&$items) { - unset($items['admin/election/candidate/settings']); - $items['admin/election/candidate/fields']['type'] = MENU_NORMAL_ITEM; - $items['admin/election/candidate/fields']['description'] = t('Manage fields for election candidates.'); - $items['admin/election/candidate/display']['type'] = MENU_NORMAL_ITEM; - $items['admin/election/candidate/display']['description'] = t('Manage display for election candidates.'); -} - -/** - * Implements hook_field_extra_fields(). - */ -function election_candidate_field_extra_fields() { - $extra = array(); - $extra['election_candidate']['election_candidate'] = array( - 'form' => array( - 'post' => array( - 'label' => t('Post'), - 'description' => t('The post for this nomination.'), - 'weight' => -1, - ), - 'first_name' => array( - 'label' => t('First name'), - 'description' => t('The candidate\'s first name(s).'), - 'weight' => 0, - ), - 'last_name' => array( - 'label' => t('Last name'), - 'description' => t('The candidate\'s last name(s).'), - 'weight' => 1, - ), - 'mail' => array( - 'label' => t('Email address'), - 'description' => t('The candidate\'s email address.'), - 'weight' => 2, - ), - 'phone' => array( - 'label' => t('Phone number'), - 'description' => t('The candidate\'s phone number.'), - 'weight' => 3, - ), - ), - 'display' => array( - 'election' => array( - 'label' => t('Election'), - 'description' => t('The election for this nomination.'), - 'weight' => 0, - ), - 'post' => array( - 'label' => t('Post'), - 'description' => t('The post/position for this nomination.'), - 'weight' => 1, - ), - 'full-name' => array( - 'label' => t('Name'), - 'description' => t('The candidate\'s name.'), - 'weight' => 2, - ), - ), - ); - return $extra; -} - - -/** - * Title callback for election/%election_candidate/view (output should not be escaped here - * as it is done later). - * - * @param stdClass $election - * @param stdClass $candidate - * - * @return string - */ -function election_candidate_page_title($election, $candidate) { - return $candidate->first_name . ' ' . $candidate->last_name; -} - -/** - * Wrapper function to allow saving an election candidate. - * - * @param stdClass $candidate - * Election candidate object. - * @return bool - */ -function election_candidate_save($candidate) { - return entity_get_controller('election_candidate')->save($candidate); -} - -/** - * Wrapper function to allow deleting multiple candidates. - * - * @param array $candidate_ids - * Array of candidate IDs. - * @return bool - */ -function election_candidate_delete_multiple(array $candidate_ids) { - return entity_get_controller('election_candidate')->delete($candidate_ids); -} - -/** - * Wrapper function to allow deleting an individual election. - * - * @see election_candidate_delete_multiple() - * - * @param mixed $candidate_id - * Single candidate ID. - * @return bool - */ -function election_candidate_delete($candidate_id) { - return election_candidate_delete_multiple(array($candidate_id)); -} - - -/* - * Find the nominations (election_candidate entities) for a specified election - * and user. - * - * @param stdClass $election - * Election object. - * @param stdClass $account - * Optional $user object. - * - * @return - * FALSE if the account is anonymous, or a SelectQuery object. - */ -function election_candidate_get_user_nominations(stdClass $election, $account = NULL) { - if ($account === NULL) { - global $user; - $account = $user; - } - if ($account->uid == 0) { - return array(); - } - $select = db_query( - 'SELECT ec.*, ep.title AS post_title, ep.exclusive FROM {election_candidate} ec LEFT JOIN {election_post} ep USING (post_id) WHERE ec.uid = :uid AND ep.election_id = :eid', - array( - ':eid' => $election->election_id, - ':uid' => $account->uid, - ) - ); - return $select->fetchAll(); -} - -/* - * Find the posts that a candidate may be nominated for. - * - * @param stdClass $election - * Election object. - * @param array $nominations - * Array of the user's previous nominations (election_candidate objects). - * @param stdClass $account - * User object. - * - * @return - * Array of post IDs. - */ -function election_candidate_get_available_posts(stdClass $election, $nominations = NULL, $account = NULL) { - if ($nominations === NULL) { - if ($account === NULL) { - global $user; - $account = $user; - } - $nominations = election_candidate_get_user_nominations($election, $account); - } - $has_exclusive = FALSE; - $prev_post_ids = array(); - foreach ($nominations as $nomination) { - if ($nomination->exclusive) { - $has_exclusive = TRUE; - } - $prev_post_ids[] = $nomination->post_id; - } - $select = db_select('election_post', 'ep')->fields('ep', array('post_id')); - $select->condition('election_id', $election->election_id, '='); - if ($prev_post_ids && !user_access('allow duplicate nominations')) { - $select->condition('post_id', $prev_post_ids, 'NOT IN'); - } - if ($has_exclusive && !user_access('bypass nomination exclusivity')) { - $select->condition('exclusive', 0, '='); - } - $select->orderBy('title'); - $result = $select->execute(); - return $result->fetchCol(); -} - -/** - * URI callback for a single election candidate. - * - * @return array - */ -function election_candidate_uri($candidate) { - $path = 'election-candidate/' . $candidate->candidate_id; - if (!empty($candidate->election_id)) { - $election = election_load($candidate->election_id); - $path = election_uri_path($election) . '/candidate/' . $candidate->candidate_id; - } - return array( - 'path' => $path, - ); -} - -/** - * Return the path part of the election candidate URI callback as a string. - * - * @return string. - */ -function election_candidate_uri_path($candidate) { - $uri = entity_uri('election_candidate', $candidate); - return $uri['path']; -} - -/** - * Label callback for an election_candidate, returning the candidate's name. - * - * @param stdClass $entity - * @param string $entity_type - * - * @return string - */ -function election_candidate_label(stdClass $entity, $entity_type) { - return $entity->first_name . ' ' . $entity->last_name; -} - -/** - * Load multiple candidates. - * - * @param mixed $candidate_ids - * An array of election candidate IDs. - * - * @return stdClass - * A stdClass election_candidate object. - */ -function election_candidate_load_multiple(array $candidate_ids = array()) { - return entity_load('election_candidate', $candidate_ids); -}