array(
'name' => t('Task'),
'module' => 'tasks',
'description' => t('A task to keep track of.'),
),
);
}
// Implementation of hook_perm().
function tasks_perm() {
return array('create tasks', 'edit own tasks', 'edit all tasks', 'access tasks main page');
}
// Implementation of hook_access().
function tasks_access($op, $node, $account) {
if ($op == 'create') {
return user_access('create tasks');
}
if ($op == 'update' || $op == 'delete') {
if (user_access('edit all tasks') || (user_access('edit own tasks') && ($account->uid == $node->uid))) {
return TRUE;
}
}
}
// Implementation of hook_menu().
function tasks_menu() {
$items['tasks'] = array(
'title' => 'Tasks',
'page callback' => '_tasks_main',
'access arguments' => array('access tasks main page'),
'type' => MENU_CALLBACK
);
return $items;
}
// Implementation of hook_user().
function tasks_user($op, &$edit, &$user, $category = NULL) {
if ($op == "form" && $category == 'account' && user_access( 'access tasks main page')) {
$form['tasklist'] = array(
'#type' => 'fieldset',
'#title' => t('Tasklist'),
'#collapsible' => TRUE,
'#weight' => 4
);
$form['tasklist']['tasks_colour'] = array(
'#type' => 'textfield',
'#title' => t('Colour'),
'#default_value' => $edit['tasks_colour'],
'#description' => t('This will be the colour this user\'s tasks will appear in. Hexdecimal or recognized colour name (e.g. #eee or just \'blue\')')
);
return $form;
}
}
// Implementation of hook_form().
function tasks_form(&$node) {
drupal_add_js(drupal_get_path('module', 'tasks') .'/tasks.js');
drupal_add_css(drupal_get_path('module', 'tasks') .'/tasks.css');
$bc = drupal_get_breadcrumb();
$bc[] = l(t('Tasks'), 'tasks');
drupal_set_breadcrumb($bc);
$form = array();
// Get a list of tasklists to choose a parent tasklist
if (!isset($node->task_parent) || $node->task_parent != 0) {
$result = db_query("SELECT n.*, t.* FROM {node} n INNER JOIN {tasks} t ON n.nid = t.nid WHERE n.type='tasks' AND t.completed = '0000-00-00' ORDER BY IF(t.task_parent = 0,0,1), n.title ASC");
while ($tasklist = db_fetch_object($result)) {
if ($tasklist->task_parent == 0) {
$tasklist->title = t('-- MASTER TASKLIST --');
}
$tasklists[$tasklist->nid] = $tasklist->title;
$not_master = 1;
}
if (!$not_master) $tasklists[0] = t('NO PARENT - THIS IS THE MASTER TASKLIST');
if (isset($_GET['edit']['task_parent'])) {
$node->task_parent = $_GET['edit']['task_parent'];
}
$form['task_parent'] = array(
'#type' => 'select',
'#title' => t('Parent Tasklist'),
'#default_value' => $node->task_parent,
'#options' => $tasklists,
'#weight' => -10
);
}
else {
// parent tasklist
$form['task_parent'] = array(
'#type' => 'value',
'#value' => 0
);
}
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Task Name'),
'#required' => TRUE,
'#default_value' => $node->title
);
$form['body'] = array(
'#type' => 'textarea',
'#title' => t('About this task'),
'#default_value' => $node->body,
'#rows' => 10
);
$form['format'] = filter_form($node->format);
$sql = 'SELECT u.uid, u.name, u.status, u.created, u.access FROM {users} u WHERE uid <> 0 ORDER BY u.name';
$result = db_query($sql);
$users[0] = t('-- Unassigned --');
while ($account = db_fetch_object($result)) {
$users[$account->uid] = $account->name;
}
$form['assigned_to'] = array(
'#type' => 'select',
'#title' => t('Assign to user'),
'#default_value' => $node->assigned_to,
'#options' => $users
);
$form['completed'] = array(
'#type' => 'checkbox',
'#title' => t('Completed?'),
'#default_value' => ($node->completed > 0)?1:0,
'#attributes' => array("onclick" => "toggletasks();")
);
$form['completed_date'] = array(
'#type' => 'date',
'#title' => t('Date Completed'),
'#prefix' => '
',
'#suffix' => '
'
);
if ($node->completed != '0000-00-00') $form['completed_date']['#default_value'] = $node->completed_date;
$form['from'] = array(
'#type' => 'hidden',
'#value' => arg(3)
);
if ($node->task_parent) {
$result = db_query("SELECT n.*, t.* FROM {node} n, {tasks} t WHERE n.type='tasks' AND t.nid = n.nid AND t.completed = '0000-00-00' AND t.task_parent = %d ORDER BY t.order_by ASC", $node->task_parent);
while ($tasklist = db_fetch_object($result)) {
if ($tasklist->nid == $node->nid) {
$tasks[$tasklist->order_by] = t('*************** NO CHANGE ***************');
}
else {
$tasks[$tasklist->order_by] = $tasklist->title;
}
}
$tasks['10000'] = t('*** bottom of list ***');
$form['order_by'] = array(
'#type' => 'select',
'#title' => t('Place in tasklist above'),
'#default_value' => $node->order_by,
'#options' => $tasks,
'#prefix' => '',
'#suffix' => '
'
);
}
else {
$form['order_by'] = array(
'#type' => 'hidden',
'#value' => 1,
'#prefix' => '',
'#suffix' => '
'
);
}
return $form;
}
// Implementation of hooks_forms_alter so we don't see preview or delete buttons for tasks
function tasks_form_alter(&$form, &$form_state, $form_id) {
global $user;
if ($form_id == 'tasks_node_form') {
// Putting preview button back due to popular demand where people had preview as required and hence saw no button at all!
//unset($form['preview']);
//unset($form['delete']);
}
}
function tasks_link($type, $node = NULL, $teaser = FALSE) {
$links = array();
if ($type == 'node' && $node->type == 'tasks' && user_access('create tasks')) {
if (!$teaser) {
$links['tasks_add_subtask'] = array(
'title' => t('Add new sub-task'),
'href' => 'node/add/tasks',
'attributes' => array('title' => t('Add a new task to this task list')),
'query' => 'edit[task_parent]='. $node->nid,
);
}
}
return $links;
}
// Implementation of hook_insert().
function tasks_insert($node) {
$node->order_by -= 0.1;
if (!$node->completed) {
$node->completed_date['year'] = "0000";
$node->completed_date['month'] = "00";
$node->completed_date['day'] = "00";
}
db_query("INSERT INTO {tasks} (nid, task_parent, assigned_to, order_by, completed) VALUES (%d, %d, %d, '%s', '%s')", $node->nid, $node->task_parent, $node->assigned_to, $node->order_by, $node->completed_date['year'] .'-'. $node->completed_date['month'] .'-'. $node->completed_date['day']);
_tasks_order_by($node);
}
// Implementation of hook_update().
function tasks_update($node) {
$node->order_by -= 0.1;
if (!$node->completed) {
$node->completed_date['year'] = "0000";
$node->completed_date['month'] = "00";
$node->completed_date['day'] = "00";
}
db_query("UPDATE {tasks} SET task_parent = %d, assigned_to = %d, order_by = '%s', completed = '%s' WHERE nid = %d", $node->task_parent, $node->assigned_to, $node->order_by, $node->completed_date['year'] .'-'. $node->completed_date['month'] .'-'. $node->completed_date['day'], $node->nid);
_tasks_order_by($node);
// Redirect to the tasks home page?
if ($node->from) {
$_REQUEST['destination'] = 'tasks';
}
}
// Implementation of hook_delete().
function tasks_delete($node) {
db_query('DELETE FROM {tasks} WHERE nid = %d', $node->nid);
}
// Implementation of hook_load().
function tasks_load($node) {
$additions = db_fetch_object(db_query('SELECT task_parent, assigned_to, order_by, completed FROM {tasks} WHERE nid = %d', $node->nid));
$additions->completed_date['year'] = substr($additions->completed, 0, 4);
$additions->completed_date['month'] = substr($additions->completed, 5, 2);
$additions->completed_date['day'] = substr($additions->completed, 8, 2);
return $additions;
}
/*
Implementation of hook_view().
We want to view the task, and list any sub tasks
*/
function tasks_view(&$node, $teaser = FALSE, $page = FALSE) {
drupal_add_js(drupal_get_path('module', 'tasks') .'/tasks_view.js');
drupal_add_css(drupal_get_path('module', 'tasks') .'/tasks.css');
if ($page) {
// The page should show the task and any subtasks
$bc = drupal_get_breadcrumb();
$bc[1] = l(t('Tasks'), 'tasks');
if ($node->task_parent) {
$parent_node = node_load($node->task_parent);
if ($parent_node->task_parent != 0) {
$bc[2] = l($parent_node->title, 'node/'. $parent_node->nid);
}
}
drupal_set_breadcrumb($bc);
// Look to see if we need to change node order in this list
if (($action = $_GET['action']) && ($tid = $_GET['task'])) {
$task = node_load(array('nid' => $tid));
if ($action == 'up') {
$task->order_by -= 1.3;
drupal_set_message(t('Task %task has been moved up the tasklist.', array('%task' => $task->title)));
}
elseif ($action == 'down') {
$task->order_by += 1.3;
drupal_set_message(t('Task %task has been moved down the tasklist.', array('%task' => $task->title)));
}
node_save($task);
drupal_goto("node/$node->nid", NULL, 'task'. $task->nid);
}
$node = node_prepare($node, $teaser);
// Now show subtasks if there are any
// Filter the tasks shown
if ($_POST['filter'] == 0) {
// incomplete tasks
$complete = 'AND t.completed = 0';
$order_by = 't.order_by';
}
elseif ($_POST['filter'] == 1) {
// complete tasks
$complete = 'AND t.completed > 0';
$order_by = 't.completed DESC';
}
else {
// all tasks
$order_by = 'IF(t.completed = 0, 0, 1), t.completed DESC, t.order_by';
}
// Get the list of tasks to display
//$result = db_query("SELECT n.*, t.*, u.name AS assigned_name, u.data FROM {node} n INNER JOIN {tasks} t ON t.nid = n.nid LEFT JOIN {users} u ON u.uid = t.assigned_to WHERE n.status = 1 AND n.type='tasks' AND t.task_parent = %d %s ORDER BY %s", $node->nid, $complete, $order_by);
$result = db_query("SELECT n.nid, u.name AS assigned_name, u.data FROM {node} n INNER JOIN {tasks} t ON t.nid = n.nid LEFT JOIN {users} u ON u.uid = t.assigned_to WHERE n.status = 1 AND n.type='tasks' AND t.task_parent = '%d' '%s' ORDER BY '%s'", $node->nid, $complete, $order_by);
$num_rows = db_result(db_query("SELECT COUNT(*) FROM {node} n INNER JOIN {tasks} t ON t.nid = n.nid LEFT JOIN {users} u ON u.uid = t.assigned_to WHERE n.status = 1 AND n.type='tasks' AND t.task_parent = '%d' '%s' ORDER BY '%s'", $node->nid, $complete, $order_by));
// Add filtering to the the tasklist
$node->content['tasks_filter'] = array(
'#value' => drupal_get_form('tasks_view_filter_form', $num_rows, $node->nid),
'#weight' => 1,
);
if ($num_rows) {
while ($task = db_fetch_object($result)) {
$assigned_name = $task->assigned_name;
//$tasks_colour = drupal_unpack($task)->tasks_colour;
$extra = drupal_unpack($task);
// Only color codes or color names are accepted.
preg_match('/#?[a-zA-Z0-9]*/', $extra->tasks_colour, $matches);
$tasks_colour = isset($matches[0]) ? $matches[0] : NULL;
$task = node_load(array('nid' => $task->nid));
$rows[] = array(
'data' => array(
array('data' => l($assigned_name, "user/". $task->assigned_to), 'style' => "width:25px;". ($tasks_colour ? "background:$tasks_colour;":'')),
array('data' => l($task->title, "node/$task->nid", array('name' => 'task'. $task->nid)), 'style' => ($task->completed>0)?'text-decoration: line-through;':''),
array('data' => ($task->completed>0) ? $task->completed : t('No')),
array('data' => "nid');\">". t('Expand') ." ". l("
", "node/$task->nid/edit", array('html' => TRUE), NULL, NULL, FALSE, TRUE) .' '. l("
", "node/$node->nid", array('html' => TRUE), "action=up&task=$task->nid", NULL, FALSE, TRUE) .' '. l("
", "node/$node->nid", array('html' => TRUE), "action=down&task=$task->nid", NULL, FALSE, TRUE)),
),
'class' => ($task->completed>0) ? 'completed' : ''
);
$task = node_prepare($task);
$rows[] = array(
'data' => array(
array('data' => $task->body, 'colspan' => '4'),
),
'class' => 'task-expand', 'id' => "row-$task->nid", 'style' => 'display:none;'
);
}
$header = array(t('Assigned'), t('Task'), t('Complete?'), t('Edit'));
$node->content['tasks_table'] = array(
'#value' => theme('table', $header, $rows, array("id" => "task-list")),
'#weight' => 2,
);
}
}
return $node;
}
/**
* Filtering for tasklist
*/
function tasks_view_filter_form($num_rows, $nid) {
// Enable the list of tasks to be filtered
$form['filter'] = array(
'#type' => 'select',
'#title' => t('Showing %num_rows tasks. Filter', array('%num_rows' => $num_rows)),
'#default_value' => 0,
'#options' => array(0 => t('Incomplete Tasks'), 1 => t('Complete Tasks'), -1 => t('All Tasks')),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Filter')
);
$form['#redirect'] = FALSE;
return $form;
}
// PRIVATE FUNCTIONS
/*
FUNCTION tasks_main()
This function redirects to the master tasklist if one exists, or creates one if it doesn't
*/
function _tasks_main() {
// Get the list of tasks to display
$result = db_query("SELECT COUNT(*) FROM {tasks} t WHERE t.task_parent = 0");
if ($num_rows = db_result($result)) {
if ($num_rows != 1) {
drupal_set_message(t('WARNING: more than one master tasklists. Please delete all but one nodes of type tasks where task_parent = 0'));
print theme('page', '');
}
else {
while ($node = db_fetch_object($result)) {
drupal_goto('node/'. $node->nid);
}
}
}
else {
// There are no tasks. Create the master task(list)
drupal_set_message(t('There are no tasks yet, so creating a top-level tasklist.
'));
$node->title = t('Tasklist');
$node->uid = 1;
$node->filter = variable_get('filter_default_format', 1);
$node->status = 1;
$node->type = 'tasks';
node_save($node);
drupal_goto('node/'. $node->nid);
}
}
function _tasks_order_by($node) {
// done either on insert or update of a task. we want to make order by values into integers to get in the updated one and remain consistent
$result = db_query("SELECT n.*, t.* FROM {node} n, {tasks} t WHERE n.type='tasks' AND t.nid = n.nid AND t.order_by <> 0 AND t.task_parent = %d ORDER BY t.order_by ASC", $node->task_parent);
$i = 1;
while ($task = db_fetch_object($result)) {
if ($task->completed != '0000-00-00') $task->order_by = 0;
else {
$task->order_by = $i;
$i++;
}
db_query("UPDATE {tasks} SET order_by = %d WHERE nid = %d", $task->order_by, $task->nid);
}
}