/[drupal]/contributions/modules/tasks/tasks.module
ViewVC logotype

Contents of /contributions/modules/tasks/tasks.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.18 - (show annotations) (download) (as text)
Tue Jun 19 20:11:44 2007 UTC (2 years, 5 months ago) by scor
Branch: MAIN
CVS Tags: DRUPAL-5--2-0, DRUPAL-5--1-2, HEAD
Branch point for: DRUPAL-5--2, DRUPAL-5
Changes since 1.17: +3 -2 lines
File MIME type: text/x-php
- Patch #66865 by scor: select the parent automatically when adding a subtask
1 <?php
2 // $Id: tasks.module,v 1.17 2007/06/19 19:53:03 scor Exp $
3
4 // Implementation of hook_help()
5 function tasks_help($section) {
6 switch ($section) {
7 case 'node/add#tasks':
8 return t('This is a task type with a few fields.');
9 }
10 }
11
12 // Implementation of hook_info
13 function tasks_node_info() {
14 return array(
15 'tasks' => array(
16 'name' => t('Task'),
17 'module' => 'tasks',
18 'description' => t('A task to keep track of.'),
19 ),
20 );
21 }
22
23 // Implementation of hook_perm().
24 function tasks_perm() {
25 return array('create tasks', 'edit own tasks', 'edit all tasks', 'access tasks main page');
26 }
27
28 // Implementation of hook_access().
29 function tasks_access($op, $node) {
30 global $user;
31
32 if ($op == 'create') {
33 return user_access('create tasks');
34 }
35
36 if ($op == 'update' || $op == 'delete') {
37 if (user_access('edit all tasks') || (user_access('edit own tasks') && ($user->uid == $node->uid))) {
38 return TRUE;
39 }
40 }
41 }
42
43 // Implementation of hook_menu().
44 function tasks_menu($may_cache) {
45 $items = array();
46
47 if ($may_cache) {
48 $items[] = array(
49 'path' => 'node/add/tasks',
50 'title' => t('Task'),
51 'access' => user_access('create tasks')
52 );
53 $items[] = array(
54 'path' => 'tasks',
55 'title' => t('Tasks'),
56 'callback' => '_tasks_main',
57 'access' => user_access('access tasks main page'),
58 'type' => MENU_CALLBACK
59 );
60 }
61
62 return $items;
63 }
64
65 // hook_user implementations
66 function tasks_user($op, &$edit, &$user, $category = NULL) {
67 if($op == "form" && $category == 'account' && user_access('access tasks main page')) {
68 $form['tasklist'] = array(
69 '#type' => 'fieldset',
70 '#title' => t('Tasklist'),
71 '#collapsible' => TRUE,
72 '#weight' => 4
73 );
74 $form['tasklist']['tasks_colour'] = array(
75 '#type' => 'textfield',
76 '#title' => t('Colour'),
77 '#default_value' => $edit['tasks_colour'],
78 '#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\')')
79 );
80
81 return $form;
82 }
83 }
84
85 // Implementation of hook_form().
86 function tasks_form(&$node) {
87 drupal_add_js(drupal_get_path('module', 'tasks').'/tasks.js');
88 drupal_add_css(drupal_get_path('module', 'tasks').'/tasks.css');
89
90 $bc = drupal_get_breadcrumb();
91 $bc[] = l(t('Tasks'), 'tasks');
92 drupal_set_breadcrumb($bc);
93
94 $form = array();
95
96 // Get a list of tasklists to choose a parent tasklist
97 if (!isset($node->task_parent) || $node->task_parent != 0) {
98 $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");
99
100 while ($tasklist = db_fetch_object($result)) {
101 if ($tasklist->task_parent == 0) {
102 $tasklist->title = t('-- MASTER TASKLIST --');
103 }
104 $tasklists[$tasklist->nid] = $tasklist->title;
105 $not_master = 1;
106 }
107 if (!$not_master) $tasklists[0] = t('NO PARENT - THIS IS THE MASTER TASKLIST');
108
109 if (isset($_GET['edit']['task_parent'])) {
110 $node->task_parent = $_GET['edit']['task_parent'];
111 }
112 $form['task_parent'] = array(
113 '#type' => 'select',
114 '#title' => t('Parent Tasklist'),
115 '#default_value' => $node->task_parent,
116 '#options' => $tasklists,
117 '#weight' => -10
118 );
119 }
120 else {
121 // parent tasklist
122 $form['task_parent'] = array(
123 '#type' => 'value',
124 '#value' => 0
125 );
126 }
127
128 $form['title'] = array(
129 '#type' => 'textfield',
130 '#title' => t('Task Name'),
131 '#required' => TRUE,
132 '#default_value' => $node->title
133 );
134
135 $form['body'] = array(
136 '#type' => 'textarea',
137 '#title' => t('About this task'),
138 '#default_value' => $node->body,
139 '#rows' => 10
140 );
141
142 $form['format'] = filter_form($node->format);
143
144
145 $sql = 'SELECT u.uid, u.name, u.status, u.created, u.access FROM {users} u WHERE uid != 0 ORDER BY u.name';
146 $result = db_query($sql);
147
148 $users[0] = t('-- Unassigned --');
149 while ($account = db_fetch_object($result)) {
150 $users[$account->uid] = $account->name;
151 }
152
153 $form['assigned_to'] = array(
154 '#type' => 'select',
155 '#title' => t('Assign to user'),
156 '#default_value' => $node->assigned_to,
157 '#options' => $users
158 );
159
160 $form['completed'] = array(
161 '#type' => 'checkbox',
162 '#title' => t('Completed?'),
163 '#default_value' => ($node->completed > 0)?1:0,
164 '#attributes' => array("onclick"=>"toggletasks();")
165 );
166
167 $form['completed_date'] = array(
168 '#type' => 'date',
169 '#title' => t('Date Completed'),
170 '#prefix' => '<div id="completedate">',
171 '#suffix' => '</div>'
172 );
173 if ($node->completed != '0000-00-00') $form['completed_date']['#default_value'] = $node->completed_date;
174
175 $form['from'] = array(
176 '#type' => 'hidden',
177 '#value' => arg(3)
178 );
179
180 if ($node->task_parent) {
181 $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 = $node->task_parent ORDER BY t.order_by ASC");
182
183 while ($tasklist = db_fetch_object($result)) {
184 if ($tasklist->nid == $node->nid) {
185 $tasks[$tasklist->order_by] = t('*************** NO CHANGE ***************');
186 }
187 else {
188 $tasks[$tasklist->order_by] = $tasklist->title;
189 }
190 }
191 $tasks['10000'] = t('*** bottom of list ***');
192
193 $form['order_by'] = array(
194 '#type' => 'select',
195 '#title' => t('Place in tasklist above'),
196 '#default_value' => $node->order_by,
197 '#options' => $tasks,
198 '#prefix' => '<div id="orderby">',
199 '#suffix' => '</div>'
200 );
201 }
202 else {
203 $form['order_by'] = array(
204 '#type' => 'hidden',
205 '#value' => 1,
206 '#prefix' => '<div id="orderby">',
207 '#suffix' => '</div>'
208 );
209 }
210
211
212 return $form;
213 }
214
215
216
217 // Implementation of hooks_forms_alter so we don't see preview or delete buttons for tasks
218 function tasks_form_alter($form_id, &$form) {
219 global $user;
220
221 if ($form_id == 'tasks_node_form') {
222 // Putting preview button back due to popular demand where people had preview as required and hence saw no button at all!
223 //unset($form['preview']);
224 //unset($form['delete']);
225 }
226 }
227
228 function tasks_link($type, $node = NULL, $teaser = FALSE) {
229 $links = array();
230
231 if ($type == 'node' && $node->type == 'tasks' && user_access('create tasks')) {
232 if (!$teaser) {
233 $links['tasks_add_subtask'] = array(
234 'title' => t('Add new sub-task'),
235 'href' => 'node/add/tasks',
236 'attributes' => array('title' => t('Add a new task to this task list')),
237 'query' => 'edit[task_parent]='.$node->nid,
238 );
239 }
240 }
241
242 return $links;
243 }
244
245 // Implementation of hook_insert().
246 function tasks_insert($node) {
247 $node->order_by -= 0.1;
248
249 if (!$node->completed) {
250 $node->completed_date['year'] = "0000";
251 $node->completed_date['month'] = "00";
252 $node->completed_date['day'] = "00";
253 }
254
255 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']);
256 _tasks_order_by($node);
257 }
258
259
260 // Implementation of hook_update().
261 function tasks_update($node) {
262 $node->order_by -= 0.1;
263
264 if (!$node->completed) {
265 $node->completed_date['year'] = "0000";
266 $node->completed_date['month'] = "00";
267 $node->completed_date['day'] = "00";
268 }
269
270 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);
271 _tasks_order_by($node);
272
273 // Redirect to the tasks home page?
274 if ($node->from) {
275 $_REQUEST['destination'] = 'tasks';
276 }
277 }
278
279
280 // Implementation of hook_delete().
281 function tasks_delete($node) {
282 db_query('DELETE FROM {tasks} WHERE nid = %d', $node->nid);
283 }
284
285
286 // Implementation of hook_load().
287 function tasks_load($node) {
288 $additions = db_fetch_object(db_query('SELECT task_parent, assigned_to, order_by, completed FROM {tasks} WHERE nid = %d', $node->nid));
289
290 $additions->completed_date['year'] = substr($additions->completed,0,4);
291 $additions->completed_date['month'] = substr($additions->completed,5,2);
292 $additions->completed_date['day'] = substr($additions->completed,8,2);
293
294 return $additions;
295 }
296
297
298 /*
299 Implementation of hook_view().
300
301 We want to view the task, and list any sub tasks
302 */
303 function tasks_view(&$node, $teaser = FALSE, $page = FALSE) {
304 drupal_add_js(drupal_get_path('module', 'tasks').'/tasks_view.js');
305 drupal_add_css(drupal_get_path('module', 'tasks').'/tasks.css');
306
307 if ($page) {
308 // The page should show the task and any subtasks
309 $bc = drupal_get_breadcrumb();
310 $bc[1] = l(t('Tasks'), 'tasks');
311 if($node->task_parent) {
312 $parent_node = node_load($node->task_parent);
313 if($parent_node->task_parent != 0) {
314 $bc[2] = l($parent_node->title, 'node/'.$parent_node->nid);
315 }
316 }
317 drupal_set_breadcrumb($bc);
318
319 // Look to see if we need to change node order in this list
320 if (($action = $_GET['action']) && ($tid = $_GET['task'])) {
321 $task = node_load(array('nid'=>$tid));
322 if ($action == 'up') {
323 $task->order_by -= 1.3;
324 drupal_set_message(t('Task <b>%task</b> has been moved <b>up</b> the tasklist.', array('%task' => $task->title)));
325 }
326 elseif ($action == 'down') {
327 $task->order_by += 1.3;
328 drupal_set_message(t('Task <b>%task</b> has been moved <b>down</b> the tasklist.', array('%task' => $task->title)));
329 }
330 node_save($task);
331 drupal_goto("node/$node->nid",null,'task'.$task->nid);
332 }
333
334 $node = node_prepare($node, $teaser);
335
336
337 // Now show subtasks if there are any
338
339 // Filter the tasks shown
340 if ($_POST['filter'] == 0) {
341 // incomplete tasks
342 $complete = 'AND t.completed = 0';
343 $order_by = 't.order_by';
344 }
345 elseif ($_POST['filter'] == 1) {
346 // complete tasks
347 $complete = 'AND t.completed > 0';
348 $order_by = 't.completed DESC';
349 }
350 else {
351 // all tasks
352 $order_by = 'IF(t.completed = 0, 0, 1), t.completed DESC, t.order_by';
353 }
354
355 // Get the list of tasks to display
356 //$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);
357 $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);
358
359 $num_rows = db_num_rows($result);
360
361 // Add filtering to the the tasklist
362 $node->content['tasks_filter'] = array(
363 '#value' => drupal_get_form('tasks_view_filter_form', $num_rows, $node->nid),
364 '#weight' => 1,
365 );
366
367 if ($num_rows) {
368 while ($task = db_fetch_object($result)) {
369 $assigned_name = $task->assigned_name;
370 //$tasks_colour = drupal_unpack($task)->tasks_colour;
371 $extra = drupal_unpack($task);
372 $tasks_colour = $extra->tasks_colour;
373 $task = node_load(array('nid'=>$task->nid));
374 $rows[] = array(
375 'data' => array(
376 array('data' => l($assigned_name, "user/".$task->assigned_to), 'style' => "width:25px;".($tasks_colour ? "background:$tasks_colour;":'')),
377 array('data' => l($task->title, "node/$task->nid", array('name'=>'task'.$task->nid)), 'style'=>($task->completed>0)?'text-decoration: line-through;':''),
378 array('data' => ($task->completed>0) ? $task->completed : t('No')),
379 array('data' => "<a href='javascript: void(true);' onClick=\"javascript:toggleVisibility('row-$task->nid');\">". t('Expand') ."</a> ".l("<img src=\"".base_path().drupal_get_path('module', 'tasks')."/icon_edit.gif\" border=\"0\" />", "node/$task->nid/edit/home",array(),null,null,false,true).' '.l("<img src=\"".base_path().drupal_get_path('module', 'tasks')."/arrow_up.png\" border=\"0\" />","node/$node->nid",array(),"action=up&task=$task->nid", null, false, true).' '.l("<img src=\"".base_path().drupal_get_path('module', 'tasks')."/arrow_down.png\" border=\"0\" />","node/$node->nid",array(),"action=down&task=$task->nid", null, false, true)),
380 ),
381 'class' => ($task->completed>0) ? 'completed' : ''
382 );
383 $task = node_prepare($task);
384 $rows[] = array(
385 'data' => array(
386 array('data' => $task->body, 'colspan' => '4'),
387 ),
388 'class' => 'task-expand', 'id' => "row-$task->nid", 'style' => 'display:none;'
389 );
390 }
391 $header = array(t('Assigned'),t('Task'), t('Complete?'), t('Edit'));
392 $node->content['tasks_table'] = array(
393 '#value' => theme('table', $header, $rows, array("id"=>"task-list")),
394 '#weight' => 2,
395 );
396 }
397 }
398
399 return $node;
400 }
401
402 /**
403 * Filtering for tasklist
404 */
405 function tasks_view_filter_form($num_rows, $nid) {
406 // Enable the list of tasks to be filtered
407 $form['filter'] = array(
408 '#type' => 'select',
409 '#title' => t('Showing %num_rows tasks. Filter', array('%num_rows' => $num_rows)),
410 '#default_value' => 0,
411 '#options' => array(0 => t('Incomplete Tasks'), 1 => t('Complete Tasks'), -1 => t('All Tasks')),
412 );
413 $form['submit'] = array(
414 '#type' => 'submit',
415 '#value' => t('Filter')
416 );
417 $form['#redirect'] = FALSE;
418
419 return $form;
420 }
421
422
423
424
425
426 // PRIVATE FUNCTIONS
427
428
429 /*
430 FUNCTION tasks_main()
431
432 This function redirects to the master tasklist if one exists, or creates one if it doesn't
433
434
435 */
436 function _tasks_main() {
437
438
439 // Get the list of tasks to display
440 $result = db_query("SELECT t.* FROM {tasks} t WHERE t.task_parent = 0");
441
442 if ($num_rows = db_num_rows($result)) {
443 if ($num_rows != 1) {
444 drupal_set_message(t('WARNING: more than one master tasklists. Please delete all but one nodes of type tasks where task_parent = 0'));
445 print theme('page','');
446 }
447 else {
448 while ($node = db_fetch_object($result)) {
449 drupal_goto('node/'.$node->nid);
450 }
451 }
452 }
453 else {
454 // There are no tasks. Create the master task(list)
455 drupal_set_message(t('<p>There are no tasks yet, so creating a top-level tasklist.</p>'));
456 $node->title = t('Tasklist');
457 $node->uid = 1;
458 $node->filter = variable_get('filter_default_format', 1);
459 $node->status = 1;
460 $node->type = 'tasks';
461 node_save($node);
462 drupal_goto('node/'.$node->nid);
463 }
464 }
465
466
467
468 function _tasks_order_by($node) {
469 // 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
470
471 $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);
472
473 $i = 1;
474 while ($task = db_fetch_object($result)) {
475 if ($task->completed != '0000-00-00') $task->order_by = 0;
476 else {
477 $task->order_by = $i;
478 $i++;
479 }
480
481 db_query("UPDATE {tasks} SET order_by = %d WHERE nid = %d", $task->order_by, $task->nid);
482 }
483 }

  ViewVC Help
Powered by ViewVC 1.1.2