Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • project/election
  • issue/election-3249448
  • issue/election-3264848
  • issue/election-3019446
4 results
Show changes
Commits on Source (827)
Showing
with 1976 additions and 0 deletions
# Election
Election is a module for Drupal 7 providing online voting.
## Dependencies
* Entity API (http://drupal.org/project/entity)
* Views (http://drupal.org/project/views)
* Date (http://drupal.org/project/date)
* Libraries API (http://drupal.org/project/libraries)
## How to use this module
1. Enable at least one of the 'election type' modules (election_stv or
election_referendum), and all dependencies.
2. Visit /elections to view the list of elections. You can add/edit/delete
elections from here.
3. Visit /admin/people/permissions to configure permissions.
4. Visit /admin/config/election to configure fields and display settings.
There are several optional sub-modules you can also enable, providing further
functionality, including Election Condition, Election Statistics, Election
Results, and Election Export.
## Note on terminology
'Post' is a generic name for a single element of an election.
For referendums, the post is a *question*, e.g. "Should Britain join the Euro?",
which voters answer. For STV elections, the post is an electoral *position*
(for example, "Prime Minister"), for which candidates stand, and for which
voters cast ranked-choice votes.
Posts are Drupal entities, bundled by election type. For example, an STV
election position is an 'election_post' entity with the bundle name 'stv_post'.
## Copyright
Copyright 2012 UCLU (University College London Union)\
25 Gordon St, London WC1H 0AY\
http://uclu.org/
## Author
Patrick Dawkins (drupal.org username: pjcdawkins)
<?php
/**
* @file
* Administration page callbacks for the Election module.
*/
/**
* Page callback for editing an election, path: election/%election/edit.
*
* @param object $election
* The election object (loaded by the menu system).
*
* @return array
* Render array generated by Form API for the form: election_form.
*/
function election_page_edit($election) {
$type = _election_type_get_info($election->type);
$title = t(
'Edit @type: %title',
array(
'@type' => $type['name'],
'%title' => $election->title,
)
);
drupal_set_title($title, PASS_THROUGH);
election_set_breadcrumb($election);
module_load_include('inc', 'election', 'election.forms');
return drupal_get_form('election_form', $election);
}
/**
* Page callback for adding an election, path: elections/add/%type.
*
* @param string $type_machine_name
* The machine name of the election type (bundle key).
*
* @return array
* Render array generated by Form API for the form: election_form.
*/
function election_page_add($type_machine_name) {
if (!$type = _election_type_get_info($type_machine_name)) {
return MENU_NOT_FOUND;
}
$election = entity_get_controller('election')->create(array('type' => $type_machine_name));
drupal_set_title(
t('Add new @type', array('@type' => $type['name'])),
PASS_THROUGH
);
module_load_include('inc', 'election', 'election.forms');
return drupal_get_form('election_form', $election);
}
<?php
/**
* @file
* API documentation file.
*
* This file contains no working PHP code; it exists to provide additional
* documentation for doxygen as well as to document hooks in the standard
* Drupal manner.
*/
/**
* Defines election types.
*
* Default election types are provided by the election_stv and
* election_referendum sub-modules. Other types can be provided using this hook.
* Information about existing election types is loaded via the election_types()
* function.
*
* For working examples, see:
* election_types/referendum/election_referendum.election.inc
* election_types/stv/election_stv.election.inc
*
* @return array
* An array of election type arrays, keyed by a unique machine name. Election
* type arrays can include:
* - name: (Required) The human-readable name of the election type, sanitized.
* - description: A description of the election type, sanitized.
* - post name: The name of the election's posts, as a singular noun. See
* README.txt. The name for a referendum's posts may be 'question', while
* another election's posts may be referred to as 'role', 'position', or
* 'title', perhaps.
* - post name plural: The plural version of the post name (default: post name
* + s).
* - has candidates: Whether the election type has candidates. Modules
* providing elections that have candidates should depend on the
* election_candidate submodule.
* - vote form: The name of a callback altering the voting form. This option
* is provided as a more convenient alternative to hook_form_FORM_ID_alter()
* to avoid complications with confirm form logic.
* The function takes the parameters:
* array $form - The form array from election_vote_form().
* array $form_state - The form_state array from election_vote_form().
* - export: Whether the election results can be exported as an archive of
* ballot (.blt) files. This needs the election_export submodule.
*
* @see election_types()
*/
function hook_election_type_info() {
return array(
'fptp' => array(
'name' => t('FPTP election'),
'description' => t('A first-past-the-post election type, where voters can select a single candidate who wins based on a simple majority with a quorum.'),
'post name' => t('position'),
'has candidates' => TRUE,
'export' => TRUE,
'vote form' => 'election_fptp_vote_form',
),
);
}
/**
* Alter existing election types.
*
* @param array $types
* An array of election types.
*
* @see hook_election_type_info()
*/
function hook_election_type_info_alter(array &$types) {
// Example: alter the referendum election type to enable exporting.
if (isset($types['referendum'])) {
$types['referendum']['export'] = TRUE;
}
}
/**
* Runs when nominations opens.
*
* For scheduled changes, this hook will run only if election_cron module is
* enabled. It will run the next time cron runs after the scheduled time.
*
* @param int $election_id
* The election ID.
* @param bool $scheduled
* TRUE if a scheduled change, FALSE if manual.
*/
function hook_election_nominations_open($election_id, $scheduled) {
watchdog('election', 'Nominations opened @how for @type %title (@id).', array(
'@how' => $scheduled ? 'by schedule' : 'manually',
'@type' => $election->type_info['name'],
'%title' => $election->title,
'@id' => $election->election_id,
));
}
/**
* Runs when nominations closes.
*
* For scheduled changes, this hook will run only if election_cron module is
* enabled. It will run the next time cron runs after the scheduled time.
*
* @param int $election_id
* The election ID.
* @param bool $scheduled
* TRUE if a scheduled change, FALSE if manual.
*/
function hook_election_nominations_close($election_id, $scheduled) {
watchdog('election', 'Nominations closed @how for @type %title (@id).', array(
'@how' => $scheduled ? 'by schedule' : 'manually',
'@type' => $election->type_info['name'],
'%title' => $election->title,
'@id' => $election->election_id,
));
}
/**
* Runs when voting opens.
*
* For scheduled changes, this hook will run only if election_cron module is
* enabled. It will run the next time cron runs after the scheduled time.
*
* @param int $election_id
* The election ID.
* @param bool $scheduled
* TRUE if a scheduled change, FALSE if manual.
*/
function hook_election_voting_open($election_id, $scheduled) {
watchdog('election', 'Voting opened @how for @type %title (@id).', array(
'@how' => $scheduled ? 'by schedule' : 'manually',
'@type' => $election->type_info['name'],
'%title' => $election->title,
'@id' => $election->election_id,
));
}
/**
* Runs when voting closes.
*
* For scheduled changes, this hook will run only if election_cron module is
* enabled. It will run the next time cron runs after the scheduled time.
*
* @param int $election_id
* The election ID.
* @param bool $scheduled
* TRUE if a scheduled change, FALSE if manual.
*/
function hook_election_voting_close($election_id, $scheduled) {
watchdog('election', 'Voting closed @how for @type %title (@id).', array(
'@how' => $scheduled ? 'by schedule' : 'manually',
'@type' => $election->type_info['name'],
'%title' => $election->title,
'@id' => $election->election_id,
));
}
/**
* @file
* CSS for the Election module.
*/
/* Unpublished elections, posts, and candidates */
.election-unpublished.election-teaser,
.election-post-unpublished.election-post-teaser,
.election-candidate-unpublished.election-candidate-teaser {
background-color: #fff4f4;
}
/* Election statuses */
.election-status-open {
color: #347235;
font-weight: bold;
}
.election-status-closed {
color: #880000;
}
.election-status-future {
color: inherit;
font-weight: inherit;
}
/* Candidate statuses */
.election-candidate-status-elected {
color: #347235;
}
/* Ballot paper */
#election-vote-form #edit-clear-form {
float: right;
}
.election-ballot-row td {
padding: 10px;
}
.election-ballot-item {
font-size: 1.1em;
}
.election-ballot-row .form-item {
margin: 0;
padding: 0;
}
/* Candidate views */
.view-election-candidates h3 {
margin-top: 1em;
}
.election-candidate-row {
margin: 1em;
}
.election-candidate-name {
font-size: 1.1em;
}
.election-candidate-random-order-note {
font-style: oblique;
}
/* Manage Candidates view */
.view-election-candidates-admin .views-field-title,
.view-election-candidates-admin .views-field-candidate-name {
overflow: hidden;
max-width: 20em;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Titles of embedded lists of posts and candidates */
.election-posts > h2,
.election-post-candidates > h2 {
clear: both;
margin-bottom: 0.5em;
margin-top: 1em;
}
/* Item of information */
.election-info {
margin-bottom: 0.5em;
margin-top: 0.5em;
}
.election-info .label {
font-weight: bold;
}
/* Teasers */
.election-teaser,
.election-post-teaser,
.election-candidate-teaser {
padding-left: 15px;
}
.election-teaser h2,
.election-post-teaser h2,
.election-candidate-teaser h2 {
margin-left: -15px;
}
/* Election vote button */
.election-post {
position: relative;
}
.election-vote-button {
position: absolute;
right: 0;
top: 1em;
}
.election-vote-button a {
background-color: #fee94f;
border: 1px solid #ffaa22;
border-radius: 5px;
font-family: sans-serif;
font-size: 1.3em;
padding: 0.5em 0.8em;
text-decoration: none;
}
.election-vote-button a:link,
.election-vote-button a:visited {
color: #333333;
}
.election-vote-button a:hover,
.election-vote-button a:active,
.election-vote-button a:focus {
color: #000000;
}
.election-vote-button a:active {
position: relative;
top: 1px;
left: 1px;
}
.election-post-teaser .election-vote-button a {
font-size: 1em;
padding: 0.3em 0.5em;
}
/* Leave room for button next to post title. */
.election-post > h3 {
margin-right: 3em;
}
/* Election vote access explanation */
.election-vote-access-passed {
color: #347235;
}
.election-vote-access-failed {
color: #880000;
}
/* Election vote display filter (allowing to hide ineligible posts) */
.election-vote-filter-posts a {
cursor: pointer;
}
.election-vote-filter-posts a.active {
color: inherit;
cursor: auto;
}
/* Statistics */
.election-statistics-user-agents .user-agent {
overflow: hidden;
max-width: 20em;
text-overflow: ellipsis;
white-space: nowrap;
}
<?php
/**
* @file
* Form functions for the Election module.
*/
/**
* Form builder function for adding or editing an election.
*/
function election_form($form, &$form_state, stdClass $election) {
$form['#id'] = 'election-form';
$form['#election'] = $election;
$form_state['election'] = $election;
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#maxlength' => 255,
'#default_value' => isset($election->title) ? $election->title : '',
'#required' => TRUE,
);
$date_format = variable_get('date_format_short', 'Y-m-d H:i');
if (module_exists('date_popup')) {
$date_widget = 'date_popup';
}
else {
$date_widget = 'date_text';
}
if (!isset($election->type_info)) {
$election->type_info = _election_type_get_info($election->type);
}
if (!empty($election->type_info['has candidates'])) {
$form['nominations'] = array(
'#type' => 'fieldset',
'#title' => t('Nominations'),
'#collapsible' => TRUE,
);
$nopen_default = isset($election->nopen_time) ? $election->nopen_time : NULL;
$nclose_default = isset($election->nclose_time) ? $election->nclose_time : NULL;
$form['nominations']['nstatus'] = array(
'#type' => 'select',
'#title' => t('Nominations status'),
'#default_value' => isset($election->nstatus) ? $election->nstatus : ELECTION_STATUS_CLOSED,
'#options' => election_status_options(),
);
$form['nominations']['nschedule'] = array(
'#title' => t('Nominations schedule'),
'#type' => 'fieldset',
'#description' => t('Set the opening and closing times for nominations.'),
'#states' => array(
'visible' => array(
':input[name=nstatus]' => array('value' => (string) ELECTION_STATUS_SCHEDULED),
),
),
);
$form['nominations']['nschedule']['nopen_time'] = array(
'#title' => t('Opening time'),
'#type' => $date_widget,
'#default_value' => $nopen_default ? date('Y-m-d H:i:s', $nopen_default) : NULL,
'#date_format' => $date_format,
'#date_year_range' => '-2:+5',
);
$form['nominations']['nschedule']['nclose_time'] = array(
'#title' => t('Closing time'),
'#type' => $date_widget,
'#default_value' => $nclose_default ? date('Y-m-d H:i:s', $nclose_default) : NULL,
'#date_format' => $date_format,
'#date_year_range' => '-2:+5',
);
}
$vopen_default = isset($election->vopen_time) ? $election->vopen_time : NULL;
$vclose_default = isset($election->vclose_time) ? $election->vclose_time : NULL;
$form['voting'] = array(
'#type' => 'fieldset',
'#title' => t('Voting'),
'#collapsible' => TRUE,
);
$form['voting']['vstatus'] = array(
'#type' => 'select',
'#title' => t('Voting status'),
'#default_value' => isset($election->vstatus) ? $election->vstatus : ELECTION_STATUS_CLOSED,
'#options' => election_status_options(),
);
$messages = _election_check_election_readiness($election);
if ($messages) {
$form['voting']['vstatus']['#description'] = '<div class="messages warning">' . theme('item_list', array('items' => $messages)) . '</div>';
}
$form['voting']['vschedule'] = array(
'#title' => t('Voting schedule'),
'#type' => 'fieldset',
'#description' => t('Set the opening and closing times for voting.'),
'#states' => array(
'visible' => array(
':input[name=vstatus]' => array('value' => (string) ELECTION_STATUS_SCHEDULED),
),
),
);
if (!empty($election->type_info['may anonymize'])) {
$form['voting']['settings_anonymize'] = array(
'#type' => 'checkbox',
'#title' => t('Anonymize voting (extra secret mode)'),
'#description' => t('If enabled, votes will be completely anonymized in the database. The undo and export features will not be available.'),
'#default_value' => !empty($election->settings['anonymize']),
);
}
$form['voting']['vschedule']['vopen_time'] = array(
'#title' => t('Opening time'),
'#type' => $date_widget,
'#default_value' => $vopen_default ? date('Y-m-d H:i:s', $vopen_default) : NULL,
'#date_format' => $date_format,
'#date_year_range' => '-2:+5',
);
$form['voting']['vschedule']['vclose_time'] = array(
'#title' => t('Closing time'),
'#type' => $date_widget,
'#default_value' => $vclose_default ? date('Y-m-d H:i:s', $vclose_default) : NULL,
'#date_format' => $date_format,
'#date_year_range' => '-2:+5',
);
$form['published'] = array(
'#type' => 'checkbox',
'#title' => t('Published'),
'#default_value' => isset($election->published) ? $election->published : 0,
'#weight' => 99,
'#description' => t("This allows those with the '!perm' permission to view the election.", array(
'!perm' => t('View published elections'),
)),
);
$form['buttons'] = array(
'#type' => 'actions',
'#weight' => 100,
);
$form['buttons']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#submit' => array('election_form_submit'),
);
if (!empty($election->election_id)) {
$form['buttons']['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
'#submit' => array('election_form_delete_submit'),
'#access' => entity_access('delete', 'election', $election),
);
}
$cancel_path = empty($election->election_id) ? 'elections' : election_uri_path($election);
if (!empty($_GET['destination'])) {
$options = drupal_parse_url($_GET['destination']);
$cancel_path = $options['path'];
}
$form['buttons']['cancel'] = array(
'#type' => 'link',
'#title' => t('Cancel'),
'#href' => $cancel_path,
);
form_load_include($form_state, 'inc', 'election', 'election.forms');
$form['#validate'][] = 'election_form_validate';
// Add custom fields from the Field system.
field_attach_form('election', $election, $form, $form_state);
return $form;
}
/**
* Checks if a vote is ready to be published.
*
* @param object $election
* The election object.
*
* @return array
* An array of error messages. Empty array means the vote is ready.
*/
function _election_check_election_readiness(stdClass $election) {
$messages = array();
// Election is published.
if (empty($election->published)) {
$args = array(
'@type' => $election->type_info['name'],
);
$messages[] = t('This @type is not published.', $args);
}
// Other checks are not possible before the election has an election_id.
if (!$election->election_id) {
return $messages;
}
// Election posts are published.
$query = 'SELECT TRUE
FROM {election_post}
WHERE election_id = :election_id
AND published = 0';
$args = array('election_id' => $election->election_id);
$results = db_query($query, $args);
if ($results->fetchField()) {
$args = array(
'@type' => $election->type_info['name'],
'@url' => url('election/' . $election->election_id . '/posts-admin', array('query' => array('published' => 0))),
'@post_type' => $election->type_info['post name'],
);
$messages[] = t('This @type contains <a href="@url">at least one @post_type</a> that is not published.', $args);
}
if (!empty($election->type_info['has candidates'])) {
// Candidates are published.
$query = 'SELECT TRUE
FROM {election_post} ep
JOIN {election_candidate} ec USING (post_id)
WHERE ep.election_id = :election_id
AND ec.published = 0';
$args = array('election_id' => $election->election_id);
$results = db_query($query, $args);
if ($results->fetchField()) {
$args = array(
'@type' => $election->type_info['name'],
'@url' => url('election/' . $election->election_id . '/candidates-admin', array('query' => array('published' => 0))),
);
$messages[] = t('This @type contains <a href="@url">at least one candidate</a> that is not published.', $args);
}
// Posts have enough candidates.
$query = 'SELECT * FROM (
SELECT post_id, title, vacancy_count, count(candidate_id) AS count
FROM {election_post} ep
LEFT JOIN {election_candidate} ec USING (post_id)
WHERE ep.election_id = :election_id
GROUP BY post_id, title, vacancy_count
) sub
WHERE count <= vacancy_count';
$args = array('election_id' => $election->election_id);
$results = db_query($query, $args)->fetchAll();
if ($results) {
// Link to all posts without enough candidates.
$posts = array();
foreach ($results as $post) {
$posts[] = l($post->title, 'election-post/' . $post->post_id);
}
$args = array(
'@type' => $election->type_info['name'],
'@post_type' => $election->type_info['post name'],
);
$messages[] = array(
'data' => format_plural(count($posts), 'This @type contains a @post_type without enough candidates:', 'This @type contains more than one @post_type without enough candidates:', $args),
'children' => $posts,
);
}
}
return $messages;
}
/**
* Form validate function for the form election_form.
*/
function election_form_validate($form, &$form_state) {
// VALIDATE VOTING SCHEDULE...
$vstatus = $form_state['values']['vstatus'];
$vopen_time = _election_normalize_datetime($form_state['values']['vopen_time']);
$vclose_time = _election_normalize_datetime($form_state['values']['vclose_time']);
// Check that the opening and closing times are set if voting is scheduled.
if ($vstatus == ELECTION_STATUS_SCHEDULED
&& (empty($vopen_time) || empty($vclose_time))) {
form_set_error('vschedule', t('You must set the opening and closing times when the voting status is Scheduled.'));
}
// Check that the closing time is after the opening time.
elseif ($vstatus == ELECTION_STATUS_SCHEDULED
&& $vclose_time <= $vopen_time) {
form_set_error('vschedule', t('The closing time of voting must be after the opening time.'));
}
// VALIDATE NOMINATIONS SCHEDULE...
if (isset($form_state['values']['nstatus'])) {
$nstatus = $form_state['values']['nstatus'];
$nopen_time = _election_normalize_datetime($form_state['values']['nopen_time']);
$nclose_time = _election_normalize_datetime($form_state['values']['nclose_time']);
// Check that nominations and voting are not open at the same time.
if ($nstatus == ELECTION_STATUS_OPEN && $vstatus == ELECTION_STATUS_OPEN) {
form_set_error('vstatus', t('Voting should not be open at the same time as nominations.'));
}
// Check that the opening and closing times are set, if relevant.
elseif ($nstatus == ELECTION_STATUS_SCHEDULED
&& (empty($nopen_time) || empty($nclose_time))) {
form_set_error('nschedule', t('You must set the opening and closing times when the nominations status is Scheduled.'));
}
// Check that the closing time is after the opening time.
elseif ($nstatus == ELECTION_STATUS_SCHEDULED
&& $nclose_time <= $nopen_time) {
form_set_error('nschedule', t('The closing time of nominations must be after the opening time.'));
}
// Check that the voting time is after the nominations close.
elseif ($vstatus == ELECTION_STATUS_SCHEDULED
&& $vopen_time < $nclose_time) {
form_set_error('nschedule', t('Nominations can only be scheduled so that they close before the start of voting.'));
}
}
// For dates that have changed, display a warning for dates in the past.
foreach (array('n' => 'nominations', 'v' => 'voting') as $key => $value) {
foreach (array('open', 'close') as $open_close) {
if (isset($form_state['values'][$key . $open_close . '_time'])) {
$time_old = _election_normalize_datetime($form[$value][$key . 'schedule'][$key . $open_close . '_time']['#default_value']);
$time_new = _election_normalize_datetime($form_state['values'][$key . $open_close . '_time']);
if (is_int($time_new) && $time_old !== $time_new && $time_new < REQUEST_TIME) {
$message = t('@what @which is in the past.', array(
'@what' => $form[$value][$key . 'schedule']['#title'],
'@which' => $form[$value][$key . 'schedule'][$key . $open_close . '_time']['#title'],
));
drupal_set_message($message, 'warning');
}
}
}
}
// Check other Fields.
field_attach_form_validate('election', $form_state['election'], $form, $form_state);
}
/**
* Form submit function for the Save button in the form election_form.
*/
function election_form_submit($form, &$form_state) {
global $user;
$election = &$form_state['election'];
if (empty($election->uid)) {
$election->uid = $user->uid;
}
foreach ($form_state['values'] as $property => $value) {
if (substr($property, 0, 9) == 'settings_') {
$key = substr($property, 9);
$election->settings[$key] = $value;
}
}
foreach ($election as $property => $value) {
if (isset($form_state['values'][$property])) {
$election->$property = $form_state['values'][$property];
}
}
field_attach_submit('election', $election, $form, $form_state);
// Save the election.
election_save($election);
// Notify the user that the election was saved.
$type = _election_type_get_info($election->type);
drupal_set_message(
t('The @type %title was saved.', array('@type' => $type['name'], '%title' => $election->title))
);
if (empty($_GET['destination'])) {
$form_state['redirect'] = election_uri_path($election);
}
}
/**
* Form submit function for the Delete button in the form election_form.
*/
function election_form_delete_submit($form, &$form_state) {
$destination = array();
if (isset($_GET['destination'])) {
$destination = drupal_get_destination();
unset($_GET['destination']);
}
$election = $form['#election'];
$form_state['redirect'] = array(
election_uri_path($election) . '/delete',
array('query' => $destination),
);
}
/**
* Form builder function to confirm the delete action for an election.
*
* @see confirm_form()
*/
function election_form_delete_confirm($form, &$form_state, stdClass $election) {
election_set_breadcrumb($election);
$form['#election'] = $election;
$form['election_id'] = array(
'#type' => 'value',
'#value' => $election->election_id,
);
return confirm_form(
$form,
t('Are you sure you want to delete %title?', array('%title' => $election->title)),
election_uri_path($election),
t('Deleting an election also deletes ALL associated data, for example votes. This action cannot be undone.'),
t('Delete'),
t('Cancel')
);
}
/**
* Submit callback, called after confirming delete for an election.
*/
function election_form_delete_confirm_submit($form, &$form_state) {
if ($form_state['values']['confirm']) {
$election = election_load($form_state['values']['election_id']);
election_delete($form_state['values']['election_id']);
watchdog('election', 'Deleted election "%title" (type: @type)', array('@type' => $election->type, '%title' => $election->title));
$type = _election_type_get_info($election->type);
drupal_set_message(
t('The @type %title has been deleted.', array('@type' => $type['name'], '%title' => $election->title))
);
}
if (empty($_GET['destination'])) {
$form_state['redirect'] = 'elections';
}
}
name = Election
description = Provides online voting.
core = 7.x
package = Election
dependencies[] = entity
dependencies[] = views
dependencies[] = date
stylesheets[all][] = election.css
files[] = includes/election-default.controller.inc
files[] = includes/election.controller.inc
files[] = views/handlers/election_views_handler_field_link.inc
files[] = views/handlers/election_views_handler_field_link_delete.inc
files[] = views/handlers/election_views_handler_field_link_edit.inc
files[] = views/handlers/election_views_handler_filter_published.inc
files[] = tests/ElectionCandidateAccessTestCase.test
files[] = tests/ElectionCandidateCrudTestCase.test
files[] = tests/ElectionCandidateNominationAccessTestCase.test
files[] = tests/ElectionCandidateTokenTestCase.test
files[] = tests/ElectionCandidateTypeCrudTestCase.test
files[] = tests/ElectionCandidateViewAccessTestCase.test
files[] = tests/ElectionCrudTestCase.test
files[] = tests/ElectionPostAccessTestCase.test
files[] = tests/ElectionPostCrudTestCase.test
files[] = tests/ElectionPostViewAccessTestCase.test
files[] = tests/ElectionUnitTestCase.test
files[] = tests/ElectionVoteAccessByRoleTestCase.test
files[] = tests/ElectionVoteAccessCandidatesTestCase.test
files[] = tests/ElectionVoteAccessPreventDuplicateTestCase.test
files[] = tests/ElectionWebTestCase.test
configure = admin/config/election
<?php
/**
* @file
* Entity property information for the Election module.
*/
/**
* Implements hook_entity_property_info().
*/
function election_entity_property_info() {
$info = array();
// Add metadata about election properties.
$properties = &$info['election']['properties'];
$properties = array(
'election_id' => array(
'label' => t('Election ID'),
'description' => t('Primary key: the unique identifier for an election.'),
'type' => 'integer',
'schema field' => 'election_id',
),
'type' => array(
'label' => t('Type'),
'type' => 'token',
'description' => t('The election type.'),
'required' => TRUE,
'schema field' => 'type',
'options list' => '_election_get_type_options',
'setter callback' => 'entity_property_verbatim_set',
),
'uid' => array(
'label' => t('Owner'),
'description' => t('The user who created or who owns the election.'),
'type' => 'user',
'schema field' => 'uid',
),
'published' => array(
'label' => t('Published status'),
'description' => t('Whether or not the election is published.'),
'type' => 'boolean',
'options list' => '_election_get_published_options',
'schema field' => 'published',
'required' => TRUE,
),
'title' => array(
'label' => t('Title'),
'description' => t('The title of the election.'),
'type' => 'text',
'schema field' => 'title',
'required' => TRUE,
'setter callback' => 'entity_property_verbatim_set',
),
'vstatus' => array(
'label' => t('Voting status'),
'description' => t('The voting status of the election.'),
'type' => 'integer',
'schema field' => 'vstatus',
'required' => TRUE,
'setter callback' => 'entity_property_verbatim_set',
),
'vopen_time' => array(
'label' => t('Voting open time'),
'description' => t('The date and time when voting opens.'),
'type' => 'date',
'schema field' => 'vopen_time',
'setter callback' => 'entity_property_verbatim_set',
),
'vclose_time' => array(
'label' => t('Voting closing time'),
'description' => t('The date and time when voting closes.'),
'type' => 'date',
'schema field' => 'vclose_time',
'setter callback' => 'entity_property_verbatim_set',
),
'nstatus' => array(
'label' => t('Nominations status'),
'description' => t('The nominations status of the election.'),
'type' => 'integer',
'schema field' => 'nstatus',
'required' => TRUE,
'setter callback' => 'entity_property_verbatim_set',
),
'nopen_time' => array(
'label' => t('Nominations open time'),
'description' => t('The date and time when nominations open.'),
'type' => 'date',
'schema field' => 'nopen_time',
'setter callback' => 'entity_property_verbatim_set',
),
'nclose_time' => array(
'label' => t('Nominations closing time'),
'description' => t('The date and time when nominations close.'),
'type' => 'date',
'schema field' => 'nclose_time',
'setter callback' => 'entity_property_verbatim_set',
),
'created' => array(
'label' => t('Created date'),
'description' => t('The date when the election was created.'),
'type' => 'date',
'schema field' => 'created',
'setter callback' => 'entity_property_verbatim_set',
),
'changed' => array(
'label' => t('Last modified date'),
'description' => t('The date when the election settings were last updated.'),
'type' => 'date',
'schema field' => 'changed',
'setter callback' => 'entity_property_verbatim_set',
),
);
return $info;
}
<?php
/**
* @file
* Install functions for the Election module.
*/
require_once 'includes/election.constants.inc';
/**
* Implements hook_schema().
*/
function election_schema() {
$schema = array();
$schema['election'] = array(
'description' => 'The main table for the election module.',
'fields' => array(
'election_id' => array(
'description' => 'Primary key: identifier for an election.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
'type' => array(
'description' => 'The type of the election (machine name).',
'type' => 'varchar',
'length' => 100,
'not null' => TRUE,
),
'title' => array(
'description' => 'The title of the election - a human-readable identifier.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
),
'uid' => array(
'description' => 'The {users}.uid of the election\'s owner/creator. NULL means the user has been deleted.',
'type' => 'int',
'unsigned' => TRUE,
),
'published' => array(
'description' => 'Allows view access to all those with the "view published elections" permission.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
),
'vstatus' => array(
'description' => sprintf(
'The voting status: open %d, closed %d, or scheduled %d.',
ELECTION_STATUS_OPEN,
ELECTION_STATUS_CLOSED,
ELECTION_STATUS_SCHEDULED
),
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => ELECTION_STATUS_CLOSED,
),
'vopen_time' => array(
'description' => 'The Unix timestamp for when voting opens (if scheduled). NULL means it is not scheduled.',
'type' => 'int',
),
'vclose_time' => array(
'description' => 'The Unix timestamp for when voting closes (if scheduled). NULL means it is not scheduled.',
'type' => 'int',
),
'nstatus' => array(
'description' => sprintf(
'The nominations status: open %d, closed %d, or scheduled %d.',
ELECTION_STATUS_OPEN,
ELECTION_STATUS_CLOSED,
ELECTION_STATUS_SCHEDULED
),
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => ELECTION_STATUS_CLOSED,
),
'nopen_time' => array(
'description' => 'The Unix timestamp for when nominations open (if scheduled). NULL means it is not scheduled.',
'type' => 'int',
),
'nclose_time' => array(
'description' => 'The Unix timestamp for when nominations close (if scheduled). NULL means it is not scheduled.',
'type' => 'int',
),
'settings' => array(
'description' => 'A serialized array of any further settings for this election. NULL means there are no further settings.',
'type' => 'blob',
'size' => 'normal',
'serialize' => TRUE,
),
'created' => array(
'description' => 'The Unix timestamp for when the election was created.',
'type' => 'int',
'not null' => TRUE,
),
'changed' => array(
'description' => 'The Unix timestamp for when the election was most recently changed.',
'type' => 'int',
'not null' => TRUE,
),
),
'primary key' => array('election_id'),
'indexes' => array(
'type' => array('type'),
'uid' => array('uid'),
'published' => array('published'),
'vstatus' => array('vstatus'),
'nstatus' => array('nstatus'),
'vperiod' => array('vopen_time', 'vclose_time'),
'nperiod' => array('nopen_time', 'nclose_time'),
'created' => array('created'),
'title' => array('title'),
),
);
return $schema;
}
/**
* Implements hook_uninstall().
*/
function election_uninstall() {
drupal_load('module', 'election');
foreach (array_keys(election_types()) as $bundle) {
field_attach_delete_bundle('election', $bundle);
}
}
/**
* Add the 'published' column to the election table.
*/
function election_update_7101() {
db_add_field('election', 'published', array(
'description' => 'Allows view access to all those with the "view published elections" permission.',
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
));
db_add_index('election', 'published', array('published'));
// Publish all existing elections (they used to be published anyway).
db_update('election')
->fields(array('published' => 1))
->execute();
// Rename 'view any election' permission to 'view published elections'.
db_update('role_permission')
->fields(array('permission' => 'view published elections'))
->condition('permission', 'view any election')
->execute();
}
/**
* Update existing posts with new bundle names.
*/
function election_update_7102() {
drupal_static_reset('election_types');
foreach (election_types() as $type_machine_name => $type) {
$post_ids = db_query('SELECT post_id FROM {election_post} ep LEFT JOIN {election} e USING (election_id) WHERE e.type = :type', array(':type' => $type_machine_name))->fetchCol();
if (!empty($post_ids)) {
db_update('election_post')
->fields(array('type' => $type['post machine name']))
->condition('post_id', $post_ids, 'IN')
->execute();
}
}
}
/**
* Rename election_post bundles for default election types.
*/
function election_update_7103() {
field_attach_rename_bundle('election_post', 'motion', 'referendum_post');
field_attach_rename_bundle('election_post', 'position', 'stv_post');
}
/**
* Add 'settings' field.
*/
function election_update_7104() {
if (db_field_exists('election', 'settings')) {
return;
}
db_add_field('election', 'settings', array(
'description' => 'A serialized array of any further settings for this election.',
'type' => 'blob',
'size' => 'normal',
'serialize' => TRUE,
));
}
/**
* Rebuild the registry to account for moved classes.
*/
function election_update_7105() {
registry_rebuild();
}
/**
* Make certain columns NOT NULL.
*/
function election_update_7106() {
db_drop_index('election', 'title');
db_change_field('election', 'title', 'title', array(
'description' => 'The title of the election - a human-readable identifier.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
), array('indexes' => array('title' => array('title'))));
db_change_field('election', 'changed', 'changed', array(
'description' => 'The Unix timestamp for when the election was most recently changed.',
'type' => 'int',
'not null' => TRUE,
));
}
/**
* Remove unneccessary default values from database schema.
*/
function election_update_7107() {
db_drop_index('election', 'created');
db_change_field('election', 'created', 'created', array(
'description' => 'The Unix timestamp for when the election was created.',
'type' => 'int',
'not null' => TRUE,
), array('indexes' => array('created' => array('created'))));
}
<?php
/**
* @file
* Provides the Election rule plugin for the Menu Position module.
*/
/**
* Checks if the election is of a certain type.
*
* @param array $variables
* An array containing each of the variables saved in the database necessary
* to evaluate this condition of the rule.
*
* @return bool
* TRUE if condition applies successfully. Otherwise FALSE.
*/
function election_menu_position_condition_election(array $variables) {
$args = arg();
if ($args[0] == 'election' && !empty($args[1]) && is_numeric($args[1])) {
$election = election_load($args[1]);
$type = $election->type;
}
if (empty($election)) {
return FALSE;
}
return (in_array($type, $variables['election_type']));
}
/**
* Adds form elements for the "election" plugin to the rule configuration form.
*
* @param array $form
* A reference to the "add/edit rule" form array. New form elements should be
* added directly to this array.
* @param array $form_state
* A reference to the current form state.
*/
function election_menu_position_rule_election_form(array &$form, array &$form_state) {
$variables = array();
$form['conditions']['election'] = array(
'#type' => 'fieldset',
'#title' => t('Elections'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$type_options = array();
$types = election_types();
foreach ($types as $type_machine_name => $type) {
$type_options[$type_machine_name] = drupal_ucfirst($type['name']);
}
$form['conditions']['election']['election_type'] = array(
'#type' => 'checkboxes',
'#title' => t('Election types'),
'#default_value' => !empty($variables['election_type']) ? $variables['election_type'] : array(),
'#options' => $type_options,
'#description' => t('Apply this rule only for elections of the given type(s).'),
'#weight' => -20,
);
// Add a submit handler.
$form['#submit'][] = 'election_menu_position_rule_election_form_submit';
}
/**
* Prepares the "election_type" variables to be stored in the rule.
*
* @param array $form
* A reference to the "add/edit rule" form array.
* @param array $form_state
* A reference to the current form state, including submitted values.
*/
function election_menu_position_rule_election_form_submit(array &$form, array &$form_state) {
// The user has added our plugin's form elements as a condition for the rule.
if (!empty($form_state['values']['election_type'])) {
// Remove any 0 valued options.
foreach ($form_state['values']['election_type'] as $key => $value) {
if ($value === 0) {
unset($form_state['values']['election_type'][$key]);
}
}
// Determine if any checkboxes were on.
if (!empty($form_state['values']['election_type'])) {
// Add this plugin's variables to the rule.
$variables = array(
'election_type' => $form_state['values']['election_type'],
);
$form_state['values']['conditions']['election'] = $variables;
}
}
}
This diff is collapsed.
<?php
/**
* @file
* Menu callbacks for the Election module.
*/
/**
* Page callback for listing elections.
*/
function election_page_list() {
drupal_set_title(t('Elections'), PASS_THROUGH);
// If the user is a site administrator, and there are no election type modules
// enabled, prompt them to enable at least one.
if (user_access('create elections') && user_access('administer modules')) {
$types = election_types();
if (!count($types)) {
drupal_set_message(t("You need to enable an 'election type' module (see !Modules) in order to add elections.", array(
'!Modules' => l(t('Modules'), 'admin/modules', array('fragment' => 'election_types')),
)), 'warning');
}
}
// Embed the View that lists elections.
$view = views_get_view('elections');
$view->override_path = current_path();
return $view->preview('embed');
}
<?php
/**
* @file
* Pathauto hooks for the Election module.
*/
/**
* Implements hook_pathauto().
*/
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 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.pathauto.inc';
foreach (election_types() as $type_machine_name => $type) {
$settings['patternitems'][$type_machine_name] = t('Pattern for all %type paths', array('%type' => $type['name']));
}
return (object) $settings;
}
}
/**
* Allow bulk updating of paths. See the Pathauto module.
*
* @param array $context
* The Batch API context array.
*
* @see election_pathauto()
*/
function election_pathauto_bulk_update_batch_process(array &$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();
_election_pathauto_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().
*
* Used primarily by the bulk delete form.
*/
function election_path_alias_types() {
$objects = array(
'election/' => t('Elections'),
);
return $objects;
}
<?php
/**
* @file
* Theme and preprocess functions for the Election module.
*/
/**
* Theme function for displaying a piece of information which isn't a field.
*/
function theme_election_info_item($variables) {
$label = $variables['label'];
$value = $variables['value'];
$html = $variables['html'];
$classes = $variables['classes'];
$children = $variables['children'] ? $variables['children'] : array();
$classes[] = 'election-info';
if (!empty($label)) {
$classes[] = drupal_html_class('election-info-' . $label);
}
$content = '';
if ($label) {
$content .= '<span class="label">' . check_plain($label) . ':</span> ';
}
$content .= '<span class="value">'
. ($html ? $value : check_plain($value))
. drupal_render_children($children)
. '</span>';
$container = array(
'#theme' => 'container',
'#children' => $content,
'#attributes' => array('class' => $classes),
);
return drupal_render($container);
}
/**
* Determine the election's status, for theme_election_status().
*/
function template_preprocess_election_status(&$variables) {
$election = $variables['election'];
$status_prefix = $variables['status_prefix'];
$short = $variables['short'];
$status = $election->{$status_prefix . 'status'};
$open_time = $election->{$status_prefix . 'open_time'};
$close_time = $election->{$status_prefix . 'close_time'};
// Provide Boolean variables for open, scheduled and future.
$variables['open'] = _election_is_open($status, $open_time, $close_time);
$variables['scheduled'] = ($status == ELECTION_STATUS_SCHEDULED);
$variables['future'] = (REQUEST_TIME < $open_time);
$variables['past'] = (REQUEST_TIME > $close_time);
// Provide an array of CSS classes.
$classes = array();
if ($variables['open']) {
$classes['open'] = 'election-status-open';
}
else {
$classes['closed'] = 'election-status-closed';
}
if ($variables['scheduled']) {
$classes['scheduled'] = 'election-status-scheduled';
if ($variables['future']) {
$classes['future'] = 'election-status-future';
}
elseif ($variables['past']) {
$classes['past'] = 'election-status-past';
}
}
$type = (empty($election->type_info)) ? _election_type_get_info($election->type) : $election->type_info;
// Nominations aren't relevant to elections that don't have candidates.
if ($status_prefix == 'n' && empty($type['has candidates'])) {
$variables['status'] = t('N/A');
$classes['na'] = 'election-status-na';
unset($classes['closed']);
}
elseif ($variables['scheduled'] && $variables['future']) {
if ($short) {
$variables['status'] = t('In %interval', array(
'%interval' => format_interval($open_time - REQUEST_TIME, 1),
));
}
else {
$variables['status'] = t('From %date (in @interval)', array(
'%date' => format_date($open_time),
'@interval' => format_interval($open_time - REQUEST_TIME),
));
}
}
elseif ($variables['scheduled'] && $variables['open']) {
if ($short) {
$variables['status'] = t('Scheduled (now open)');
}
else {
$variables['status'] = t('Open until %date', array('%date' => format_date($close_time)));
}
}
elseif ($variables['scheduled']) {
$variables['status'] = t('Closed %interval ago', array(
'%interval' => format_interval(REQUEST_TIME - $close_time, $short ? 1 : 2),
));
}
elseif ($variables['open']) {
$variables['status'] = t('Open');
}
else {
$variables['status'] = t('Closed');
}
$variables['classes'] = $classes;
}
/**
* Display an election's voting or nominating status.
*
* Variables:
* $election - An election object.
* $status_prefix - Type of status: 'v' = voting (default), 'n' = nominations.
* $status - A string describing the status (sanitized).
* $open - A Boolean indicating whether the status is open.
* $scheduled - A Boolean indicating whether the status is scheduled.
*/
function theme_election_status($variables) {
$attributes = array('class' => $variables['classes']);
return '<span' . drupal_attributes($attributes) . '>'
. $variables['status']
. '</span>';
}
/**
* Process variables for election.tpl.php.
*
* The $variables['elements'] array contains the following arguments:
* - #election
* - #view_mode.
*
* @see election.tpl.php
*/
function template_preprocess_election(&$variables) {
$election = $variables['elements']['#election'];
$view_mode = $variables['elements']['#view_mode'];
// Detect whether the election is on its own page.
$page_election = menu_get_object('election');
$is_page = (!empty($page_election) && $page_election->election_id == $election->election_id);
// Create some basic useful variables.
$variables['view_mode'] = $view_mode;
$variables['teaser'] = ($view_mode == 'teaser');
$variables['page'] = $is_page;
$variables['election'] = $election;
$variables['title'] = check_plain($election->title);
$uri = election_uri($election);
$variables['election_url'] = url($uri['path'], $uri['options']);
// Flatten the $election object's member fields.
$variables = array_merge((array) $election, $variables);
// Create the $content variable to contain fields for templates.
$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', $election, $variables['content'], $variables);
$variables['classes_array'][] = drupal_html_class('election-type-' . $election->type);
if ($view_mode == 'teaser') {
$variables['classes_array'][] = 'election-teaser';
}
if (!$election->published) {
$variables['classes_array'][] = 'election-unpublished';
}
$variables['theme_hook_suggestions'][] = 'election__' . $election->type;
$variables['theme_hook_suggestions'][] = 'election__' . $election->election_id;
}
<?php
/**
* @file
* Token integration for the Election module.
*/
/**
* Implements hook_token_info().
*/
function election_token_info() {
$info = array();
$info['types'] = array(
'election' => array(
'name' => t('Elections'),
'description' => t('Tokens related to elections.'),
'needs-data' => 'election',
),
'election_type' => array(
'name' => t('Election types'),
'description' => t('Tokens related to election types.'),
'needs-data' => 'election_type_mn',
),
);
$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 type of the election.'),
),
'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_type' => array(
'machine-name' => array(
'name' => t('Machine name'),
'description' => t('The machine name of the election type (default).'),
),
'name' => array(
'name' => t('Name'),
'description' => t('The human-readable name of the election type.'),
),
'name-ucfirst' => array(
'name' => t('Name (ucfirst)'),
'description' => t('The election type name run through drupal_ucfirst().'),
),
'post-name' => array(
'name' => t('Post name'),
'description' => t('The human-readable post name for the election type.'),
),
'post-name-ucfirst' => array(
'name' => t('Post name (ucfirst)'),
'description' => t('The post name run through drupal_ucfirst().'),
),
),
);
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 'title':
$replacements[$original] = $sanitize ? check_plain($election->title) : $election->title;
break;
case 'created':
$replacements[$original] = format_date($election->created, 'medium');
break;
}
}
if ($election_tokens = token_find_with_prefix($tokens, 'type')) {
$replacements += token_generate('election_type', $election_tokens, array('election_type_mn' => $election->type), $options);
}
}
elseif ($type == 'election_type' && !empty($data['election_type_mn'])) {
$type_machine_name = $data['election_type_mn'];
$type = _election_type_get_info($type_machine_name);
foreach ($tokens as $name => $original) {
switch ($name) {
case 'name':
$replacements[$original] = $sanitize ? check_plain($type['name']) : $type['name'];
break;
case 'name-ucfirst':
$replacements[$original] = $sanitize ? check_plain(drupal_ucfirst($type['name'])) : drupal_ucfirst($type['name']);
break;
case 'machine-name':
$replacements[$original] = $sanitize ? check_plain($type_machine_name) : $type_machine_name;
break;
case 'post-name':
$post_name = election_get_post_name($type_machine_name);
$replacements[$original] = $sanitize ? check_plain($post_name) : $post_name;
break;
case 'post-name-ucfirst':
$post_name = election_get_post_name($type_machine_name);
$replacements[$original] = $sanitize ? check_plain(drupal_ucfirst($post_name)) : drupal_ucfirst($post_name);
break;
}
}
}
return $replacements;
}
<?php
/**
* @file
* Default theme implementation to display an election.
*/
?>
<div id="election-<?php print $election->election_id; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
<?php if (!$page): ?>
<?php if (isset($title_prefix)): ?>
<?php print render($title_prefix); ?>
<?php endif; ?>
<h2<?php print $title_attributes; ?>><a href="<?php print $election_url; ?>"><?php print $title; ?></a></h2>
<?php if (isset($title_suffix)): ?>
<?php print render($title_suffix); ?>
<?php endif; ?>
<?php endif; ?>
<div class="content"<?php print $content_attributes; ?>>
<?php print render($content); ?>
</div>
</div>
<?php
/**
* @file
* Views integration for the Election module.
*/
/**
* Implements hook_views_query_substitutions().
*/
function election_views_query_substitutions() {
return array(
'***EDIT_ANY_ELECTION***' => intval(user_access('edit any election')),
);
}
/**
* Implements hook_views_data().
*/
function election_views_data() {
$data = array();
$data['election']['published_or_admin'] = array(
'title' => t('Published or admin'),
'help' => t('Filters out unpublished content if the current user cannot view it.'),
'filter' => array(
'field' => 'status',
'handler' => 'election_views_handler_filter_published',
'label' => t('Published or admin'),
),
);
$data['election']['view_election'] = array(
'field' => array(
'title' => t('Link'),
'help' => t('A link to the election.'),
'handler' => 'election_views_handler_field_link',
),
);
$data['election']['edit_election'] = array(
'field' => array(
'title' => t('Edit link'),
'help' => t('A link to edit the election.'),
'handler' => 'election_views_handler_field_link_edit',
),
);
$data['election']['delete_election'] = array(
'field' => array(
'title' => t('Delete link'),
'help' => t('A link to delete the election.'),
'handler' => 'election_views_handler_field_link_delete',
),
);
return $data;
}
<?php
/**
* @file
* ElectionCandidateTypeUIController class.
*/
/**
* Candidate UI controller.
*/
class ElectionCandidateTypeUIController extends EntityDefaultUIController {
/**
* Overrides hook_menu() defaults.
*/
public function hook_menu() {
$items = parent::hook_menu();
$items[$this->path]['description'] = 'Manage candidate types, including adding and removing fields and the display of fields.';
return $items;
}
}
<?php
/**
* @file
* Class ElectionCandidateTypeController.
*/
/**
* The controller for election candidate type entities.
*/
class ElectionCandidateTypeController extends EntityAPIControllerExportable {
/**
* Set defaults for candidate types.
*
* @param array $values
* Array of candidate field values.
*
* @return object
* A candidate type object with all default fields initialized.
*/
public function create(array $values = array()) {
$values += array(
'id' => '',
'is_new' => TRUE,
'data' => '',
);
return parent::create($values);
}
}
<?php
/**
* Class used for election candidate type entities.
*/
class ElectionCandidateType extends Entity {
public $type;
public $label;
public $status;
/**
* Overrides Entity::__construct to provide the entity type.
*/
public function __construct($values = array()) {
parent::__construct($values, 'election_candidate_type');
}
/**
* Determine whether this type is locked.
*/
public function isLocked() {
if (!empty($this->is_new)) {
return FALSE;
}
return (($this->status & ENTITY_IN_CODE) || ($this->status & ENTITY_FIXED));
}
}
<?php
/**
* @file
* Class ElectionCandidateController.
*/
/**
* Entity controller for candidates (in the Election module).
*/
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' => '',
'published' => 1,
'cstatus' => ELECTION_CANDIDATE_HOPEFUL,
'uid' => '',
'summary' => '',
'manifesto' => '',
'photo' => '',
'proposer' => new stdClass(),
'seconders' => array(),
'candidate_category' => 0,
'type' => '',
'created' => 0,
'changed' => 0,
);
// Overwrite default values with supplied values.
$values = array_merge($default_values, $values);
return parent::create($values);
}
}