optimize proxy implementation

This commit is contained in:
DavidBadura 2015-07-08 23:29:50 +00:00
parent 79e63251f4
commit 95870fc7a2
4 changed files with 162 additions and 35 deletions

View File

@ -0,0 +1,30 @@
<?php
namespace DavidBadura\Taskwarrior\Proxy;
/**
* @author David Badura <d.a.badura@gmail.com>
*/
class UuidContainer
{
/**
* @var string
*/
protected $uuid;
/**
* @param string $uuid
*/
public function __construct($uuid)
{
$this->uuid = $uuid;
}
/**
* @return string
*/
public function getUuid()
{
return $this->uuid;
}
}

View File

@ -304,7 +304,7 @@ class Task
/**
* @param Task[] $tasks
*/
public function setDependencies(array $tasks)
public function setDependencies(array $tasks = [])
{
$this->depends = new ArrayCollection();

View File

@ -6,11 +6,11 @@ use DavidBadura\Taskwarrior\Config\Context;
use DavidBadura\Taskwarrior\Config\Report;
use DavidBadura\Taskwarrior\Exception\ReferenceException;
use DavidBadura\Taskwarrior\Exception\TaskwarriorException;
use DavidBadura\Taskwarrior\Proxy\UuidContainer;
use DavidBadura\Taskwarrior\Query\QueryBuilder;
use DavidBadura\Taskwarrior\Serializer\Handler\CarbonHandler;
use DavidBadura\Taskwarrior\Serializer\Handler\DependsHandler;
use DavidBadura\Taskwarrior\Serializer\Handler\RecurringHandler;
use DavidBadura\Taskwarrior\Serializer\Handler\TaskHandler;
use Doctrine\Common\Collections\ArrayCollection;
use JMS\Serializer\Handler\HandlerRegistryInterface;
use JMS\Serializer\JsonSerializationVisitor;
@ -18,9 +18,9 @@ use JMS\Serializer\Naming\CamelCaseNamingStrategy;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use JMS\Serializer\Serializer;
use JMS\Serializer\SerializerBuilder;
use ProxyManager\Factory\LazyLoadingGhostFactory;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\Proxy\LazyLoadingInterface;
use ProxyManager\Proxy\ValueHolderInterface;
/**
* @author David Badura <d.a.badura@gmail.com>
@ -92,17 +92,9 @@ class TaskManager
return $this->tasks[$uuid];
}
$tasks = $this->filter($uuid);
$task = $this->exportOne($uuid);
if (count($tasks) == 0) {
return null;
}
if (count($tasks) == 1) {
return $tasks[0];
}
throw new TaskwarriorException();
return $this->tasks[$uuid] = $task;
}
/**
@ -114,15 +106,34 @@ class TaskManager
$result = $this->export($filter);
foreach ($result as $key => $task) {
if (isset($this->tasks[$task->getUuid()])) {
$result[$key] = $this->tasks[$task->getUuid()];
$this->merge($result[$key], $task);
// not yet known? then remember it
if (!isset($this->tasks[$task->getUuid()])) {
$this->tasks[$task->getUuid()] = $task;
continue;
}
$this->tasks[$task->getUuid()] = $task;
// replace result entry
$result[$key] = $prev = $this->tasks[$task->getUuid()];
// not proxy? update task
if (!$prev instanceof LazyLoadingInterface || !$prev instanceof ValueHolderInterface) {
$this->merge($prev, $task);
continue;
}
// wrapper object is a task? skip
if ($prev->getWrappedValueHolderValue() instanceof Task) {
continue;
}
// replace proxy initializer
$prev->setProxyInitializer(function (&$wrappedObject, LazyLoadingInterface $proxy) use ($task) {
$proxy->setProxyInitializer(null);
$wrappedObject = $task;
});
}
return new ArrayCollection($result);
@ -301,21 +312,21 @@ class TaskManager
return $this->tasks[$uuid];
}
$self = $this;
$factory = new LazyLoadingValueHolderFactory();
$initializer = function (
&$wrappedObject,
LazyLoadingInterface $proxy,
$method,
array $parameters,
& $initializer
) use ($self, $uuid) {
$initializer = null;
$wrappedObject = $this->export($uuid)[0];
return true;
$method
) use ($uuid) {
if ('getUuid' == $method) {
if (!$wrappedObject) {
$wrappedObject = new UuidContainer($uuid);
}
} else {
$proxy->setProxyInitializer(null);
$wrappedObject = $this->exportOne($uuid);
}
};
$task = $factory->createProxy('DavidBadura\Taskwarrior\Task', $initializer);
@ -328,7 +339,12 @@ class TaskManager
*/
private function refresh(Task $task)
{
$clean = $this->export($task->getUuid())[0];
// skip refresh & initailize task
if ($task instanceof LazyLoadingInterface && !$task->isProxyInitialized()) {
return;
}
$clean = $this->exportOne($task->getUuid());
$this->merge($task, $clean);
}
@ -340,19 +356,38 @@ class TaskManager
{
$json = $this->taskwarrior->export($filter);
/** @var Task[] $tasks */
$tasks = $this->getSerializer()->deserialize($json, 'array<DavidBadura\Taskwarrior\Task>', 'json');
foreach ($tasks as $task) {
if ($task->getDependencies()) {
continue;
if (!$task->getDependencies()) {
$task->setDependencies([]);
}
$task->setDependencies(array());
}
return $tasks;
}
/**
* @param string|array $filter
* @return Task
* @throws TaskwarriorException
*/
private function exportOne($filter)
{
$tasks = $this->export($filter);
if (count($tasks) == 0) {
throw new TaskwarriorException('task not found');
}
if (count($tasks) > 1) {
throw new TaskwarriorException('multiple task found');
}
return $tasks[0];
}
/**
* @param Task $task
* @throws TaskwarriorException

View File

@ -138,8 +138,10 @@ class TaskManagerTest extends \PHPUnit_Framework_TestCase
public function testDontFind()
{
$this->setExpectedException('DavidBadura\Taskwarrior\Exception\TaskwarriorException',
"task not found");
$task = $this->taskManager->find('56464asd46s4adas54da6');
$this->assertNull($task);
}
public function testDoubleSave()
@ -806,7 +808,6 @@ class TaskManagerTest extends \PHPUnit_Framework_TestCase
$this->taskManager->save($task1);
}
public function testDependencies()
{
$task1 = new Task();
@ -828,6 +829,7 @@ class TaskManagerTest extends \PHPUnit_Framework_TestCase
$temp2 = $temp1->getDependencies()[0];
$this->assertInstanceOf('DavidBadura\Taskwarrior\Task', $temp2);
$this->assertEquals($task2->getUuid(), $temp2->getUuid());
$this->assertEquals('b', $temp2->getDescription());
$temp1->removeDependency($temp2);
@ -840,6 +842,66 @@ class TaskManagerTest extends \PHPUnit_Framework_TestCase
$this->assertCount(0, $temp1->getDependencies());
}
public function testLazyReferencesUuid()
{
$task = $this->taskManager->getReference('foo');
$this->assertEquals('foo', $task->getUuid());
}
public function testLazyReferencesNotFound()
{
$this->setExpectedException('DavidBadura\Taskwarrior\Exception\TaskwarriorException');
$task = $this->taskManager->getReference('foo');
$task->getDescription();
}
public function testLazyReferencesLoad()
{
$task = new Task();
$task->setDescription('foo');
$this->taskManager->save($task);
$this->taskManager->clear();
$task2 = $this->taskManager->getReference($task->getUuid());
$this->assertNotSame($task, $task2);
$this->assertEquals('foo', $task2->getDescription());
}
public function testSameReferences()
{
$task = new Task();
$task->setDescription('foo');
$this->taskManager->save($task);
$task2 = $this->taskManager->getReference($task->getUuid());
$this->assertSame($task, $task2);
$this->assertEquals('foo', $task2->getDescription());
}
public function testFilterReferences()
{
$task = new Task();
$task->setDescription('foo');
$this->taskManager->save($task);
$this->taskManager->clear();
$task = $this->taskManager->getReference($task->getUuid());
$this->taskManager->filter();
$this->assertEquals('foo', $task->getDescription());
}
/**
* @param string $string
* @return \DateTime