'tasks', 'title' => t('Tasks'), 'callback' => '_tasks_advanced_main', 'access' => user_access('access tasks main page') && user_access('access all tasks'), 'type' => MENU_CALLBACK ); $items[] = array( 'path' => 'tasks/user', 'title' => t('My tasks'), 'callback' => '_tasks_advanced_main', 'callback arguments' => array('user'), 'access' => user_access('access tasks main page') && user_access('access all tasks'), 'type' => MENU_CALLBACK ); // dynamic menu items $items[] = array( 'path' => 'tasks', 'title' => t('Tasks'), 'callback' => '_tasks_advanced_main', 'access' => user_access('access tasks main page') && user_access('access all tasks'), 'type' => MENU_DYNAMIC_ITEM ); if ($user->uid) { $items[] = array( 'path' => 'tasks/user/'.$user->uid, 'title' => t('My tasks'), 'callback' => '_tasks_advanced_main', 'callback arguments' => array('user', $user->uid), 'access' => user_access('access tasks main page') && user_access('access own tasks'), 'type' => MENU_DYNAMIC_ITEM ); } } return $items; } /** * Implementation of hook_form_alter(). * * @ingroup tasks_advanced_core */ function tasks_advanced_form_alter($form_id, &$form) { global $user; drupal_add_css(drupal_get_path('module', 'tasks_advanced').'/tasks_advanced.css'); $node = isset($form['#node']) ? $form['#node'] : NULL; $tasks_advanced_visible = (variable_get('event_nodeapi_'. $type, TRUE) ? FALSE : TRUE); $taskcategories = _tasks_advanced_taskcategory(); $tasktypes = _tasks_advanced_tasktype(); if ($form_id == 'tasks_node_form') { $form['tasks_advanced'] = array( '#type' => 'fieldset', '#title' => t('Details'), '#collapsible' => FALSE, '#collapsed' => $tasks_advanced_visible, '#attributes' => array("id" => "tasks_advanced"), '#weight' => -14, ); $form['tasks_advanced']['taskcategory'] = array( '#type' => 'select', '#title' => t('Task Category'), '#default_value' => (isset($node->taskcategory) ? $node->taskcategory : 'unknown'), '#options' => $taskcategories, '#description' => t(''), '#weight' => 0, ); $form['tasks_advanced']['tasktype'] = array( '#type' => 'radios', '#title' => t('Task Type'), '#default_value' => (isset($node->tasktype) ? $node->tasktype : 'action'), '#options' => $tasktypes, '#description' => t(''), '#weight' => 0, ); $form['from'] = array( '#type' => 'hidden', '#value' => arg(3).(arg(4) ? '/'.arg(4).(arg(5) ? '/'.arg(5) : '') : ''), ); // alter parent tasklist to only contain project types, and add a class for styling $parents = _tasks_advanced_projects($node->nid); $form['parent']['#prefix'] = '
'; $form['parent']['#suffix'] = '
'; $form['parent']['#options'] = $parents; } } function _tasks_advanced_projects($nid) { if (!$nid) { $nid = 0; } $result = db_query("SELECT n.nid, n.title, t.task_parent as parent FROM {node} n INNER JOIN {tasks} t ON t.nid = n.nid INNER JOIN {tasks_advanced} a ON a.nid = n.nid WHERE n.type='tasks' AND t.completed = '0000-00-00' AND a.tasktype = 'project' AND n.nid != {$nid} ORDER BY IF(t.task_parent = 0,0,1), n.title ASC"); while ($tasklist = db_fetch_object($result)) { if ($tasklist->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'); } return $tasklists; } function _tasks_advanced_taskcategory($taskcategory = NULL) { $taskcategories = array('unknown' => t('Unknown'), 'next' => t('Next Action'), 'waiting' => t('Waiting For'), 'someday' => t('Some Day'), 'list' => t('List'), 'reference' => t('Reference'), 'inactive' => t('Inactive')); return ($taskcategory != NULL ? $taskcategories[$taskcategory] : $taskcategories); } function _tasks_advanced_tasktype($tasktype = NULL) { $tasktypes = array('action' => t('Action'), 'project' => t('Project')); return ($tasktype != NULL ? $tasktypes[$tasktype] : $tasktypes); } /** * Implementation of hook_nodeapi(). * * @ingroup tasks_advanced_core */ function tasks_advanced_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { // only apply to task nodes if ($node->type == 'tasks') { switch ($op) { case 'validate': case 'submit': // lets make sure we get good values $taskcategories = _tasks_advanced_taskcategory(); $tasktypes = _tasks_advanced_tasktype(); if (!array_key_exists($node->taskcategory, $taskcategories)) { $node->taskcategory = 'unknown'; } if (!array_key_exists($node->tasktype, $tasktypes)) { $node->tasktype = 'action'; } break; case 'insert': // fetch parent for tree info $parent_node = _tasks_advanced_get_node($node->parent); // update tree to make place for new node _tasks_advanced_tree_insert($parent_node); // insert new record db_query("INSERT INTO {tasks_advanced} (nid, taskcategory, tasktype, task_tree_left, task_tree_right, task_tree_depth) VALUES (%d, '%s', '%s', %d, %d, %d)", $node->nid, $node->taskcategory, $node->tasktype, $parent_node->task_tree_right, $parent_node->task_tree_right + 1, $parent_node->task_tree_depth + 1); break; case 'update': // update the tree if the parent has changed if (($_GET['action'] == 'up' || $_GET['action'] == 'down') == FALSE) { if (_tasks_advanced_tree_move($node, $node->parent)) { drupal_set_message(t('Task '.$node->title.' has been moved to another location on the tasklist.')); } } // update record db_query("UPDATE {tasks_advanced} SET taskcategory = '%s', tasktype = '%s' WHERE nid = %d", $node->taskcategory, $node->tasktype, $node->nid); if ($node->from) { $_REQUEST['destination'] = $node->from; } break; case 'delete': // update tree to fill place of missing node _tasks_advanced_tree_extract($node); // delete record db_query("DELETE FROM {tasks_advanced} WHERE nid = %d", $node->nid); break; case 'load': $record = db_query('SELECT taskcategory, tasktype, task_tree_left, task_tree_right, task_tree_depth FROM {tasks_advanced} WHERE nid = %d', $node->nid); $object = db_fetch_object($record); return array( 'taskcategory' => $object->taskcategory, 'tasktype' => $object->tasktype, 'task_tree_left' => $object->task_tree_left, 'task_tree_right' => $object->task_tree_right, 'task_tree_depth' => $object->task_tree_depth, ); break; case 'view': case 'rss item': break; } } } /** * Implementation of hook_user(). * * @ingroup tasks_advanced_core */ function tasks_advanced_user($op, &$edit, &$user, $category = NULL) { if($op == "view") { $items[] = array( 'title' => t("Tasks"), 'value' => l(t('View !s\'s tasks', array('!s' => $user->name)), "tasks/user/".$user->uid), 'class' => 'tasks', ); return array(t('Tasks') => $items); } } /** * @defgroup tasks_advanced_callback Functions which are the menu callbacks for this module */ /** * Output user headers. * * @ingroup tasks_advanced_callback * @param $type string 'user' for individual user page * @param $uid integer User's id * @return string html */ function _tasks_advanced_main($type = NULL, $uid = NULL) { global $user; drupal_add_js(drupal_get_path('module', 'tasks').'/tasks_view.js'); drupal_add_css(drupal_get_path('module', 'tasks_advanced').'/tasks_advanced.css'); // Set proper breadcrumb $bc = drupal_get_breadcrumb(); if ($type == NULL) { $bc[] = l(t('Tasks'), 'tasks'); } elseif ($type == 'user' && $uid == $user->uid) { // Need to remove 'my tasks' part off breadcrumb array_pop($bc); } if ($type == 'user') { if ($uid == NULL) { // Need to redirect to current user drupal_goto('tasks/user/'.$user->uid); } else { if ($uid === 0 || $uid == '0') { // Add title and special headers drupal_set_title(t('Unassigned Tasks')); // Add breadcrumb trail $bc[] = l(t('Unassigned'), 'tasks/user/'.$uid); } else { $new_user = user_load(array('uid' => $uid)); if (!$new_user->uid) { return drupal_not_found(); } // Add title and special headers drupal_set_title(t('%name’s Tasks', array('%name' => ucfirst($new_user->name)))); $output = '

User ID: '.$uid.'

'; // Add breadcrumb trail $bc[] = l(t('!name', array('!name' => ucfirst($new_user->name))), 'tasks/user/'.$uid); } } } else { drupal_set_title(t('Tasks')); if (!user_access('access all tasks')) { drupal_goto('tasks/user/'.$user->uid); } if ($uid != NULL) { drupal_goto('tasks'); } } // Finalize breadcrumb 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, 'type' => 'tasks')); if ($action == 'up') { $task->order_by -= 1.3; node_save($task); if (_tasks_advanced_tree_sort($task, -1)) { drupal_set_message(t('Task '.$task->title.' has been moved up the tasklist.')); } } elseif ($action == 'down') { $task->order_by += 1.3; node_save($task); if (_tasks_advanced_tree_sort($task, 1)) { drupal_set_message(t('Task '.$task->title.' has been moved down the tasklist.')); } } if ($type == 'user') { drupal_goto('tasks/user/'.$uid); } else { drupal_goto('tasks'); } } // Setup filtering $query = new StdClass(); if (isset($_SESSION['_tasks_advanced_query'])) { $query = $_SESSION['_tasks_advanced_query']; } else { // Set filtering defaults $query->status = array(1); } // Add user to filter if ($uid == NULL) { unset($query->uid); } else { $query->uid = array($uid); } // Populate filter $query = _tasks_advanced_query_parse($query); $_SESSION['_tasks_advanced_query'] = $query; // Make database calls $sql = _tasks_advanced_query_sql($query); $result = db_query($sql); $num_rows = db_num_rows($result); // Enable the list of tasks to be filtered $output .= drupal_get_form('tasks_advanced_view_filter_form', $num_rows, $query); // only proceed if we have tasks to display if ($num_rows > 0) { $rows = array(); $init = TRUE; $userid = -1; $username = -1; // loop through each task while ($task = db_fetch_object($result)) { // is this a new user? if ($username != $task->assigned_name) { // if we're showing all user's tasks, we need to add headers for each user if ($type != 'user') { if ($init == FALSE) { $output .= _tasks_advanced_user_headers($userid, $username); $output .= _tasks_advanced_row_headers($rows); $rows = array(); } else { // initialization complete $init = FALSE; } } $userid = $task->assigned_to; $username = $task->assigned_name; unset($previous_task); } // Is another user the owner of our parent? // If so, we need to insert an 'unknown' parent // to keep hierarchy somewhat consistent. // It's still a bit of a hack, since it doesn't // show the real parent, and doesn't reflect // the depth either. if (isset($previous_task)) { if (($task->task_tree_depth > $previous_task->task_tree_depth && $task->parent != $previous_task->nid) || ($task->task_tree_depth == $previous_task->task_tree_depth && $task->parent != $previous_task->parent)) { if ($task->task_tree_left > $previous_task->task_tree_left && $task->task_tree_right < $previous_task->task_tree_right && $task->task_tree_depth > 2) { // this is a grandchild of this task $rows[] =_tasks_advanced_task_placeholder($task, $type, $uid, TRUE); } else { $rows[] =_tasks_advanced_task_placeholder($task, $type, $uid); } } } else { if ($task->task_tree_depth > 1) { $rows[] =_tasks_advanced_task_placeholder($task, $type, $uid); } } $previous_task = drupal_clone($task); $task_rows = _tasks_advanced_task($task, $type, $uid); $rows[] = $task_rows[0]; $rows[] = $task_rows[1]; } if ($type != 'user') { $output .= _tasks_advanced_user_headers($userid, $username); } $output .= _tasks_advanced_row_headers($rows); $rows = array(); } else { // no tasks to display $output .= '

'.t('No tasks found.').'

'; } print theme('page', $output); } /** * Filtering for tasklist */ function tasks_advanced_view_filter_form($num_rows, &$query) { // Create dropdown options lists $status = array(1 => t('Incomplete Tasks'), 2 => t('Complete Tasks'), 0 => t('All Tasks')); $taskcategories = array_merge(array(0 => 'All Tasks'), _tasks_advanced_taskcategory()); $tasktypes = array_merge(array(0 => 'All Tasks'), _tasks_advanced_tasktype()); // Enable the list of tasks to be filtered $form['filter'] = array( '#type' => 'fieldset', '#title' => t('Filter'), '#collapsible' => TRUE, '#collapsed' => FALSE, '#weight' => -1, ); $form['filter']['label'] = array( '#value' => t('Showing %num_rows tasks.', array('%num_rows' => $num_rows)), ); $form['filter']['status'] = array( '#type' => 'select', '#title' => t('Status'), '#default_value' => (isset($query->status) ? $query->status[0] : '0'), '#options' => $status, ); $form['filter']['taskcategory'] = array( '#type' => 'select', '#title' => t('Category'), '#default_value' => (isset($query->taskcategory) ? $query->taskcategory[0] : '0'), '#options' => $taskcategories, ); $form['filter']['tasktype'] = array( '#type' => 'select', '#title' => t('Task Type'), '#default_value' => (isset($query->tasktype) ? $query->tasktype[0] : '0'), '#options' => $tasktypes, ); $form['filter']['submit'] = array( '#type' => 'submit', '#value' => t('Filter') ); $form['#redirect'] = FALSE; return $form; } function _tasks_advanced_query_parse($query = NULL) { $fields = array('status', 'taskcategory', 'tasktype'); if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_POST['form_id'] == 'tasks_advanced_view_filter_form') { foreach ($_POST as $key => $value) { if (!empty($value) && in_array($key, $fields)) { $query->$key = !is_array($value) ? explode(',', $value) : $value; $_POST[$key] = is_array($value) ? implode(',', $value) : $value; } else { unset($query->$key); } } $_POST = array(); } else { foreach ($_GET as $key => $value) { if (!empty($value) && in_array($key, $fields)) { $query->$key = explode(',', $value); } else { unset($query->$key); } } } return $query; } function _tasks_advanced_query_sql_field($field, $values, $operator = ' OR ') { $sql = array(); if (!is_array($values)) { $values = array($values); } foreach ($values as $value) { $value = db_escape_string($value); $sql[] = ($like && $field != 'p.pid') ? "$field LIKE '%$value%'" : "$field = '$value'"; } if ($sql) { return '('. implode($operator, $sql) .')'; } } function _tasks_advanced_query_sql($query) { $order = 'u.name, a.task_tree_left ASC, IF(t.completed = 0, 0, 1), t.completed DESC'; $sql = array(); foreach ($query as $key => $value) { switch ($key) { case 'status': switch ($value[0]) { case 1: $order = 'u.name, a.task_tree_left ASC'; $sql[] = 't.completed = 0000-00-00'; break; case 2: $order = 'u.name, a.task_tree_left ASC, t.completed DESC'; $sql[] = 't.completed != 0000-00-00'; break; } break; case 'taskcategory': $sql[] = _tasks_advanced_query_sql_field('a.taskcategory', $value); break; case 'tasktype': $sql[] = _tasks_advanced_query_sql_field('a.tasktype', $value); break; case 'uid': $sql[] = _tasks_advanced_query_sql_field('u.uid', $value); break; } } $sql_str = "SELECT n.nid, t.task_parent as parent, u.name AS assigned_name, t.assigned_to, a.taskcategory, a.tasktype, a.task_tree_left, a.task_tree_right, a.task_tree_depth, u.data FROM {node} n INNER JOIN {tasks} t ON t.nid = n.nid INNER JOIN {tasks_advanced} a ON a.nid = n.nid LEFT JOIN {users} u ON u.uid = t.assigned_to WHERE n.status = 1 AND n.type='tasks' ". (count($sql) > 0 ?" AND (". implode(") AND (", $sql) .")" : '').' '." ORDER BY {$order}"; $sql = db_rewrite_sql($sql_str); return $sql; } /** * Rebuild tree structure. * * Based on "Modified Preorder Tree Traversal" article at * http://www.sitepoint.com/article/hierarchical-data-database * * @param $parent object task * @param $left integer left side of tree * @return $right integer */ function tasks_advanced_rebuild_tree($parent, $left, $depth = 0) { // the right value of this node is the left value + 1 $right = $left + 1; // get all children of this node $result = db_query("SELECT nid tas_parent as parent FROM {tasks} WHERE task_parent = %d", $parent); while ($row = db_fetch_object($result)) { // recursive execution of this function for each // child of this node // $right is the current right value, which is // incremented by the rebuild_tree function $right = tasks_advanced_rebuild_tree($row->parent, $right, $depth + 1); } // we've got the left value, and now that we've processed // the children of this node we also know the right value db_query("UPDATE {tasks_advanced} SET task_tree_left = %d, task_tree_right = %d, task_tree_depth = %d WHERE nid = %d", $left, $right, $depth, $parent); // return the right value of this node + 1 $return = $right + 1; return $return; } /** * @defgroup tasks_advanced_support Functions that support the tasks_advanced system */ /** * Retrieve tasks_advanced part of a node using its nid. * * @ingroup tasks_advanced_support * @param $nid integer Node's nid * @return void */ function _tasks_advanced_get_node($nid) { $record = db_query('SELECT t.nid, t.task_parent as parent, a.tasktype, a.task_tree_left, a.task_tree_right, a.task_tree_depth FROM {tasks} t INNER JOIN {tasks_advanced} a ON a.nid = t.nid WHERE t.nid = %d LIMIT 1', $nid); $object = db_fetch_object($record); return $object; } /** * Retrieve tasks_advanced part of a node using its left value. * * @ingroup tasks_advanced_support * @param $left integer Node's left * @return void */ function _tasks_advanced_get_node_by_left($left) { $record = db_query('SELECT * FROM {tasks_advanced} WHERE task_tree_left = %d LIMIT 1', $left); $object = db_fetch_object($record); return $object; } /** * Retrieve tasks_advanced part of a node using its right value. * * @ingroup tasks_advanced_support * @param $right integer Node's right * @return void */ function _tasks_advanced_get_node_by_right($right) { $record = db_query('SELECT * FROM {tasks_advanced} WHERE task_tree_right = %d LIMIT 1', $right); $object = db_fetch_object($record); return $object; } /** * Insert node into tree structure as child of parent. * * @ingroup tasks_advanced_support * @param $parent_node object Node where to insert child into tree * @param $children integer Amount of children you want to make space for; default 1 * @return void */ function _tasks_advanced_tree_insert(&$parent_node, $children = 1) { $space = $children * 2; db_query("UPDATE {tasks_advanced} SET task_tree_right = (task_tree_right + ".$space.") WHERE task_tree_right > %d", $parent_node->task_tree_right - 1); db_query("UPDATE {tasks_advanced} SET task_tree_left = (task_tree_left + ".$space.") WHERE task_tree_left > %d", $parent_node->task_tree_right - 1); return TRUE; } /** * Extract node from tree structure. * * @ingroup tasks_advanced_support * @param $node object Node to extract from tree * @param $children integer Amount of children you want to remove space for; default 1 * @return void */ function _tasks_advanced_tree_extract(&$node, $children = 1) { $space = $children * 2; db_query("UPDATE {tasks_advanced} SET task_tree_right = (task_tree_right - ".$space.") WHERE task_tree_right > %d", $node->task_tree_right - 1); db_query("UPDATE {tasks_advanced} SET task_tree_left = (task_tree_left - ".$space.") WHERE task_tree_left > %d", $node->task_tree_right - 1); return TRUE; } /** * Move a branch of the tree to a different parent. * * @ingroup tasks_advanced_support * @param $records recordset Recordset to extract nids from * @return array Array of nids */ function _tasks_advanced_fetch_ids_from_recordset($records) { $ids = array(); while ($row = db_fetch_object($records)) { $ids[] = $row->nid; } return $ids; } /** * Change the order of a node, limited to the same parent. * * @ingroup tasks_advanced_support * @param $node object Node to change order of * @param $direction integer 1 or -1 * @return boolean TRUE on success, FALSE on failure */ function _tasks_advanced_tree_sort(&$node, $direction) { // get node to swap with: WHERE right = left - 1 || WHERE left = right + 1 if ($direction < 0) { $node_b = _tasks_advanced_get_node_by_right($node->task_tree_left - 1); $node_a = $node; } else { $node_a = _tasks_advanced_get_node_by_left($node->task_tree_right + 1); $node_b = $node; } // get list of IDs for branch A $records = db_query("SELECT nid FROM {tasks_advanced} WHERE task_tree_left BETWEEN %d AND %d", $node_a->task_tree_left, $node_a->task_tree_right); $ids_a = _tasks_advanced_fetch_ids_from_recordset($records); if (count($ids_a) == 0) { return FALSE; } $space_a = $node_b->task_tree_right - $node_b->task_tree_left + 1; // get list of IDs for branch B $records = db_query("SELECT nid FROM {tasks_advanced} WHERE task_tree_left BETWEEN %d AND %d", $node_b->task_tree_left, $node_b->task_tree_right); $ids_b = _tasks_advanced_fetch_ids_from_recordset($records); if (count($ids_b) == 0) { return FALSE; } $space_b = $node_a->task_tree_right - $node_a->task_tree_left + 1; // update branch A db_query("UPDATE {tasks_advanced} SET task_tree_left = (task_tree_left - %d), task_tree_right = (task_tree_right - %d) WHERE nid IN (%s)", $space_a, $space_a, implode(', ', $ids_a)); // update branch B db_query("UPDATE {tasks_advanced} SET task_tree_left = (task_tree_left + %d), task_tree_right = (task_tree_right + %d) WHERE nid IN (%s)", $space_b, $space_b, implode(', ', $ids_b)); return TRUE; } /** * Move a branch of the tree to a different parent. * * @ingroup tasks_advanced_support * @param $node object Node to move * @param $parent integer Parent node's nid * @return boolean TRUE on success, FALSE on failure */ function _tasks_advanced_tree_move(&$node, $parent) { // fetch parent node $parent_node = _tasks_advanced_get_node($parent); // make sure we're not moving to a child of current branch if ($node->task_tree_left < $parent_node->task_tree_left && $node->task_tree_right > $parent_node->task_tree_right) { return FALSE; } // make sure we're not moving a node with an unchanged parent if ($parent_node->task_tree_left < $node->task_tree_left && $parent_node->task_tree_right > $node->task_tree_right && $parent_node->task_tree_depth == $node->task_tree_depth - 1) { /* print "Not doing anything...
\n"; print "Level: {$node->task_tree_depth}
\n"; print "Parent Level: {$parent_node->task_tree_depth}
\n"; */ return FALSE; } // fetch ids for branch we're moving $records = db_query("SELECT nid FROM {tasks_advanced} WHERE task_tree_left BETWEEN %d AND %d", $node->task_tree_left, $node->task_tree_right); $ids = _tasks_advanced_fetch_ids_from_recordset($records); $ids_str = implode(', ', $ids); // calculate size of extracted node $size_of_node = $node->task_tree_right - $node->task_tree_left + 1; $depth_diff = $parent_node->task_tree_depth + 1 - $node->task_tree_depth; // calculate min and max for left and right that we need to move // this makes sure we don't affect any records needlessly if ($parent_node->task_tree_left < $node->task_tree_left && $parent_node->task_tree_right > $node->task_tree_right && $parent_node->task_tree_depth < $node->task_tree_depth - 1) { // moving up the chain $minmax_a = $node->task_tree_right + 1; $minmax_b = $parent_node->task_tree_right - 1; $direction = -1; $size_of_move = $parent_node->task_tree_right - 1 - $node->task_tree_right; } elseif ($parent_node->task_tree_left < $node->task_tree_left) { // moving left $minmax_a = $parent_node->task_tree_right; $minmax_b = $node->task_tree_left; $direction = 1; $size_of_move = $parent_node->task_tree_right + $size_of_node - 1 - $node->task_tree_right; } else { // moving right $minmax_a = $parent_node->task_tree_right - 1; $minmax_b = $node->task_tree_right; $direction = -1; $size_of_move = $parent_node->task_tree_right - 1 - $node->task_tree_right; } $min = min($minmax_a, $minmax_b); $max = max($minmax_a, $minmax_b); // remove space for item we're moving db_query("UPDATE {tasks_advanced} SET task_tree_left = (task_tree_left + %d) WHERE task_tree_left >= %d AND task_tree_left <= %d AND nid NOT IN (%s)", $size_of_node * $direction, $min, $max, $ids_str); db_query("UPDATE {tasks_advanced} SET task_tree_right = (task_tree_right + %d) WHERE task_tree_right >= %d AND task_tree_right <= %d AND nid NOT IN (%s)", $size_of_node * $direction, $min, $max, $ids_str); // insert node as last of new parent node's children db_query("UPDATE {tasks_advanced} SET task_tree_left = (task_tree_left + %d), task_tree_right = (task_tree_right + %d), task_tree_depth = (task_tree_depth + %d) WHERE nid IN (%s)", $size_of_move, $size_of_move, $depth_diff, $ids_str); return TRUE; } /** * Output user headers. * * @ingroup tasks_advanced_support * @param $uid integer User's id * @param $username string User's name * @return string html */ function _tasks_advanced_user_headers($uid, $username) { if ($username) { $output .= '

'.l(t('%name’s Tasks', array('%name' => ucfirst($username))), 'tasks/user/'.$uid, array(), NULL, NULL, FALSE, TRUE).'

'; } else { $output .= '

'.l(t('Unassigned Tasks'), 'tasks/user/'.$uid, array(), NULL, NULL, FALSE, TRUE).'

'; } return $output; } /** * Output row headers. * * @ingroup tasks_advanced_support * @param $rows array row * @return string html */ function _tasks_advanced_row_headers(&$rows) { $header = array( array('data' => '', 'class' => 'tasks_advanced-colourcode'), array('data' => t('Assigned'), 'class' => 'tasks_advanced-assigned'), array('data' => t('Task'), 'class' => 'tasks_advanced-title'), array('data' => t('Complete?'), 'class' => 'tasks_advanced-completed'), array('data' => t('Details'), 'class' => 'tasks_advanced-details'), array('data' => t('Edit'), 'class' => 'tasks_advanced-edit'), array('data' => t('Order'), 'class' => 'tasks_advanced-order'), ); $output = theme('table', $header, $rows, array('class' => 'task-list')); return $output; } /** * Output a placeholder parent task. * * @ingroup tasks_advanced_support * @param $object object task * @param $type string "user" for individual user page * @param $uid integer User's id * @return array of table row */ function _tasks_advanced_task_placeholder(&$object, $type = NULL, $uid = NULL, $subtask = FALSE) { $assigned_name = $object->assigned_name; if ($object->assigned_to == 0) { $assigned_name = t('none'); } $extra = drupal_unpack($object); $tasks_colour = $extra->tasks_colour; $task = node_load(array('nid' => $object->nid, 'type' => 'tasks')); $row = array( 'data' => array( array( 'data' => '+', 'class' => 'tasks_advanced-colourcode', ), array( 'data' => l($assigned_name, "tasks/user/{$task->assigned_to}"), 'class' => 'tasks_advanced-assigned', ), array( 'data' => ($subtask ? ''.' └─ '.''.t('Unknown Subtask') : t('Unknown Task')), 'class' => 'tasks_advanced-title', ), array( 'data' => ' ', 'class' => 'tasks_advanced-completed', ), array( 'data' => ' ', 'class' => 'tasks_advanced-details', ), array( 'data' => ' ', 'class' => 'tasks_advanced-edit', ), array( 'data' => ' ', 'class' => 'tasks_advanced-order', ), ), ); return $row; } /** * Output a single task. * * @ingroup tasks_advanced_support * @param $object object task * @param $type string "user" for individual user page * @param $uid integer User's id * @return array of table rows */ function _tasks_advanced_task(&$object, $type = NULL, $uid = NULL) { $rows = array(); $assigned_name = $object->assigned_name; if ($object->assigned_to == 0) { $assigned_name = t('none'); } $extra = drupal_unpack($object); $tasks_colour = $extra->tasks_colour; $task = node_load(array('nid' => $object->nid, 'type' => 'tasks')); $tasks_indent = ($object->task_tree_depth > 1 ? ((($object->task_tree_depth - 2) * 3) + 3) : 0); $rows[] = array( 'data' => array( array( 'data' => l(''.($task->tasktype == 'project' ? '+' : ' ').'', "node/{$task->nid}", array(), NULL, NULL, FALSE, TRUE ), 'class' => 'tasks_advanced-colourcode', ), array( 'data' => l($assigned_name, "tasks/user/{$task->assigned_to}"), 'class' => 'tasks_advanced-assigned', ), array( 'data' => ($object->task_tree_depth > 1 ? ''.str_repeat(' ', ($object->task_tree_depth - 2) * 4).' └─ '.'' : '').l($task->title, "node/{$task->nid}", array('name' => 'task'.$task->nid)), //"[{$task->task_tree_left}, {$task->task_tree_right}]". 'class' => 'tasks_advanced-title', 'style' => ($task->completed > 0 ? 'text-decoration: line-through; ' : '').($tasks_indent > 0 ? "padding-left: {$tasks_indent}ex; text-indent: -{$tasks_indent}ex;" : ''), ), array( 'data' => ($task->completed > 0 ? $task->completed : t('No')), 'class' => 'tasks_advanced-completed', ), array( 'data' => "nid}');\">".t('View')." ", 'class' => 'tasks_advanced-details', ), array( 'data' => l("", "node/{$task->nid}/edit/tasks".($type ? "/{$type}" : '').($uid ? "/{$uid}" : ''),array(),null,null,false,true), 'class' => 'tasks_advanced-edit', ), array( 'data' => l(t('Up'), $_GET['q'], array(), "action=up&task={$task->nid}").' '.l(t('Down'), $_GET['q'], array(), "action=down&task={$task->nid}"), 'class' => 'tasks_advanced-order', ), ), ); $task = node_prepare($task); $rows[] = array( 'data' => array( '', array( 'data' => $task->body, 'colspan' => '6', ), ), 'id' => "row-$task->nid", 'class' => 'task-expand', 'style' => 'display:none;', ); return $rows; }