Taskwarrior/src/Taskwarrior.php

323 lines
6.8 KiB
PHP
Raw Normal View History

2015-02-05 13:41:03 -06:00
<?php
namespace DavidBadura\Taskwarrior;
use JMS\Serializer\SerializerBuilder;
use Symfony\Component\Filesystem\Filesystem;
2015-02-05 16:00:30 -06:00
use Symfony\Component\Process\ProcessBuilder;
2015-02-05 13:41:03 -06:00
/**
* @author David Badura <d.a.badura@gmail.com>
*/
class Taskwarrior
{
/**
* @var array
*/
private $rcOptions;
/**
* @var Task[]
*/
private $tasks = [];
/**
* @param string $taskrc
* @param string $taskData
2015-02-05 16:00:30 -06:00
* @param array $rcOptions
2015-02-05 13:41:03 -06:00
*/
public function __construct($taskrc = '~/.taskrc', $taskData = '~/.task', $rcOptions = [])
{
$this->rcOptions = array_merge(
array(
'rc:' . $taskrc,
'rc.data.location=' . $taskData,
2015-02-05 15:28:00 -06:00
'rc.json.array=true',
2015-02-05 13:41:03 -06:00
'rc.confirmation=no',
),
$rcOptions
);
}
/**
* @param Task $task
*/
public function save(Task $task)
{
if (!$task->getUuid()) {
$this->add($task);
} else {
$this->edit($task);
}
}
/**
* @param string $uuid
* @return Task
* @throws TaskwarriorException
*/
public function find($uuid)
{
if (isset($this->tasks[$uuid])) {
return $this->tasks[$uuid];
}
2015-02-06 02:49:28 -06:00
$tasks = $this->filterAll($uuid);
2015-02-05 13:41:03 -06:00
if (count($tasks) == 0) {
return null;
}
if (count($tasks) == 1) {
return $tasks[0];
}
throw new TaskwarriorException();
}
/**
* @param $filter
* @return Task[]
*/
2015-02-06 02:49:28 -06:00
public function filterAll($filter = '')
2015-02-05 13:41:03 -06:00
{
$result = $this->export($filter);
foreach ($result as $key => $task) {
if (isset($this->tasks[$task->getUuid()])) {
$result[$key] = $this->tasks[$task->getUuid()];
continue;
}
$this->tasks[$task->getUuid()] = $task;
}
return $result;
}
2015-02-05 16:00:30 -06:00
/**
* @param string $filter
* @return Task[]
*/
2015-02-06 02:49:28 -06:00
public function filter($filter = '')
2015-02-05 16:00:30 -06:00
{
2015-02-06 02:49:28 -06:00
$tasks = $this->filterAll($filter . ' status:pending');
2015-02-05 17:34:57 -06:00
return $this->sort($tasks);
2015-02-05 16:00:30 -06:00
}
2015-02-05 13:41:03 -06:00
/**
* @param Task $task
*/
public function delete(Task $task)
{
2015-02-05 16:00:30 -06:00
if (!$task->getUuid()) {
return;
}
$this->command('delete', $task->getUuid());
2015-02-05 17:09:29 -06:00
$this->update($task);
2015-02-05 13:41:03 -06:00
}
/**
* @param Task $task
*/
public function done(Task $task)
{
2015-02-05 16:00:30 -06:00
if (!$task->getUuid()) {
return;
}
$this->command('done', $task->getUuid());
2015-02-05 17:09:29 -06:00
$this->update($task);
2015-02-05 13:41:03 -06:00
}
/**
*
*/
public function clear()
{
$this->tasks = [];
}
/**
* @param $json
* @return string
* @throws TaskwarriorException
*/
private function import($json)
{
$fs = new Filesystem();
$file = tempnam(sys_get_temp_dir(), 'task') . '.json';
$fs->dumpFile($file, $json);
$output = $this->command('import', $file);
if (!preg_match('/([0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12})/', $output, $matches)) {
throw new TaskwarriorException();
}
return $matches[1];
}
/**
* @param string $filter
* @return Task[]
*/
private function export($filter = '')
{
$json = $this->command('export', $filter);
2015-02-05 15:28:00 -06:00
$serializer = SerializerBuilder::create()
->addDefaultHandlers()
->build();
2015-02-05 13:41:03 -06:00
2015-02-05 15:28:00 -06:00
return $serializer->deserialize($json, 'array<DavidBadura\Taskwarrior\Task>', 'json');
2015-02-05 13:41:03 -06:00
}
/**
* @param string $command
* @param string $filter
2015-02-05 16:00:30 -06:00
* @param array $options
2015-02-05 13:41:03 -06:00
* @return string
* @throws TaskwarriorException
*/
private function command($command, $filter = null, $options = array())
{
$builder = $this->createProcessBuilder();
if ($filter) {
$builder->add($filter);
}
$builder->add($command);
foreach ($options as $param) {
$builder->add($param);
}
$process = $builder->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new TaskwarriorException(
$process->getErrorOutput(),
$process->getExitCode(),
$process->getCommandLine()
);
}
return $process->getOutput();
}
/**
* @param Task $task
* @throws TaskwarriorException
*/
private function add(Task $task)
{
$json = $this->serializeTask($task);
$uuid = $this->import($json);
2015-02-05 17:09:29 -06:00
$this->setValue($task, 'uuid', $uuid);
2015-02-05 13:41:03 -06:00
$this->tasks[$uuid] = $task;
$this->update($task);
}
/**
* @param Task $task
*/
private function edit(Task $task)
{
2015-02-05 17:09:29 -06:00
$options = [];
if ($task->getDue()) {
$options[] = 'due:' . $task->getDue()->format('Ymd\THis\Z');
2015-02-05 17:34:57 -06:00
} else {
$options[] = 'due:';
2015-02-05 17:09:29 -06:00
}
$options[] = $task->getDescription();
2015-02-05 13:41:03 -06:00
$this->command('modify', $task->getUuid(), $options);
2015-02-05 17:09:29 -06:00
$this->update($task);
2015-02-05 13:41:03 -06:00
}
/**
* @param Task $task
*/
private function update(Task $task)
{
2015-02-05 17:09:29 -06:00
$clean = $this->export($task->getUuid())[0];
$this->setValue($task, 'urgency', $clean->getUrgency());
$this->setValue($task, 'status', $clean->getStatus());
2015-02-05 13:41:03 -06:00
}
2015-02-05 17:34:57 -06:00
/**
* @param Task[] $tasks
* @return Task[]
*/
private function sort(array $tasks)
{
usort($tasks, function (Task $a, Task $b) {
if(0 != $diff = $b->getUrgency() - $a->getUrgency()) {
return $diff;
}
return $a->getEntry() >= $b->getEntry() ? 1 : -1;
});
return $tasks;
}
2015-02-05 13:41:03 -06:00
/**
* @return ProcessBuilder
*/
private function createProcessBuilder()
{
$builder = new ProcessBuilder();
foreach ($this->rcOptions as $option) {
$builder->add($option);
}
$builder->setPrefix('task');
$builder->setTimeout(360);
return $builder;
}
/**
*
* @param Task $task
* @return string
*/
private function serializeTask(Task $task)
{
$serializer = SerializerBuilder::create()
->addDefaultHandlers()
->build();
$result = $serializer->serialize($task, 'json');
return str_replace("\\/", "/", $result);
}
/**
2015-02-05 17:09:29 -06:00
* @param Task $task
* @param string $attr
* @param mixed $value
2015-02-05 13:41:03 -06:00
*/
2015-02-05 17:09:29 -06:00
private function setValue(Task $task, $attr, $value)
2015-02-05 13:41:03 -06:00
{
2015-02-05 17:09:29 -06:00
$reflectionClass = new \ReflectionClass('DavidBadura\Taskwarrior\Task');
2015-02-05 17:34:57 -06:00
$prop = $reflectionClass->getProperty($attr);
2015-02-05 17:09:29 -06:00
$prop->setAccessible(true);
$prop->setValue($task, $value);
2015-02-05 13:41:03 -06:00
}
}