From 95870fc7a23b79650a50cbff943c8a3ea7248fd7 Mon Sep 17 00:00:00 2001 From: DavidBadura Date: Wed, 8 Jul 2015 23:29:50 +0000 Subject: [PATCH] optimize proxy implementation --- src/Proxy/UuidContainer.php | 30 +++++++++++ src/Task.php | 2 +- src/TaskManager.php | 99 +++++++++++++++++++++++++------------ tests/TaskManagerTest.php | 66 ++++++++++++++++++++++++- 4 files changed, 162 insertions(+), 35 deletions(-) create mode 100644 src/Proxy/UuidContainer.php diff --git a/src/Proxy/UuidContainer.php b/src/Proxy/UuidContainer.php new file mode 100644 index 0000000..30ac92c --- /dev/null +++ b/src/Proxy/UuidContainer.php @@ -0,0 +1,30 @@ + + */ +class UuidContainer +{ + /** + * @var string + */ + protected $uuid; + + /** + * @param string $uuid + */ + public function __construct($uuid) + { + $this->uuid = $uuid; + } + + /** + * @return string + */ + public function getUuid() + { + return $this->uuid; + } +} \ No newline at end of file diff --git a/src/Task.php b/src/Task.php index adcc979..b4af602 100644 --- a/src/Task.php +++ b/src/Task.php @@ -304,7 +304,7 @@ class Task /** * @param Task[] $tasks */ - public function setDependencies(array $tasks) + public function setDependencies(array $tasks = []) { $this->depends = new ArrayCollection(); diff --git a/src/TaskManager.php b/src/TaskManager.php index e0b798c..df091b8 100644 --- a/src/TaskManager.php +++ b/src/TaskManager.php @@ -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 @@ -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, + &$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', '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 diff --git a/tests/TaskManagerTest.php b/tests/TaskManagerTest.php index 6955328..c6e0fed 100644 --- a/tests/TaskManagerTest.php +++ b/tests/TaskManagerTest.php @@ -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