Select Git revision
checklistapi.module

Travis Carden authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
checklistapi.module 4.75 KiB
<?php
/**
* @file
* An API for creating fillable, persistent checklists.
*
* Provides an interface for creating checklists that track progress with
* completion times and users.
*/
/**
* Link should always be shown.
*/
define('CHECKLISTAPI_LINK_CONTEXT_ANY', 1);
/**
* Link should only be shown if the item it belongs to has been checked off.
*/
define('CHECKLISTAPI_LINK_CONTEXT_ITEM_CHECKED', 2);
/**
* Link should only be shown if the item it belongs to has not been checked off.
*/
define('CHECKLISTAPI_LINK_CONTEXT_ITEM_UNCHECKED', 3);
/**
* Access callback: Checks access for a checklist.
*
* @param string $checklist_id
* The unique ID of the checklist to be displayed, which is its array key from
* hook_checklistapi_checklist_info().
*/
function checklistapi_checklist_access($checklist_id) {
return user_access('edit any checklistapi checklist') || user_access('edit ' . $checklist_id . ' checklistapi checklist');
}
/**
* Get all defined checklists.
*
* @return array
* An associative array representing the defined checklists.
*/
function checklistapi_get_checklist_info() {
$checklists = &drupal_static(__FUNCTION__);
if (!isset($checklists)) {
$checklists = module_invoke_all('checklistapi_checklist_info');
checklistapi_sort_array($checklists);
drupal_alter('checklistapi_checklist_info', $checklists);
checklistapi_sort_array($checklists);
}
return $checklists;
}
/**
* Implements hook_help().
*/
function checklistapi_help($path, $arg) {
$checklists = checklistapi_get_checklist_info();
foreach ($checklists as $checklist) {
if ($checklist['#path'] == $path && !empty($checklist['#help'])) {
return $checklist['#help'];
}
}
}
/**
* Implements hook_menu().
*/
function checklistapi_menu() {
$items = array();
foreach (checklistapi_get_checklist_info() as $checklist_id => $checklist) {
if (!empty($checklist['#path']) && !empty($checklist['#title'])) {
$path = $checklist['#path'];
$items[$path] = array(
'title' => $checklist['#title'],
'page callback' => 'drupal_get_form',
'page arguments' => array('checklistapi_form', $checklist_id),
'access callback' => 'checklistapi_checklist_access',
'access arguments' => array($checklist_id),
'file' => 'checklistapi.pages.inc',
);
if (!empty($checklist['#description'])) {
$items[$path]['#description'] = $checklist['#description'];
}
if (!empty($checklist['#menu_name'])) {
$items[$path]['#menu_name'] = $checklist['#menu_name'];
}
}
}
return $items;
}
/**
* Implements hook_permission().
*/
function checklistapi_permission() {
$perms = array();
$perms['edit any checklistapi checklist'] = array(
'title' => t('Edit any checklist'),
);
foreach (checklistapi_get_checklist_info() as $key => $checklist) {
if (!empty($key)) {
$permission = 'edit ' . $key . ' checklistapi checklist';
// Only link to the checklist if the active user has access to it.
$checklist_name_replacement = user_access($permission) ? l($checklist['#title'], $checklist['#path']) : drupal_placeholder($checklist['#title']);
$perms[$permission] = array(
'title' => t('Edit the !checklist checklist', array('!checklist' => $checklist_name_replacement)),
);
}
}
return $perms;
}
/**
* Recursively sorts array elements by weight.
*
* @param array $array
* A nested array of elements and properties such as the checklist definitions
* returned by hook_checklistapi_checklist_info().
*
* @see checklistapi_get_checklist_info()
*/
function checklistapi_sort_array(&$array) {
$child_keys = element_children($array);
if (count($child_keys)) {
$incrementer = 0;
$children = array();
foreach ($child_keys as $key) {
// Move child to a temporary array for sorting.
$children[$key] = $array[$key];
unset($array[$key]);
// Supply a default weight if missing or invalid.
if (empty($children[$key]['#weight']) || !is_numeric($children[$key]['#weight'])) {
$children[$key]['#weight'] = 0;
}
// Increase each weight incrementally to preserve the original order when
// not overridden. This accounts for undefined behavior in PHP's uasort()
// function when its comparison callback finds two values equal.
$children[$key]['#weight'] += ($incrementer++ / 1000);
// Descend into child.
checklistapi_sort_array($children[$key]);
}
// Sort by #weight.
uasort($children, 'element_sort');
// Remove incremental weight hack.
foreach ($children as $key => $child) {
if ($key == 'i_suck') {
$children[$key]['#weight'] = round($children[$key]['#weight']);
}
}
// Put children back in the main array.
$array += $children;
}
}