<?php if (!defined('PmWiki')) exit(); // // Copyright (C) Julian I. Kamil <julian.kamil@gmail.com> // No warranty is provided. Use at your own risk. // // Name: todo.php // Author: Julian I. Kamil <julian.kamil@gmail.com> // Created: 2005-03-17 // Description: // This is a PmWiki plugin that provides the capability // to manage a list of to do items. // // History: // 2005-03-17 jik Created. // 2005-03-18 jik Added the ability to filter todo lists // by status and category. // // Initials: // jik - Julian I. Kamil <julian.kamil@gmail.com> // /* * Based on TODO v0.2 * Modified by Didier Lebrun <dl@vaour.net> * * - Fix URLs in ToDoList() * - Sort on any field * - Allow any group (defined in local/config.php) * - Allow customized options lists (defined in local/config.php) * - Allow custom libels (defined in local/config.php) */ define(TODO_VERSION, '0.21beta'); // Can be customized in local/config.php SDV($ToDoGroup, 'TODO'); SDV($todo_priority_names, array( '5' => 'High', '4' => 'Medium high', '3' => 'Medium', '2' => 'Medium low', '1' => 'Low' )); SDV($todo_urgency_names, array( '5' => 'High', '4' => 'Medium high', '3' => 'Medium', '2' => 'Medium low', '1' => 'Low' )); SDV($todo_status_names, array( 'Open', 'In progress', 'On hold', 'Completed', 'Overdue' )); SDV($todo_category_names, array( 'Personal', 'Business', 'Other' )); SDV($todo_field_names, array( 'ID', 'Category', 'Status', 'Priority', 'Urgency', 'Create date', 'Due date', 'Description' )); SDV($todo_delay_names, array( 'tomorrow', 'next week', )); SDV($todo_date_format, 'Y-m-d'); markup( 'todoform', 'inline', '/\\(:todoform:\\)/e', "ToDoForm(\$pagename)" ); markup( 'todolist', 'directive', '/\\(:todolist\\s*(.*?):\\)/e', "ToDoList('', \$pagename, array('q' => PSS('$1')))" ); function GetDirectiveArgs($arguments, $defaults = array()) { $terms = preg_split( '/((?<!\\S)[-+]?[\'"].*?[\'"](?!\\S)|\\S+)/', $arguments['q'], -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); foreach($terms as $term) { if (trim($term)=='') { continue; } if (preg_match('/([^\'":=]*)[:=]([\'"]?)(.*?)\\2$/', $term, $match)) { $defaults[$match[1]] = str_replace("_"," ",$match[3]); } else { if (substr($term, 0, 1)=='-') { $defaults[substr($term, 1)] = 0; } elseif (substr($term, 0, 1)=='+') { $defaults[substr($term, 1)] = 1; } else { $defaults[$term] = 1; } } } return $defaults; } function ToDoForm($pagename) { global $todo_urgency_names, $todo_priority_names, $todo_status_names, $todo_category_names, $todo_field_names, $todo_delay_names, $todo_date_format; for ($index = 1; $index <= count($todo_priority_names); $index++) { $todo_priorities_code .= "<input type='radio' name='todo-priority' value='$index' />\n" ; } for ($index = 1; $index <= count($todo_urgency_names); $index++) { $todo_urgency_code .= "<input type='radio' name='todo-urgency' value='$index' />\n" ; } $todo_status_code = '<select name="todo-status">'; for ($index = 0; $index < count($todo_status_names); $index++) { $todo_status_code .= "<option>$todo_status_names[$index]</option>\n" ; } $todo_status_code .= '</select>'; $todo_category_code = '<select name="todo-category">'; for ($index = 0; $index < count($todo_category_names); $index++) { $todo_category_code .= "<option>$todo_category_names[$index]</option>\n" ; } $todo_category_code .= '</select>'; $todo_priority_low = $todo_priority_names[min(array_keys($todo_priority_names))]; $todo_priority_high = $todo_priority_names[max(array_keys($todo_priority_names))]; $todo_urgency_low = $todo_urgency_names[min(array_keys($todo_priority_names))]; $todo_urgency_high = $todo_urgency_names[max(array_keys($todo_priority_names))]; $create_date = date($todo_date_format); $tomorrow_date = date($todo_date_format, mktime(0, 0, 0, date('m'), date('d')+1, date('Y'))); $next_week_date = date($todo_date_format, mktime(0, 0, 0, date('m'), date('d')+7, date('Y'))); $output[] = <<< EOT <form method='post'> <input type='hidden' name='action' value='posttodo' /> <input type='hidden' name='todo-create-date' value='{$create_date}' /> <table cellspacing='0' cellpadding='0' class="todo-form"> <tr> <td class='heading'> $todo_field_names[1]: </td> <td> {$todo_category_code} </td> </tr> <tr> <td class='heading'> $todo_field_names[2]: </td> <td> {$todo_status_code} </td> </tr> <tr> <td class='heading'> $todo_field_names[3]: </td> <td> {$todo_priority_low} {$todo_priorities_code} {$todo_priority_high} </td> </tr> <tr> <td class='heading'> $todo_field_names[4]: </td> <td> {$todo_urgency_low} {$todo_urgency_code} {$todo_urgency_high} </td> </tr> <tr> <td class='heading'> $todo_field_names[5]: </td> <td> {$create_date} </td> </tr> <tr valign='top'> <td class='heading'> $todo_field_names[6]: </td> <td> <div> <input type='radio' name='todo-due-date' value='{$tomorrow_date}' checked> {$tomorrow_date} ($todo_delay_names[0]) </div> <div> <input type='radio' name='todo-due-date' value='{$next_week_date}'> {$next_week_date} ($todo_delay_names[1]) </div> <div> <input type='radio' name='todo-due-date' value='0'> <input type='text' name='todo-due-specific-date' size='10'> </div> </td> </tr> <tr> <td class='heading'> $todo_field_names[7]: </td> <td> <input type='text' name='todo-description' size='54' /> </td> </tr> <tr> <td class='heading'> </td> <td> <input type='submit' value='Submit' accesskey='s' /> </td> </tr> </table> </form> </post> EOT; return FmtPageName(implode('', $output), $pagename); } $HTMLStylesFmt[] = <<< EOT .todo-form { border: 1px none #aaa; text-decoration: none; } .todo-form tr td { font-weight: plain; text-align: left; padding: 4px; } .todo-form tr td.heading { text-align: right; width: 200px; padding-right: 6px; } .todo-list { border: 1px solid #aaa; text-decoration: none; } .todo-list thead tr td { font-weight: plain; text-align: left; padding-top: 4px; padding-bottom: 4px; padding-left: 8px; padding-right: 8px; border-top: 1px solid #aaa; border-bottom: 1px solid #666; border-right: 1px solid #aaa; background-color: #ccc; } .todo-list thead tr td.first { border-left: 1px solid #aaa; } .todo-list tbody tr td { padding-top: 4px; padding-bottom: 4px; padding-left: 8px; padding-right: 8px; border-bottom: 1px solid #aaa; border-right: 1px solid #aaa; } .todo-list tbody tr td.first { border-left: 1px solid #aaa; } .todo-list tbody tr td.bottom { border-bottom: 1px solid #666; } .todo-list tbody tr td.description { background-color: #eee; } .todo-list tbody tr td div { padding: none; padding-top: 4px; padding-bottom: 4px; } .todo-list tbody tr td div.heading { border-bottom: 1px solid #aaa; } EOT; /* a { text-decoration: none; } */ include_once("$FarmD/scripts/author.php"); if ($action=='posttodo') { Lock(2); foreach(ListPages("/^$ToDoGroup\\.\\d/") as $i) { $todo = max(@$todo, substr($i, strlen($ToDoGroup) + 1)); } $pagename = sprintf("$ToDoGroup.%05d", @$todo+1); $action = 'edit'; $_REQUEST['post'] = 1; $priority = $todo_priority_names[$_REQUEST['todo-priority']]; $urgency = $todo_urgency_names[$_REQUEST['todo-urgency']]; $_POST['text'] = <<< EOT $todo_field_names[1]: {$_REQUEST['todo-category']} $todo_field_names[2]: {$_REQUEST['todo-status']} $todo_field_names[3]: {$_REQUEST['todo-priority']} -- {$priority} $todo_field_names[4]: {$_REQUEST['todo-urgency']} -- {$urgency} $todo_field_names[5]: {$_REQUEST['todo-create-date']} $todo_field_names[6]: {$_REQUEST['todo-due-date']} $todo_field_names[7]: {$_REQUEST['todo-description']} EOT; } function ToDoList($format, $pagename, $options) { global $ToDoGroup, $todo_field_names; $settings['status'] = 'All'; $settings['category'] = 'All'; $arguments = GetDirectiveArgs($options, $settings); /* printf("<pre>Arguments: \n"); print_r($arguments); printf("</pre>\n"); */ // Get sort args if (isset($_GET['order'])) $order=$_GET['order']; elseif (isset($_POST['order'])) $order=$_POST['order']; else $order=''; $output[] = <<< EOT <table cellspacing='0' cellpadding='0' class="todo-list" align='center'> EOT; $output[] = <<< EOT <thead> <tr> <td class='first'>[[{$pagename}?order=id | $todo_field_names[0]]]</td> <!-- <td>[[{$pagename}?order=category | $todo_field_names[1]]]</td> --> <td>[[{$pagename}?order=status | $todo_field_names[2]]]</td> <td>[[{$pagename}?order=priority | $todo_field_names[3]]]</td> <td>[[{$pagename}?order=urgency | $todo_field_names[4]]]</td> <td>[[{$pagename}?order=create_date | $todo_field_names[5]]]</td> <td>[[{$pagename}?order=due_date | $todo_field_names[6]]]</td> </tr> </thead> EOT; // $options = array_merge($options, @$_REQUEST); $todo_list = ListPages("/^$ToDoGroup\\.\\d+$/"); foreach ($todo_list as $todo_item) { $page = ReadPage($todo_item); preg_match_all( "/(^|\n)([A-Za-z][^:]*):([^\n]*)/", $page['text'], $match ); $title_parts = split('\.', $todo_item); $category = split(':', $match[0][0]); $status = split(':', $match[0][1]); $priority = split(':', $match[0][2]); $numeric_priority = split('--', $priority[1]); $urgency = split(':', $match[0][3]); $numeric_urgency = split('--', $urgency[1]); $create_date = split(':', $match[0][4]); $due_date = split(':', $match[0][5]); $description = split(':', $match[0][6]); $display = TRUE; if (! empty($arguments['status'])) { if (! ($arguments['status'] === 'All')) { if (! (trim($status[1]) === $arguments['status'])) { $display = FALSE; } } } if (! empty($arguments['category'])) { if (! ($arguments['category'] === 'All')) { if (! (trim($category[1]) === $arguments['category'])) { $display = FALSE; } } } // Prepare the arrays for sorting if ($display) { $todo_items[] = array( id => $title_parts[1], category => $category[1], status => $status[1], priority => $priority[1], numeric_priority => $numeric_priority[0], urgency => $urgency[1], numeric_urgency => $numeric_urgency[0], create_date => $create_date[1], due_date => $due_date[1], description => $description[1] ); if ($order) $sort_field[] = ${$order}[1]; } } // Sort the array if ($order) array_multisort($sort_field, SORT_ASC, $todo_items); /* print("<pre>"); printf("Category argument: [%s] ", $arguments['category']); printf("Category value: [%s]\n\n", $category[1]); print("</pre>"); */ // Display the sorted items foreach ($todo_items as $item) { $output[] = <<< EOT <tbody> <tr> <td valign='top' colspan='1' rowspan='2' class='first bottom'> <div>[[{$ToDoGroup}.{$item['id']} | {$item['id']}]]</div> <div>[[{$ToDoGroup}.{$item['id']}?action=edit | (edit)]]</div> </td> <!-- <td colspan='1'> {$category[1]} </td> --> <td colspan='1'> {$item['status']} </td> <td colspan='1'> {$item['numeric_priority']} </td> <td colspan='1'> {$item['numeric_urgency']} </td> <td colspan='1'> {$item['create_date']} </td> <td colspan='1'> {$item['due_date']} </td> </tr> <!-- <tr> <td colspan='6'> <a href=''> Description </a> </td> </tr> --> <tr> <td colspan='5' class='bottom description'> {$item['category']} — {$item['description']} </td> </tr> </tbody> EOT; // } } $output[] = <<< EOT </table> EOT; return FmtPageName(implode('', $output), $pagename); } ?>