<?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']} &mdash; {$item['description']}
        </td>
    </tr>
    </tbody>
EOT;
//        }
    }

    $output[] = <<< EOT
</table>
EOT;

    return FmtPageName(implode('', $output), $pagename);
}

?>