Skip to content

Commit cb38897

Browse files
committed
Add lookup strategy to writer
1 parent 45a36fa commit cb38897

File tree

4 files changed

+177
-83
lines changed

4 files changed

+177
-83
lines changed

src/DoctrineWriter.php

+33-65
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Port\Doctrine;
44

55
use Port\Doctrine\Exception\UnsupportedDatabaseTypeException;
6+
use Port\Doctrine\LookupStrategy\FieldsLookupStrategy;
67
use Port\Writer;
78
use Doctrine\Common\Util\Inflector;
89
use Doctrine\DBAL\Logging\SQLLogger;
@@ -26,20 +27,6 @@ class DoctrineWriter implements Writer, Writer\FlushableWriter
2627
*/
2728
protected $objectManager;
2829

29-
/**
30-
* Fully qualified model name
31-
*
32-
* @var string
33-
*/
34-
protected $objectName;
35-
36-
/**
37-
* Doctrine object repository
38-
*
39-
* @var ObjectRepository
40-
*/
41-
protected $objectRepository;
42-
4330
/**
4431
* @var ClassMetadata
4532
*/
@@ -60,57 +47,50 @@ class DoctrineWriter implements Writer, Writer\FlushableWriter
6047
protected $truncate = true;
6148

6249
/**
63-
* List of fields used to lookup an object
64-
*
65-
* @var array
50+
* @var LookupStrategy
6651
*/
67-
protected $lookupFields = [];
52+
private $lookupStrategy;
6853

69-
/**
70-
* Method used for looking up the item
71-
*
72-
* @var array
73-
*/
74-
protected $lookupMethod;
54+
public static function withLookupStrategy(
55+
ObjectManager $objectManager,
56+
LookupStrategy $lookupStrategy
57+
) {
58+
return new self($objectManager, null, null, $lookupStrategy);
59+
}
7560

7661
/**
7762
* Constructor
7863
*
79-
* @param ObjectManager $objectManager
80-
* @param string $objectName
81-
* @param string|array $index Field or fields to find current entities by
82-
* @param string $lookupMethod Method used for looking up the item
64+
* @param ObjectManager $objectManager
65+
* @param string $objectName
66+
* @param string|array $index Field or fields to find current
67+
* entities by
68+
* @param string $lookupMethod Method used for looking up the item
69+
* @param LookupStrategy $lookupStrategy
70+
*
71+
* @throws UnsupportedDatabaseTypeException
8372
*/
8473
public function __construct(
8574
ObjectManager $objectManager,
8675
$objectName,
8776
$index = null,
88-
$lookupMethod = 'findOneBy'
77+
$lookupMethod = 'findOneBy',
78+
LookupStrategy $lookupStrategy = null
8979
) {
9080
$this->ensureSupportedObjectManager($objectManager);
9181
$this->objectManager = $objectManager;
92-
$this->objectRepository = $objectManager->getRepository($objectName);
9382
$this->objectMetadata = $objectManager->getClassMetadata($objectName);
94-
//translate objectName in case a namespace alias is used
95-
$this->objectName = $this->objectMetadata->getName();
96-
if ($index) {
97-
if (is_array($index)) {
98-
$this->lookupFields = $index;
99-
} else {
100-
$this->lookupFields = [$index];
83+
84+
if ($objectManager !== null && $index !== null) {
85+
$lookupStrategy = (new FieldsLookupStrategy($objectManager, $objectName))
86+
->withIndex($index);
87+
88+
if ($lookupMethod) {
89+
$lookupStrategy = $lookupStrategy->withLookupMethod($lookupMethod);
10190
}
102-
}
10391

104-
if (!method_exists($this->objectRepository, $lookupMethod)) {
105-
throw new \InvalidArgumentException(
106-
sprintf(
107-
'Repository %s has no method %s',
108-
get_class($this->objectRepository),
109-
$lookupMethod
110-
)
111-
);
92+
$this->lookupStrategy = $lookupStrategy;
11293
}
113-
$this->lookupMethod = [$this->objectRepository, $lookupMethod];
11494
}
11595

11696
/**
@@ -189,7 +169,7 @@ public function writeItem(array $item)
189169
public function flush()
190170
{
191171
$this->objectManager->flush();
192-
$this->objectManager->clear($this->objectName);
172+
$this->objectManager->clear($this->objectMetadata->getName());
193173
}
194174

195175
/**
@@ -284,7 +264,9 @@ protected function truncateTable()
284264
$query = $connection->getDatabasePlatform()->getTruncateTableSQL($tableName, true);
285265
$connection->executeQuery($query);
286266
} elseif ($this->objectManager instanceof \Doctrine\ODM\MongoDB\DocumentManager) {
287-
$this->objectManager->getDocumentCollection($this->objectName)->remove(array());
267+
$this->objectManager->getDocumentCollection(
268+
$this->objectMetadata->getName()
269+
)->remove([]);
288270
}
289271
}
290272

@@ -320,27 +302,13 @@ protected function reEnableLogging()
320302
*/
321303
protected function findOrCreateItem(array $item)
322304
{
323-
$object = null;
324305
// If the table was not truncated to begin with, find current object
325306
// first
326307
if (!$this->truncate) {
327-
if (!empty($this->lookupFields)) {
328-
$lookupConditions = array();
329-
foreach ($this->lookupFields as $fieldName) {
330-
$lookupConditions[$fieldName] = $item[$fieldName];
331-
}
332-
333-
$object = call_user_func($this->lookupMethod, $lookupConditions);
334-
} else {
335-
$object = $this->objectRepository->find(current($item));
336-
}
337-
}
338-
339-
if (!$object) {
340-
return $this->getNewInstance();
308+
return $this->lookupStrategy->lookup($item);
341309
}
342310

343-
return $object;
311+
return $this->getNewInstance();
344312
}
345313

346314
protected function ensureSupportedObjectManager(ObjectManager $objectManager)

src/LookupStrategy.php

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Port\Doctrine;
4+
5+
/**
6+
* Finds existing objects in the database.
7+
*/
8+
interface LookupStrategy
9+
{
10+
/**
11+
* Look up an item in the database.
12+
*
13+
* @param array $item
14+
*
15+
* @return mixed | null Null if no object was found.
16+
*/
17+
public function lookup(array $item);
18+
}
+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
namespace Port\Doctrine\LookupStrategy;
4+
5+
use Doctrine\Common\Persistence\ObjectManager;
6+
use Doctrine\Common\Persistence\ObjectRepository;
7+
use Port\Doctrine\LookupStrategy;
8+
9+
/**
10+
* Default lookup strategy using object fields.
11+
*/
12+
class FieldsLookupStrategy implements LookupStrategy
13+
{
14+
/**
15+
* @var ObjectManager
16+
*/
17+
private $objectManager;
18+
19+
/**
20+
* @var ObjectRepository
21+
*/
22+
private $objectRepository;
23+
24+
/**
25+
* @var array
26+
*/
27+
private $lookupFields;
28+
29+
/**
30+
* @var string
31+
*/
32+
private $lookupMethod = 'findOneBy';
33+
34+
/**
35+
* @param ObjectManager $objectManager
36+
* @param string $objectName Fully qualified model name
37+
*/
38+
public function __construct(ObjectManager $objectManager, $objectName)
39+
{
40+
$this->objectManager = $objectManager;
41+
$this->objectRepository = $objectManager->getRepository($objectName);
42+
$this->lookupFields = $objectManager->getClassMetadata($objectName)->getIdentifierFieldNames();
43+
}
44+
45+
/**
46+
* @param string $field Field to current current objects by.
47+
*
48+
* @return self
49+
*/
50+
public function withLookupField($field)
51+
{
52+
return $this->withLookupFields([$field]);
53+
}
54+
55+
/**
56+
* Create lookup strategy with index
57+
*
58+
* @param array $fields Fields to find current objects by.
59+
*
60+
* @return self
61+
*/
62+
public function withLookupFields(array $fields)
63+
{
64+
$new = clone $this;
65+
$this->lookupFields = $fields;
66+
67+
return $new;
68+
}
69+
70+
/**
71+
* Doctrine repository method for finding objects.
72+
*
73+
* @param string $lookupMethod
74+
*
75+
* @return self
76+
*/
77+
public function withLookupMethod($lookupMethod)
78+
{
79+
if (!method_exists($this->objectRepository, $lookupMethod)) {
80+
throw new \InvalidArgumentException(
81+
sprintf(
82+
'Repository %s has no method %s',
83+
get_class($this->objectRepository),
84+
$lookupMethod
85+
)
86+
);
87+
}
88+
89+
$new = clone $this;
90+
$new->lookupMethod = [$this->objectRepository, $lookupMethod];
91+
92+
return $new;
93+
}
94+
95+
/**
96+
* {@inheritdoc}
97+
*/
98+
public function lookup(array $item)
99+
{
100+
$lookupConditions = array();
101+
foreach ($this->lookupFields as $fieldName) {
102+
$lookupConditions[$fieldName] = $item[$fieldName];
103+
}
104+
105+
return call_user_func($this->lookupMethod, $lookupConditions);
106+
}
107+
}

tests/DoctrineWriterTest.php

+19-18
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Port\Doctrine\Tests;
44

55
use Port\Doctrine\DoctrineWriter;
6+
use Port\Doctrine\LookupStrategy\FieldsLookupStrategy;
67
use Port\Doctrine\Tests\Fixtures\Entity\TestEntity;
78

89
class DoctrineWriterTest extends \PHPUnit_Framework_TestCase
@@ -57,11 +58,7 @@ public function testUnsupportedDatabaseTypeException()
5758
protected function getEntityManager()
5859
{
5960
$em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
60-
->setMethods(array('getRepository', 'getClassMetadata', 'persist', 'flush', 'clear', 'getConnection', 'getReference'))
61-
->disableOriginalConstructor()
62-
->getMock();
63-
64-
$repo = $this->getMockBuilder('Doctrine\ORM\EntityRepository')
61+
->setMethods(['getRepository', 'getClassMetadata', 'persist', 'flush', 'clear', 'getConnection', 'getReference'])
6562
->disableOriginalConstructor()
6663
->getMock();
6764

@@ -112,10 +109,6 @@ protected function getEntityManager()
112109
->method('executeQuery')
113110
->with('TRUNCATE SQL');
114111

115-
$em->expects($this->once())
116-
->method('getRepository')
117-
->will($this->returnValue($repo));
118-
119112
$em->expects($this->once())
120113
->method('getClassMetadata')
121114
->will($this->returnValue($metadata));
@@ -139,11 +132,7 @@ protected function getEntityManager()
139132
protected function getMongoDocumentManager()
140133
{
141134
$dm = $this->getMockBuilder('Doctrine\ODM\MongoDB\DocumentManager')
142-
->setMethods(array('getRepository', 'getClassMetadata', 'persist', 'flush', 'clear', 'getConnection', 'getDocumentCollection'))
143-
->disableOriginalConstructor()
144-
->getMock();
145-
146-
$repo = $this->getMockBuilder('Doctrine\ODM\MongoDB\DocumentRepository')
135+
->setMethods(['getClassMetadata', 'persist', 'flush', 'clear', 'getConnection', 'getDocumentCollection'])
147136
->disableOriginalConstructor()
148137
->getMock();
149138

@@ -192,10 +181,6 @@ protected function getMongoDocumentManager()
192181
$connection->expects($this->never())
193182
->method('executeQuery');
194183

195-
$dm->expects($this->once())
196-
->method('getRepository')
197-
->will($this->returnValue($repo));
198-
199184
$dm->expects($this->once())
200185
->method('getClassMetadata')
201186
->will($this->returnValue($metadata));
@@ -284,4 +269,20 @@ public function testFlushAndClear()
284269
$writer = new DoctrineWriter($em, 'Port:TestEntity');
285270
$writer->finish();
286271
}
272+
273+
public function testWithLookupStrategy()
274+
{
275+
$em = $this->getEntityManager();
276+
277+
$lookupStrategy = new FieldsLookupStrategy($em, 'Port:TestEntity');
278+
$writer = DoctrineWriter::withLookupStrategy($this->getEntityManager(), $lookupStrategy);
279+
280+
$item = [
281+
'firstProperty' => 'some value',
282+
'secondProperty' => 'some other value',
283+
'firstAssociation'=> new TestEntity(),
284+
];
285+
$writer->writeItem($item);
286+
$writer->finish();
287+
}
287288
}

0 commit comments

Comments
 (0)