From ba51c8349fb124c5fe0273125e333ca452029dfc Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 21 Mar 2015 15:56:47 +0100 Subject: [PATCH 001/332] check if document should be update, by calling document callback, close #91 --- Solr.php | 4 ++++ Tests/SolrTest.php | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/Solr.php b/Solr.php index 72acc983..540f04c4 100644 --- a/Solr.php +++ b/Solr.php @@ -317,6 +317,10 @@ public function updateDocument($entity) { $metaInformations = $this->metaInformationFactory->loadInformation($entity); + if (!$this->addToIndex($metaInformations, $entity)) { + return; + } + $doc = $this->toDocument($metaInformations); $event = new Event($this->solrClientCore, $metaInformations); diff --git a/Tests/SolrTest.php b/Tests/SolrTest.php index b442952d..0ed1e37e 100644 --- a/Tests/SolrTest.php +++ b/Tests/SolrTest.php @@ -183,6 +183,24 @@ public function testUpdateDocument() $solr->updateDocument(new ValidTestEntity()); } + public function testDoNotUpdateDocumentIfDocumentCallbackAvoidIt() + { + $this->eventDispatcher->expects($this->never()) + ->method('dispatch'); + + $this->assertUpdateQueryWasNotExecuted(); + + $information = new MetaInformation(); + $information->setSynchronizationCallback('shouldBeIndex'); + $this->setupMetaFactoryLoadOneCompleteInformation($information); + + $filteredEntity = new ValidTestEntityFiltered(); + $filteredEntity->shouldIndex = true; + + $solr = new Solr($this->solrClientFake, $this->commandFactory, $this->eventDispatcher, $this->metaFactory, $this->mapper); + $solr->updateDocument($filteredEntity); + } + public function testRemoveDocument() { $this->assertDeleteQueryWasExecuted(); From 186fd18824d008df4d077898f9afbc9d0c31cf35 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 21 Mar 2015 16:04:14 +0100 Subject: [PATCH 002/332] introduce AbstractSolrTest to avoid multiple test-execution of solr-testcases --- Tests/AbstractSolrTest.php | 124 ++++++++++++++++++++++++++++++++++++ Tests/MulticoreSolrTest.php | 4 +- Tests/SolrTest.php | 115 +-------------------------------- 3 files changed, 128 insertions(+), 115 deletions(-) create mode 100644 Tests/AbstractSolrTest.php diff --git a/Tests/AbstractSolrTest.php b/Tests/AbstractSolrTest.php new file mode 100644 index 00000000..086d94d8 --- /dev/null +++ b/Tests/AbstractSolrTest.php @@ -0,0 +1,124 @@ +metaFactory = $metaFactory = $this->getMock( + 'FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory', + array(), + array(), + '', + false + ); + $this->config = $this->getMock('FS\SolrBundle\SolrConnection', array(), array(), '', false); + $this->commandFactory = CommandFactoryStub::getFactoryWithAllMappingCommand(); + $this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcher', array(), array(), '', false); + $this->mapper = $this->getMock('FS\SolrBundle\Doctrine\Mapper\EntityMapper', array(), array(), '', false); + + $this->solrClientFake = $this->getMock('Solarium\Client', array(), array(), '', false); + } + + protected function assertUpdateQueryExecuted() + { + $updateQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); + $updateQuery->expects($this->once()) + ->method('addDocument'); + + $updateQuery->expects($this->once()) + ->method('addCommit'); + + $this->solrClientFake + ->expects($this->once()) + ->method('createUpdate') + ->will($this->returnValue($updateQuery)); + } + + protected function assertUpdateQueryWasNotExecuted() + { + $updateQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); + $updateQuery->expects($this->never()) + ->method('addDocument'); + + $updateQuery->expects($this->never()) + ->method('addCommit'); + + $this->solrClientFake + ->expects($this->never()) + ->method('createUpdate'); + } + + protected function assertDeleteQueryWasExecuted() + { + $deleteQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); + $deleteQuery->expects($this->once()) + ->method('addDeleteQuery') + ->with($this->isType('string')); + + $deleteQuery->expects($this->once()) + ->method('addCommit'); + + $this->solrClientFake + ->expects($this->once()) + ->method('createUpdate') + ->will($this->returnValue($deleteQuery)); + + $this->solrClientFake + ->expects($this->once()) + ->method('update') + ->with($deleteQuery); + } + + protected function setupMetaFactoryLoadOneCompleteInformation($metaInformation = null) + { + if (null === $metaInformation) { + $metaInformation = MetaTestInformationFactory::getMetaInformation(); + } + + $this->metaFactory->expects($this->once()) + ->method('loadInformation') + ->will($this->returnValue($metaInformation)); + } + + protected function assertQueryWasExecuted($data = array()) + { + $selectQuery = $this->getMock('Solarium\QueryType\Select\Query\Query', array(), array(), '', false); + $selectQuery->expects($this->once()) + ->method('setQuery'); + + $queryResult = new ResultFake($data); + + $this->solrClientFake + ->expects($this->once()) + ->method('createSelect') + ->will($this->returnValue($selectQuery)); + + $this->solrClientFake + ->expects($this->once()) + ->method('select') + ->with($selectQuery) + ->will($this->returnValue($queryResult)); + } + + protected function mapOneDocument() + { + $this->mapper->expects($this->once()) + ->method('toDocument') + ->will($this->returnValue($this->getMock('Solarium\QueryType\Update\Query\Document\DocumentInterface'))); + } +} \ No newline at end of file diff --git a/Tests/MulticoreSolrTest.php b/Tests/MulticoreSolrTest.php index 73df6ab7..7520e6c6 100644 --- a/Tests/MulticoreSolrTest.php +++ b/Tests/MulticoreSolrTest.php @@ -8,10 +8,10 @@ use FS\SolrBundle\Tests\Util\CommandFactoryStub; use FS\SolrBundle\Tests\Util\MetaTestInformationFactory; -class MulticoreSolrTest extends SolrTest +class MulticoreSolrTest extends AbstractSolrTest { - private function assertUpdateQueryExecuted() + protected function assertUpdateQueryExecuted() { $updateQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); $updateQuery->expects($this->once()) diff --git a/Tests/SolrTest.php b/Tests/SolrTest.php index 0ed1e37e..f19426fe 100644 --- a/Tests/SolrTest.php +++ b/Tests/SolrTest.php @@ -24,94 +24,9 @@ * * @group facade */ -class SolrTest extends \PHPUnit_Framework_TestCase +class SolrTest extends AbstractSolrTest { - protected $metaFactory = null; - protected $config = null; - protected $commandFactory = null; - protected $eventDispatcher = null; - protected $mapper = null; - protected $solrClientFake = null; - - public function setUp() - { - $this->metaFactory = $metaFactory = $this->getMock( - 'FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory', - array(), - array(), - '', - false - ); - $this->config = $this->getMock('FS\SolrBundle\SolrConnection', array(), array(), '', false); - $this->commandFactory = CommandFactoryStub::getFactoryWithAllMappingCommand(); - $this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcher', array(), array(), '', false); - $this->mapper = $this->getMock('FS\SolrBundle\Doctrine\Mapper\EntityMapper', array(), array(), '', false); - - $this->solrClientFake = $this->getMock('Solarium\Client', array(), array(), '', false); - } - - private function assertUpdateQueryExecuted() - { - $updateQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); - $updateQuery->expects($this->once()) - ->method('addDocument'); - - $updateQuery->expects($this->once()) - ->method('addCommit'); - - $this->solrClientFake - ->expects($this->once()) - ->method('createUpdate') - ->will($this->returnValue($updateQuery)); - } - - private function assertUpdateQueryWasNotExecuted() - { - $updateQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); - $updateQuery->expects($this->never()) - ->method('addDocument'); - - $updateQuery->expects($this->never()) - ->method('addCommit'); - - $this->solrClientFake - ->expects($this->never()) - ->method('createUpdate'); - } - - protected function assertDeleteQueryWasExecuted() - { - $deleteQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); - $deleteQuery->expects($this->once()) - ->method('addDeleteQuery') - ->with($this->isType('string')); - - $deleteQuery->expects($this->once()) - ->method('addCommit'); - - $this->solrClientFake - ->expects($this->once()) - ->method('createUpdate') - ->will($this->returnValue($deleteQuery)); - - $this->solrClientFake - ->expects($this->once()) - ->method('update') - ->with($deleteQuery); - } - - protected function setupMetaFactoryLoadOneCompleteInformation($metaInformation = null) - { - if (null === $metaInformation) { - $metaInformation = MetaTestInformationFactory::getMetaInformation(); - } - - $this->metaFactory->expects($this->once()) - ->method('loadInformation') - ->will($this->returnValue($metaInformation)); - } - public function testCreateQuery_ValidEntity() { $this->setupMetaFactoryLoadOneCompleteInformation(); @@ -195,7 +110,7 @@ public function testDoNotUpdateDocumentIfDocumentCallbackAvoidIt() $this->setupMetaFactoryLoadOneCompleteInformation($information); $filteredEntity = new ValidTestEntityFiltered(); - $filteredEntity->shouldIndex = true; + $filteredEntity->shouldIndex = false; $solr = new Solr($this->solrClientFake, $this->commandFactory, $this->eventDispatcher, $this->metaFactory, $this->mapper); $solr->updateDocument($filteredEntity); @@ -233,26 +148,6 @@ public function testClearIndex() $solr->clearIndex(); } - private function assertQueryWasExecuted($data = array()) - { - $selectQuery = $this->getMock('Solarium\QueryType\Select\Query\Query', array(), array(), '', false); - $selectQuery->expects($this->once()) - ->method('setQuery'); - - $queryResult = new ResultFake($data); - - $this->solrClientFake - ->expects($this->once()) - ->method('createSelect') - ->will($this->returnValue($selectQuery)); - - $this->solrClientFake - ->expects($this->once()) - ->method('select') - ->with($selectQuery) - ->will($this->returnValue($queryResult)); - } - public function testQuery_NoResponseKeyInResponseSet() { $this->assertQueryWasExecuted(); @@ -348,12 +243,6 @@ public function testAddEntity_FilteredEntityWithUnknownCallback() } } - protected function mapOneDocument() - { - $this->mapper->expects($this->once()) - ->method('toDocument') - ->will($this->returnValue($this->getMock('Solarium\QueryType\Update\Query\Document\DocumentInterface'))); - } } From da9d036d242724e24286ae147b13e7fea5767ea0 Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Mon, 23 Mar 2015 07:47:37 +0100 Subject: [PATCH 003/332] increase required php version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 496f7d15..3f2b28be 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "homepage": "https://github.com/floriansemm/SolrBundle", "license": "MIT", "require": { - "php": ">=5.3.2", + "php": ">=5.4.5", "solarium/solarium": "*" }, "require-dev": { From 43cad34a2508900709e6c7b9c6c9ab8bf22930da Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sat, 28 Mar 2015 20:01:06 +0100 Subject: [PATCH 004/332] Add php nightly to build matrix --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c1c50560..f49adc44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ php: - 5.4 - 5.5 - 5.6 + - nightly before_script: - echo "extension=mongo.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` - curl -s http://getcomposer.org/installer | php From 09fbd4793b49a75ef7bfc63472be2375708cb7de Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sat, 28 Mar 2015 20:04:48 +0100 Subject: [PATCH 005/332] Update .travis.yml --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f49adc44..aa7359b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,9 @@ language: php services: mongodb php: - - 5.3 - 5.4 - 5.5 - 5.6 - - nightly before_script: - echo "extension=mongo.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` - curl -s http://getcomposer.org/installer | php From 590b75280ce4892a4f2395b33000701fd2530c2a Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 4 Apr 2015 15:16:19 +0200 Subject: [PATCH 006/332] get class properties recursive from entire class-hierarchy, fixes #89 --- Doctrine/Annotation/AnnotationReader.php | 27 +++++++++++++--- .../Annotation/AnnotationReaderTest.php | 31 +++++++++++++++++-- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/Doctrine/Annotation/AnnotationReader.php b/Doctrine/Annotation/AnnotationReader.php index e56d90ac..cb73a9dc 100644 --- a/Doctrine/Annotation/AnnotationReader.php +++ b/Doctrine/Annotation/AnnotationReader.php @@ -32,8 +32,7 @@ public function __construct() */ private function getPropertiesByType($entity, $type) { - $reflectionClass = new \ReflectionClass($entity); - $properties = array_merge($reflectionClass->getProperties(), $this->getParentProperties($reflectionClass)); + $properties = $this->readClassProperties($entity); $fields = array(); foreach ($properties as $property) { @@ -61,11 +60,11 @@ private function getPropertiesByType($entity, $type) private function getParentProperties(\ReflectionClass $reflectionClass) { $parent = $reflectionClass->getParentClass(); - if ($parent == null) { - return array(); + if ($parent != null) { + return array_merge($reflectionClass->getProperties(), $this->getParentProperties($parent)); } - return $parent->getProperties(); + return $reflectionClass->getProperties(); } /** @@ -226,4 +225,22 @@ private function getClassAnnotation($entity, $annotationName) return $annotation; } + + /** + * @param object $entity + * + * @return \ReflectionProperty[] + */ + private function readClassProperties($entity) + { + $reflectionClass = new \ReflectionClass($entity); + $inheritedProperties = array_merge($reflectionClass->getProperties(), $this->getParentProperties($reflectionClass)); + + $properties = array(); + foreach ($inheritedProperties as $property) { + $properties[$property->getName()] = $property; + } + + return $properties; + } } diff --git a/Tests/Doctrine/Annotation/AnnotationReaderTest.php b/Tests/Doctrine/Annotation/AnnotationReaderTest.php index d32b41d6..cac28592 100644 --- a/Tests/Doctrine/Annotation/AnnotationReaderTest.php +++ b/Tests/Doctrine/Annotation/AnnotationReaderTest.php @@ -209,9 +209,20 @@ public function readAnnotationsFromBaseClass() $reader = new AnnotationReader(); $fields = $reader->getFields(new ChildEntity()); - $this->assertEquals(2, count($fields)); + $this->assertEquals(3, count($fields)); $this->assertTrue($reader->hasDocumentDeclaration(new ChildEntity())); } + + /** + * @test + */ + public function readAnnotationsFromMultipleClassHierarchy() + { + $reader = new AnnotationReader(); + $fields = $reader->getFields(new ChildEntity2()); + + $this->assertEquals(4, count($fields)); + } } use FS\SolrBundle\Doctrine\Annotation as Solr; @@ -226,7 +237,13 @@ abstract class BaseEntity * * @Solr\Field(type="integer") */ - private $field; + private $baseField1; + + /** + * + * @Solr\Field(type="integer") + */ + protected $baseField2; } class ChildEntity extends BaseEntity @@ -234,5 +251,13 @@ class ChildEntity extends BaseEntity /** * @Solr\Field(type="integer") */ - private $childField; + protected $childField1; +} + +class ChildEntity2 extends ChildEntity +{ + /** + * @Solr\Field(type="integer") + */ + protected $childField2; } \ No newline at end of file From edd488485f7d8aaf1db3dcff1614e771179f24e1 Mon Sep 17 00:00:00 2001 From: The Gitter Badger Date: Fri, 24 Apr 2015 19:44:32 +0000 Subject: [PATCH 007/332] Added Gitter badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f9045b78..922ac283 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ This Bundle provides a simple API to index and query a Solr Index. # Configuration +[![Join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + The bundle requires a working doctrine-orm or doctrine-mongodb configuration. There are no differences in the use. ## Install the Bundle From 929c2d646cc612d2b43782aa0194d05dd1ff186c Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Fri, 24 Apr 2015 21:50:39 +0200 Subject: [PATCH 008/332] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 922ac283..a9ceda12 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ This Bundle provides a simple API to index and query a Solr Index. -# Configuration +And do not forget to [![join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge -[![Join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +# Configuration The bundle requires a working doctrine-orm or doctrine-mongodb configuration. There are no differences in the use. From 7167ac8b157c20f6f9e9c61c4e370bb2b0712bbe Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Fri, 24 Apr 2015 21:51:07 +0200 Subject: [PATCH 009/332] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a9ceda12..eefa587f 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This Bundle provides a simple API to index and query a Solr Index. -And do not forget to [![join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge +And do not forget to [![join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) # Configuration From d44580f3cc5eba4fa50be183bf1148ada972869f Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Fri, 24 Apr 2015 21:53:57 +0200 Subject: [PATCH 010/332] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eefa587f..d11100fe 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This Bundle provides a simple API to index and query a Solr Index. -And do not forget to [![join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +And do not forget to join [![join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) # Configuration From c05a4ef42aa8da5b682d5806b9fcddafaaabb063 Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Fri, 24 Apr 2015 21:54:43 +0200 Subject: [PATCH 011/332] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d11100fe..8056fa50 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This Bundle provides a simple API to index and query a Solr Index. -And do not forget to join [![join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +And do not forget to join the Gitter chat [![join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) # Configuration From e88b68060ea94542d4aa6e02d75c8f17070c45f6 Mon Sep 17 00:00:00 2001 From: Nils Langner Date: Sun, 17 May 2015 16:52:45 +0200 Subject: [PATCH 012/332] Update README.md Changed corename --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8056fa50..21c61bd9 100644 --- a/README.md +++ b/README.md @@ -61,10 +61,10 @@ You have to setup the connection options path: /solr/core1 core: corename timeout: 5 - core1: + core2: host: host port: 8983 - path: /solr/core1 + path: /solr/core2 core: corename timeout: 5 From bd4f880b019103d2999f1730b0676dd0ca6c42e0 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Thu, 25 Jun 2015 10:52:41 +0200 Subject: [PATCH 013/332] listener listens on wrong events #96, add phpdoc --- .../SynchronizationSummaryListener.php | 21 +++++++++++++++++-- Resources/config/services.xml | 4 ++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Event/Listener/SynchronizationSummaryListener.php b/Event/Listener/SynchronizationSummaryListener.php index 4d965362..765409ac 100644 --- a/Event/Listener/SynchronizationSummaryListener.php +++ b/Event/Listener/SynchronizationSummaryListener.php @@ -10,15 +10,29 @@ class SynchronizationSummaryListener { - private $commandResult = null; - private $resultFactory = null; + /** + * @var ConsoleCommandResults + */ + private $commandResult; + /** + * @var ConsoleResultFactory + */ + private $resultFactory; + + /** + * @param ConsoleCommandResults $commandResult + * @param ConsoleResultFactory $resultFactory + */ public function __construct(ConsoleCommandResults $commandResult, ConsoleResultFactory $resultFactory) { $this->commandResult = $commandResult; $this->resultFactory = $resultFactory; } + /** + * @param Event $event + */ public function onSolrError(Event $event) { if ($event instanceof ErrorEvent) { @@ -28,6 +42,9 @@ public function onSolrError(Event $event) } } + /** + * @param Event $event + */ public function onSolrSuccess(Event $event) { $this->commandResult->success( diff --git a/Resources/config/services.xml b/Resources/config/services.xml index f21815e7..32dfe054 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -70,8 +70,8 @@ - - + + From b99a07ea86573810004896387a69cf0d9912d365 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 3 Jul 2015 09:09:40 +0200 Subject: [PATCH 014/332] major code-cleanups and more api-doc fixes --- Client/Builder.php | 5 +- Client/Client.php | 3 + Client/SolrBuilder.php | 2 + Command/ClearIndexCommand.php | 9 ++ Command/SynchronizeIndexCommand.php | 14 ++- Console/CommandResult.php | 32 ++++--- Console/ConsoleCommandResults.php | 6 +- Console/ConsoleErrorListOutput.php | 6 ++ Console/ConsoleResultFactory.php | 8 +- DependencyInjection/Configuration.php | 24 ++--- DependencyInjection/FSSolrExtension.php | 12 +-- Doctrine/Annotation/AnnotationReader.php | 8 +- Doctrine/Annotation/Document.php | 20 +++- Doctrine/Annotation/Field.php | 7 +- Doctrine/Annotation/Id.php | 4 + Doctrine/Annotation/SynchronizationFilter.php | 1 + .../ClassnameResolver/ClassnameResolver.php | 4 + .../ClassnameResolverException.php | 2 +- .../KnownNamespaceAliases.php | 3 + Doctrine/Hydration/DoctrineHydrator.php | 18 ++-- Doctrine/Hydration/HydrationModes.php | 8 +- .../{Hydrator.php => HydratorInterface.php} | 6 +- Doctrine/Hydration/IndexHydrator.php | 10 +- Doctrine/Hydration/ValueHydrator.php | 10 +- Doctrine/Mapper/EntityMapper.php | 14 +-- Doctrine/Mapper/Mapping/CommandFactory.php | 2 +- Doctrine/Mapper/MetaInformation.php | 12 ++- Doctrine/Mapper/MetaInformationFactory.php | 2 +- Event/ErrorEvent.php | 4 + Event/Event.php | 5 +- Event/Events.php | 3 + Event/Listener/AbstractLogListener.php | 3 +- Event/Listener/ClearIndexLogListener.php | 7 +- Event/Listener/DeleteLogListener.php | 4 + Event/Listener/ErrorLogListener.php | 7 +- Event/Listener/InsertLogListener.php | 3 + .../SynchronizationSummaryListener.php | 2 + Event/Listener/UpdateLogListener.php | 4 + FSSolrBundle.php | 9 +- Query/AbstractQuery.php | 4 +- Query/FindByDocumentNameQuery.php | 3 +- Query/FindByIdentifierQuery.php | 2 + Query/SolrQuery.php | 3 + Repository/Repository.php | 17 ++-- Repository/RepositoryInterface.php | 7 ++ Resources/config/event_listener.xml | 88 +++++++++-------- Resources/config/log_listener.xml | 71 +++++++------- Resources/config/services.xml | 95 +++++++++++-------- Solr.php | 16 ++-- Tests/AbstractSolrTest.php | 18 ++-- Tests/Console/ConsoleResultFactoryTest.php | 10 +- .../FSSolrExtensionTest.php | 4 +- .../KnownNamespaceAliasesTest.php | 3 +- .../Hydration/DoctrineHydratorTest.php | 12 ++- .../Doctrine/Hydration/ValueHydratorTest.php | 1 + Tests/Doctrine/Mapper/EntityMapperTest.php | 4 +- .../Integration/Bootstrap/FeatureContext.php | 13 +-- Tests/Integration/EventDispatcherFake.php | 8 +- composer.json | 67 +++++++------ phpunit.xml.dist | 2 +- 60 files changed, 467 insertions(+), 284 deletions(-) rename Doctrine/Hydration/{Hydrator.php => HydratorInterface.php} (62%) diff --git a/Client/Builder.php b/Client/Builder.php index afdd6eba..6b7b3151 100644 --- a/Client/Builder.php +++ b/Client/Builder.php @@ -1,7 +1,10 @@ applyQuery($delete, $index); } + /** + * Runs a *:* delete query on all cores + */ public function clearCores() { $delete = $this->solariumClient->createUpdate(); diff --git a/Client/SolrBuilder.php b/Client/SolrBuilder.php index 06656e94..22fbec0f 100644 --- a/Client/SolrBuilder.php +++ b/Client/SolrBuilder.php @@ -23,6 +23,8 @@ public function __construct(array $settings) } /** + * {@inheritdoc} + * * @return Client */ public function build() diff --git a/Command/ClearIndexCommand.php b/Command/ClearIndexCommand.php index 3f126f43..3862f6ee 100644 --- a/Command/ClearIndexCommand.php +++ b/Command/ClearIndexCommand.php @@ -8,8 +8,14 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +/** + * Command clears the whole index + */ class ClearIndexCommand extends ContainerAwareCommand { + /** + * {@inheritdoc} + */ protected function configure() { $this @@ -17,6 +23,9 @@ protected function configure() ->setDescription('Clear the whole index'); } + /** + * {@inheritdoc} + */ protected function execute(InputInterface $input, OutputInterface $output) { $solr = $this->getContainer()->get('solr.client'); diff --git a/Command/SynchronizeIndexCommand.php b/Command/SynchronizeIndexCommand.php index a41b7374..f4e23948 100644 --- a/Command/SynchronizeIndexCommand.php +++ b/Command/SynchronizeIndexCommand.php @@ -8,8 +8,14 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +/** + * Command synchronizes the DB with solr + */ class SynchronizeIndexCommand extends ContainerAwareCommand { + /** + * {@inheritdoc} + */ protected function configure() { $this->setName('solr:synchronize') @@ -24,6 +30,9 @@ protected function configure() ->setDescription('Index all entities'); } + /** + * {@inheritdoc} + */ protected function execute(InputInterface $input, OutputInterface $output) { $entity = $input->getArgument('entity'); @@ -52,7 +61,8 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($entities as $entity) { try { $solr->synchronizeIndex($entity); - } catch (\Exception $e) {} + } catch (\Exception $e) { + } } $results = $this->getContainer()->get('solr.console.command.results'); @@ -76,8 +86,10 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * @param string $source + * * @throws \InvalidArgumentException if $source is unknown * @throws \RuntimeException if no doctrine instance is configured + * * @return AbstractManagerRegistry */ private function getObjectManager($source) diff --git a/Console/CommandResult.php b/Console/CommandResult.php index 0520ade9..46a2e699 100644 --- a/Console/CommandResult.php +++ b/Console/CommandResult.php @@ -2,10 +2,14 @@ namespace FS\SolrBundle\Console; - +/** + * DTO class which is used to render command result reports + */ class CommandResult { /** + * Entity Id + * * @var int */ private $resultId; @@ -13,23 +17,25 @@ class CommandResult /** * @var string */ - private $message; + private $entityClassname; /** + * Holds the error-message in case of an error + * * @var string */ - private $entity; + private $errorMessage = ''; /** - * @param int $resultId - * @param string $entity - * @param string string $message + * @param int $resultId + * @param string $entityClassname + * @param string $errorMessage */ - public function __construct($resultId, $entity, $message = '') + public function __construct($resultId, $entityClassname, $errorMessage = '') { $this->resultId = $resultId; - $this->entity = $entity; - $this->message = $message; + $this->entityClassname = $entityClassname; + $this->errorMessage = $errorMessage; } /** @@ -43,16 +49,16 @@ public function getResultId() /** * @return string */ - public function getEntity() + public function getEntityClassname() { - return $this->entity; + return $this->entityClassname; } /** * @return string */ - public function getMessage() + public function getErrorMessage() { - return $this->message; + return $this->errorMessage; } } \ No newline at end of file diff --git a/Console/ConsoleCommandResults.php b/Console/ConsoleCommandResults.php index 9d75f3a0..ab5bc1bb 100644 --- a/Console/ConsoleCommandResults.php +++ b/Console/ConsoleCommandResults.php @@ -2,7 +2,11 @@ namespace FS\SolrBundle\Console; - +/** + * Class collects information about failed and succeed operations on entities + * + * Used to display summaries in the console + */ class ConsoleCommandResults { diff --git a/Console/ConsoleErrorListOutput.php b/Console/ConsoleErrorListOutput.php index 79d9c621..e454592d 100644 --- a/Console/ConsoleErrorListOutput.php +++ b/Console/ConsoleErrorListOutput.php @@ -6,6 +6,9 @@ use Symfony\Component\Console\Helper\TableHelper; use Symfony\Component\Console\Output\OutputInterface; +/** + * Helper class which renders a table of errored entities + */ class ConsoleErrorListOutput { /** @@ -35,6 +38,9 @@ public function __construct(OutputInterface $output, TableHelper $tableHelperSet $this->tableHelperSet = $tableHelperSet; } + /** + * Renders a table of all errored entities + */ public function render() { $this->output->writeln(''); diff --git a/Console/ConsoleResultFactory.php b/Console/ConsoleResultFactory.php index ec16955f..1e7bc25d 100644 --- a/Console/ConsoleResultFactory.php +++ b/Console/ConsoleResultFactory.php @@ -2,15 +2,18 @@ namespace FS\SolrBundle\Console; - use FS\SolrBundle\Event\ErrorEvent; use FS\SolrBundle\Event\Event; +/** + * Factory class for CommandResult objects, see fromEvent method + */ class ConsoleResultFactory { /** * @param Event $event + * * @return CommandResult */ public function fromEvent(Event $event) @@ -25,6 +28,7 @@ public function fromEvent(Event $event) /** * @param Event $event + * * @return null|number */ private function getResultId(Event $event) @@ -38,6 +42,7 @@ private function getResultId(Event $event) /** * @param Event $event + * * @return string */ private function getClassname(Event $event) @@ -51,6 +56,7 @@ private function getClassname(Event $event) /** * @param Event $event + * * @return string */ private function getMessage(Event $event) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index dbf8954e..706cb1e0 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -17,17 +17,17 @@ public function getConfigTreeBuilder() $rootNode = $treeBuilder->root('fs_solr'); $rootNode->children() ->arrayNode('endpoints') - ->useAttributeAsKey('name') - ->prototype('array') - ->children() - ->scalarNode('host')->end() - ->scalarNode('port')->end() - ->scalarNode('path')->end() - ->scalarNode('core')->end() - ->scalarNode('timeout')->end() - ->booleanNode('active')->defaultValue(true)->end() - ->end() - ->end() + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->scalarNode('host')->end() + ->scalarNode('port')->end() + ->scalarNode('path')->end() + ->scalarNode('core')->end() + ->scalarNode('timeout')->end() + ->booleanNode('active')->defaultValue(true)->end() + ->end() + ->end() ->end() // ->arrayNode('clients') // ->useAttributeAsKey('name') @@ -40,7 +40,7 @@ public function getConfigTreeBuilder() // ->end() // ->end() ->booleanNode('auto_index')->defaultValue(true)->end() - ->end(); + ->end(); return $treeBuilder; } diff --git a/DependencyInjection/FSSolrExtension.php b/DependencyInjection/FSSolrExtension.php index aa2e86cb..607ab573 100644 --- a/DependencyInjection/FSSolrExtension.php +++ b/DependencyInjection/FSSolrExtension.php @@ -14,7 +14,7 @@ class FSSolrExtension extends Extension { /** - * @param array $configs + * @param array $configs * @param ContainerBuilder $container */ public function load(array $configs, ContainerBuilder $container) @@ -37,7 +37,7 @@ public function load(array $configs, ContainerBuilder $container) } /** - * @param array $config + * @param array $config * @param ContainerBuilder $container */ private function setupClients(array $config, ContainerBuilder $container) @@ -50,7 +50,7 @@ private function setupClients(array $config, ContainerBuilder $container) /** * - * @param array $config + * @param array $config * @param ContainerBuilder $container */ private function setupDoctrineConfiguration(array $config, ContainerBuilder $container) @@ -59,7 +59,7 @@ private function setupDoctrineConfiguration(array $config, ContainerBuilder $con $entityManagers = $container->getParameter('doctrine.entity_managers'); $entityManagersNames = array_keys($entityManagers); - foreach($entityManagersNames as $entityManager) { + foreach ($entityManagersNames as $entityManager) { $container->getDefinition('solr.doctrine.classnameresolver.known_entity_namespaces')->addMethodCall( 'addEntityNamespaces', array(new Reference(sprintf('doctrine.orm.%s_configuration', $entityManager))) @@ -71,7 +71,7 @@ private function setupDoctrineConfiguration(array $config, ContainerBuilder $con $documentManagers = $container->getParameter('doctrine_mongodb.odm.document_managers'); $documentManagersNames = array_keys($documentManagers); - foreach($documentManagersNames as $documentManager) { + foreach ($documentManagersNames as $documentManager) { $container->getDefinition('solr.doctrine.classnameresolver.known_entity_namespaces')->addMethodCall( 'addDocumentNamespaces', array(new Reference(sprintf('doctrine_mongodb.odm.%s_configuration', $documentManager))) @@ -90,7 +90,7 @@ private function setupDoctrineConfiguration(array $config, ContainerBuilder $con * * listener-methods expecting different types of events * - * @param array $config + * @param array $config * @param ContainerBuilder $container */ private function setupDoctrineListener(array $config, ContainerBuilder $container) diff --git a/Doctrine/Annotation/AnnotationReader.php b/Doctrine/Annotation/AnnotationReader.php index cb73a9dc..cb9987e2 100644 --- a/Doctrine/Annotation/AnnotationReader.php +++ b/Doctrine/Annotation/AnnotationReader.php @@ -1,6 +1,8 @@ boost)) { throw new \InvalidArgumentException(sprintf('Invalid boost value %s', $this->boost)); } - + $float = floatval($this->boost); return $float ?: null; } diff --git a/Doctrine/Annotation/Field.php b/Doctrine/Annotation/Field.php index 04baf7af..e3df76c7 100644 --- a/Doctrine/Annotation/Field.php +++ b/Doctrine/Annotation/Field.php @@ -4,6 +4,8 @@ use Doctrine\Common\Annotations\Annotation; /** + * Defines a field of a solr-document + * * @Annotation */ class Field extends Annotation @@ -20,7 +22,7 @@ class Field extends Annotation public $name; /** - * @var numeric + * @var float */ public $boost = 0; @@ -44,6 +46,7 @@ class Field extends Annotation * eg: title_s * * @throws \RuntimeException + * * @return string */ public function getNameWithAlias() @@ -53,6 +56,7 @@ public function getNameWithAlias() /** * @param string $type + * * @return string */ private function getTypeSuffix($type) @@ -86,6 +90,7 @@ public function __toString() /** * @throws \InvalidArgumentException if boost is not a number + * * @return number */ public function getBoost() diff --git a/Doctrine/Annotation/Id.php b/Doctrine/Annotation/Id.php index bb4dafcd..dd96709c 100644 --- a/Doctrine/Annotation/Id.php +++ b/Doctrine/Annotation/Id.php @@ -1,4 +1,5 @@ doctrine = $doctrine; $this->valueHydrator = $valueHydrator; } /** - * @param $document - * @param MetaInformation $metaInformation - * - * @return object + * {@inheritdoc} */ public function hydrate($document, MetaInformation $metaInformation) { diff --git a/Doctrine/Hydration/HydrationModes.php b/Doctrine/Hydration/HydrationModes.php index 553bbc43..7ff89307 100644 --- a/Doctrine/Hydration/HydrationModes.php +++ b/Doctrine/Hydration/HydrationModes.php @@ -2,9 +2,15 @@ namespace FS\SolrBundle\Doctrine\Hydration; - class HydrationModes { + /** + * use only the values from the index. Ignore not indexed db values. + */ const HYDRATE_INDEX = 'index'; + + /** + * use values from the index and db. Resulting entity holds also not indexed values. + */ const HYDRATE_DOCTRINE = 'doctrine'; } \ No newline at end of file diff --git a/Doctrine/Hydration/Hydrator.php b/Doctrine/Hydration/HydratorInterface.php similarity index 62% rename from Doctrine/Hydration/Hydrator.php rename to Doctrine/Hydration/HydratorInterface.php index 6a559914..da6b1a10 100644 --- a/Doctrine/Hydration/Hydrator.php +++ b/Doctrine/Hydration/HydratorInterface.php @@ -4,11 +4,11 @@ use FS\SolrBundle\Doctrine\Mapper\MetaInformation; -interface Hydrator +interface HydratorInterface { /** - * @param $document - * @param MetaInformation $metaInformation + * @param object $document + * @param MetaInformation $metaInformation holds the target entity * * @return object */ diff --git a/Doctrine/Hydration/IndexHydrator.php b/Doctrine/Hydration/IndexHydrator.php index 8cb0ae41..d5fa593f 100644 --- a/Doctrine/Hydration/IndexHydrator.php +++ b/Doctrine/Hydration/IndexHydrator.php @@ -7,23 +7,23 @@ /** * hydrates Entity from Document */ -class IndexHydrator implements Hydrator +class IndexHydrator implements HydratorInterface { /** - * @var Hydrator + * @var HydratorInterface */ private $valueHydrator; /** - * @param Hydrator $valueHydrator + * @param HydratorInterface $valueHydrator */ - public function __construct(Hydrator $valueHydrator) + public function __construct(HydratorInterface $valueHydrator) { $this->valueHydrator = $valueHydrator; } /** - * @param $document + * @param $document * @param MetaInformation $metaInformation * * @return object diff --git a/Doctrine/Hydration/ValueHydrator.php b/Doctrine/Hydration/ValueHydrator.php index 168634e8..a2c2501b 100644 --- a/Doctrine/Hydration/ValueHydrator.php +++ b/Doctrine/Hydration/ValueHydrator.php @@ -4,13 +4,13 @@ use FS\SolrBundle\Doctrine\Mapper\MetaInformation; -class ValueHydrator implements Hydrator +/** + * Maps all values of a given document on a target-entity + */ +class ValueHydrator implements HydratorInterface { /** - * @param $document - * @param MetaInformation $metaInformation - * - * @return object + * {@inheritdoc} */ public function hydrate($document, MetaInformation $metaInformation) { diff --git a/Doctrine/Mapper/EntityMapper.php b/Doctrine/Mapper/EntityMapper.php index 683c8d75..debdff82 100644 --- a/Doctrine/Mapper/EntityMapper.php +++ b/Doctrine/Mapper/EntityMapper.php @@ -2,7 +2,7 @@ namespace FS\SolrBundle\Doctrine\Mapper; use FS\SolrBundle\Doctrine\Hydration\HydrationModes; -use FS\SolrBundle\Doctrine\Hydration\Hydrator; +use FS\SolrBundle\Doctrine\Hydration\HydratorInterface; use FS\SolrBundle\Doctrine\Mapper\Mapping\AbstractDocumentCommand; use FS\SolrBundle\Doctrine\Annotation\Index as Solr; use Solarium\QueryType\Update\Query\Document\Document; @@ -15,12 +15,12 @@ class EntityMapper private $mappingCommand = null; /** - * @var Hydrator + * @var HydratorInterface */ private $doctrineHydrator; /** - * @var Hydrator + * @var HydratorInterface */ private $indexHydrator; @@ -30,10 +30,10 @@ class EntityMapper private $hydrationMode = ''; /** - * @param Hydrator $doctrineHydrator - * @param Hydrator $indexHydrator + * @param HydratorInterface $doctrineHydrator + * @param HydratorInterface $indexHydrator */ - public function __construct(Hydrator $doctrineHydrator, Hydrator $indexHydrator) + public function __construct(HydratorInterface $doctrineHydrator, HydratorInterface $indexHydrator) { $this->doctrineHydrator = $doctrineHydrator; $this->indexHydrator = $indexHydrator; @@ -65,7 +65,7 @@ public function toDocument(MetaInformation $meta) /** * @param \ArrayAccess $document - * @param object $sourceTargetEntity + * @param object $sourceTargetEntity * * @return object * diff --git a/Doctrine/Mapper/Mapping/CommandFactory.php b/Doctrine/Mapper/Mapping/CommandFactory.php index b0f0b632..e1bce63b 100644 --- a/Doctrine/Mapper/Mapping/CommandFactory.php +++ b/Doctrine/Mapper/Mapping/CommandFactory.php @@ -27,7 +27,7 @@ public function get($command) /** * @param AbstractDocumentCommand $command - * @param string $commandName + * @param string $commandName */ public function add(AbstractDocumentCommand $command, $commandName) { diff --git a/Doctrine/Mapper/MetaInformation.php b/Doctrine/Mapper/MetaInformation.php index 8be8358c..3ac1c943 100644 --- a/Doctrine/Mapper/MetaInformation.php +++ b/Doctrine/Mapper/MetaInformation.php @@ -22,7 +22,7 @@ class MetaInformation private $documentName = ''; /** - * @var array + * @var Field[] */ private $fields = array(); @@ -94,7 +94,7 @@ public function getDocumentName() } /** - * @return array With instances of FS\SolrBundle\Doctrine\Annotation\Field + * @return Field[] */ public function getFields() { @@ -118,7 +118,7 @@ public function getEntity() } /** - * @param string $identifiert + * @param string $identifier */ public function setIdentifier($identifier) { @@ -142,7 +142,7 @@ public function setDocumentName($documentName) } /** - * @param multitype: $fields + * @param Field[] $fields */ public function setFields($fields) { @@ -151,6 +151,7 @@ public function setFields($fields) /** * @param string $field + * * @return boolean */ public function hasField($field) @@ -172,7 +173,8 @@ public function setFieldValue($field, $value) } /** - * @param unknown_type $field + * @param string $field + * * @return Field|null */ public function getField($field) diff --git a/Doctrine/Mapper/MetaInformationFactory.php b/Doctrine/Mapper/MetaInformationFactory.php index f91aa3cb..d557152f 100644 --- a/Doctrine/Mapper/MetaInformationFactory.php +++ b/Doctrine/Mapper/MetaInformationFactory.php @@ -42,7 +42,7 @@ public function setClassnameResolver(ClassnameResolver $classnameResolver) } /** - * @param $entity + * @param object $entity * * @return MetaInformation * diff --git a/Event/ErrorEvent.php b/Event/ErrorEvent.php index c690f0fd..1eb09e2b 100644 --- a/Event/ErrorEvent.php +++ b/Event/ErrorEvent.php @@ -1,6 +1,10 @@ sourceEvent; } + /** + * @return bool + */ public function hasSourceEvent() { return $this->sourceEvent !== null; diff --git a/Event/Events.php b/Event/Events.php index 360c0923..9020547e 100644 --- a/Event/Events.php +++ b/Event/Events.php @@ -2,6 +2,9 @@ namespace FS\SolrBundle\Event; +/** + * List of event which can be fired + */ final class Events { const PRE_INSERT = 'solr.pre_insert'; diff --git a/Event/Listener/AbstractLogListener.php b/Event/Listener/AbstractLogListener.php index 8d9cb6ea..2cd30c6b 100644 --- a/Event/Listener/AbstractLogListener.php +++ b/Event/Listener/AbstractLogListener.php @@ -2,7 +2,6 @@ namespace FS\SolrBundle\Event\Listener; use FS\SolrBundle\Doctrine\Mapper\MetaInformation; -use FS\SolrBundle\Event\EventListenerInterface; use Psr\Log\LoggerInterface; abstract class AbstractLogListener @@ -23,6 +22,7 @@ public function __construct(LoggerInterface $logger) /** * @param MetaInformation $metaInformation + * * @return string */ protected function createDocumentNameWithId(MetaInformation $metaInformation) @@ -32,6 +32,7 @@ protected function createDocumentNameWithId(MetaInformation $metaInformation) /** * @param MetaInformation $metaInformation + * * @return string */ protected function createFieldList(MetaInformation $metaInformation) diff --git a/Event/Listener/ClearIndexLogListener.php b/Event/Listener/ClearIndexLogListener.php index 5a8d844a..b7508bb2 100644 --- a/Event/Listener/ClearIndexLogListener.php +++ b/Event/Listener/ClearIndexLogListener.php @@ -2,11 +2,16 @@ namespace FS\SolrBundle\Event\Listener; - use FS\SolrBundle\Event\Event; +/** + * Create a log-entry if the index was cleared + */ class ClearIndexLogListener extends AbstractLogListener { + /** + * @param Event $event + */ public function onClearIndex(Event $event) { $this->logger->debug(sprintf('clear index')); diff --git a/Event/Listener/DeleteLogListener.php b/Event/Listener/DeleteLogListener.php index a6f9e90c..30d69cd7 100644 --- a/Event/Listener/DeleteLogListener.php +++ b/Event/Listener/DeleteLogListener.php @@ -1,8 +1,12 @@ getExceptionMessage(); diff --git a/Event/Listener/InsertLogListener.php b/Event/Listener/InsertLogListener.php index 6d2e6e76..162f908d 100644 --- a/Event/Listener/InsertLogListener.php +++ b/Event/Listener/InsertLogListener.php @@ -3,6 +3,9 @@ use FS\SolrBundle\Event\Event; +/** + * Create a log-entry if a document was insert + */ class InsertLogListener extends AbstractLogListener { diff --git a/Event/Listener/SynchronizationSummaryListener.php b/Event/Listener/SynchronizationSummaryListener.php index 765409ac..5b6e97a9 100644 --- a/Event/Listener/SynchronizationSummaryListener.php +++ b/Event/Listener/SynchronizationSummaryListener.php @@ -8,6 +8,8 @@ use FS\SolrBundle\Event\ErrorEvent; use FS\SolrBundle\Event\Event; +/** + */ class SynchronizationSummaryListener { /** diff --git a/Event/Listener/UpdateLogListener.php b/Event/Listener/UpdateLogListener.php index d9f4960e..cf052755 100644 --- a/Event/Listener/UpdateLogListener.php +++ b/Event/Listener/UpdateLogListener.php @@ -1,8 +1,12 @@ addCompilerPass(new AddCreateDocumentCommandPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION); - } + $container->addCompilerPass(new AddCreateDocumentCommandPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION); + } } diff --git a/Query/AbstractQuery.php b/Query/AbstractQuery.php index 2343d240..3003f863 100644 --- a/Query/AbstractQuery.php +++ b/Query/AbstractQuery.php @@ -24,7 +24,7 @@ abstract class AbstractQuery extends Query private $entity = null; /** - * @return the $entity + * @return object */ public function getEntity() { @@ -56,7 +56,7 @@ public function getDocument() } /** - * @param \FS\SolrBundle\Solr $solr + * @param Solr $solr */ public function setSolr($solr) { diff --git a/Query/FindByDocumentNameQuery.php b/Query/FindByDocumentNameQuery.php index 96bd1f6f..6fa5d428 100644 --- a/Query/FindByDocumentNameQuery.php +++ b/Query/FindByDocumentNameQuery.php @@ -1,7 +1,6 @@ - - - FS\SolrBundle\Doctrine\ORM\Listener\AddDocumentListener - FS\SolrBundle\Doctrine\ORM\Listener\DeleteDocumentListener - FS\SolrBundle\Doctrine\ORM\Listener\UpdateDocumentListener - - FS\SolrBundle\Doctrine\ODM\Listener\AddDocumentListener - FS\SolrBundle\Doctrine\ODM\Listener\DeleteDocumentListener - FS\SolrBundle\Doctrine\ODM\Listener\UpdateDocumentListener - - - - - - - - - - - - - - - - - - - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + + FS\SolrBundle\Doctrine\ORM\Listener\AddDocumentListener + + + FS\SolrBundle\Doctrine\ORM\Listener\DeleteDocumentListener + + + FS\SolrBundle\Doctrine\ORM\Listener\UpdateDocumentListener + + + FS\SolrBundle\Doctrine\ODM\Listener\AddDocumentListener + + + FS\SolrBundle\Doctrine\ODM\Listener\DeleteDocumentListener + + + FS\SolrBundle\Doctrine\ODM\Listener\UpdateDocumentListener + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + \ No newline at end of file diff --git a/Resources/config/log_listener.xml b/Resources/config/log_listener.xml index 82c16513..f91c71da 100644 --- a/Resources/config/log_listener.xml +++ b/Resources/config/log_listener.xml @@ -1,46 +1,47 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + FS\SolrBundle\Event\Listener\InsertLogListener FS\SolrBundle\Event\Listener\UpdateLogListener FS\SolrBundle\Event\Listener\DeleteLogListener - FS\SolrBundle\Event\Listener\ErrorLogListener - FS\SolrBundle\Event\Listener\ClearIndexLogListener - - - - - - - - - - - - - - - - - - - - + FS\SolrBundle\Event\Listener\ErrorLogListener + FS\SolrBundle\Event\Listener\ClearIndexLogListener + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + - - - - - - - + + \ No newline at end of file diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 32dfe054..511162ff 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> @@ -11,53 +11,63 @@ Solarium\Client FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory - FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory - - FS\SolrBundle\Doctrine\ClassnameResolver\ClassnameResolver - FS\SolrBundle\Doctrine\ClassnameResolver\KnownNamespaceAliases + FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory + + + + FS\SolrBundle\Doctrine\ClassnameResolver\ClassnameResolver + + + FS\SolrBundle\Doctrine\ClassnameResolver\KnownNamespaceAliases + FS\SolrBundle\Doctrine\Mapper\Mapping\MapAllFieldsCommand - FS\SolrBundle\Doctrine\Mapper\Mapping\MapIdentifierCommand + FS\SolrBundle\Doctrine\Mapper\Mapping\MapIdentifierCommand + FS\SolrBundle\Console\ConsoleCommandResults - FS\SolrBundle\Event\Listener\SynchronizationSummaryListener + + FS\SolrBundle\Event\Listener\SynchronizationSummaryListener + FS\SolrBundle\Console\ConsoleResultFactory - - - - - - - + + + + + + + - + - + - + + + - + - + - + + + + + + + - - + + - - - - - - - - @@ -66,29 +76,30 @@ - - + + - - - + + + - - + + - - - + + + - + diff --git a/Solr.php b/Solr.php index 540f04c4..6abc1845 100644 --- a/Solr.php +++ b/Solr.php @@ -1,7 +1,7 @@ solrClientCore = $client; $this->commandFactory = $commandFactory; $this->eventManager = $manager; @@ -73,7 +75,7 @@ public function __construct( $this->entityMapper = $entityMapper; } - + /** * @return Client */ @@ -212,7 +214,7 @@ public function addDocument($entity) /** * @param MetaInformation $metaInformation - * @param object $entity + * @param object $entity * * @return boolean * diff --git a/Tests/AbstractSolrTest.php b/Tests/AbstractSolrTest.php index 086d94d8..4caf6a13 100644 --- a/Tests/AbstractSolrTest.php +++ b/Tests/AbstractSolrTest.php @@ -46,7 +46,7 @@ protected function assertUpdateQueryExecuted() $this->solrClientFake ->expects($this->once()) ->method('createUpdate') - ->will($this->returnValue($updateQuery)); + ->will($this->returnValue($updateQuery)); } protected function assertUpdateQueryWasNotExecuted() @@ -68,7 +68,7 @@ protected function assertDeleteQueryWasExecuted() $deleteQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); $deleteQuery->expects($this->once()) ->method('addDeleteQuery') - ->with($this->isType('string')); + ->with($this->isType('string')); $deleteQuery->expects($this->once()) ->method('addCommit'); @@ -76,12 +76,12 @@ protected function assertDeleteQueryWasExecuted() $this->solrClientFake ->expects($this->once()) ->method('createUpdate') - ->will($this->returnValue($deleteQuery)); + ->will($this->returnValue($deleteQuery)); $this->solrClientFake ->expects($this->once()) ->method('update') - ->with($deleteQuery); + ->with($deleteQuery); } protected function setupMetaFactoryLoadOneCompleteInformation($metaInformation = null) @@ -92,7 +92,7 @@ protected function setupMetaFactoryLoadOneCompleteInformation($metaInformation = $this->metaFactory->expects($this->once()) ->method('loadInformation') - ->will($this->returnValue($metaInformation)); + ->will($this->returnValue($metaInformation)); } protected function assertQueryWasExecuted($data = array()) @@ -106,19 +106,19 @@ protected function assertQueryWasExecuted($data = array()) $this->solrClientFake ->expects($this->once()) ->method('createSelect') - ->will($this->returnValue($selectQuery)); + ->will($this->returnValue($selectQuery)); $this->solrClientFake ->expects($this->once()) ->method('select') - ->with($selectQuery) - ->will($this->returnValue($queryResult)); + ->with($selectQuery) + ->will($this->returnValue($queryResult)); } protected function mapOneDocument() { $this->mapper->expects($this->once()) ->method('toDocument') - ->will($this->returnValue($this->getMock('Solarium\QueryType\Update\Query\Document\DocumentInterface'))); + ->will($this->returnValue($this->getMock('Solarium\QueryType\Update\Query\Document\DocumentInterface'))); } } \ No newline at end of file diff --git a/Tests/Console/ConsoleResultFactoryTest.php b/Tests/Console/ConsoleResultFactoryTest.php index 55e464df..2ef4376a 100644 --- a/Tests/Console/ConsoleResultFactoryTest.php +++ b/Tests/Console/ConsoleResultFactoryTest.php @@ -23,7 +23,7 @@ public function resultFromErrorEventContainsExceptionMessage() $factory = new ConsoleResultFactory(); $result = $factory->fromEvent($error); - $this->assertEquals('message', $result->getMessage()); + $this->assertEquals('message', $result->getErrorMessage()); } /** @@ -37,8 +37,8 @@ public function resultNotContainsIdAndEntityWhenMetaInformationNull() $result = $factory->fromEvent($event); $this->assertEquals(null, $result->getResultId()); - $this->assertEquals('', $result->getEntity()); - $this->assertEquals('', $result->getMessage()); + $this->assertEquals('', $result->getEntityClassname()); + $this->assertEquals('', $result->getErrorMessage()); } /** @@ -59,8 +59,8 @@ public function resultFromSuccessEventContainsNoMessage() $result = $factory->fromEvent($event); $this->assertEquals(1, $result->getResultId()); - $this->assertEquals('an entity', $result->getEntity()); - $this->assertEquals('', $result->getMessage()); + $this->assertEquals('an entity', $result->getEntityClassname()); + $this->assertEquals('', $result->getErrorMessage()); } } \ No newline at end of file diff --git a/Tests/DependencyInjection/FSSolrExtensionTest.php b/Tests/DependencyInjection/FSSolrExtensionTest.php index 5baf0e5d..24c28f8a 100644 --- a/Tests/DependencyInjection/FSSolrExtensionTest.php +++ b/Tests/DependencyInjection/FSSolrExtensionTest.php @@ -26,12 +26,12 @@ public function setUp() private function enableOdmConfig() { - $this->container->setParameter('doctrine_mongodb.odm.document_managers', array('default'=>'odm.default.mananger')); + $this->container->setParameter('doctrine_mongodb.odm.document_managers', array('default' => 'odm.default.mananger')); } private function enableOrmConfig() { - $this->container->setParameter('doctrine.entity_managers', array('default'=>'orm.default.mananger')); + $this->container->setParameter('doctrine.entity_managers', array('default' => 'orm.default.mananger')); } private function commonConfig() diff --git a/Tests/Doctrine/ClassnameResolver/KnownNamespaceAliasesTest.php b/Tests/Doctrine/ClassnameResolver/KnownNamespaceAliasesTest.php index 4d899f10..29985b06 100644 --- a/Tests/Doctrine/ClassnameResolver/KnownNamespaceAliasesTest.php +++ b/Tests/Doctrine/ClassnameResolver/KnownNamespaceAliasesTest.php @@ -5,7 +5,8 @@ use FS\SolrBundle\Doctrine\ClassnameResolver\KnownNamespaceAliases; -class KnownNamespaceAliasesTest extends \PHPUnit_Framework_TestCase { +class KnownNamespaceAliasesTest extends \PHPUnit_Framework_TestCase +{ /** * @test diff --git a/Tests/Doctrine/Hydration/DoctrineHydratorTest.php b/Tests/Doctrine/Hydration/DoctrineHydratorTest.php index 2d5564ac..5375b0c9 100644 --- a/Tests/Doctrine/Hydration/DoctrineHydratorTest.php +++ b/Tests/Doctrine/Hydration/DoctrineHydratorTest.php @@ -4,6 +4,8 @@ use FS\SolrBundle\Doctrine\Hydration\DoctrineHydrator; +use FS\SolrBundle\Doctrine\Hydration\DoctrineHydratorInterface; +use FS\SolrBundle\Doctrine\Mapper\MetaInformation; use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; use FS\SolrBundle\Tests\Doctrine\Mapper\SolrDocumentStub; use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntity; @@ -37,7 +39,7 @@ public function foundEntityInDbReplacesEntityOldTargetEntity() $obj = new SolrDocumentStub(array()); $obj->id = 1; - $hydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\Hydrator'); + $hydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\HydratorInterface'); $hydrator->expects($this->once()) ->method('hydrate') ->with($obj, $metainformations) @@ -72,7 +74,7 @@ public function entityFromDbNotFoundShouldNotModifyMetainformations() $obj = new SolrDocumentStub(array()); $obj->id = 1; - $hydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\Hydrator'); + $hydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\HydratorInterface'); $hydrator->expects($this->once()) ->method('hydrate') ->with($obj, $metainformations) @@ -87,9 +89,9 @@ public function entityFromDbNotFoundShouldNotModifyMetainformations() } /** - * @param $metainformations - * @param $fetchedFromDoctrine - * @param $hydratedDocument + * @param MetaInformation $metainformations + * @param object $fetchedFromDoctrine + * @param object $hydratedDocument */ private function assertEntityFromDBReplcesTargetEntity($metainformations, $fetchedFromDoctrine, $hydratedDocument) { diff --git a/Tests/Doctrine/Hydration/ValueHydratorTest.php b/Tests/Doctrine/Hydration/ValueHydratorTest.php index f798cffd..a054aab5 100644 --- a/Tests/Doctrine/Hydration/ValueHydratorTest.php +++ b/Tests/Doctrine/Hydration/ValueHydratorTest.php @@ -4,6 +4,7 @@ use FS\SolrBundle\Doctrine\Hydration\ValueHydrator; +use FS\SolrBundle\Doctrine\Hydration\ValueHydratorInterface; use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; use FS\SolrBundle\Tests\Doctrine\Mapper\SolrDocumentStub; use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntity; diff --git a/Tests/Doctrine/Mapper/EntityMapperTest.php b/Tests/Doctrine/Mapper/EntityMapperTest.php index 38dec220..c9b0cd1a 100644 --- a/Tests/Doctrine/Mapper/EntityMapperTest.php +++ b/Tests/Doctrine/Mapper/EntityMapperTest.php @@ -21,8 +21,8 @@ class EntityMapperTest extends \PHPUnit_Framework_TestCase public function setUp() { - $this->doctrineHydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\Hydrator'); - $this->indexHydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\Hydrator'); + $this->doctrineHydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\HydratorInterface'); + $this->indexHydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\HydratorInterface'); } public function testToDocument_EntityMayNotIndexed() diff --git a/Tests/Integration/Bootstrap/FeatureContext.php b/Tests/Integration/Bootstrap/FeatureContext.php index d7c48d05..d51d6c0a 100644 --- a/Tests/Integration/Bootstrap/FeatureContext.php +++ b/Tests/Integration/Bootstrap/FeatureContext.php @@ -27,7 +27,7 @@ class FeatureContext extends BehatContext */ public function __construct(array $parameters) { - $autoload = __DIR__ . '/../vendor/autoload.php'; + $autoload = __DIR__ . '/../vendor/autoload.php'; if (file_exists($autoload)) { require_once $autoload; } else { @@ -84,12 +84,12 @@ private function setupEntityMapper() $registry = new \FS\SolrBundle\Tests\Integration\DoctrineRegistryFake(); $entityMapper = new \FS\SolrBundle\Doctrine\Mapper\EntityMapper( - new \FS\SolrBundle\Doctrine\Hydration\DoctrineHydrator( + new \FS\SolrBundle\Doctrine\Hydration\DoctrineHydratorInterface( $registry, - new \FS\SolrBundle\Doctrine\Hydration\ValueHydrator() + new \FS\SolrBundle\Doctrine\Hydration\ValueHydratorInterface() ), - new \FS\SolrBundle\Doctrine\Hydration\IndexHydrator( - new \FS\SolrBundle\Doctrine\Hydration\ValueHydrator() + new \FS\SolrBundle\Doctrine\Hydration\IndexHydratorInterface( + new \FS\SolrBundle\Doctrine\Hydration\ValueHydratorInterface() ) ); @@ -151,7 +151,8 @@ private function setupSolrClient() public function assertInsertSuccessful() { if (!$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::POST_INSERT) || - !$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::PRE_INSERT)) { + !$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::PRE_INSERT) + ) { throw new RuntimeException('Insert was not successful'); } } diff --git a/Tests/Integration/EventDispatcherFake.php b/Tests/Integration/EventDispatcherFake.php index 12827a50..44a29263 100644 --- a/Tests/Integration/EventDispatcherFake.php +++ b/Tests/Integration/EventDispatcherFake.php @@ -26,7 +26,7 @@ class EventDispatcherFake implements EventDispatcherInterface * @param string $eventName The name of the event to dispatch. The name of * the event is the name of the method that is * invoked on listeners. - * @param Event $event The event to pass to the event handlers/listeners. + * @param Event $event The event to pass to the event handlers/listeners. * If not supplied, an empty Event instance is created. * * @return Event @@ -88,9 +88,9 @@ public function eventOccurred($eventName) /** * Adds an event listener that listens on the specified events. * - * @param string $eventName The event to listen on + * @param string $eventName The event to listen on * @param callable $listener The listener - * @param integer $priority The higher this value, the earlier an event + * @param integer $priority The higher this value, the earlier an event * listener will be triggered in the chain (defaults to 0) * * @api @@ -119,7 +119,7 @@ public function addSubscriber(EventSubscriberInterface $subscriber) * Removes an event listener from the specified events. * * @param string|array $eventName The event(s) to remove a listener from - * @param callable $listener The listener to remove + * @param callable $listener The listener to remove */ public function removeListener($eventName, $listener) { diff --git a/composer.json b/composer.json index 3f2b28be..6635120c 100644 --- a/composer.json +++ b/composer.json @@ -1,33 +1,38 @@ { - "name": "floriansemm/solr-bundle", - "type": "symfony-bundle", - "description": "Symfony2 Solr integration bundle", - "keywords": ["search", "index", "symfony", "solr"], - "homepage": "https://github.com/floriansemm/SolrBundle", - "license": "MIT", - "require": { - "php": ">=5.4.5", - "solarium/solarium": "*" - }, - "require-dev": { - "doctrine/doctrine-module": "*", - "doctrine/doctrine-orm-module": "*", - "doctrine/mongodb": "*", - "doctrine/mongodb-odm": "*", - "symfony/dependency-injection": "*", - "symfony/http-kernel": "*", - "symfony/config": "*", - "symfony/doctrine-bridge": "*" - }, - "minimum-stability": "alpha", - "autoload": { - "psr-0": { - "FS\\SolrBundle": "" - } - }, - "suggest": { - "doctrine/mongodb": "Required if you want to use the MongoDB ODM features", - "doctrine/mongodb-odm": "Required if you want to use the MongoDB ODM features" - }, - "target-dir": "FS/SolrBundle" + "name": "floriansemm/solr-bundle", + "type": "symfony-bundle", + "description": "Symfony2 Solr integration bundle", + "keywords": [ + "search", + "index", + "symfony", + "solr" + ], + "homepage": "https://github.com/floriansemm/SolrBundle", + "license": "MIT", + "require": { + "php": ">=5.4.5", + "solarium/solarium": "*" + }, + "require-dev": { + "doctrine/doctrine-module": "*", + "doctrine/doctrine-orm-module": "*", + "doctrine/mongodb": "*", + "doctrine/mongodb-odm": "*", + "symfony/dependency-injection": "*", + "symfony/http-kernel": "*", + "symfony/config": "*", + "symfony/doctrine-bridge": "*" + }, + "minimum-stability": "alpha", + "autoload": { + "psr-0": { + "FS\\SolrBundle": "" + } + }, + "suggest": { + "doctrine/mongodb": "Required if you want to use the MongoDB ODM features", + "doctrine/mongodb-odm": "Required if you want to use the MongoDB ODM features" + }, + "target-dir": "FS/SolrBundle" } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index c7fb3206..b6a426e3 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,7 +10,7 @@ stopOnFailure="false" syntaxCheck="false" bootstrap="Tests/bootstrap.php" -> + > From 4feeb82ff68c2eeb3e70d2fbfeb5b24132c22ff7 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 3 Jul 2015 09:36:59 +0200 Subject: [PATCH 015/332] introduce interface for solr class --- Solr.php | 16 +++++----------- SolrInterface.php | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 SolrInterface.php diff --git a/Solr.php b/Solr.php index 6abc1845..02ecb281 100644 --- a/Solr.php +++ b/Solr.php @@ -19,7 +19,7 @@ /** * Class allows to index doctrine entities */ -class Solr +class Solr implements SolrInterface { @@ -129,11 +129,7 @@ public function createQuery($entity) } /** - * @param string $entityAlias - * - * @return Repository - * - * @throws \RuntimeException if repository does not extend FS\SolrBundle\Repository\Repository + * {@inheritdoc} */ public function getRepository($entityAlias) { @@ -160,7 +156,7 @@ public function getRepository($entityAlias) } /** - * @param object $entity + * {@inheritdoc} */ public function removeDocument($entity) { @@ -192,7 +188,7 @@ public function removeDocument($entity) } /** - * @param object $entity + * {@inheritdoc} */ public function addDocument($entity) { @@ -235,9 +231,7 @@ private function addToIndex(MetaInformation $metaInformation, $entity) } /** - * @param AbstractQuery $query - * - * @return array of found documents + * {@inheritdoc} */ public function query(AbstractQuery $query) { diff --git a/SolrInterface.php b/SolrInterface.php new file mode 100644 index 00000000..9619ccda --- /dev/null +++ b/SolrInterface.php @@ -0,0 +1,43 @@ + Date: Mon, 6 Jul 2015 15:13:20 +0200 Subject: [PATCH 016/332] introduce interface for meta-information --- Doctrine/Mapper/MetaInformation.php | 29 ++++---- Doctrine/Mapper/MetaInformationInterface.php | 74 ++++++++++++++++++++ 2 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 Doctrine/Mapper/MetaInformationInterface.php diff --git a/Doctrine/Mapper/MetaInformation.php b/Doctrine/Mapper/MetaInformation.php index 3ac1c943..e60123e8 100644 --- a/Doctrine/Mapper/MetaInformation.php +++ b/Doctrine/Mapper/MetaInformation.php @@ -3,7 +3,7 @@ use FS\SolrBundle\Doctrine\Annotation\Field; -class MetaInformation +class MetaInformation implements MetaInformationInterface { /** @@ -57,8 +57,7 @@ class MetaInformation private $index = ''; /** - * - * @return number + * {@inheritdoc} */ public function getEntityId() { @@ -70,7 +69,7 @@ public function getEntityId() } /** - * @return string + * {@inheritdoc} */ public function getIdentifier() { @@ -78,7 +77,7 @@ public function getIdentifier() } /** - * @return string + * {@inheritdoc} */ public function getClassName() { @@ -86,7 +85,7 @@ public function getClassName() } /** - * @return string + * {@inheritdoc} */ public function getDocumentName() { @@ -94,7 +93,7 @@ public function getDocumentName() } /** - * @return Field[] + * {@inheritdoc} */ public function getFields() { @@ -102,7 +101,7 @@ public function getFields() } /** - * @return string + * {@inheritdoc} */ public function getRepository() { @@ -110,7 +109,7 @@ public function getRepository() } /** - * @return object + * {@inheritdoc} */ public function getEntity() { @@ -173,9 +172,7 @@ public function setFieldValue($field, $value) } /** - * @param string $field - * - * @return Field|null + * {@inheritdoc} */ public function getField($field) { @@ -203,7 +200,7 @@ public function setEntity($entity) } /** - * @return array + * {@inheritdoc} */ public function getFieldMapping() { @@ -219,7 +216,7 @@ public function setFieldMapping($fieldMapping) } /** - * @return number + * {@inheritdoc} */ public function getBoost() { @@ -247,7 +244,7 @@ public function hasSynchronizationFilter() } /** - * @return string + * {@inheritdoc} */ public function getSynchronizationCallback() { @@ -271,7 +268,7 @@ public function setIndex($index) } /** - * @return string + * {@inheritdoc} */ public function getIndex() { diff --git a/Doctrine/Mapper/MetaInformationInterface.php b/Doctrine/Mapper/MetaInformationInterface.php new file mode 100644 index 00000000..f92b7bce --- /dev/null +++ b/Doctrine/Mapper/MetaInformationInterface.php @@ -0,0 +1,74 @@ + Date: Mon, 6 Jul 2015 15:24:22 +0200 Subject: [PATCH 017/332] wrong formatting of services definition causes error while cache-clear, #98 --- Resources/config/event_listener.xml | 35 +++++++++-------------------- Resources/config/log_listener.xml | 3 +-- Resources/config/services.xml | 29 +++++++----------------- 3 files changed, 19 insertions(+), 48 deletions(-) diff --git a/Resources/config/event_listener.xml b/Resources/config/event_listener.xml index a3378a57..b35836e1 100644 --- a/Resources/config/event_listener.xml +++ b/Resources/config/event_listener.xml @@ -5,23 +5,12 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - FS\SolrBundle\Doctrine\ORM\Listener\AddDocumentListener - - - FS\SolrBundle\Doctrine\ORM\Listener\DeleteDocumentListener - - - FS\SolrBundle\Doctrine\ORM\Listener\UpdateDocumentListener - - - FS\SolrBundle\Doctrine\ODM\Listener\AddDocumentListener - - - FS\SolrBundle\Doctrine\ODM\Listener\DeleteDocumentListener - - - FS\SolrBundle\Doctrine\ODM\Listener\UpdateDocumentListener - + FS\SolrBundle\Doctrine\ORM\Listener\AddDocumentListener + FS\SolrBundle\Doctrine\ORM\Listener\DeleteDocumentListener + FS\SolrBundle\Doctrine\ORM\Listener\UpdateDocumentListener + FS\SolrBundle\Doctrine\ODM\Listener\AddDocumentListener + FS\SolrBundle\Doctrine\ODM\Listener\DeleteDocumentListener + FS\SolrBundle\Doctrine\ODM\Listener\UpdateDocumentListener @@ -30,24 +19,20 @@ - + - + - + - + diff --git a/Resources/config/log_listener.xml b/Resources/config/log_listener.xml index f91c71da..b9799c8b 100644 --- a/Resources/config/log_listener.xml +++ b/Resources/config/log_listener.xml @@ -9,8 +9,7 @@ FS\SolrBundle\Event\Listener\UpdateLogListener FS\SolrBundle\Event\Listener\DeleteLogListener FS\SolrBundle\Event\Listener\ErrorLogListener - FS\SolrBundle\Event\Listener\ClearIndexLogListener - + FS\SolrBundle\Event\Listener\ClearIndexLogListener diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 511162ff..46cbd508 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -11,24 +11,16 @@ Solarium\Client FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory - FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory - + FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory - - FS\SolrBundle\Doctrine\ClassnameResolver\ClassnameResolver - - - FS\SolrBundle\Doctrine\ClassnameResolver\KnownNamespaceAliases - + FS\SolrBundle\Doctrine\ClassnameResolver\ClassnameResolver + FS\SolrBundle\Doctrine\ClassnameResolver\KnownNamespaceAliases FS\SolrBundle\Doctrine\Mapper\Mapping\MapAllFieldsCommand - FS\SolrBundle\Doctrine\Mapper\Mapping\MapIdentifierCommand - + FS\SolrBundle\Doctrine\Mapper\Mapping\MapIdentifierCommand FS\SolrBundle\Console\ConsoleCommandResults - - FS\SolrBundle\Event\Listener\SynchronizationSummaryListener - + FS\SolrBundle\Event\Listener\SynchronizationSummaryListener FS\SolrBundle\Console\ConsoleResultFactory @@ -41,21 +33,17 @@ - + - - - + @@ -89,8 +77,7 @@ - + From 114cdb51b56286fcd4778f1bfbaa333757423111 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Tue, 7 Jul 2015 15:40:44 +0200 Subject: [PATCH 018/332] run query in configured index, #99 --- Query/AbstractQuery.php | 21 +++++++++++++++++++++ Solr.php | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Query/AbstractQuery.php b/Query/AbstractQuery.php index 3003f863..6709e3cd 100644 --- a/Query/AbstractQuery.php +++ b/Query/AbstractQuery.php @@ -18,6 +18,11 @@ abstract class AbstractQuery extends Query */ protected $solr = null; + /** + * @var string + */ + protected $index = null; + /** * @var object */ @@ -80,4 +85,20 @@ public function setHydrationMode($mode) { $this->getSolr()->getMapper()->setHydrationMode($mode); } + + /** + * @return string + */ + public function getIndex() + { + return $this->index; + } + + /** + * @param string $index + */ + public function setIndex($index) + { + $this->index = $index; + } } diff --git a/Solr.php b/Solr.php index 02ecb281..4c0e6fe0 100644 --- a/Solr.php +++ b/Solr.php @@ -122,6 +122,7 @@ public function createQuery($entity) $query = new SolrQuery(); $query->setSolr($this); $query->setEntity($entity); + $query->setIndex($metaInformation->getIndex()); $query->setMappedFields($metaInformation->getFieldMapping()); @@ -238,11 +239,12 @@ public function query(AbstractQuery $query) $entity = $query->getEntity(); $queryString = $query->getQuery(); + $runQueryInIndex = $query->getIndex(); $query = $this->solrClientCore->createSelect($query->getOptions()); $query->setQuery($queryString); try { - $response = $this->solrClientCore->select($query); + $response = $this->solrClientCore->select($query, $runQueryInIndex); } catch (\Exception $e) { $errorEvent = new ErrorEvent(null, null, 'query solr'); $errorEvent->setException($e); From 518c51c78c63e6a19b9e8d77a179108087e73330 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Thu, 9 Jul 2015 08:30:14 +0200 Subject: [PATCH 019/332] update solr-test to cover issue #99 --- Tests/AbstractSolrTest.php | 4 ++-- Tests/SolrTest.php | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Tests/AbstractSolrTest.php b/Tests/AbstractSolrTest.php index 4caf6a13..9c761cfd 100644 --- a/Tests/AbstractSolrTest.php +++ b/Tests/AbstractSolrTest.php @@ -95,7 +95,7 @@ protected function setupMetaFactoryLoadOneCompleteInformation($metaInformation = ->will($this->returnValue($metaInformation)); } - protected function assertQueryWasExecuted($data = array()) + protected function assertQueryWasExecuted($data = array(), $index) { $selectQuery = $this->getMock('Solarium\QueryType\Select\Query\Query', array(), array(), '', false); $selectQuery->expects($this->once()) @@ -111,7 +111,7 @@ protected function assertQueryWasExecuted($data = array()) $this->solrClientFake ->expects($this->once()) ->method('select') - ->with($selectQuery) + ->with($selectQuery, $index) ->will($this->returnValue($queryResult)); } diff --git a/Tests/SolrTest.php b/Tests/SolrTest.php index f19426fe..b5e57897 100644 --- a/Tests/SolrTest.php +++ b/Tests/SolrTest.php @@ -150,14 +150,16 @@ public function testClearIndex() public function testQuery_NoResponseKeyInResponseSet() { - $this->assertQueryWasExecuted(); - - $solr = new Solr($this->solrClientFake, $this->commandFactory, $this->eventDispatcher, $this->metaFactory, $this->mapper); - $document = new Document(); $document->addField('document_name_s', 'name'); $query = new FindByDocumentNameQuery(); $query->setDocument($document); + $query->setIndex('index0'); + + $this->assertQueryWasExecuted(array(), 'index0'); + + $solr = new Solr($this->solrClientFake, $this->commandFactory, $this->eventDispatcher, $this->metaFactory, $this->mapper); + $entities = $solr->query($query); $this->assertEquals(0, count($entities)); @@ -167,15 +169,17 @@ public function testQuery_OneDocumentFound() { $arrayObj = new SolrDocumentStub(array('title_s' => 'title')); - $this->assertQueryWasExecuted(array($arrayObj)); - - $solr = new Solr($this->solrClientFake, $this->commandFactory, $this->eventDispatcher, $this->metaFactory, $this->mapper); - $document = new Document(); $document->addField('document_name_s', 'name'); + $query = new FindByDocumentNameQuery(); $query->setDocument($document); $query->setEntity(new ValidTestEntity()); + $query->setIndex('index0'); + + $this->assertQueryWasExecuted(array($arrayObj), 'index0'); + + $solr = new Solr($this->solrClientFake, $this->commandFactory, $this->eventDispatcher, $this->metaFactory, $this->mapper); $entities = $solr->query($query); $this->assertEquals(1, count($entities)); From c7c8b5713eefb26806056ce41431af6b2045e63c Mon Sep 17 00:00:00 2001 From: floriansemm Date: Thu, 9 Jul 2015 08:44:13 +0200 Subject: [PATCH 020/332] verify that correct index is passed to update method --- Tests/AbstractSolrTest.php | 8 +++++++- Tests/SolrTest.php | 14 ++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Tests/AbstractSolrTest.php b/Tests/AbstractSolrTest.php index 9c761cfd..de5d10bd 100644 --- a/Tests/AbstractSolrTest.php +++ b/Tests/AbstractSolrTest.php @@ -34,7 +34,7 @@ public function setUp() $this->solrClientFake = $this->getMock('Solarium\Client', array(), array(), '', false); } - protected function assertUpdateQueryExecuted() + protected function assertUpdateQueryExecuted($index = null) { $updateQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); $updateQuery->expects($this->once()) @@ -47,6 +47,12 @@ protected function assertUpdateQueryExecuted() ->expects($this->once()) ->method('createUpdate') ->will($this->returnValue($updateQuery)); + + $this->solrClientFake + ->expects($this->once()) + ->method('update') + ->with($updateQuery, $index); + } protected function assertUpdateQueryWasNotExecuted() diff --git a/Tests/SolrTest.php b/Tests/SolrTest.php index b5e57897..111fa81c 100644 --- a/Tests/SolrTest.php +++ b/Tests/SolrTest.php @@ -206,7 +206,7 @@ public function testAddEntity_ShouldNotIndexEntity() public function testAddEntity_ShouldIndexEntity() { - $this->assertUpdateQueryExecuted(); + $this->assertUpdateQueryExecuted('index0'); $this->eventDispatcher->expects($this->exactly(2)) ->method('dispatch'); @@ -216,6 +216,7 @@ public function testAddEntity_ShouldIndexEntity() $information = MetaTestInformationFactory::getMetaInformation(); $information->setSynchronizationCallback('shouldBeIndex'); + $information->setIndex('index0'); $this->setupMetaFactoryLoadOneCompleteInformation($information); $this->mapOneDocument(); @@ -226,6 +227,9 @@ public function testAddEntity_ShouldIndexEntity() $this->assertTrue($entity->getShouldBeIndexedWasCalled(), 'filter method was not called'); } + /** + * @expectedException \BadMethodCallException + */ public function testAddEntity_FilteredEntityWithUnknownCallback() { $this->assertUpdateQueryWasNotExecuted(); @@ -238,13 +242,7 @@ public function testAddEntity_FilteredEntityWithUnknownCallback() $this->setupMetaFactoryLoadOneCompleteInformation($information); $solr = new Solr($this->solrClientFake, $this->commandFactory, $this->eventDispatcher, $this->metaFactory, $this->mapper); - try { - $solr->addDocument(new InvalidTestEntityFiltered()); - - $this->fail('BadMethodCallException expected'); - } catch (\BadMethodCallException $e) { - $this->assertTrue(true); - } + $solr->addDocument(new InvalidTestEntityFiltered()); } } From ff4483e1526cb28f9af63a77b6d1cdf99d38482b Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 10 Jul 2015 09:17:30 +0200 Subject: [PATCH 021/332] use MetaInformationInterface for typehints, improve documenation for hydration --- Doctrine/Hydration/DoctrineHydrator.php | 6 +++--- Doctrine/Hydration/HydratorInterface.php | 15 ++++++++++---- Doctrine/Hydration/IndexHydrator.php | 11 ++++------ Doctrine/Hydration/ValueHydrator.php | 4 ++-- Doctrine/Mapper/EntityMapper.php | 4 ++-- .../Mapping/AbstractDocumentCommand.php | 6 +++--- .../Mapper/Mapping/MapAllFieldsCommand.php | 6 +++--- Doctrine/Mapper/MetaInformation.php | 3 +++ Doctrine/Mapper/MetaInformationInterface.php | 6 ++++++ Event/Event.php | 20 ++++++++++--------- Event/Listener/AbstractLogListener.php | 10 +++++----- Solr.php | 20 +++++++++---------- SolrInterface.php | 2 +- 13 files changed, 64 insertions(+), 49 deletions(-) diff --git a/Doctrine/Hydration/DoctrineHydrator.php b/Doctrine/Hydration/DoctrineHydrator.php index 0b82fd77..635af9d5 100644 --- a/Doctrine/Hydration/DoctrineHydrator.php +++ b/Doctrine/Hydration/DoctrineHydrator.php @@ -2,11 +2,11 @@ namespace FS\SolrBundle\Doctrine\Hydration; -use FS\SolrBundle\Doctrine\Mapper\MetaInformation; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; use Symfony\Bridge\Doctrine\RegistryInterface; /** - * A hydrator finds the entity for a given solr-document. This entity is updated with the solr-document values. + * A doctrine-hydrator finds the entity for a given solr-document. This entity is updated with the solr-document values. * * The hydration is necessary because fields, which are not declared as solr-field, will not populate in the result. */ @@ -36,7 +36,7 @@ public function __construct(RegistryInterface $doctrine, HydratorInterface $valu /** * {@inheritdoc} */ - public function hydrate($document, MetaInformation $metaInformation) + public function hydrate($document, MetaInformationInterface $metaInformation) { $entityId = $document->id; $doctrineEntity = $this->doctrine diff --git a/Doctrine/Hydration/HydratorInterface.php b/Doctrine/Hydration/HydratorInterface.php index da6b1a10..f2394bb6 100644 --- a/Doctrine/Hydration/HydratorInterface.php +++ b/Doctrine/Hydration/HydratorInterface.php @@ -2,15 +2,22 @@ namespace FS\SolrBundle\Doctrine\Hydration; -use FS\SolrBundle\Doctrine\Mapper\MetaInformation; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; +/** + * When the index was queried the resulting entities can be instantiated in different ways: + * + * 1. use corresponding db-entity which can contain not indexed properties. The fields of the solr-document will update + * the fields of the entity. Not indexed entity-fields remain untouched with their db-values. + * 2. use a blank entity. Not index fields remain untouched. + */ interface HydratorInterface { /** - * @param object $document - * @param MetaInformation $metaInformation holds the target entity + * @param object $document + * @param MetaInformationInterface $metaInformation holds the target entity * * @return object */ - public function hydrate($document, MetaInformation $metaInformation); + public function hydrate($document, MetaInformationInterface $metaInformation); } \ No newline at end of file diff --git a/Doctrine/Hydration/IndexHydrator.php b/Doctrine/Hydration/IndexHydrator.php index d5fa593f..a687194d 100644 --- a/Doctrine/Hydration/IndexHydrator.php +++ b/Doctrine/Hydration/IndexHydrator.php @@ -2,10 +2,10 @@ namespace FS\SolrBundle\Doctrine\Hydration; -use FS\SolrBundle\Doctrine\Mapper\MetaInformation; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; /** - * hydrates Entity from Document + * Hydrates blank Entity from Document */ class IndexHydrator implements HydratorInterface { @@ -23,12 +23,9 @@ public function __construct(HydratorInterface $valueHydrator) } /** - * @param $document - * @param MetaInformation $metaInformation - * - * @return object + * {@inheritdoc} */ - public function hydrate($document, MetaInformation $metaInformation) + public function hydrate($document, MetaInformationInterface $metaInformation) { $sourceTargetEntity = $metaInformation->getEntity(); $targetEntity = clone $sourceTargetEntity; diff --git a/Doctrine/Hydration/ValueHydrator.php b/Doctrine/Hydration/ValueHydrator.php index a2c2501b..466ae8df 100644 --- a/Doctrine/Hydration/ValueHydrator.php +++ b/Doctrine/Hydration/ValueHydrator.php @@ -2,7 +2,7 @@ namespace FS\SolrBundle\Doctrine\Hydration; -use FS\SolrBundle\Doctrine\Mapper\MetaInformation; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; /** * Maps all values of a given document on a target-entity @@ -12,7 +12,7 @@ class ValueHydrator implements HydratorInterface /** * {@inheritdoc} */ - public function hydrate($document, MetaInformation $metaInformation) + public function hydrate($document, MetaInformationInterface $metaInformation) { $targetEntity = $metaInformation->getEntity(); diff --git a/Doctrine/Mapper/EntityMapper.php b/Doctrine/Mapper/EntityMapper.php index debdff82..ec0fd59c 100644 --- a/Doctrine/Mapper/EntityMapper.php +++ b/Doctrine/Mapper/EntityMapper.php @@ -50,11 +50,11 @@ public function setMappingCommand(AbstractDocumentCommand $command) } /** - * @param MetaInformation $meta + * @param MetaInformationInterface $meta * * @return Document */ - public function toDocument(MetaInformation $meta) + public function toDocument(MetaInformationInterface $meta) { if ($this->mappingCommand instanceof AbstractDocumentCommand) { return $this->mappingCommand->createDocument($meta); diff --git a/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php b/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php index 25364683..b4e92b40 100644 --- a/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php +++ b/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php @@ -1,7 +1,7 @@ getFields(); if (count($fields) == 0) { diff --git a/Doctrine/Mapper/MetaInformation.php b/Doctrine/Mapper/MetaInformation.php index e60123e8..b411869d 100644 --- a/Doctrine/Mapper/MetaInformation.php +++ b/Doctrine/Mapper/MetaInformation.php @@ -3,6 +3,9 @@ use FS\SolrBundle\Doctrine\Annotation\Field; +/** + * Holds meta-information about an entity + */ class MetaInformation implements MetaInformationInterface { diff --git a/Doctrine/Mapper/MetaInformationInterface.php b/Doctrine/Mapper/MetaInformationInterface.php index f92b7bce..05a6bebb 100644 --- a/Doctrine/Mapper/MetaInformationInterface.php +++ b/Doctrine/Mapper/MetaInformationInterface.php @@ -67,8 +67,14 @@ public function getBoost(); */ public function getSynchronizationCallback(); + /** + * @return boolean + */ + public function hasSynchronizationFilter(); + /** * @return string */ public function getIndex(); + } \ No newline at end of file diff --git a/Event/Event.php b/Event/Event.php index cf2fc81d..6fbd6317 100644 --- a/Event/Event.php +++ b/Event/Event.php @@ -1,19 +1,19 @@ getDocumentName() . ':' . $metaInformation->getEntityId(); } /** - * @param MetaInformation $metaInformation + * @param MetaInformationInterface $metaInformation * * @return string */ - protected function createFieldList(MetaInformation $metaInformation) + protected function createFieldList(MetaInformationInterface $metaInformation) { return implode(', ', $metaInformation->getFields()); } diff --git a/Solr.php b/Solr.php index 4c0e6fe0..ec29d7f2 100644 --- a/Solr.php +++ b/Solr.php @@ -2,10 +2,10 @@ namespace FS\SolrBundle; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; use Solarium\QueryType\Update\Query\Document\Document; use FS\SolrBundle\Doctrine\Mapper\EntityMapper; use FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory; -use FS\SolrBundle\Doctrine\Mapper\MetaInformation; use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; use FS\SolrBundle\Event\ErrorEvent; use FS\SolrBundle\Event\Event; @@ -210,14 +210,14 @@ public function addDocument($entity) } /** - * @param MetaInformation $metaInformation - * @param object $entity + * @param MetaInformationInterface $metaInformation + * @param object $entity * * @return boolean * * @throws \BadMethodCallException if callback method not exists */ - private function addToIndex(MetaInformation $metaInformation, $entity) + private function addToIndex(MetaInformationInterface $metaInformation, $entity) { if (!$metaInformation->hasSynchronizationFilter()) { return true; @@ -332,11 +332,11 @@ public function updateDocument($entity) } /** - * @param MetaInformation $metaInformation + * @param MetaInformationInterface $metaInformation * * @return Document */ - private function toDocument(MetaInformation $metaInformation) + private function toDocument(MetaInformationInterface $metaInformation) { $command = $this->commandFactory->get('all'); @@ -347,11 +347,11 @@ private function toDocument(MetaInformation $metaInformation) } /** - * @param object $doc - * @param MetaInformation $metaInformation - * @param Event $event + * @param object $doc + * @param MetaInformationInterface $metaInformation + * @param Event $event */ - private function addDocumentToIndex($doc, MetaInformation $metaInformation, Event $event) + private function addDocumentToIndex($doc, MetaInformationInterface $metaInformation, Event $event) { try { $indexName = $metaInformation->getIndex(); diff --git a/SolrInterface.php b/SolrInterface.php index 9619ccda..7e791391 100644 --- a/SolrInterface.php +++ b/SolrInterface.php @@ -37,7 +37,7 @@ public function updateDocument($entity); * * @return Repository * - * @throws \RuntimeException if repository does not extend FS\SolrBundle\Repository\Repository + * @throws \RuntimeException if repository of the given $entityAlias does not extend FS\SolrBundle\Repository\Repository */ public function getRepository($entityAlias); } \ No newline at end of file From a354f3f95fa50a7389567ae33da7ed53001a5ac1 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 10 Jul 2015 09:18:02 +0200 Subject: [PATCH 022/332] verify that all cores are called --- Tests/AbstractSolrTest.php | 1 + Tests/MulticoreSolrTest.php | 34 ++++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Tests/AbstractSolrTest.php b/Tests/AbstractSolrTest.php index de5d10bd..d86eb075 100644 --- a/Tests/AbstractSolrTest.php +++ b/Tests/AbstractSolrTest.php @@ -53,6 +53,7 @@ protected function assertUpdateQueryExecuted($index = null) ->method('update') ->with($updateQuery, $index); + return $updateQuery; } protected function assertUpdateQueryWasNotExecuted() diff --git a/Tests/MulticoreSolrTest.php b/Tests/MulticoreSolrTest.php index 7520e6c6..c6cec110 100644 --- a/Tests/MulticoreSolrTest.php +++ b/Tests/MulticoreSolrTest.php @@ -10,8 +10,14 @@ class MulticoreSolrTest extends AbstractSolrTest { - - protected function assertUpdateQueryExecuted() + /** + * parent method assert that Client::update is called only once. We have to verify that all cores are called. + * + * @param string $index + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function assertUpdateQueryExecuted($index = null) { $updateQuery = $this->getMock('Solarium\QueryType\Update\Query\Query', array(), array(), '', false); $updateQuery->expects($this->once()) @@ -24,6 +30,8 @@ protected function assertUpdateQueryExecuted() ->expects($this->once()) ->method('createUpdate') ->will($this->returnValue($updateQuery)); + + return $updateQuery; } /** @@ -31,7 +39,7 @@ protected function assertUpdateQueryExecuted() */ public function addDocumentToAllCores() { - $this->assertUpdateQueryExecuted(); + $updateQuery = $this->assertUpdateQueryExecuted(); $this->eventDispatcher->expects($this->any()) ->method('dispatch'); @@ -45,8 +53,13 @@ public function addDocumentToAllCores() 'core1' => array() ))); - $this->solrClientFake->expects($this->exactly(2)) - ->method('update'); + $this->solrClientFake->expects($this->at(2)) + ->method('update') + ->with($updateQuery, 'core0'); + + $this->solrClientFake->expects($this->at(3)) + ->method('update') + ->with($updateQuery, 'core1'); $metaInformation = MetaTestInformationFactory::getMetaInformation(); $metaInformation->setIndex('*'); @@ -61,7 +74,7 @@ public function addDocumentToAllCores() */ public function updateDocumentInAllCores() { - $this->assertUpdateQueryExecuted(); + $updateQuery = $this->assertUpdateQueryExecuted(); $this->eventDispatcher->expects($this->exactly(2)) ->method('dispatch'); @@ -75,8 +88,13 @@ public function updateDocumentInAllCores() 'core1' => array() ))); - $this->solrClientFake->expects($this->exactly(2)) - ->method('update'); + $this->solrClientFake->expects($this->at(2)) + ->method('update') + ->with($updateQuery, 'core0'); + + $this->solrClientFake->expects($this->at(3)) + ->method('update') + ->with($updateQuery, 'core1'); $metaInformation = MetaTestInformationFactory::getMetaInformation(); From bc8e7d6c65a0d851d81bda18fcc16abef90323a2 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 10 Jul 2015 09:24:49 +0200 Subject: [PATCH 023/332] activate behat --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index aa7359b4..2495c39a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ before_script: script: - phpunit + - php behat.phar notifications: email: - fsemm.travis-ci@gmx.de From 2c827f9f15d909fd756a52a329cf012f1a90f230 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 10 Jul 2015 10:25:36 +0200 Subject: [PATCH 024/332] update behat to version 3 --- .gitignore | 11 +++++++ .../Bootstrap/CrudFeatureContext.php | 23 ++++++------- .../Integration/Bootstrap/FeatureContext.php | 31 +++++++----------- behat.phar | Bin 1849723 -> 0 bytes behat.yml | 9 +++-- composer.json | 6 +++- 6 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 .gitignore delete mode 100644 behat.phar diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a0332143 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Created by .ignore support plugin (hsz.mobi) +### Composer template +composer.phar +vendor/ +bin/ + +# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file +# composer.lock + + diff --git a/Tests/Integration/Bootstrap/CrudFeatureContext.php b/Tests/Integration/Bootstrap/CrudFeatureContext.php index 5ce049ed..a270b118 100644 --- a/Tests/Integration/Bootstrap/CrudFeatureContext.php +++ b/Tests/Integration/Bootstrap/CrudFeatureContext.php @@ -1,9 +1,10 @@ solr = $this->getMainContext()->getSolrInstance(); + $this->solr = $this->getSolrInstance(); $this->entity = new \FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntity(); $this->entity->setId(\FS\SolrBundle\Tests\Util\EntityIdentifier::generate()); @@ -40,13 +41,13 @@ public function iAddThisEntityToSolr() */ public function shouldNoErrorOccurre() { - $eventDispatcher = $this->getMainContext()->getEventDispatcher(); + $eventDispatcher = $this->getEventDispatcher(); if ($eventDispatcher->errorsOccurred()) { - throw new RuntimeException(sprintf('error occurred while indexing: %s', $eventDispatcher->getOccurredErrors())); + throw new \RuntimeException(sprintf('error occurred while indexing: %s', $eventDispatcher->getOccurredErrors())); } - $this->getMainContext()->assertInsertSuccessful(); + $this->assertInsertSuccessful(); } /** @@ -62,7 +63,7 @@ public function iUpdateOneAttribute() */ public function theIndexShouldBeUpdated() { - $client = $this->getMainContext()->getSolrClient(); + $client = $this->getSolrClient(); $entityId = $this->entity->getId(); $query = $client->createSelect(); @@ -70,14 +71,14 @@ public function theIndexShouldBeUpdated() $resultset = $client->select($query); if ($resultset->getNumFound() == 0) { - throw new RuntimeException(sprintf('could not find document with id %s after update', $entityId)); + throw new \RuntimeException(sprintf('could not find document with id %s after update', $entityId)); } foreach ($resultset as $document) { $changedFieldValue = $document['text_t']; if ($changedFieldValue != $this->entity->getText()) { - throw new RuntimeException(sprintf('updated entity with id %s was not updated in solr', $entityId)); + throw new \RuntimeException(sprintf('updated entity with id %s was not updated in solr', $entityId)); } } } @@ -95,7 +96,7 @@ public function iDeleteTheEntity() */ public function iShouldNotFindTheEntityInSolr() { - $client = $this->getMainContext()->getSolrClient(); + $client = $this->getSolrClient(); $entityId = $this->entity->getId(); $query = $client->createSelect(); diff --git a/Tests/Integration/Bootstrap/FeatureContext.php b/Tests/Integration/Bootstrap/FeatureContext.php index d51d6c0a..b5021312 100644 --- a/Tests/Integration/Bootstrap/FeatureContext.php +++ b/Tests/Integration/Bootstrap/FeatureContext.php @@ -1,12 +1,13 @@ useContext('crud', new CrudFeatureContext()); - $this->eventDispatcher = new \FS\SolrBundle\Tests\Integration\EventDispatcherFake(); } @@ -84,12 +77,12 @@ private function setupEntityMapper() $registry = new \FS\SolrBundle\Tests\Integration\DoctrineRegistryFake(); $entityMapper = new \FS\SolrBundle\Doctrine\Mapper\EntityMapper( - new \FS\SolrBundle\Doctrine\Hydration\DoctrineHydratorInterface( + new \FS\SolrBundle\Doctrine\Hydration\DoctrineHydrator( $registry, - new \FS\SolrBundle\Doctrine\Hydration\ValueHydratorInterface() + new \FS\SolrBundle\Doctrine\Hydration\ValueHydrator() ), - new \FS\SolrBundle\Doctrine\Hydration\IndexHydratorInterface( - new \FS\SolrBundle\Doctrine\Hydration\ValueHydratorInterface() + new \FS\SolrBundle\Doctrine\Hydration\IndexHydrator( + new \FS\SolrBundle\Doctrine\Hydration\ValueHydrator() ) ); @@ -113,7 +106,7 @@ private function setupCommandFactory() */ private function setupMetaInformationFactory() { - $ormConfiguration = new Doctrine\ORM\Configuration(); + $ormConfiguration = new \Doctrine\ORM\Configuration(); $ormConfiguration->addEntityNamespace('FSTest:ValidTestEntity', 'FS\SolrBundle\Tests\Doctrine\Mapper'); $knowNamespaces = new \FS\SolrBundle\Doctrine\ClassnameResolver\KnownNamespaceAliases(); @@ -138,11 +131,11 @@ private function setupSolrClient() 'default' => array( 'host' => 'localhost', 'port' => 8983, - 'path' => '/solr/', + 'path' => '/solr/core0', ) ); - $builder = new \FS\SolrBundle\Builder\SolrBuilder($config); + $builder = new \FS\SolrBundle\Client\SolrBuilder($config); $solrClient = $builder->build(); return $solrClient; @@ -153,7 +146,7 @@ public function assertInsertSuccessful() if (!$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::POST_INSERT) || !$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::PRE_INSERT) ) { - throw new RuntimeException('Insert was not successful'); + throw new \RuntimeException('Insert was not successful'); } } } diff --git a/behat.phar b/behat.phar deleted file mode 100644 index 48089f28ace0d81381a83df7754cd410cf3073f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1849723 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�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

v`THUlDs#UB-Y`~h zkM6i$lO-?6>8_9hZt6k&fTNIEhs+JSMXuLXaA7TDir|^@#AdL@f$+kMpvx2=8@q8D z2X`7VgYJ981_dPxr*WQ0OE$BGf>*!MCb7~5F6o4UuV zO3V5#gE3M*-h3+Ikz}(ixC$Y>DdQ%DZFoQi{a4wr@q_qNu#xY*l#zT9Ijm^eGic2f zEb^3qzBI9%|5Zj%AH8JKietUqB_BD;s%$9=^-ee0(b9g`P?_&4jiTrcvdt3%*w-ip z)yH5#--tJE#t7NcNLYo|<##sQ&Ly04&6 zgV#_Ka&;NljPR~NLyqcwU>Eex`<3Gie zVU+Y(@sc+R1_2c zQ_6Og4qag_nScGT#F__HNOf(czGxQ| z1A%bviDvKvEF;8tvOw>K{=P(AH{>f+)JHFP8jJHd?{R(+VH23HgA@@&nnLq^!WM38w5650-BdM2UF}Mpll9VuHq(&<%4kgYJRz7O56nJK&fFW z{K?K<$YMfDFOD#+SBht)eII+Tm==tc5*eXvN*$E}g+!9Ii_R}ZYC?Q#PIP4_n#c)< zyI`CVw9uHTpQ%s7F^P+e>6F4U-S4f0FE)41a4$JgX7KS@Z>X|%bGZ~y6<&6P*^tO9 z+x4AdPM5Yxp!cOz;zrOKK5s|Vm4;*RvQqOuAgo}clZ;dI+PZ68cN2rXHZBq5u~R?^& zPRLu&#AxX@wML0T`!h!b496N#JqQ*R4o^aVF+J97rr~c|G3B}q+}g8_27}NYgCf-` zo1$iOs9Ni}H-nazLiXLHb4na<0b94EKde?xF6iv;(=R%z=Oc1zPMb-+qSkF0u;Xgc zTDcM?($*dQlv#=uF${)YV5*w4UJbh2BC1qGS-k5ehaOrttXKI+3g6MkC&?{9mfoe> z(1ow?xr&@?Es$MdnhxtNH!0#(fUXaHEIFNy>B@p(ydchF^J$vmD+oy5_(>y0b51_j z!cwy~>&}4OxpS&Hwb+?z?!0q*cIVV0{?)#M?G^I=DYqMHYL70>1BHWSRmz-&HdpC# zAj6!b+2JD~7X4H(elI-{*$)>kw(%G*qTQbV_Egmu(m zssXe^8f8JJl2L)y>~gxuLIP)V8J@^tDGW7iTLBa>F4ek1+_J+)N(FAE8|0+)xKJ73 z#+W@|SHg0)T_J=5IRZSDx}`$2_JXNdJ&$mD5&$`}D?IYH7eM3H^JO}h#AGm^Ww9<; zErV{Pv4|Y#SnoQNA-=6~gVkoMZ^p8th+W$Z{b0fqJryI`uQuu`!=Xplvhv-!5BsiGEt^)JXx9Uk*fpLgw)5f*{)I|w%8=&GClrp zh9z-d&Y;Bka9IvGXAZ3>lSj}`*r-b$+QI7H$4~pnBcMhRggyXb$5Te%oC1tABude$ zmr+RHl2TYz1&Pkre_ROtlgoj++Sn68G(=Ke_$xRi6=Uj7y5nx;Wj=r`loRSr<jVg((aMO8wP`Om9=Op;$YAMgzn;yo)ALtMA@=HQ5E>A3|;;DsbrZ(-4YMv zXb~}cG9$9V2XJg>vGdRz{+XnIh8JhDT6W5waRCY>m`SOC2)T}BF0UM7Hz@iG@vS*%KBCFE`qRqS97z-1W`S#oaN$-U8nD8qPRR5E?=+pV)36LUO+lgFBuGg;dwUGpKRm#LzU#^#)U>b&vpSn&A za6V-fbOVr@?YqQu1xA=JOevNu9Ix z8J|rrvp$tBigBnu!dn?}jB&JdPx>f}79mARQM~aBb6WA4Voh6&pza0jpDZb}ph-qb zf`dLTC$qf#OGwGw?=X+p;b|eN-~<15&pw^R(>ekBCrZZL*I@mMGA91s>~<<<3&I^Sr{#L~vrLJtLc>da(UMNOQJY64Ru8 z(aA}mGwqaWnoTh?Gu}AQnZE*CjS7V67Uef1WmA0QqM2G2Z!}3bAxoqy8HyZNW=eH; zV5uSuyhg6ae%(g0bkxu;&blE?Rbpnz%Z{!`K$0vQY0NJ#EVk$v*<3b=d~x`-o02GN zE@OGJ$359fM~kUue8UyY&$rBQ&$qF4?}x!d*$%g*L>^T-23jzQf;~$QAxpNC z(Yk{$wKW^cc2mMY#(giNjAu9TLg@mDQP6evPyiAd=;1w~KFXlsWq21*pzV=((zCpU zvJ{)GST8d?LHU&TJQn##tcQ)L;a?UikNmoG++0yhwP`x)#B&QiuWCsMwhYHjG4y_H zc_9PL@zt%0bQdSkFC|z6qs4U4%AkIDl8zE3A1Nb@3vL69@Z!O*HB+0fFYrOcu2O2v zgNsB_FI#QWCgF+gC(X`ZyJ*D3AtSLzb1ZJpH`3t*QVy8~Zoi;3T(kE7K`kJJ`t+j9pSO%c_DlKk`TY)|ndS4y>Dr!2P53|2aS z-6FAI(TO4>WE048aF%nW%q!9j+X({;u>4M6z}}_kj6s3u5MJNdsZweoCjv;u%As>Z z2DluO!izsjzv_r}sx?+=xW!dv)rZ51uPb>4jxOM%+?8gF zh(|X9ui4G?CV&Ckg=7=Bi>QWEcL7+ck^-h2@*L56-aB6!3_63ZK(vNTx|i6^zHAr$ zJ<0I#PS5})dUb4-^$m1&oYpV@y}`dKi0aHZk%}$sQ?ay&YR-p0Hz>LbWrJ5mhI(eh?kSpq84ARZeEuZ z8=t_k1ZNjHB^A_lu0P+p^)65dcZEOPYK(k-fmzQF4}fPNu%#zn*CcEurRX4_1%;af z<#fOXIW5G$TJ{;kbZzppp}g}eSKww;Iy*L0Nri?CBG#ClaetO-fUX+OUa|E?Gt^UG zdgfJV+as6i{SFGT%nqikLzml(x3J)>!d)vR*83^yB}1Xavn~e5Q5J>ART`_vt@sVw z8suLRtzVQU3tGFHkD6~sDBktL-hp_r{qxc2f<-G{JR8pDqgnV{A6e;Y{CM>9g0^%= zVaB^(Aa$_Whhp4FIS~AdO}X@vpEADZ5@MsjfM@4c^V=`K`l|VEDzBVg!o>XU>Uj1R z+UfLl^EK*j%r^cux_oeYJ{+HIK+C<4ZtMxeL(93s4Ff)S@m8p(86wB%Y>aRn);^xl zHjpA6w;McPHpFMI$4FUaoubD(Tid(Ow>gx6Dn-uTK-)eZlhzKec;c6EC;Jl{SSJw5 zMR7>b08qvn>2#yzcol4}yTT=69UZiPYX{vc(iO%eM@4hX2cK`s^*WG{_P=vq{#_s3 zWf_*cm(#n}aKrwUdRhYFgW(nG@XS`j{M{S+fRln$=4i$$E5RErFdN@XoTI5PS|RT^ z_kt`(r~XkCR_&6mN2I9P)zRg8I!1YBO>haAK)&L*n^|FxnZR*@@>hI%Ak zw(eMnF|al5>{Mf)9#4;;D^9w&RH|(T4rWPIx)b3b+t=+#QQA-tz{P~_+Z~yP7HeUJ z+XFwkoV_hHhZK!cpK^ydg0jMYQYD~4(Hx3B*^>Y@$`+KoF(ybBD_jp?kW2C>_!M-b zN6zG$o1f2b;;=(`rt}7_%X&Va)0Ht2nfqikpR?%lEklQrhYl;RN%^mdRIAn+qK}~# zGAN19D z4sc7ZYW~mv+!RA~aH`+l%9$^Rte6)+OjxAhMo!%J&tPMCOMW^j`A*tN&WMv=C%r4O z3K=KEDDWls5dpm(I46Q}o-qbdGqB1^{FN!GgL1RtMkP|lb$;8UE|p}@;xrSrhsY?w zzs8rSwJdq*qrYAa&+z+{(Ks<<7w9MKHE)EmrWae3K=4LRFr1FJ&W3Z3T7|FMwGzT4 zCqaRNS%CU^Cs2?joy;L)9Y`C<^q1NcD>2`i>n|VD1FwPZTR1}@v7Ng}4xbd+?2w#L z2?QAx5&G6-thZ12CEL1~l?}FSqngjTZ`je>4Xlyo6tC*y6XRH9SQV!V!4w9=spKg9 z{H14&@|6jYRDW2%rF=Z+TPZtQo>w`^8zvG<;G+=m%JkbwZ^I*6%yJy|K|^q=;J>92 zL3)xeRGsQVb}10AK}V$CrEo|v!!vY{v1g``P~7q{x^>%Wu**6|27Zdzv^m3&w<&J& z297Ow%f*%_RSHwFQS8(PE)bXm{W^<|bV_rIW1H~z%~vI+TTzw{ux`+Tc8P*6wkbBn zyzyuTxQfY+#H^!FqhglX%6{?m(>fcc=3JGK61==q>|k5x&=nJhV7e&5O2vkb=+6kU z^Z5xCT7-nxA(7okfHWsTcM+Gq9@T&>Hk zQChbT(@_i7(g)Ptqg$d>J6xcRo!FxI$zB>GsFTNPV&i~*IfhD6I_ zMQhHaPoE4`nhqxC{MGnk`{&EqaO));Z{^%?CT!e2?wxbC8IYN%&&DDv zM2}@o9|U`ghN{|M&D4!WxsI;tQ*=6siZ|(DQFhjsW=(-N6nx3{DsEP(f&~_oAWrW{ zxc`$dyhz|#hlBMT`=G|H*x`uDX|nch@rVSKg=P=`(57NmCdig)M5Xu8vA47!ak?`w z&IPAZfhFvht44I+5>Bb~A>+38OzXCRTzfHmgZ%rA=x=T z5<&gISAr9UWo}v0$>jp2aDXijO2+`0tS}pG6Ocpd(66`!F2{M;7w9vQg3R1nfnP)t zS(;_UE>-+}G1rKlGe0R;2{O>Y2_bnA8}iS7-r>jpI*fwU#~B{YIIH$C zZw}9sx`!t$L7QRQ7Exn$SZdPS7XscXH z@c{+yJNKiu0z#CZD7qbV9AM6tY7W;qq$?jzms(4oPVaCHnc!WsZJL1kfs^EXdNYFb z|M>y+3Y!1(qy}Wt>PiaD-sK6AVz2ZdEtV0SV-W!w7&w!O4Raf>wsMg{FsW-KYJ}K;K)ZHrA{wbip(=i#F`dMcSt7 zhi|(#2;)hP@v_!GqR-7hT#ZUKX1|Y)yAA2b2-#=$jQAhr0=x&BxR1#m8Y8PHs{%bm zMHh_(x?h1ZG(HPAX*+3H9vE`gF5w@lq7E=B5s zR9?X@KONGc)YR5~olyeB7qP;GU62fo&6LnZ3gvGdu6|rYogdA{lAe86%y~^&)HIyC zhrv1gzI$ZQ#H~suHcsI8<~;-~U69O4=e0h1xD$UbxJTD6r~a^x&4vn+%u#JUwgxZg z!4Mp9lg5{4qa3V)f9I6Zq9S4jklBrH*JoNU4b{$yHWCZD>!T_THu znw;QWH$1RIqvDvO5`<#(anuxjTN9AsJ|}xcwvlIf!U0}5rNv%YM(E1=E-AMHJCbuN z(m*AyGFBlG`;Xsi0EqEDqQPC%4S4tEZCoi%HhE+4tCkWVyppnlxr$S@C>yKH(TMBr z28|c1QjnAV;m1qS3pJOROh@XvbKhuTy}~$0HGOqW=?WUmDr>dzy>Brc5(W8SljIAw zj2b1az!61h%0&4Ue-d1PR`+4kHo}kYCIlOhM@$J4B>l61swBGt0W-Cit4Ya3CM&n|_W)?!KLbo~3n^-gb6P6m-)jBVApM zf`B&^)FNZ~g?nmK!I!y;xcRHCp$0G9Mgqa$Udi-qIy^p*t0E{gvT^b90(a&nb{!Wt z^)bN36xU^L+*m`2;N$7+;h22=cs!d7&qwPA2M>4l4i2#RwL>Ji7cXSJ69~^2FMb@JpS^ei?+32l#kJ$^ z*WJ0czWWv}?ph9V>k#|1;beX$a=3paq(^we-T@zxA?=cPPd_n2QrfcpSTHNF??C8H zFF&fAcB)4+-rf3_;D~ndGvpVzx(pb-+nbb`nTVWzWfTG9sl-Ui<@D% z@_mUKGHYZDqnX)#_9mZw7cSSbjieSomd2dy>m z(PLctH%0@gIk=m2B~}vsAQL_vP($Z5c-tTi0&+e&JGpny@K8!ew;VN|~g%x8J(8Q|0f*;tfu-fmF_2Zr9d6R8U_1O009 zae)s?O2TQ|qzsuge-=s`ZH9)BYCu988HIhxrA|UlxQJ#~zc~u)yM(496?k*ABn?CN zo%={5L5iyjG#E_Mx|K@w;5=CjsT>iL(+QlS1Iu?9qYofCIcQ@?m95(WQkuDQKkPbR zyQdU)yt)%Z8|omx#;3u1t`|EifV%euFUay@@$MKmA2vay=flaQ`FcWv#jg+imyP2Q zZxhSp|ACT;V|dt3PshW_wE6lk8;AD$1Cajl#-TK2>woyg*E4)Kth5z3HtDYPW zXUFrq2*V%VJs*fU9C zBWO%Q5!AWB+KkU{4DMn{7r17EPf4Ra{n0D_#QrC6#Ewv3^Og4ZA*gObEfEJ7-D%DR zpyHO3_^N~}rpx6WorxqA%tyo7(MzW3bFA^?=_`GxNrir@^Zi!?}h^Svttz6Zq}=A5EY_C$s*hta|?G&zL04m;;`Ge*?%&g z%~337I(-#fl}fu;R9U4<*iu+JU(kktf;gSMg*ODX0LGU(4wisRb;GkW`q8*Vt|@Hh z-Pnzom`rgK8+8Ft7Yc>NMr7E{>G(A_C^j-V8e?f+pU5W<%q;NQ2aR`Fj$`?S{bc4sH{~1w+1_&z3x-VByJ%R!D`j7)_T^Ce!n5I$TTl-)!XsvE69u=7PHJTuG!I*I zKD>|>c0Ftj{UCr;j8;M@@?DYW;8jvS|Jt`LyiF*+c<&5l#D7iYe``t8YTVFOF+`fk z)b0dVd#3QB-a-R5N1h||j!?ggk0$b%ili7$-ZoR5Lr^WKG zO9=~=X22+Hd=7)7VjJL2azXPi)>-tiIr_63a@E92Uq=N~KuMNhBNam&PN!!wtItex zw|RyK_4qIQB||ORe+j$-Oj8b74G?h4NOmgQDB&|(a7h9}CDyTun^DBnl)VyQq(A8K8rLo&0S8+PlGGMlV&<<<9o`qoE$XY0`C@G)oA@)DB zx=)H|CBYHuoa%3=|5O;a26NRA>&>A|6mQPe4~5gv3bV<i|QHOQi^@9I~BnJ=RgIQgRX;`XsJeNB_h?7u%BGavKSAxbaB053Rg$%|IuJhlnN zkb=F(8e>KCES15Kp$~jBS2!j`SU6)=|Aur5+E!UTna6D38CHgtO#~omNmKi8eR-}WiNVIkn zdX?BU9f=6(MF6zH0s-ZUb8RbMc-J!H;Ui}afnj=NfPlEr3hZ@$TqVX5?0Argqk$)c? za@^TvkkWqg6USb;QyJ(`(1JX6G&=4;s_Vbnd>Xyz!*Z*pw6nT%K%U0!$2#;=?v``5*j+5?8-AU3em5y2Jopb9R~9`SPkw_q!J zbT}@N7#UauDPTSN{Btc{-2bYni|-%aE7*$fLO+5-D*jS(V*yG^0B*6B9oQ*O$RTAK z{Ln2b0eGc}Gug06PVf#u@k z9wgZG28zp)d%1$5U6%{hP^g$&*d5rADdJOQ)Mi;nC_S`~AniHa$v>(HELo7GmiUU2 zR1Y}15j25?0(G?W>lb_2u&de8DEzYH+Dj75k&(7gFPaX(2|fPJvp+sVElqyHt)s0W z802f)kkp4)rwv55#uJVqO)r~Q6V#BWT!(KO4#l%8Jgg-0or4gWsDL|p1$AI5>aWz5 zg*xQ$1+apm9OiV7^s+k_eA01QrB7N`phOj%$4a8Y8WV3I!wJxK=<@H^OzfmIR85A5 zI3=j?YZ&AqQI?AWXR6(Y{4m9(tM~Gkco-vgm(lFAN71+th))@-RF8uSD9@gmhUW~> zzEqIl%`qTR-%LL8Ls+8d4}&|%g#FRNw)(L6)8-57?RpG-JXK>ITMMz zrdCO}Xl%k5GjFL7I8Z&mlwc6J+shK_ecCDKu)e0K;CS|Ch^JR{I;JYD8 zjzvr4de8ZLhJd(80SrK0q0skiJUko!ZKMJmz5=|aA=hZ2$3#G4*Qg)xTTzX$4Z?&= z^eF!P+dKDt#{|l1aXhAm&|*vYO{-|H@L!*ZKh5wo6(Ws13KeB4v$6xrS;7yVV-h4- z0K@(ObAQ9}z{Dd*@PlBiZ_khsI6j^k3W#hr;Tl;&HrSY9XsZkPVh>O4U{_=1XAxM* z5j+}B2A6a{y)(EUWF=5;bZwUXo`9;wl`9TQg*0XXB~+ale0~JcR+Qmtuh~G) zI;#XfIDh3WZ#Q55?svaak4x2yyAvxwR>)ZQa<+r-H4y;YrSCY(W_`}GnHJrK9U^*c z0y76sh%6La=CLHIm|D=jm=!_FC};sti6+TsBp%^d1NnGv@B*rnK!fU*h?!H7%8q)n zu!w8sm_HzEI6ztPK2H@c0N18K`4b@tDv)>y>YCXCn;RoH1%dl!T%Af7R|H-aAqj0n0i-2a;*<9IVAh)P)u&ew=ySd1+`br9yCH{XH}$_L4#(a#_Sr>tbkFM>o4=8`{6 zwD$A)+1?1rAs5ix?M>2)P(5kQ^Re`lCSM>aX8Pt4b=LN;aDxokss}`x$m{76KAC5*BPc$8)YBD~ZAg4+$(XDKn zfA_70RMiklBBZQIMjJitW~1}z>k&}Cc?k=UFW^vAXORROF_H~h6uPcAi4@Y^hSX;y z)-_d4Oh6affekggoecG^v_ChRD@@3Fim2GXJ0AN*ZO>zaxQNULe;%| zGon)l#Hm%$Np{d<;5;(cNpCLRF{%Q}yCAVMBswy4^L#qLM0V55;cIw=rqhGNAp>E} zkDE^(TM;?7@~`jM*Z=wCvD*~Q<_Yi5&aNgCTK`e^jEwn%C2=AnEJ22DHQO_P*LVWExVURFle*)e|Gu#|)Ifal>sE z$ds_*>pELWS5%fhvr`jB|Bl$k4M8gJdakW=X`-41soyHik>w?NceHnP8FYca()(xS zV7cA~vr@thuMkbXGZ3XLnmp;32m0k_0_XwI65S3kw$$dy&3CuZ4xWNInq-#KxVQ71Jb#|%eT;EO={-;aCseu0+4-y;e z8BH8L=!Y5^$T9~um~3iZ%ba(^CaE~Lxmw(#xORvXn90t9mFjH9}5Kzl!+klK4x;OND9yrX+W_RsY*^_btIIc!pddj-qXN!2Q_tl zO*(WfI<(8zEPa+*F>kYhfzjV4Nl?iSGd}?L1}o{jaC4VmqUl0QEHY|MiT<&8nIPq3 z=;a|#+BR!?gqIK&?bMPq`m9p_7m;eKikB>F0mXW324>W3sGDcY`pXsWj)1+Xxgqi! zWo>BQjr@(cB^QkcMf42NShHCc5$#THf0_rKPH`MlGSq+`+(>L2sC}!TJ@g`gN}lVR6|ze8 zYblqe6H)^~z*wq2yr=>*2R!j^0!(Hkz^j^QXo=d2n5OJvb>)a!T-0fEJxHQCN{6Vg zAj(#`A}(LQxpRNv@;O%k1PUl9T=Y&ESzeILQLQw@Ui|6RHGO$qWCvN#b0IUeE0-!s zcX5If4};JQHzanHkp8i!DOS{H&N?sp8C+wQE07Omn@U8y*FeT|n4~~^?rJiIWVI37 z$r=jH7M0@lmIYS~DX=0SN49B~%qt-@QUQVxmv4=ul~j_@eHVUk)t>Ok-oR8gS;Lu+ zH{^Dx5QppA* z!@aF|!OL*+z^(3M;Ig-yzs#qT16(e}Ho7MwIS?e)NNyDt5lWw*Ce0H@{hqwI&1(Si z>~#pFJbXOg(`p{a?M1h^uo8;}f0TEEGuh>*+1+qF(spj}Pl4J5Eu74M)L=V(y$ zl3a;d@6LZQgw%}}LD@2GAf>dE?jpM8!iY_hUGp9(Dwh(6?C9PV@{twfA-lGKz?kiL zk|wOTG_2p8W}_}Z{P+bwkU&~&)UPn|8N*H{zMhW&$ zc;Yom-q5mN^!Bnj8{Krfn%u%1KZwDJ?@eodvuo55IMUXUm(qD z4(IIE8Nz_FU~me!u;fF0cX5W$;+cNa!8p{1VP}O3lcq@8Xm*_KpTIMs<3nBduBN@D1l9DW`YQZ7Us zl!0)je3bg87dtGa%qUiIgoWxNzu^q5#Syr@+}iP~dZ8r(kgya5ST9WtxHaDwj@c9JN5FrKN%a$I0U z&RJdyVgAb@@7FQT5BnXbaw=tyWM*2Nh<+di_3Ujnn$eOhB$8x8Y{fDiGZNr7AzTLm z$}{W~8<5mGRpb<*oj3(MBHlm*oU1srCn#Njs!z#}9Q|5EBN`sIwo+i(UHaLoME|u| zO}QSQYFRnsK7b5JAB6u7enf_cW@sSD!B803FOD5NjZ(=Umgops_1HoUaRyf{E-ZEp zx-oc$z$C6T*dQ1-A4DiaMnVvjCBTTw@u}Q0=^b}RGeih4Y&!`gP8;MO%``2RK^g@X zReea4^DDGu4hynFbU_Hp_P{MAfOszE(5WQf3nqNmGF=r6?vmDqrF!qkUrF41rxtbJ zze-Mye-ucLDGiibEtwC%{9-#=sI$WfiDZd3B2`G~$fy|N`al@W`YkAZw6f^24)P24 zkChhW5M@45E~{8&wL(?SMYV;)jqAR1UuVmj;yAueRPtn0XBf_IT*}2_)sn@zPp-<$ zVX{`3)KXE3g!BK;CB^s6_YE*V%6n$8Z#$Efc7)DQoA4cBXhLc0?)`U_D`c=15o z_j*zO{jz#-rw}^m5kxS{0JJ9aW|50JhnGGorO_lq7X%50U486_OvLxr*_7O|PSX_` z4}FA=9B9Rz?L=4v^jDKvom;a!65!}~g>nc0Rq3gE4n31Ji{c4$P23q1?ZO;`Z8;|ZZP@ZJ!5fIqBV6`P5Pk4COYVdA|uSMM7jLX@gnwuNA zn9|N=P16w^WWj&#l`D5b#1va8IVTNT$rh(1!(v(`X6H0@?riteUa?f)e*d`>8qVnrnE0D3+z z9Sk$EHWn>P6oy_>#UeK8WeJM&5_!9!ZN40ttY=>|&Ua*bzLsW$rz_anqTY9`2#=zO zdBAJ@VT8>jf8Wi5j$s$!VAn29WhRD;OP{cVjJx!{0O&PvBDx_Dw^=g86C2(Ln{NRJqT1bHhaFu;bc8@cl5ZIrd;8Igv1VkhLXvN zuhsS}w?E5`iRO6^a6S1i@Sr5uMY%s362~nTyDmw=N6$L0nr}1=6i8Mhq63u+ePfXL z`aQr-VI$fs$JVDc?8Xz{`@q$hJN$xGblV1uaRJwk=lY6Un@iphhI9K2L)uv&`SB-p z!6%eyeT?akG-t{EzKP$WwO!o5B>3yJuE$9>T@<#iz+M;gaOsFJ>QGMvuy=8BCJ_%1 zMJ~eOJXBYn^Rz(d*>S)+QQ1o1$ufDWUe)n%f$M>J@6ku`p^xWI2vF}7H0+7x2n6=j zcIP$0EJAL$WZWDfVS0MrvHUPL=*}L?GS=6oY)F95Fjt?`2ENW~BJI0BQf#pCjP>y7i6$ zmVxmkeNR&20>G{GuT$qc6!u*45C+JPMQA0<%`sbxhF#k`%WsrvaXpJ$tk)-j=R&1r zNQS3n+<7%s(WCGooWmbDe;rJngSKY?6_*(0;;MXQ9ZVY6S!r#gEPW#NXH)6k)Jqpl z5E)BdOh81<_-~>@ufzkmG+iWExsBo;gc2K3NP5E$mCq;RRgd`iEKU~%;+CVuNdC$I ze9#}r0)6D1cI^hD9{~hD{6Qv#Q}Kl($S1CZ-Nt+g*mTAcK}a}8#IH9ZEwTWCh;j|B z+velRIH6q`IrcA^mrM`93wxlCef6b1Qz7hRYCH%b!8rufSRiZ05@OpwxA7WPLt>kP z)p)*itn@>V9u_@5?jCJ%0(@^`!@$B7Ee@!l=IE6NC3mhn`7t63%0znxfUiPS;V0@O zEff!q$tnf5UTL|-s}#wHiK4;gt*m(|c40JPjFRcbj8hGznv6^AaJpMGgN!T4{vfN| zI)r|v4I6&5OzU{{3!R~9fbwnK)>|272zkbkU?_ayv#Kg4!vHYjPOV#_|Ie}p$2`4}VY#`jJCXk#Hb>vAlZX<<$ss@9>z8s1u!k{71Ez;1*D zH75VzimcfrbQU4{pk>yc9}STe&5tYvBRRhB9*ieYLdTa6r$@%VKgbOkddOW_DMcj$ zGLYnnn9NvlkI`>v@4xiInNe9Jz4o$<(Ot_)h)@b5Uxgl5iaGqGRyqI1l9s=>W=cnT zU(N5md^)N#-})vL~SR#iJHQftMvnCg2^jI6%k7*aB_`eu0f7`eQcPbYPnnb|gx7b&)JM0Pi2oYJ-zjaqY` zB6ai+v(2&zqEmH^R8x0XOQLi;1iaBo4s%Pw7a?A%VMZR=w6#}8qQr0ls3+17RCB0& zwL_uh88_NQl_{5#ih!Zw|wAchrnQ{;1FQt7`c)J^_vCI`8sj$ zq!HQhe8*}cS4Y99AZZ#{lP(N0E~TNaBP~1c2Tp?%Md>Vc-Aov9gJ`mAJ0Ta@vG_m_ z4V9|X(aavN)=VvZh%c0k77ys;>iiI{d7LJn`>2lkP*q>yiD#@mv&CaHiv9 zs{OE*t$Z@L8*Vjslx8e32Brj4iSGniJ!21o3)=v@!FR?k<<=NDUlLa59iehWk2I}H ziO04g)5&%w&%+YbCsXGzI|1gZoT-K@aS;=-t}1ENX?BGhPz>{uQ_Eda{Z>U zunO1;lnZj7I~>=%y8@GK%x^XbtT1c55z(o}OrSPXRzE`-}n919koN>|>owDTgZ zeZxTjI8j^?$-(v(L~uDil8OWzVMAW;v%Fmh^poc1`1mHZ5A^eaZleE9)|D7d?%8Ml z6_G2GuBV^GPY2`U0jpdO&fgv|VG60w0~8+D&rp3F&myNCJ$4gf$PJcoG)2bz(({Iy zIIV)V(v09v*s{T~7D>NZE#M{(mfrmacFmRQ{0fd$7JitV`l18?MV(xm)jiZoy~w_q zLj6L?^ebKm4ws-z1H?4KR$7UyOG{izZfA@jyvx8%!_PkGg*)X0gT42~n7-mZW0rYF zLeqEZeF%?lOG2!!kaQ<>8p{!DpIQ~VCM&^73->iP=Kw`32{Ion15T~&(qJ%VPB5W9 z#Oy=j!M-bp$;Vw$(-0ODs$LV(v=T@YASJn3Qf_vMauLAAS-7tB!@S>)zSlzSGOnow z9az$oJ1|^noAz6k(~AC#Mc=fSF>f~JALr51&xCEE95U@NFufyQoGfwk?OV4!$b1mc{x*0%2_F zw+|BO>PGTu@3jl(%Syd8S8X>>-MMdEbeBG@ z0CqlV9No^2Y<4o*iW2SPvvMQ8lKH>av7seP@nGwI7fy-@{qUD!^?%E``QW6(^L~BG zu{}_)OZFUsSt^vnA8OYv7P31{-a~8O{5$ts<0iuPRy`Z^5kSJrTLmWZp=!Dv88r|s znFobPtOb7|!3Bgw<}J!P>UuF@|K$`i-6oMdFL-I-d7Lvk3ME`#L4Z0W7HZVSA*4~h z53XdN40fczg|c)>Z6EL@8lce3P=qSitb7<<2q9;=X1Io^ZDCBl z+Xu~qRerV9ntQTomb%3uoj=sh>&mye2e1x0{W(Q5(}Y*ta8d7ROk_TaY9(rZ1uKeN zI~Y$<0j|a|+&YS{%K#lV+HJT-!Pz?${;VZ1Qe6C85jmR|7xKO$OB2E9f%vhvEld26 z>!QFW+GswGNO8)vhoOseoiALRLHL#IEq#^x*2NzHLnaZheXS3Ne;ahQ?id8x zmMqsFvV}7Lt!6u=i!jlwb8E1HsT2IkN~gp=hL}ysK}|kJ#goh7nF^q_&J4{R%|~)%ZT3Fe(N|gbls~sg~SXShMR!@Mc-QLLHaf3(-^# zmxfenL6e)|1VLhl5Q#*%f>*@WTH=Sx^Wd-eKa#O?^wgIV%8078j~WF$YI-d&c@3DL z+jOPkXDwdNz%4Ohdrp4%*B>x z-470_hoM=J1SGQ%PU>yoy6sB{J-KSLWpPpgOlYv`zzGE@&|ZTnWWyxdUfHj_NZ^#N zHwPHXDwihUNizo?>lB#mw6lTz*m1%9TO2C9j$-tcy?f0rNnSfbQxN`<=J>S?XIOpa zxkxd4?E3f(gLNY~Y`+v4*S&){YsF633y7oO$#dw?DQte`h{M)!k^YmM0)E8##b1$} zxtLee55|-6WLM&>PfskIHedg0@pMK#$C?VzKLz+UbFwTUTG3-2<+H`Ji8k6K*o{;x z!~_1?4+03^8}a~H>{UT&87s%Oqu5WSQx}}zDutlH;}#J zfaNUZ3>{948oYQoI7~qv^{C2N+Rvt)OUf+=*U2-$uaDaZCrmaknKllxnFJ1f9C4^x z3^M5-IYP|2QljyM72%5fBQ{v7KMzMZSo~wf{z89Y0QswL1mdpcJvyU@>YI8A7{G$` z;EUSL3mddH-Vt*rD*e`{Q1V;5x?joEW1TG1gwZW9pEgeCjU}L4Qg$Q+pGcZ**@a_Y zT{Z?BJ90fUfmaSkV4eA^ownFw2(VA+axf$3$uJ3pwyi`w{@p7OQVyk59CYbqL4xpQ zGG`9DjPZyL$F~0RMbdWxyru#mRL~9dqmF7IhP5~Z0?UZScVNqPEpCBw9|JA9#ekz~ zcYhI7P|Mu!-Gf0Q;W16 zIJk2k7C=xUG#q$~K^CUTf%?0%>C$J1Se=V2GV9DH>88TvHI4UPUQf!;M_;BL5K~mj z1NPoaOBEm#GXB_`CNgU^4eGs@SSwah_xdO+Ch4xumx5L!j+zd}6m+3zQvAJHQ~*H? zk?>au&^5W0k$c>;`3EQYWNZ?`<#XgecF;k-Cvfd1PkgS*udYG*R1W&jKS}L+2ZTKX z2j9%2;NrY7&JaC1=X|6>czX2tz)EJ>ip6;0bO|r#pNUq%Kif1R$SQeJt2Acf7P>jb z*A&L{1Iy`ktkv!0@tumu!YKEfFRSXo1nvXiI5nbtzLXJJbO1Vc*o-5~)3uypS?!WRsfs^XZnSy)b}l*yk5; zg-kB%3)$DW2h{)yXqfzwJ&#x zz^_9cy~|G95wF!H@@G^X3@&O)sg2msG>*lvYquZqm zHhdBpnIKsu>>;lr!#>0P3_j7x>j863UA{hB3o?J}FhL>^>}c1W&z;3@&O4^DaQEQ+V})vd4J(X1v#vf(L_I$1D5zU;U0tnesy#? zo!Qw7XB4p%RE(v(NZ7Bqz2#W9crV*C4^r)+ZM2H%x~pD-$ugmzi4yuJ!`Um%JBvHS zAnxHv(yY$j43VTo-MYj1;kCROp9+uA2L#wTPVrBPO)ZT7lmcZa)2-)Yg4a@q=~$!g z723GlRx?;V13;9W=GTNv2mWRu!#X@@mZ>?ueD*v)#Dvri@SaFk)5cWp9-0;b_}yB*{erSXT6CzPeNH0hu* zHm2G|A#BsH$lnX;t1QM-$XPf@4by7zD>8ZlDs_nT_$*#dJHwZgfuzQjS$(n0bEtJ( zB)46xBI+AfF_n=4d}cL&8yarq>OmU3tLp#C3g~d;?QvBk7G4|LD3;qZ<^2X zb}8$YznrorTseaU^;OC?YxWM<((KC`Ml;yL{FN`j8n)}3+%)UB?jS6`b6|70ET#O; z;0MQxQHgHlcc9aTC+<-)TGOytziLrk!fNrCJ@aQ@Mo_kBnZn0pAl503G78aKnhE-7&E< z|_F|Q_US#Z8$bPIU4D85MM0&(uVDlW{D}v=cl64J8w4q(h<%{(k!HM>SZN5 zHEav*pHRI^4wikGF&xVPb(XKG`kX>NBEf~4KvN!#m~fpml5A^zN1mUSdqTpI6^13` zD=XV`-&2g(%ia!l!tUB;bE>h8qu=iU%yD+W{t5>#qEebe1qA2(2G^?E+Bk`6D?I4g zc0n|ngq%0#xF!aoQ&561?e%Mn7ku&zevkm)qqFHyis`jF0+F$?WbIVcR>eT=K|a(B zKA(aQG!KUut@-+x|7`rlKW>lm1;7#qoR?ijZaWII9Ti+$`EKIhOJZVlpDoMd6XC!8z>#fMWktO@62*IxK7_H3^#Q3r zf$r}@|H*tG;{+tbe>wwF*ag1D!z(5&OITAB{W;7rguiJ?fK9>Ce&f0^@j6e#B07@R z&YbPzF>BFK)w+H}$MZ3s@R`09f;3Parf(!EUWK{`Z{+ikY;Vqjgq{CS3fEAzF$Fj- zmp*e|5{Md5+9a$T%_R6C`e>~*i@)Hbm0!v>ldI^C_+S^+7+jMj8rY@!n=Vl{oem-C za21>J#xfLt5O7Gf!uS@~Us6HNeW@ zOk-FYQJgRAEnaHl^u2|=@^gT;pGl_`(Y4oM5qD`og)-H*^=+oEtL!m;`AK76Es?2a z+KaSrVd~-#ZPz@mlUzqKFkapyZxZlh*ndbXq$r=Az&lvS<8jc?z?gc_m?en)M6YeF zz|=D{+zr_#ji+~Tnh8L)>2P+`Evsi(Xu4?zuZOcSE9VUO0qQFr9PDmB*?#_Pb8GwH zU}Ny&#ShjXKNExeA(MgDVvs@FhiOY3D+f8$WJVpO4VEOKE^311C}UMXyGKbBuW7L#mxqCY@ziZ5Kr)Q=2l06LKT z)0l5tDLvo)K=O-N22dKiTMZsT^07M76TF67X>$JpOFV2Mgh;prm3yy2mvqXaHRNR(IuK=Av z?Yb@8BL`*1++zZTOW`K3{(-r%`gA?N0qwc z{MV>!r`@9C!&ahbt?Y+_s0Bqm^nX3`z_z_@u2Sula5Bjt4JY@qr82<0=8X9F%tb?T zvkQpM z1_)?54wWlG17KPooT6dy?qaVJj)+L8OjQ!Ju~4GKTs=QQ09{V8TcepVQz_Rdy%UzX z4D$C9&#CmU^q8KypXNcR#G&k7vI$`?3?l2mU67_FvIT|`<6VhL{}6c?9Dc!B*COF$ z1@CknI6NZuAQG$1OSX*X|1&FDt_M8bb{XN%)&2Lrd@9f38w6y_k-7Q#T%L^KmGr1J z;DKX>GJTggInAY1uVE{fA|!P%`Wb2oPIX%%D0llKV%4-avA zhq#5SWXQ!vKv#|-P~<2fvRaJR^@4ProkJ%5O{&aQ-^PsS>MN`?6shd`vijVM@>O3* z^t}31bcFbjZS_4>pjcP1`kJBMp06cfTz;Q8wI9G-mCPnp=K`7ik`bK=jxw1k_=2g& zB=`<*htXUS$0)1y${@+q3*+%7(_BfCf8~85{3g7&-6iZMC09_a%DvZ#)toQwV-#;N zWkc0U+Hd-s?j#rG+6b3}uOkU3Um7Li`}Pz7C%VoCIh~+c%n?YYDaa)s%@}{Og_27^ z1vL^+vxq1I*Oa*gQhod zWp42hPcXOz@gD25ftXb+BQCv4YtMyxS3Q9pYvt8D#}P{xkji_=+xHar55np|PVj`C zkNMc47L9oS{S7d!uVE@IM(+5OSTK$f8qbl?J$fq^jkHg6%9Jd+5VDt8G<_%C#%eow zBy%^EErykhWO!+hV@9vZJ8f4SN3Sa01-(a|7VMx0qt=kXb2QqUPQ{pvnLc=kkYA|H zPfC!B+*sBOO@%aib~nh?-j#Zl^8y6p`Q;{yS0)3tGy_V>LsdetM3$fE@ohemOlj&E zIcwt;dLcBnW7&m!_hj4oiQjo}d6#Ns-nrf9(FR{s+d6=Y4XldovVc_`+ktY=r7h=3 zLfoYN^l5_V+1Ye%LT@d6Hwh2Us^R#7B#CvAbdbBQ7RagY;KV5d62&L$)I+pON?aT6 z2i63_O%eW6lBzA(C+<)_(t)s7I@F4+DqzM>s4GSlauQ~>BL44(kA2Lx7$1Zw8exB5e27Z__e02|@NQx+h17<|^^ZHL&4sbEn0AJ^ z`kA-!NcL4}2Ja>j z16OA+SVMWCMmr!2tsxvzR$8qfQnSPuX<;DdqAtR=60W!zyl&8osP20)HI8g|1(lJv zwxLH_c3?)nGo+-mFOLryVI@>#9KRnSyQy$kl6bP=m!hAnM+c&^Hiob^=$1!ZHewe7 zlWW+*zhU{Dj8Cud>S~aG!=t0=>{v>kOz|nWFtjmySz5=gVBY<*OpKgI0C*|P3h-oyJ_NpEk<1^)tnJx+JDMHgzF+h8Yx(=Z{OSso#$#FWI2VcP zS#{0nQ#^dRc)0D}KF_ZPgGJIZAtBL^KlJtEHV#(bO(T^kgYxUfs-x$h#rMTbw@6}T z3&Wixo~WBAEUBd+QM;!+z1`L}T8CSXYXdtMSEa6p(%&?E#0?n5HMO2!@F)1Y{5>@^ z34va15*nGERWzuLnmtRk$ zf(Xc4+qi6PzgmETeNpC&Pk_^i7|)Q_b9IJzxi;$*ED5o;%IhM?EJWks9D|_uE>@&6 z6f$zOYB)$-A)*%AK;Ja{Vq-8LG^nSeAFitSrW;dK612TlL7c3c$%nZ?Cr25X_}EPO z6UP|;&@TyFy&>}|v;nj;4mNN=!qUA@m)h>dA0tPX1e%mhp)xr!l zf=q4&n`#ZUf@+zyJt3vi>V*!)Lk`OiZcCikITEVQc%1P7i+pnmuge5fe1f|Yc!Rxz zLt88glXY>=w&j&=O%3&*CNOBqOt{VC8y9Ed3D`IMw~8bi^lF2-4?x83WZk zS)g-xhH&HY+ver)wR}6C@LOg#pdtRNK52rN8T8~d{PFLHKZCg?d(ZDuMx$g>%j#~z zI2@m%EYfx9VmvAL+MsDK*+p=Z+Y=w3E`a7WB6T5MkOJ`TbAsoufoD=nq$UFY{&b-` z-$fTnH9{9fVX$7h03DMq$R`5vx6#EXxw4vES=KP6@ScN>jgMZE6X-Gb2j~icva*$` z7HV!F?6|$`(xOmOeeRIRS-s#OH^J8PQPrk!eY5N`A6=SSCf)4!Cb`b@iM*C0FP0)+ zrdmu?4{)w)bK8_~8ek`o^Aws+7IKM6eOezX@muwo2vTDEx;oQ-v)4#8v8^)~p`#8N#cKw4D)k*Gyx-)+>Yi7|1zV@H)=hQth4NMqQjh zR0=xN466@i0i&5o>EuMDNsl2xu|p|0w+Yn|Fl=U_Kh=lALa?pNC2v|u%hh4I!jLc(t|+XcS%)GG!P?REOlK(En6sTi+7is{GB~s`1LC%jP=&O17e&A+lsO}n=9_yG z{!36FWIFdf)$$NdW^QZj%v6Q)ntIo@)!Jwfp!FcyG2?_dYVuEeWM)~E_o7pl&I7qr zD2!|FQPa!KUYC1-%0A$rWL-?*BGB3BxsD{asMdONKbhz$LC7~IvIrut(@n%?+&?u3 zxw1R=J3brSPqvqU&9%w%77&ndapNpjq=UgPdw zFlaE`^Y%Hd6L@vViY8hURg24$xVS!PsGtgrF(bBnPFZPe=+l<{RlFB7+g9Oqu6V0J z0F}h^;Ba8nGB!x?)!m<{3;p@Wiv0y2VF3B7Zv?mi!<`xz`6In!18{o@>2=7c?8fn< z@nm=wrEN*daR|F1mY^uvXV<)=wuLW0Da<_zbCf?@maM0CQE(>~9+s6|*x9hb=~D}k zKa3_L*kqOu-eRPgRa|*SY|mdT<5d;Ab~JlI3)6lV86?J+O`xRgJijpaVUg*Ak`ZW> z2O6UzW`2R9*~_@jfc#~3hENB@L#Y{F!?(-V9El##NCFh{7Rs1TP#;P-ocNfTp*d>6 z0~kohVZ4(3>G$`&c?ryxuz0YcaKR39>!l;q(UScs0~BdKl{m)K`4Z^OOF6(mA*;P@ zWsPmnXttE$!lJ>!)nxqFaCefILCNm5siZ>U zB=Ghi-vT@v4e@g0<(p}9jL0}ba4wb{kd9e!HwxMc$3YoyH{xXswyKbn;Pyo-@*4oMF#J47Wtd-yf zxuo`Lba> zr;X;>Xm*Z_g)z$2+X=ge_c@FD?;JRPhfTU|EZNmJR|24o`o$yKW_P*DSt014TQ z%1DAGSe^Wy>kDW&V>ovZAd)wkZq}mBeY>PQa+S~^gBDxFaw(T)!`f_AF~beZan6<5&zT7 zLk->11Z(seTO3?g8wC~Nxg`QH{xHvxJ@WUPf)^qnAP~_f*6={f$g4%3A8*iIa zG1tx#CJ|GhL|Ei9XM#|hMVQa0xDV!pL9zoNJie$Y&B#81%0B8e%gRkzP9HyJE~E!5lvaN*4c;^@aR^P^jf}lu09;dh-mq? zCm@E)Lf3i$JxGM)5``%x*9}n$_k-cgRd;yQ@J0e1rML`&1w%PQT_`+=aC9`fK=#}1 z=FO=23)1{({ELEr9(+1)Ca)wi6&wUOzYH)Z(&lz;x%gY3NAKnF~i1;M= zdnEtg?ZC%3-aqb{w-YBJmyl!;uhf0~Q}4&E@AQ7i!-jc29W`;HUA&!*PhUc#m>f6o zYL1{@Kp6p(Iv2;ws)UzQ)!{A1)o7Ay+OVl<3Jz$dHE<3 zaUOYrmZYjrm<{nK9uu%y9KnmTGilDJDj`Pm+j3tVkL`eK>Me3hs8LT6U5i5W%!t9o zNV%EIiqni^!GFv}(tK9+jL#4A7UgU{Iy-q!@ z@_1Jp5eK*z6B zoJi#V^)KRVbaMF|uXP1Tvn2|5PreSVs`W^Uovp=R*=pYuX}P}U6GKf6v$Rm1WK$uI z&eL$cJ@KHr!QQBN)6f9m(WzEVZVW+bNvV&q5K5(lg(Z>av^4`zjTP<1@`e z@`6}l!Tu<{@t$weGC^l9jSd}Gz*Sh5gifRt9r&?X!inryDHYkz)(=bw@dGBu_MIMH z&MdrOh18if@smH9pBhSH-Uh9Q_WBw+2Wlv25Cj;goC3+Hp^`?F2%0H#IfYM-rAx{@ znddL3S9q5mL8eow}$g|n>2vj_s z)i#xVMUBLBj$qDYX#{meUe&4!?yY^8e=Ay~=(v)gNh2nP;%Tfm07IqH4K&hqadr;t3nj}+gi(e(?p6ep~6FHiJ zK-x&pH^rAPG>8xXdyrwa?)B`iE-WmfPv1!urcUm*v4%If_^h*KY4*6n#3~T{3<<3P zWt}^|Yh?w+49a&#_+)A0?bGda4)bq%Y?te4KRNF#H&+ijLkq)3OR6EM(l;Ay0<|BJ zMkTBWb?U9y8eDd8rr=w0s3}Z1COnfli#mT$U$efeg5dQW`Mb6kbL&p$W9pBpFB>DPCQCceA{T@Qz|uC6}9 zCVZd7!JI`b^1T7HL_`U0fNXxR`DsuC%RJ`dQ@}C!v(4xeKgf=u5gsd9$Qf65S+q6Z z9?Ns`yb{0swZ(H$l-jT=p3=jrd~&PZ^}|7+ce1=D+?`&tw1hX6EB0L`JLZ=V;754T z8}|WN(IC*Po*-w@I4_tF|Lv_?N;Q~kMtOIkKr$pew{MS!;&3(njp(bBDML>^^iKCE|vHaz#(B(yI z;`((4s**;oGf03d+7NqbvIFGt<&?4RV=cF%9^~2$^r5T;n{0D78@{EQAKXFVliC{; zVAO-cKke~o9OdwIU-hMmJ=wNQA zLGOUFH56~65PNfonB=k2I`7;$dLfQ@^=_m2_H78j5GIQ2zl~?=eK6Kt@f0#EO5AlvLojT}^&lCG7-*N0B)qe$(+R(OBbu79f23+sfE15X=M=4dA3 zgq7>tH-w+030d}5%iS`Y;&{YobyZy!)W?^Z;$u!jxDAfR&}3L7m+WApvD&)0 zb$W&aPKB2yxJHrbOfj}3t$oWBTq>3T)%7fpCp09f2hR~UnnzIDO?gJN`lPuzKEBCK zML!?tCi>sRwLrY&SSq5VO__Av8}k$X=%<76@u2zr{bq3f_JF6AiYb(7{fsK9U&i}F zI=Sr(_X~gU;o<0Lid)3?clem!w$B@<;=Be$&y-Cy=gtYE>;vW_yc#t(t0mkdA>hs_ zG((VsrN?=E0LgL)w@U0@S0E55@}vYZ>!LD+lKV2p;-LEvXQv1?fK5qI8@M;S3)4s` zf|AS%_P7=ab{~VLA@}%=-bm;mWl86B+}h|KvtBdX4XgPRo)bYhkhO@IVG8gPyACvB zBV-zRV5?a3cZtARk5EGow{i6S(T+on34%nU6DF*!;*zy^V|)Fy>-6u9kUWAbf$BP3 zjKg?td-%ZvQ&mlnb?#0t;t+$)5Lcqd<}gW;VySDbK`vx*@IZYN2-kj+)7XhY9q2}U z+w;aR<=6Gi!Cgr8`K%y!5))2^oRnTvfQBBXIR*+xi4a;lv}p9~Tbt6Gr;d1DXYPcz zy286LxYx1(99jon#U_&sl=u4QT{qHg&kCuo5O;0f*2~e+D~R19t6{ZFk6tWSnH9cjta}6tP8hs|qS?nKD1uZAcvW!PAqHp;gr;)UO*lUo{>g-4A5DLJ6&E zA&ixbsbz_2RxT`?@TYhRbdjl?;-bcU=!asLZv#1;k<2();sWBIF86#*v2oJS8|kFh z^arK|X!DwIamGytpbZ}OqM{-w(n#cb=1zjbM5GMur6jPI(04uj)-p;-V&(P|U7W3J zJ^4Wl>oMT`#Q34;fP_c1?Am!k!Waw6po9UtKz}%%^Y&|lf?+f)p(~@t9LnD~7t;Iz z-vKpRmkgW|V{-OoES1}k*_f$BjA=E&ThzO&=r8BIj9GHJawDS#62@L1Y(_M@nJA#r zYM`1VmSly9pkLJF{K%@vC{3&W?`8%^?x1UX@kZL07_l=IGZ8)dn5Vr3(lQKIPP?)} z?*+k3;W?g;=97V8V>Fpwo#MR-lUMov1cz9#LmXIP0v)+Q)F6`*d4h$Ky{(-~CQ!(6 zk>%0w6Kflcw2?ez*0Z^-DP*3@qPz%9Ta%4%w-vD|7(|w4D$xT5wF`EP7v7S=$#+?c{+(i(f7*{u0Y|^^?`ky1IuKqA_bcvFT`~k; zt*lwQ;$_1UR8A;g*yeH0a?Ai;f(>qJT9pb#sa%$}I6KQ(%k379IJAOA{=T;QdAvB) z=f~~{TgMAXkUirG?%B59sxqeD28S}ofadZR%2pbVkBp=s3U*(VrWA0-#!7JL5~oj4 z=~7h=Mi=)^BFNe&%e=obK$kHlA{+80TeK3c7o_z z4b@du{lC0T?K@s#Z0>xO94=@YT9g{zPAu`K?W6}^lhh{*@A6`1)j^yQB&R!t z1Ljo0^b?%wtomOZIN)`0k+qiN?Zd2e%)L{~ardv(&?Kt+G2Mwy5CBq9Tel~nPoIwe zBED=6K{5^?5(WS4YM1&D{JxDI#k4DaC#Z(*+7Z|VCC6}~(h6$Fh9!qF1p_Mp7!oAE zDMvwE>b$Vf3G!D+GYCh|=+-EEAVUo5xPCh2+H1wLH;#-uZ55Mz{nM5e5QAy}0`~`_ zpK-Actl|}@I3EAj1IaPV;}dwOY$Vm8mLtQlS3MzN;O~+$Xr(sfs}#r<ly0Ofd-7TlLRFs z#hIb#f`6#-CW@KoHWX5<88pUU((&x~!85(YZo}{*Pd1DYxws1u$7g)R4wIA&ZK-1pfAdVM`Q_&Hbz8jll*#sUL3M}}2%N1|sFsP`7 z8=g58?PA)U@Npe;yGcAiFvC-RLzq`nOE-`T7-qKg6#OPH~;#Yy){s z_tE_B4ZXCs=Woyx_L1KjyFjQ@D*lI+n9W??^gTwe+wtpV7f=wvm!eO8y z+7y<^htH_vNw09$p!N#{Tyd%Ch0KF&E{U}vwIiF16SfW>`2KO{H0-+;L{2tW=v_?~ zCX5}Oee^Af-T0F&EexUezAUEYw;Z&C{x{K4{9~Z`h}l7+nnsryEHan^m2xIHqRo-+ z9<=OWGpx7j=A4XoUARl=N?&C_C!9obt!9#+Mu#u$DjM7l3O%h40%iv|!4;V7goPop zT7>x0QSo~;zXH9|{Vad9QB>O9*MqmZJb;^Yj9eq_Q+v|*ZMvC59w$MG#M}&L377KW z@}Y{2Ra?l{RGteC5s1AlUj!a+^XC_bJf7HxSw>6urrQA6^ptsoMMy%DKpXw`#vqm& z^QS*296pSi(L+R3tJ5lFZ~ukCvc7#-YQt(WSQn~_8GJ987^io}3}bD>vvD%TfSuab zAF!G@YgQOmdi9PQ6LVG=me}pe1N~B&O0+YCV zaOVsS@!`odYq(}p0>KBU>U)N2g6lV5Opu-8ZZZ7z`AsYZtAK)v+ZX?eKW@(dsX-gA z0juH|1pqaOM7OjIiYkUmdZjzB8oH>vvOYn7(Jw3mYn@(QUf^vF!*iid+NYwARHvbw zNiZ3PCOX$}(PTb6rCQU%cy1v@_A64;LrbC@kaX;il!9caYBoWNO@KslB^F2XZv;O% zFv$qApmirM`75C4H+WbrQbdAUlGzd`Hkl?8SPn^r7CXxUBX-W`f)V@U?}8BnWI1F6 z-K->y>!^+?)lIORgf!1(p)ot z3E27P!XNnc#$cWjN@=h+8@~_S$@&AkT;Ht?@-7|Sh~9lA`9k#U48^ovlYe}FD${v9 z-?0mNW;=%jXz6!Ll{)!75g3trbP`E=p;?8zXbIexyZBn+8&B9l}c`E3HW<(`y ziG*-AiWC_!;ys}={>mSfK)%}6xhuAChfEzqJN76Z62`+}Ta|KtkscNyESER~7pr84 zFp!KfVj2pYAco3$qO|7dOXD+H)27;Hf~qi6&Pq9SeO^B~V7I2{7l=_!F6%e=a4ME9 zGmt(_ex2L<7EaG9-eY?6|L!yFKraNe=j8o@IUe5{&N>S^y7!h|`jaW6e~ds2jesE| zDhOW8i~>BDf(J1;)ExI=zW|+l(Hu^vi1AIJkm%pai^HF^vivLa28QpX@;?7!gKI`N z)Q21kM~317DW2# zbE`FTdLa)H@@3rb^>8+p>nS7&m|GH1GHs1D_#!uPUc}@Mgd3q_=!3V$SuoZRuK`}p zhRCevVC;#iXK$Nle|#3+YVtQom{Sr98Rt9$oay{+^JM&LdNypn{>!=i(jIO~`9fe8 zu^zn_p`Ul$aH>m@nC&TW8bx6=dZ%$mKdaJHYXr9Z)0poZJ*{I$v6F+O-x5 zy+gzh0V>_`uaJyp>3Erq5ecaG!a*o*U}C%3r_a`hrZWWtNLHF2yCxYj+%Rju0EdYE zCRK+>#p`P}ONmiidQJ4}1|Pg&*0l>ID;*2BxwG7jTyrs4;C0WT%XFY z(rKwj_e({6CtEa<4n#vOk$rWhuuv&!7a2X;2{p-Z4Gafj!n`ub2z|vKRSP4fzQ1;o zyjAWi3Ji|i>%(g(VR+{a*l*7ke9yfNDZ+i5`{AcuIgi#s2sxjAZax``m7y3^u&88( zj~caL;7rjg9(av;JkvTw(e(v(AKoZ^gK9*~Bb%b05v(-S-NDN^s735*mm5-#hKFOc zdGlLzy+=O@$2+cFR55grwKJRQQy+mXSy42(U`&xs&=##rpaj^TUP zkqV6@tuLk?BV?->@Nh*O(Q4If6#NC__4Rmq#S8nipehLxU9-WZ;s7VfPXTGrQsoB5 zy8QRP{BbL}v;>`YfBGDekICtJgzBd+{|t9b2%y}ABm5>EHUVrpYr-FFjSVKp;ZLCj z3<7$x5@{UH)`H)N1N`HQH}}scTd2hr3g}$wO!+3cC_2%KX@*o}|+zW{5DyiaG-?aSxWaxvt43ugxI)W*u#VX^ka zCvB<@_YV=u9WAxs1cL*H3+^~!Fp_v1Y1kZIO^(k-c{qRY044Eo0WjJTSvU5CRwx3dVM zwDpZd_=REjfZr#)qa)@W&xHsP8y2GZXo{OFN0+#)G8>)Z&Y<{7(D4P5urkS*5TB{byhL?1(9ntH}odElLb2Pt{x1fus2 zJXEaIA%;8ep7O#X9Ja6vK9F&tbMuJEL!a{|0cpqYqqy}D+#cZ9moMk0StlMoI3>W& z7uQkNI(kqyI1GyXi(djb$d)hP!L)({4+}q=PBod>&ljRp{OP!?k|`oOO<-LmcQpy? ztwM!4`M}9oW=od3XOEE%QQ;qV=wt=782!-+?vdQDfe|Qh+CQ$X>5X47LveIT6ICfg zM_n}qcG1;!Qh#9O88FpQ#j^)j1el_adGVUHlkp5UWcA03r~x=!#l6V z#t=XP?HdqgvN04q+hT$h5rm0!hO^Nxn+d7Qng!i9SQyi8EPJ4&F64*3At`p(AuG|$_MdTy zp?(2pu9|UAH26j(zjMXG#WxV#lFUT;VIe9(fD}m(4MwMll7llOjGuqno+WP9q7ew@ zY$RLLCi}TGkzrCgCB-Bhn%RNTo`DdIStP^khH-%f(|2?ZgtlMxj3JIVXQzlGM9Y~QU8eaz4( z`mJYM=^s~<@n89PW5An_VAyF93y@pjbb7Oo-Bdt;MNz~V%aG4H#Dnp8nGymr3{mn& z1KQZTecO>tS28OOTFOFhvP=qN3<_a0xI18hg6yLgF9tf15fr|s<|iq4GA5jI|H3To zBdWj$!?TN*!!W2$=%mPh(NKr~N@u*6k8VwDfZu8xfDpm5&+ZQLvGczGWMEXV-sYo& zs~L(@5#HMjZXbNV_xRxX)*rW@Y{!lzjT^Sfi6VPRj);AqM4LZ33TsDU)PGlZjMK@b zSEnCg=N{9aF`bo)YRh^2q^1Rx%82xTpPI%i>08r_w-WzCfyGKVUvXLDtAAj();|;WwOn~|H$CCsn2(MDKn^WvnBTylFfCb1 z?*cc*&!>3wj{mZ#(d|YqM$cc~ZjRw3!y}zgWN`;WqC_JUyp&=vccK5|t&g)C7-0;! zWv!#eq0@pfm<71O{DvYiR^Pm|s@UF^m_E6hO~&(=aEx=gC@O>ZS}-F$TSNdMj|q>6 zPaluDB4jt-*vD7HLq6WewdgKG;~&FBA-ZJ)1PI+#`)d9YNe$wV7leuTlbIS}IanRN zkl6S!l9nZihxy87ZeadDZa2@LKHC4&=H7O*^SpVs_wCp-HXbpL6?32msIZS;H8JlWpc`Xff({C4N@&i;?LZ#>%B-{qK( zp6)?Sfai68XY2dNn|sZ(@AsZPeZGz9A7a?uo!v)!m<7^pcYg!3;@K_p&r zNP~QF(r}z%Yv8p>&^nH#*64XXh9Ss)k9W4Vcb{)_D1lOba^#AEy34;eE=HiFl# zKW#ch%wDMcWuGj#7KQsm)D=3#f+nXrGm%i4+|+lDW`AlnKl9?F-5d z4l_#QtFD7k8q;I>vu``f(Iu_bI)r|vB*_%zcjlAoH~_TVQH1PFDVThP4k=$kmq%)N z9FrX2lM+DN^DJngB|d+f2Uw;2yK~?19Db|Dt(+^-a_?AD9HKpvVaQrjSnk~Czp;-k z$GX0K!>MbvZBSOw_qiWcsX3<6jiqq}&w?Tu&+G(i?~^fC8*?un3!yKP z8%kNZwYK1{%@U%fH{rgm|IUIuswlnUQJ_vh2>`bZ^5UVTYI+#v7U3Y;CEmZjyaTme zPXOEVDMQ!+CsZor9YdF4tJ}QA#0g}rvLnWq?FnKzmz1j^0)l0d3&xgcB6}0Quu@Ov zYkN4RV!$qmX}wr5wQV{|J?d28)~(;KERkAA@mV^gk;4GC8CK5a8Fwn{MIn)TOQQt9 z1TH_1s|dYu--s{DIkd|}TsbVl@{bi63!W!wgE83&rRwD+W=zcBn(?#Q>{%c?2*6Bm zCX!P-bjeSTZiR5u_!QZ*qwU#j3hgdF+XuBvzp+d&%}#>RCC~YF0gxC7R|DX)M#@;1bc3wRuxYni@Nt2ccDBQ~*G9E8M#I z5}WYOeq7-dNEj1*y20C89gWhf%29(v=ebcSZA4FXfu^V0y`MuPhr;fdgg74(V`8G)yn7V`D`9EAVmDh12cKs1Tr8*HIQrz06Fh9 z*)DXeTv;crD&IL%xy`QD;orpDjeJdcBPH(kB9x#eZn@=(*|pS*?&GHEh*dxCBwkHO zm`XV^F^kMM<}D&a3%42$N5@Pm)w2a{oG-Oa;7FrDlo};4wvonW*^L&|<|y{VDc5M9 zhkHeF<d2h$WCf|%W-p9B{{o!H~%W3BG}!HdnFsnqb6ZrPe-3nl4wD(V$*Y&85BwhHw zuVR@IQ-wj|(C(gYj4?8ZHhVCzk?fv%z@sUo0@YZm(o~fIHTM5~C;LM7^WE3?zH!Km zm20i4l7M#i-c+|y)mnLojEsy^Mn)O|X0$K%)`+0h3F~z9G<;WaqJxr>^;OqXRVi-s z0tHvk>OQof5fko)L#|W?+EmFJelwPWE*lgCAE;8Gujx-G`x+dhIYKmurn8vL65If`U;^t?}`ZSF*&N>DW2{48)DUK}m)w3N@tL)w=wk&vmfSi4RA z;Hd?~N|+wj1Xr@T%6vJC8%^_^pPf;9jq?sN)w7l4E{e0ki^zZhFT0j)t2d*W^X+yN z`oPbC#=l23t2x>K*t!$O^NDe;$T+E=h;|FNf$XIwB`8L_`{H!dCGW)XcqgMT5IqBq z0Gqo%+<3JCRjL*h&M+Fev*{)MAa4oBGWu72LqzP|n z%A*?=2-}7d6>>0n<3OF=^RAwLvgYA5AtK3(S=X*=le^!+ftXSfA^3K4`QCM1!}2Q_ z6cy(>fuW;Gk_b?kiiCq00UYb0-u;4oVTqK@O{J}dQZrA^J>s0MqWdafz;v$kWydoA!+W_HdJ`xwoSX` zbAF=tDnVxz1R<^r%gbQ2ZSDt~t>LDKR(-~#n+xZ}aVErK>JrWhEZ3KV#^Wmrvo&Kd z$u$Meh4cW5k-3=(VdzfWO2+8~thSu81}Qf4ErJEiOBj^fk$w)ST?LXoE?MhK+%*Q9 zPv$29eMSMDY4}W%`s_k+lq@Hu7bnRCKvVoVIsOCj+T^E9!}>5>_S3ytExvb>5S?Jz zYR5i1w9U!%)L%hFU{7a;J)LMJ^BPd>FEgV76hFlAV#{6YVbd(Z+7>e5^;qLC-^BI*& zv2~Wu&#TJiC|owisH|4=5tajHQ2Z~;hNn90PEd9i4#75GI5kV8c`N8G@h?x5`j@n3 z)4miB%wiy}r>wloExx+s$E_d@I?%;JnfD5Y z=2|K!YfWw&<|Ap!$6PToThtjphn$w4O?1=uv;^R@xt&I{`+x<~FvRIoChI8Ro(9C>i~W^g)lo{rN4DlB=bhu$2<#N(>- zD;5qRM7^=W>#nCLqD0K@@By0o$p^M+75G7o zHPd)iQF?}L*4X}d1#s;nK~leKh;)Ky3Bzl>r!xm9J&smIip^Ql)jui9IK z^@C`|d6Hnt|0s9T@(L+Xd*Kq+NS-6Cno>&sHx6yWEO|SJ5r!QOLu38$7%SJ zf5c{l$axqs8K^obq5K-SMJXj;tW z1xO3NlE0m=<&)RA#cTY-d~}#S#{c&HLq5R0Hgpgpc`G6Y;N&~OGv1(agh+u2_5$cnCe4A)2;iSS;Soe^}h&3;511AD&Yp9pD$BJ`wJ7g z%eMX63?7-I!Q<&&f5HZ~@8NDVKF{sYQu12XW@_40l;`&ze}B*NwUk9HMz%9KUnS`X z>HDJ<0P;(N(8l3L;!!wjwq~vvttG6pk^8`pJ3*R5>~N=xyc`b>?aG)C>L&oLHO@pIf|jhF+mm*Age!rrH63m?%65#D7>vUw z^f?Z=lZN`VxS3PiZbTLybn_<0hE=YU+Q*HiP>Rwdccrvb6s7x1oT`cNG${+HqwFR7 zZ_kZ`Z@YC=h%^a5P%1#x5?zeP$qA{)62`QTf62+;cWS`rOII~ zTW>6bqif11^5pR`0fqnHSz*7yT^bf1YcnH+=&p~y^_Bs)d#2Tz);MeOvkLc-w6f(Gu^L`U0yEi8gAT=rPF`z< zIj49QwF=@^L}QSjQrV%pUA!EpM!qv{}|O_~)?1 zl%t-$*Cfj&->&I^f&>3tN^Mq#&t!JVVhbrvo znI=TiRg5-OJ$P_&tWSb5p5L1sZK*A88J9>71GzF%mR6|+5}7&2+w_Fl@Z>56{M|nh z2P(H_A<5ANGxXtVTYgdmrbh(N2eLJ%1-Stw{o?Xwy>U<6;uh0tEwCAo1eynX#}pnR zdIZ0qvf>`$>H=o-WO$+38zDBuf?D06vYv5f58ES5RWdO4ZgeleKdy2>xM z`SnHaT^hhif{84s*#tYMJe15K3|@JZMS__b%CO+(mZDFEQ*G4f6d48CD=<6x`U1MX za5eQ?G^9PPvnLUA9WC9i528L4Z}N_6^pOVE5Gj5H6^x@rR7rg0F@r^I-w$VnHQ8Hz zf}6HRZ>zfp!@Zw*n43Qs$mk?=3i@iA782Y;%X6zlTY#0 zxkgs4QlpV#5VlLdoZJOZHLB#dWR$f*aC3SzHsP4XAL}}}$o(iN>G5I>9Rbr=A`GLI z#{%}&ZE8-te{6uy1Xv{dO?)5e`bK|+HKhH^LJf8Ut0$BdDnMXtQu{|Pa3ait;vy1i$HZ4FXQka=@WpmT*v%k?E0Egm2K z8aXwh&2%KpGIIC`E2N1_f~)yM5_O_#d(IFxF2l=ur7qcL><$+xArUnrZ=nA6@c>Is z7PP(XqyaWtD+<7M?bV(ZD}uH7sZX>%E85f0b3t(v0iEh7o2mgoe0DXGZO#ONGr3|Z z@_mLmtY2bQ%2smWKw20jy)~mYoOn9#n;HG5Q(NQc?&&Cy;Kc)|fdIVJX)!xK&QmRanYe=9D%jBf} zNvR!TR>Xxe)Uht;impR;oaQLYmV$C{@ZrsHx`)^&nKGaae!uxdp7MSsu!Fd+XGnw$ zr>}aYinA$fq|%#|^bB~tX;Ux>mVFHGH0JA+A}wiV`~A_Y5eP;BX*RJo9lYt7YId@Q zmYBl_oB%C&Gr==cfYQ6h*eF9A)AN5*P4?#dLtJOA5Wrp44|b~b9yvDqqmxTJ#&y>y zQ7{Ze69u^40kh3uLt}V%0JzG;PtU%fV&m6-9MgD6aZxiD-X}xQ2>!{jL3_ZgQ z1K%Lk_uD$sUc#GMp905x8VGb757O&h{g3|oFV8Pu`sUfS^*>$t>2m-12EYA;Cu>)! z2zAkeL6^D%G4CQ!vrqu(_Q4uM#Aeq%W9EM;3h^os6$MC&)&&3At?L!X-iW& z)b-nPjbEc9)xfM>^C?_v!sCsIO9YF~D#*{9U`1C43wq{|yPH%z)Bp>!5yWMOgV0fS zCO1Lq&dAv4!3EH#Ai!D>AdXt{G)rfKQohFy!12jk|9#*=4hxc^hB~+h>$TKgwfJ;! zdWP~+^d5{=oc)0NWwlPE(qp+J_6!yLMz3X69-qvKEd8@Gwyf4&#Qy=|`fJ6WYIRob zkoF69hUe7Y0CJL%;q)815QeoRFT}{S2e(_l{2Sg3|x`#x;6|xB+`fcAIj& z_1idEET)Q|e`B%f$yl~irPs5@|FWq&gX0nYdb;`mX?dQ_F|86Hoo9Q4 zmpe#x*jP9)dEAZ&Bxx&Er&50C!!(c`~75=B#e>zJnWv|*xY)TfMwj*>Jx?AGES9bj4}+M-TIC{j!o zdaT8yl<$W)Q1enpDl4~JjM`)nNswXwMpQrG zp&wWBD!Jkkg(;O5BDY$bh$v<~eN|RW^-WU*ua(1d*XS679zL~9FmJd=!24~l*hY=0 z$l&1Viu%-&$K9kAuYorE6W{^C_H*1RG^^4}tCngnTPb9k1$GQMx^;fV2AYxQIMDay zvY|6cq5$L?bwP7u))o0C4qTgygc;QMdV7lgMuRph+G0(4>1egNnZHK+@MLzE-t4q~ z1jh_G0kOciwcZ1TuCz_hA$)Etq+kc-NXR&JhcxB~=F@-@{$!gz5x%hmwpkl{nzFWD z3?5wNzCWBM>Or>OG)_4sw#ASwC3O|J?A$)xu0CDX3)&7Q8yn01PW~#ULQes5Vrsmn zSu%P_@@z^ZLu?ZEXnqU7(e*H&*-a}5Huhu^wM3&72~FLuZv6iDWuYdRD3p8T>-y+% zy6_I!z+GJSHH8}WKoUN0&k+Zyi<(vN!Bw~Lzvb==l(sjs<<|qFfk07i*5=j}LM!tB z9Ph0;c2iWMa)VZ8*~ukK_UOt;7MLa}A3?t`PJ@|DGff(!!k~^@VMOb<5e$piKvaNz zqDH4?UhntT*9YU-sMieKGhQKibnXrJCI|o??w2u)c^B+VU5+Pb>s2)4K(2uh&pccz zJ+vRz4_XGz*09wEM76F;Q|)@vMtwCsQGgo*Y{9taVg7EGZSa*V{aSNt&tU?_kHCP5a z+0_*!UN$wizyD!-hjEE~AveV5P$4zMMRKGOy0Mj47fcb@V8SYc^l>Gz=C)uZV}5yn zK@kb>aSl|1*bMgA<1NY_cbZcH|n}g`>AA$l!6z`Inm@Ep5VmXw-66#MC*y)PARJ0GqC| z7P#mdzDzxm)r;9593Jgd0GOMet2CkN8W3p%?~3gcAhbJwCvwWJ&N_NPmRna7J^zlq zb&y8@2lSDDbzukuqF$A9VAJ8D8Bm{!aaiQ4Fk0 z8@*ds<#kKNSbF;aw~_6gz+K9Xb8E5QU@npyh4kqGg8Ed+90y454QG4PkxYq^3QO=4 zL}L*6F8=Ij6e4+dw;n%)Jazn7wN`lHa7=Pq;kcW@(ZLD} zryEvb-$sBaWUJc679lulD5RsFS5@<@?Js=-SbSh5+X8d<`gp|`yZ z8qn*U8t`fce25`{*kuT+niu0R!668Sj9)a6G#e48W;`{-KdlaZ{gVjR|= z4aeF))0A|Lq&_QFN)MFeoyp3cpLIl-n;*@7^zFY62IL)MlI&~O=$?AI9?;w&3{;1W z8}{ao4oih-l)-m7Hb`PpL-hW7c^Kaq zclO~ovK2c%ZFYXJM9Bjlxic8Doj$`%sq1HOh}qv4Rb)0t{z}{j@@8~+NN*5#kftMC z0m`r*(WvZ?2Vod85*A?X_#>U5vRVrXI`y2N{zy~at}wqQc9qp%I4t+ z5&IrGfpf-#Sp#%sWVuTzRqsV+9RD=gngiI)!!)R1fKjLW6RfZ5#i`OA1HlMd2Wd4l zA+Im2&MPmWuVv)up%D+ph&vzcdpu>b3^Y=r*0bh3-k%ILjSY5DXST1Jjhtm{1as8R zD~0y#v{X4m9C!2B)GEiJQ-F9B5ONN?K8y``!Igy@KPCl)+4pIugSHjAK$#qg6-wJw z9YmPkqg@Mn(`hvV6yM}s6I!Wj;?TCu@}gpmSX@@SRgDoswf0>=(Wzr)bBkg4Ue3s2 z8S%?53D7{T%c{`a6CNwW%=e&uj3rKr+ zv@JJyA31K*QVEW)Ql91Rjku-k=5o;^YjjmOL_&l?vvTWhX`G5(IYeX{+O86gT`i9j zBuP(KI<+XuBFz1Z7q~VZyCHCtHVCDutZRzL%|LK$ zCbU6U*bKR#K!iYbxioFK$;aFVVp(T3VV6e;S3NTQPo~UsE`vOJF?w|}IdQGIou;`F z_$U)nYObM>!T*)Y<)k5Dt}}%xl@_Z-=zQFeDYa&C5}rEE@U13=>fICx7y1b7eeETV zurdpede}pu1W3`2k5WTaN0J=?Gu=3Vy{7Y8Bx2bNlifwx%XA|D+GNFQCJ1sEmo4@BEu&tBQ}C(xH)7x zZ)zbd?%rfzFe)5K5u(|kTnHjf2{*c+?&C-SrIKhOiB6IdA}geX$>F+Q-GU~-@zy}* zYkmYw0OE;YbmC=#;laNNKRm~grM%XvDLej16qy0J#u#h+HPpVOf{@fV^P5D?m=Uy2 z6w4IP8iqq``#MkB+3D%nO=l%mPPpFqxS*@O^DzrvXpWJO zJ0pwulApyLFx`v#lV-yu9o0!n8?QI-bA)m5^#vi#jP9@wy>?i%{%937*vC|~ShU9Z z_UX{+bE2U4lOYY9wO0L$Gf=4M;j#qqJ@LQDGqz7&;l2skm+L#F zIjAx6gD5J-sH{#kfcnbD(dbMup_a)TpR2f@w7ivVk)E#mF0=dKB!d<*J*D6St4Asn zZWeoOY^GxA;T0F1u#FcOyotClgo|>fnu3xPHit!;fc+59Uf6a>`F*bn*$w*wy&xSPQHZr zB;1riRpk+}3;xKOnU1)m)Z&rE69}WDjF?ZS_@HK#n{6_s=6g#0TqtF29@ zKuAbU+SsLg5oXGN3_ror$aBDETD5)W zcS1+pOqJAjkvkR|Rq8Yn2hn6|QsRP{j-fRn{aaOC)2xxt!Z|BuR}RFGD7s*Q5R6{-x48#$5^ZoFb>2Ce@@{;3YQER0V}5 zuPVQKL`3_y&f!Bq=r-=7Y&d$0W8xW<=yT&!UBr3wrmnw(r$xuEGltY{S$mnn4X=x; zyskydUZJ$|F0m7?_Iw65fnM_8`egcaWY!zz-No41RaW*co-J#?1VY$e0#T2dslD2i zbS!p-Hw{CVM6P+s7?-N54NzT%kzMv7+`-3}vs?P0@`zb5GnO!ZN0m3CRhq>8)WTX&Vu0Q>uB_$Vn=dBxJB^rAT}#Ak@X& z>V)MfhIlzkq2ZaaHEX(JRk4M@l1}5{r>qDGtm<^dG?r6@a&SN%4#y(Ar}$!KC2~+* z|EiKVw{fzfT3_e)vbxN$j*krpg}7kIUI-_Js~& z9kxtROE-&Up^5F(oN7VDRukY%n}j6)3X}?C^U-9yUYl#*hQfR@2@BFMBcT_P0pL7> zZ0unx0%xUhX{hdXBtEk0~4evFnvMU=$EdiY7TY)-!ziJ@g8#7CNUr4!UF;D zq~Z{t?Q;aZ*6|6^#x@S-`!n8vlxfMal$x?)21oNo zYexE0XoV;ctJ}UyGMF*NZBr6})HU&;o}836-f2sK+Zmqtpk+PEMPYF6E5{Y#qFwffL7<%wRxFD~C@b5)krvnP%6ahu{+pcm-2OkeYLtna4m07-=pt!F&i3 z6xo>9J$+fdU5#?+X^5>Np;#!K)vkeK+f3^4xC*h(!$V=b1wrs<9#Wbmx^p344JyehC^`s111kvD-y&TDF8+6i`3g%!hgLI+SQm@zbvBP})am(0qVYC?g&z`y8p7WNHO~#TS-=vkf3O-77)SDqn3&Lo05fH@6 z{ABsyaFlaB+UF#zsK{y<>jr+wpYOry6D6u#GRmtdj7{~5eeSj1iNQAoaC}q<#I|W+ zF;}D(%!vWmHY3tP1M|hqSp7Q9vZj9m3`NzzDQG}EVp1!a#OUwyW?GP-_eOwEBqR@J zWWnTAda%|Q(CpjOox!U|Sn2&<8ZV;Z=fk7^wN^^9#AgB_lt<{#1|445y(WQ^IgAcS z8v&zY(bFPnZSoF6fV>-~gFrGHydH9Z)=-A1RFH8AR|KLm`e6? zDacCkQYkmj(TiPeqPbDe@n;KJ%sFd$An?aWj%-ckd9H zGLRXsT%+bLvzbA-JlhGq60OOc&eqhJzfYTes}2-)kBK9*?1J&lXF9;y{voz&!41TT&JX zSC7GZ_2uFg1RVl!%_hWo`HM5bwf0>fAuI7?xIP-Zm6;YARZuTiUjha^C@{}jncwIy zU5xyWPqI)j_3A+6(4g|;FkQdL$(L5~M<#Zod`no&w+Sa{K?Til%!ELjv_;5Hps6#G z18sCK7zzCfHVPaR5~SX2IUd7d9Y+(%ce;Mt(1Bcqlj2mFqAT;~Y zMr(~Wd$%M#>TOuCR*g2SJu3jJ&v~P%6$enm0vTPw-(#jN%V?#0Cyp>M4xBNyG+nJ+ zuK`+iQDhm#!2V(MPhhk)*htAxlC$XYbS>DgL*jGZWZWpfCar?(*OUe9uoD-tY|uZl zED(V|I~cu$w^OS5y=RS9S*hn@N7Lf9B*M^AxGoaw9v>vnGa&BsrqN4KA?0o#8iNX) zJ@33WLK-CTmkmC|v$h89`QiqVA7z#rRPNAn&qd9+lkwmm&^u$ffnIV4*(Sqx+b$Cn zUc!dTsJdk@`Q!5CwspW3*F^fD0Y8nyxnfZGv!1-^X>_=>TYIdb;;pl^HkWIJTbksH zW{diCQG-71q^SUkKkkL7R7aBx4q@?>yv?!kMH3KxNkr?!K+r&2&heQbgv7Vg$&=A4dwmVwCtp5K85O=qcE@V5|hB z!OvDJmAT}vJSv4*fP%x>(?$1$XJK$uq@Ea$d{FkaB@R@5HAwIlQreeP+~9EuZ{`N{ z!~DRLzcOv8-mqAc+o$8n@oWUBh)skSM;o(5V592>rWTh_3^fgoogB&h>IA1FFd?#a zgl#=h>u~xSdL0i(=n*u+SxX;+f%)#Q(i(EanL3L+2fq-(_S}qy>4d5@FJCwr>s=2J zE`=5;HQpuK#Z~NZ?=rQa>@_7^d98ctHQ9cuW?+QcDWLouh&ULIXpsG_F!7yq*F1*z z!BBDCxY#*R5nym+&!y*=OBgek zDm=Bo{>WIwNtC_giB?=jssn$vy#eAE3^bx;xH zuPVkI$QYLl@GBk8hSaj}R`WL-VW5E8DxvtfA}YAqRZVX9XOAGHqtt^y%*j|K_9po+ zJA81G3-W%n+t4nI9{7zl5dE{9484U5yD4$7m}Qfw~&eY>DE2$y2bgzQ83MuH|)W%YH$6q z=14?Vd**fkE65)ve7CN&6b$mshd*rXK6?CU3tinC!AFJoKheHeJ7w@>ce$M~mfV|X z;!eeS>;JvDw~3@tRNWlmuBT_|4M}<|!?yL;TYtT;V_LD*Bt#uY59^x~Hh zq>gy8=%QXQG~POPj(&to)e`G3q)4Ta!R%)tkW?9m9g!GA4uaOk=l0ABoW*z`Ghx68 zogGY04);Cg5NV(W9&6LZaf~U#*$7^viY5rk`Ifx}|FTf+71*qC9jglELF!~3vo3PL zbQoe}rKtvy!Gufx#0({=u7C_KcBJEESZ~Vdt&GKiWtV7S$d_7}l7 zy+%lY6ttCKLYRnQ@s|p>Kpwk3iDnB3@PPdxzgt$&+!Nb#eA~st;(L`H;m|#?gA0-{ zEt3 z5_EVA232rMumj^40$ZFgzH9P?l2nhlw+(~wgVJhsOKk7kZ*QsPeVgG};vJI}fvF@H z=E*a#U|BQ!OUb)t4F2Ch-j4ZC1YHm`mt)QQv2LHsvOl|V`5X0qaI?1dLw0VtL|3zg zle^=_PaD0r+&^RL?BNV+IIkmJMf{haF30CKLPAnP2j&)nigA1}crlb@*r0yIVKg)h zjsI7jBE^b`nqikuFxf*=Irc1KTaqWCJ6kaJCkYEJk0^c=fiJC5eepW$2n{cmTMn&C zDMOPK2;47kZYJ1QiI82xQ8_ecPVBCeR@XyEoEedDtXjHa_|lq8LBi$qDpFVypO(=* zV*@`eI-QlhVLuaxA?`Dw2mq&kGHPg>O9)yj#~t8*PV`U?$C`JH1}qq_=MY>ZG#l5E zw}=G~?v}U-JF61UGtu89IzBajGC<@)acMs(| zogV^y2N)MqHe_{z2Co0Mi~t>qxbMC6E<(fLeij+FjSyP^;RoHOwwGz|c^u>h_G?oc zq9tD3uZ|{DDoADN_38!>v82NU-4n&r0BL$DL*=9%pBib%+m2~6^a`cx#l-1EYT>go zqjAQ8WYMZCteKpe#V@-nS(e3M0A$?(^(_m zg)P!75n?=?7uFq#0yaBx3ZV40v*ZjVzByb*R?YR?oZ{L#c;7irjTzc~A%Cn{F8lLs z+QM8dQ2EG(pvujR!E&C@G$CO5sbSq0cdpze1)GxrHl~YcaKsx2AeIjgvEht$V4j69 zsCmGWIiNw0-E7UY2yq#U;r|Pjo z=>UN31~}+#wR4a9%|Yca_N%C?AJBGUx(f>z+x@>NY`-XNCDOMBxDv#f2;q;N(D96- z9bCbIf~RD71bdLG5t#*WGMY`sC8}2BHZ?S@Mud4iXP`1AhPB)!R05x_#hvO9fCdh2 zfTX89beV=tmAH*jQK1!yA^|0dj}#k?oF1tTpjc)X*)pfQWP#|!cp^ZT4l<8pt)MPS zBZtG+XaoNuHsWAD9N8iF_R0hfF_EvCsuHM{kW()GOV!otcg)d~bE4t3w93LEi_Sw}hKEv&hJB$vJC^-D3(&UQaww@ouv%R17 zmO3fl-@8=ZAG{dhB)}7d1&#McP)KjRlqYxW%o#S(k8Y!JwtpW^DJsmO`|eGSPp1-- zLq9GRwJ~;)=uDsiLVjNz<2oKz{;)Djc z`Pnf7buNOn?eku}FRp&}8P|f?ewB^r`Cafm`Z~7p}lN6Rqj>E0}a`+Gh2$cOn~*noGR-Yhm|L`AT|2QYju; z2C(8OcBbq$!Q#aMHfoAT?#Ksq7jH(d#*kG%qKkbY{;la0-u|LcfEIgN*6a7f>8l~g zl`A?yPns_t%`9HAcuXi|JIQRVaQ>Jp0-pQ5`J~I0##KipjmQ$EMZTCNiiOXGRO%Cw z+GizH+RL%!NTXp@Y`oh%JLE5a9z^7_$nJ z*OrFv;5Bk|iSPow91TWeT;BlZ4KYJ0E~0~E?tI04H0^PT?GxMBBwa=Z`M7p-Oxqr_ z6sQ7{Pj|EpWQ@cXkb`S$z-@rd5cm-J82#Dtows||B?Q6=&Gf@}C^@0;4u_9YOub;N zmuFtow@|Q~kdyR)I+Gy~r$T<^&K)5qxn{o5;BDp-?i9A48v3YraqF!m3r1x&V1nlCV}WZR)o!e%x|2cSz#7pRX)d2X z`#c09IK%R>-ZnD@eW)cvmv?S;$uI-(T?4&)Fx>k&T=)tV*m!~nM!iZ*c6za~3vUN? zWV^rysl8s0rjs%AsuU~#F?<%dh;4}CU^3hpU^l{c-m)eROH|r6(F{IL z4~#P;oFQNo0n`ZcU7mohK>|sZjCHrxX@%& zv?--KjtU0rUW>*F2aLcaW9Yj{m|JpFF~U*eL=>IaAl247!bQas++Cs9e+`(*kP+)I zhB!VBt(XbuiEDnB$r4@GTY%leyZ9J?hrkqhwE@M&NgbV~D6^TYIV5#o8?y%)BOF>H zL4oqSY>#4;e@i0joB8t_scc7L#~hi*Y)H#G`|M8_^p0w99?vE)|759v zkqzO40XsmPkr=1~_9keja6RgI8cdV0toATej+f|wo91Wq)F!r zEtgn1ZXBN*%ui-_$-kQWXSp6X!6?u0S5I5i=45yXg}9i}TEjLjUzH2m`Ych2bBx(8 zB5Q`z5%%+Pn{w%0{)vd8Yh6a$wp*tqlNJ$+^)5$cIn*u=|A5vOC3Lb5pavmHGuW0Z zUS?ttjmGhH9M~LJGth_b47}6=j8&&SVr-D2E!JE>&Pz&xlV?$k0+HF$Yb#3+8^$-Xz4Ps|%;mmv0Ora`Mc5TL48fx<`uL>&Be4gX!f7 zq>@Xx}ebyL^erR^h?PZ(Se&$$I99Qc}B_gLk>m;JemKS>OF;d6Ws= zB}pusU+DX}l_ehRjN`7A(>Y>w5Kyfl*Vk;tk_4Kr045`aSC^;u;2scr#=@JsQF9mT z6D|kSkM_BjJaJJg_QC|QCQNkbN>|YV^5dWmG^{srQVQXP!|9vR%>8?8d+%T{#!fq} zWwLB>47#5xFqe|NKinj`y0rq{!jr>>ahuKC;CXEZc9pGu&{SkyaXVE`5f zK&gNaRX(pLoB4??X(cz!*W_51)~Q$Gi<^qhO#>jG;3pH5b&y{@ezJp%Fq;pHjuLbs z`U0A6{Kfl3idsjbx0q{4P*AyKOz<)JZHk}C7tUoIW zYOOW`Omu-W>eKliHy|wH*MIl9`GS>C-O#7dw;(#n*E&? z!`x&1z4ZiJoU;!`v*N?Iaml`)5O5tf&yAsm1Zl^ z^+%y{>ow7M2Na-dcK^YMU35)aOA;_skEAL|ea7**7JIhoviF_@-Ep6mgr ziG~~@=GG~H{7K&88P7tcZxgyJeWEr`}RSW3vbO1zYoN zG`F%6bw{@5AzC()#vtm16l-!o@psWuIlhm;oEC*O;3Oc@artmayGs^=4 z&ASaY+H8k|J>R6f=p2JA=OUdk27Hy?@T9@6zCM;THB15MMjQ6Z4!KW`gh$o>DN2p# z@I76EII&R{!)aicy;el^fr~!TyduN>R?Mla1W~9kQGTjTQp6Ag!-L78Tr}aK!Ra+o z+)Klkkr#Qd^V^J^UaB9wb8CuiiAu@Gt5Qk!B%sza{;ch8Z#_kF&S#RXb9?LI{T`A% zR7mzfU{dYqpvxSI3GX>P9N7({gmM)@!B52uFsTSMpclv+L?Iv`iiZU)Hcb_o##Ac@ zQAeNO_+59*wKt^W%F55jVJDl~dAf_dTyq$m9e4Bb^30Na?{Ko!H5DzXyqMG5+=1|R zL7n#XJ-C)Pwro-inK~<*(GR=YWURo#HVv~SMy+cjxHRN|oDi!1G%&KX@xJ2Vf;jf7 zMpKI9f$d-uJ=t8QK=wQ(mx-M2r99X}G zy<)5 zCky33Stz263wLW<72@h<>i#yv8q!-7eAvS&0@GBZU1aTrGBX!eGN|g)UY1MIZ zJ%vFQ*EOW6RO~=o0g)$V3 z>0E*W3xpDOy7VT^+?D8!EjM-g=IyM97$9Z`!Cjqp_htZp!Fu9F#AoYrqK5!lJ4}4W zq}f@n==5{(o~bIGj(7x))~;kz`}n+;6!Slx{m1j0KV9xWzo}m?eWAB!2p=qIY?atR zXI#Cz7A47+DqJ{!f%d~_EXMf;8LoDb=h;uFe#+kg)V+WH4&T3Cmc&A~Nj2q%ZU>&B zg2Z9-7Kvqb&Xf!#ZOAx#SWYNr|oO0F;dutB9eVtdIa1{?Y8NjE&x zM(og!4;cVu_6_UNbpGH;d3R?thVD9=?@#tDARd`K$ZO$vE$^RdKbng=3hJXcOmgMO3z~`b^;k{5OScXr zG+DXI9SUE8kDE6i|FHAqhn?N0n|}#v;IFN*xXU}C6_+m5AjyXD)Ip+|4Swb%@JaQ- zD*B}Q>`Dna?2%k zyOIzEwefk~PR4m?KY~i#MPlxjcY^(wpa^uSBOx2&$J9#Fh#$z^In;@eL3B3aO;nKV z@cCEM!5h(CsGp?a_p#DE$<`3r$oKadnqjXi9(5c}FRg%!^>sAwK%8BFITPt)Fim%g z5Zk*%a_(VJG2NtPmqAkDyle2osUbmOIG4=lo=#m4QQ;rj&5B5(ak#-gigM5fjc5tW zz=5Bnsr-Pj0BBTHWYSE_X!wPibKOoF$*>D7uEhpS#oF+<%=k-~mfh>pEK5ztDgQtw zU!!ee@hokVTR0m~p^41SST9*YNrZt7W`jN_NS)<#LOdeG&34){B=0L^9re44r5~8B3Y`c{0Wqbo0%2{ zR=i5)leu;RGo)>AF?Vtn>tM=6ue7D%wGS7XsI@2uA*%b2pMJl&v-@OoXJ_l_BWV1+ zf9gNS=bKBn`d7cX)PFWu|Lafu=i2(8cEA2={in;9zPa7+e{-{X_8+%c@TbewFIE4W z&u`(`)o-NuFIR70y0n4E8~tx?ea%9*E>)Mlxb#n>*;{M_%ldXc00;cugaPqoKGoU$ z^bp}=9&Ts+Bvq5w+c?DcbJLf#HQO8DuC(gHtqZCt@C@1k?q|U4s1JjukCw!fQJvI_060HVYGcw+OPZFDv)nh}uSn5{d%>lN8 zINQ_Ver+eL(H520g-zj-LAeQ0DWw%23K4kS7B+J_JUpCG$}ecgFEw4*&-86 zoep?IV?Y!L$|5U`9vE2ZWS}(C;q^(lmEu?&(m;T<>F|&e!c9m49Wx>C{kXri5xDQR zXCX<`UcEdVyjrrbGLhu<1RtfZ88UB=BeKj6XQgzY#KBeR$s{k(y(bnH~t8 z2;p>0vB?GEtL3A#EG}JXBnC|SnZ!1JkmSG7b!fqv;W;Q|n>^PK{H@Y$i9+W^!n>bg z=yRNEdz0cRJ=4y1#$t))0|b&Yl5oe2F!r7;fsry~KzY zE6Xoi3A#f29%@<6l0Sz?jf$+~c;Y=~{n_yF<;|OQ3&bxq7Jec+kDN={=6HC~vNsx4 zg*>hlK-yEixF^c74X<;x`Jv6Wr65Az5K~jjvMIBG| zIF2(sJC3X@v4a%!l!o5yT25g`4atjBZsr6po6IC)BeOd?($K7|3=h-HynN*(BW2*5 zVf6}0OfNi#xur(UzL;AH2VAb05Zp`sH8vKd8QvjX+0KXd{WkAWjD+c>R~*`xacHb- zg29`KP_+PMz4UI~2K!P+Y9|(JU4?Flp=Gj5ClJ{Eskz4~M1=((kyB@mxwb9=8E5NO zX3>^93WXN#Ll$n!MJPs<&j3xZ9oQyEqN&t{>ZGx@sa|nzYGfxcC-N@P*IPzl5jTNw znr2EXR&-)zI9~Z=cEHSuSkCQBW5ppRnrP}HJJS*TDUd5V30d_`2Ds}dyq%_lPnp~S zq%73IsoHq(FK#WQ)cDqvo%vBY1cnyc?cit~M5I+q-bNA%0g1bCXY|Dj^EJF+U&9;o z75?_W`ep4BZ{&4S= zN?~6hfSn78UO(g)eW}^qkr{@pdeqDvZdpT>pw!Q&5p2=VXlp5@pR>~TXPca%%`aJs z`xa@jz&UAbtY%kNI5vh}<*r1jio2n&;cn;_mIt-T#5==qq-*nqBGs$-GabF3HZ9J$ zX)$7QVFtdE4-_6>@a9^C#Q8TaaxVqXP9BQp4#hv3kIXn>@bdj*`MH|#fAU?4mLwcA zOzS_Y_o+F-f3L2iWzGaQqtkKfa*Ci*Kt1`t(QoqAr+s;b5*DGAI^U3FpmABLabI3l zs=PZd{yVxj^wbfk$rs`ULC_*C$-AMVe8!2CQBjw9(qcFl7wO%qfB` z|4W!#gcIx`r<2#l+dumB%3q(~HE5z{5UN_AUeFV)#$55jH$KwldsEiMzy@`Z#yA9; zJxg2>8LF_279KJ+V=a}5@65S9mZ1*~gom9CsM8jAZP@k>CM`MS{bnXz|6pYN@Oapg zBqp_(hA@hhwle_c&&+x3U?gO>`9kFI#pm<_guFwgP z8_!U7H~wv+n*LfS-_`gYJP~kj*eDy$mkjh{osL|zY_aJZ6OCHsQAP`_E>O-A>Qmz2 zv^U5k&G~9OZu43jILrDTTW{F7j8mteDYba3igK*K*hzfvR&L-CUKqHoG6;*DzSEke@~ z%_jG^VfUtgads)>k?|H4%*;srxhFAUOpI-X?fyJGo%NRwy@>aZ!8y^5sQ%+HkguUL zF*0oxwCV&cTmyME{$sC!$YDOr8VH#AplcvQdRO$vkGuxLFn;qjP!9b}Yak4yZ4H!d zJ6ad70p81)PN%3;P^q&-7HA>S0qiS-TTBd`LmGre-dh|z7NO`eu}uhk-o>A_>g<_` z-jBtXZM5g+##;Zq*s+atH43Cm%bSz71v4B>_YPVZeThSc`y%9a{kB3q>r!XzwItYT zviP#qD0?Z5noRzOF;oKtCj5hucze{w2?wJ%_(a%BfE{{<5z1`iPC2MdaaU`*4MS;u@+K7#SJ$XRZg_0g zkX=@*ww`s0<*nzkU9Fqhx`f-;#=k3>HT#N`hNOrcB?J;n*CaN}`jZA5QpLBvIis!Z zSOK@9E0PqgkLD*?<{JYKz8@S?HH)t4SQN3Ku;x|z!R*-;V9mw{molA@=7H&g z_2VjKD?nW6QcXBNs`}V2c-xe`CSbp@4$uVX?^*bM+N)fVJ>MCe%yFw(^*@G#@%sJg zVEljn_XP2Z+oK~~_JrJ4*hkx&-}$eXGd|dOIlYZ7OHb(5##y&{*0mW?bLTbAwYHT{ zocP&KbgTBYT8+CKG4Rl9P}C>P+Ua0I&Rq+kriv}TxF8flkQacbJuPx+cb{|pc8 zkA@q1RTjc)u>sCIG{tb3U2?U%o!?m}?E?{UR@0N)&HN__Cx$+aBrBXto|#r70FZg_ zHV3{Lwgl7Cj#X)g`U3Xnry|&Lfi(RUdF{2`i=uFC35+PIZ>< z^XRo|Iwv@ez-*=1(4Atl0cWhoNNtl2S#{tTXA>4e^iMU9V|rb;Wu{3b^50?rei6g35>c z+ibiv;0UZoIIB5|MAv$xC06rTR%XF&i$7MbqS$kzb$50+;uSpc-IeMZ3?l&zqfBGt zn&ro>vDkISF-v4aHEjQ^vJHmau9C9c2QYXA+?kyoy_}3sJx7nL;@YiZp@NqR7YxiQ{aNN#mQ+~VbNFYEl%hPw z2|SvaU)G>kc{a_)tNHx2sWxxU$SpB=j)Y^xiCGAI=w@ibSA(}WILFc71Ry5?NzN{VQQ_1&&i*wl@48}908epVILKfl_Nf%?}i^zw~Tw%4A ze<8`dLd7)_A=u%p`hM^hIZu&TZz?yyjBs?Ac*iJlD>d~BCJ>@q?c~^Z@Q}3F;JAV- z?MLv4>CuSc*e|En!YE({zFLN=*4V~)>K)a(4~ zks?K}rV4yBIXT?t{n^B6QV0`XjRD%Qf3YAoPN@l0 zv&(c>E7;DmwPzDSiE}v7LIrYaqrX^*2H$+<*+Ao2w=K+YXkpm<#B$Gg4;`(Vs64$%Q%El~-ucH7w=7S3us&k^XHPSLVfLq@yF zUSHDv#DXGSYW~h`fj6(}pvln9wY_ui!K0wdb6w^{>@`S!`6XQ&D2Z9-r<<>l`EY=| zw#YeN*u&r^WF;@5wa+XEyFzlM`tsVJ{!pw%_L^g6ShsACR2O(aIe-1$<_lcL!z5~X z>9S6?l=;h`!eR2GzVwm{x2Ig!QS>~sA=}_*ZG^F1%a!HXM?teTt!A84>1YOp@_X3WC@E^^E|cFPS4CD{8?CR`DUMJ5 z0}AQ{WTUhJ9&XZ!sN``*fKXdAf-UeV4y%{8vEoD!XUsY zH2n{(38=fUEWc?`G6BFE*=S!RH%hkTaAV+`n6@8|nG$sJW~2HRzwXf{lHaY}5aiyb zCHvWXcH^fC!m0Odc(90`nzgZt*01aO1FbEpD}z*eEcm~VhkrZfn6KD*V;L{&kz0zR z@d#f;i}7CHk=6# zNzuSiFIBgy-`(gMy%Of!$&z!-3t*S_IR$V|fiu{$Z&6Wy~F}2;jviu9M6{L6O*S60Bz~a1~mC1ImqlLVE)xinx1^-*y zYaiL#=7ONTD z&J`Uehp8e=MY`u_yx!0J@mH$TA+Fei9WkDi?bh~18xCO*;Ct*~)L>S>zRp1M&UbG* zu&z5}vNy}IgEic;;gA})$??`>+H3JdF~zYVez@P2>$=mEbT>@dS-naGMH%tCM2u@T zJ~++)3b%%FBJOU8jcaegg+CvScf}!vV@o;voxW$LPS57rI|TvvnBl!-(YdSaQO<7U z=(BPt0?Cu%1(%S`PT7Uw-g^Sr00#;pmrBammtoH14Lw;KpL-)TC6+hRxyI7E3F`|H zDWEVoSC9tcJtGNv zx{a{bxfP|O;NI8}1C(vdR2LiuzNU38lDUcS1;0ci0b+B2S)Y`RFw-BN6vjZ9WP-+S`i zlij~Ocy#aaU$%FD+mq_G$GXv;PnFwVDOGyHpYn%U1m@nLm^a@*vt^v9-rP+liP&& z?(Y2u54U!A#pCe%20viswfWKUmOwl^o$bP-x69qx-Tl$DF9Lr>;GIJJ@80D2v`x(jG~iR~K?GFI1UK$`(Aolfdz8TT5q zHUFrofF^BUK{qPfwlrF|8A2z^l&}W5WBGy+N-(1uB*lgYK|J3EMXjqeLfxa#uIdw9 zr_EL}T5ZyGNa7I@%mA-O2UwTe3}|WD*Xf>rpCtZ;EjQS|d&En3G&Dvq*V~&N^x${u z!E;|7ogU-$8r}sJMcTzCp{C0$ufbh#k2EXIb#4HiW38_?Nl6%YsXl45 zer45aA({R#mYpIfFAy1e!(cq@tehq`TCDLZX|t@(c1`+AzrvFEhR&;>$LFy^VDL zObO#svxTJj9;OSc6Aw{!gtg^xS@(O;%4BX>93K)T5e&59vspoDfVQTZTTvCUBoYk8 zg8Zy`M1%bLEdrz5+7bXbc7I?72!zsa7))?9dfSY!a-A~=4akisgK-L_N)s}33MH9g zSHrZYj(}ZEbquuWQ2)W4oIdb1b%pO~G9ec!rSQnHd5*|}`2h~cnrVC{7rUcB$TjPGy2^|}q~zX!|O zC9=tiBr=+OPMCD1r+KymTTDrAYNk73xS5o7lAIJtxHnra(f}D z=^FWalReu|=}>>r^CRR#>vwe7+n3WJW(aoSL@kdI_a{bg)#I=b7wO&^nOYIlT1ze- zbT2(3KgIt!o|pllb}}eSj>^>$T3)%4jc6(NPD_KA(&3U)qUuFyYJYa9M6pPA1sEpC zn_~g$W>f-$7R3Hu!o80;L7dQ-;hvjdF*iMm*%v4VQT2FxrmO7*Zoa@a&!|m(pLhRhlb+O4G|7)+hal5*@KYV?a=(&)`$~MyOwr)!F z2n}~001*EGCjOy^0RfE2n>0Hp(aBbbiynKTC#PY}yH7!Y1(QV^&20@f!%u;A6s`lT zr8+|$%3Ve;9_H0ouiT}lB%)nd89!;{$~b(uxWBR%m%9q-p+IDNQvWzRl%Qoj5__lb`K6J~@+W z8|*;VJ&St#m0iG_P~qpB4o^!I`waR<4OMqHbM}cO*%2vgxf+;F=eVUQ^RDRxQw2+w?2vX?faP>%Vz!EtDJa|lEajCRI{`tH zdFAC|JFCK!)qm^_FrY29w!U7j!J3%R#>*m{Xah2w?oq`8;z!RiLc3zLG=BGcpmFT} z!|3hdiT?QZaDw|fwS6gN$JF}R;k6sgOXp_b0EA#ZJ#BG@8>NuMcexL~OD-kBKI*gr zCd0afr#YjHjsA*dia5Ed|2z{-I}$P@4R8s?**P)inV-%8pZg5(eW#o9G%uKYILMod zEjY`oROk27Hm>tH>mlCMr4oDlIo=>fw0yj3hL!{rJtRfJ`CGWON@JpawsXx&iQeen zLq1;@4XSb@EX@vol2O|CLWp=tIr#v}XG#6eC>Gw8>Y+N;UCCYRJek!E$My2<=CKyt z)}g~z(Jxq>1}wfQFbEidSinIJ>HeJp0dT!{+m7kox;VRy)PO(Tx{5DQ@Te3>3;df} z_b1j%r+2M6U10Zv>IIpWoM6Sd?S&I&hn;;mGeNKQO1#Pm20!8@&9+Yuc@mhd;sW2g zXX(ws1pDZ1P1XECYlnmBt05bO8+mTg6Nbz|r7vS62`oprir_rm;OYg1Et>IfmF*iQ z5U`adNxL>PqMYrF$8Z4F8wr};8lsOO3PX(i8bcr(If^)bkf7x~^@c=&w;!dMMcNExVN@`Y7Hiyl1F1W#hRa0|LmCR>INj? z7M!r5i#RF`CKNf4wddsC-o33bPiV?R2bml^F;UY(c^bSkn5b7cYK|yrCflO-07Z!l&>7SI>ZOz`&k~vpZzN~_p z3Wya&x`u-Y;cSvq2I#C{hgeD(eJCla;5*>uOPbDcb=7mg!*y^(Tl3y8 LSlF}3 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 AmH+?% diff --git a/behat.yml b/behat.yml index c13e6411..76be48ef 100644 --- a/behat.yml +++ b/behat.yml @@ -1,4 +1,7 @@ default: - paths: - features: Tests/Integration/Features - bootstrap: Tests/Integration/Bootstrap \ No newline at end of file + suites: + crud: + paths: [ Tests/Integration/Features ] + contexts: + - FS\SolrBundle\Tests\Integration\Bootstrap\FeatureContext + - FS\SolrBundle\Tests\Integration\Bootstrap\CrudFeatureContext diff --git a/composer.json b/composer.json index 6635120c..c497db1c 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "symfony/dependency-injection": "*", "symfony/http-kernel": "*", "symfony/config": "*", - "symfony/doctrine-bridge": "*" + "symfony/doctrine-bridge": "*", + "behat/behat": "3.*" }, "minimum-stability": "alpha", "autoload": { @@ -30,6 +31,9 @@ "FS\\SolrBundle": "" } }, + "config": { + "bin-dir": "bin" + }, "suggest": { "doctrine/mongodb": "Required if you want to use the MongoDB ODM features", "doctrine/mongodb-odm": "Required if you want to use the MongoDB ODM features" From 6c60720062a8c067d4e3e436b89ab96a3caecc4f Mon Sep 17 00:00:00 2001 From: Rodrigo Prado Date: Fri, 10 Jul 2015 12:16:10 -0300 Subject: [PATCH 025/332] changed highlighting php code added how to install with composer and syntax highlighting php code --- README.md | 110 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 21c61bd9..c86b0caf 100644 --- a/README.md +++ b/README.md @@ -17,18 +17,24 @@ Bundle 1. Register bundle in AppKernel.php - # app/AppKernel.php +# app/AppKernel.php - $bundles = array( - // ... - new FS\SolrBundle\FSSolrBundle(), - // ... - ); +```php +$bundles = array( + // ... + new FS\SolrBundle\FSSolrBundle(), + // ... +); +``` 2. Add Bundle to autoload A. Via composer, add in your composer.json + composer require floriansemm/solr-bundle + + or + "require": { // ... "floriansemm/solr-bundle": "dev-master" @@ -76,6 +82,7 @@ With this config you can setup two cores: `core1` and `core2`. See section `Spec To put an entity to the index, you must add some annotations to your entity: +```php // your Entity // .... @@ -119,6 +126,7 @@ To put an entity to the index, you must add some annotations to your entity: */ private $created_at = null; } +``` ### Supported field types @@ -139,7 +147,7 @@ It is possible to use custum field types (schema.xml). In some cases a entity should not be index. For this you have the `SynchronizationFilter` Annotation. - +```php /** * @Solr\Document * @Solr\SynchronizationFilter(callback="shouldBeIndex") @@ -154,6 +162,7 @@ In some cases a entity should not be index. For this you have the `Synchronizati // put your logic here } } +``` The callback property specifies an callable function, which decides whether the should index or not. @@ -161,6 +170,7 @@ The callback property specifies an callable function, which decides whether the It is possible to specify a core dedicated to a document +```php /** * @Solr\Document(index="core0") */ @@ -168,10 +178,12 @@ It is possible to specify a core dedicated to a document { // ... } +``` All documents will be indexed in the core `core0`. If your entities/document have different languages then you can setup a callback method, which returns the preferred core for the entity. +```php /** * @Solr\Document(indexHandler="indexHandler") */ @@ -184,11 +196,14 @@ a callback method, which returns the preferred core for the entity. } } } +``` Each core must setup up in the config.yml under `endpoints`. If you leave the `index` or `indexHandler` property empty, then a default core will be used (first in the `endpoints` list). To index a document in all cores use `*` as index value: - @Solr\Document(index="*") +```php +@Solr\Document(index="*") +``` ## Solr field configuration @@ -203,11 +218,13 @@ For details have a look into your schema.xml. So if you have an entity with a property "category", then you don't need a type-declaration in the annotation: - /** - * @Solr\Field - * @ORM\Column(name="category", type="text") - */ - private $category = ''; +```php +/** + * @Solr\Field + * @ORM\Column(name="category", type="text") + */ +private $category = ''; +``` The field has in this case automaticaly the type "general_text". @@ -217,11 +234,13 @@ If you persist this entity, it will put automaticlly to the index. Update and de To query the index you have to call some services. - $query = $this->get('solr')->createQuery('AcmeDemoBundle:Post'); - $query->addSearchTerm('title', 'my title'); +```php +$query = $this->get('solr')->createQuery('AcmeDemoBundle:Post'); +$query->addSearchTerm('title', 'my title'); + +$result = $result = $query->getResult(); +``` - $result = $result = $query->getResult(); - The $result array contains all found entities. The solr-service does all mappings from SolrDocument to your entity for you. @@ -229,22 +248,25 @@ to your entity for you. The pervious examples have queried only the field 'title'. You can also query all fields with a string. - $query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post'); - $query->queryAllFields('my title'); - - $result = $query->getResult(); +```php +$query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post'); +$query->queryAllFields('my title'); +$result = $query->getResult(); +``` ## Define Result-Mapping To narrow the mapping, you can use the `addField()` method. - $query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post'); - $query->addSearchTerm('title', 'my title'); - $query->addField('id'); - $query->addField('text'); +```php +$query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post'); +$query->addSearchTerm('title', 'my title'); +$query->addField('id'); +$query->addField('text'); - $result = $query->getResult(); +$result = $query->getResult(); +``` In this case only the fields id and text will be mapped (addField()), so title and created_at will be empty. If nothing was found $result is empty. @@ -258,25 +280,31 @@ HydrationMode tells the Bundle how to create an entity from a document. With a custom query: - $query = $this->get('solr')->createQuery('AcmeDemoBundle:Post'); - $query->setHydrationMode($mode) +```php +$query = $this->get('solr')->createQuery('AcmeDemoBundle:Post'); +$query->setHydrationMode($mode) +``` With a custom document-repository you have to set the property `$hydrationMode` itself: - public function find($id) - { - $this->hydrationMode = HydrationModes::HYDRATE_INDEX; - - return parent::find($id); - } +```php +public function find($id) +{ + $this->hydrationMode = HydrationModes::HYDRATE_INDEX; + + return parent::find($id); +} +``` ## Index manually an entity To index your entities manually, you can do it the following way: - $this->get('solr')->addDocument($entity); - $this->get('solr')->updateDocument($entity); - $this->get('solr')->deleteDocument($entity); +```php +$this->get('solr')->addDocument($entity); +$this->get('solr')->updateDocument($entity); +$this->get('solr')->deleteDocument($entity); +``` `deleteDocument()` requires that the entity-id is set. @@ -285,9 +313,11 @@ To index your entities manually, you can do it the following way: If you specify your own repository you must extend the `FS\SolrBundle\Repository\Repository` class. The useage is the same like Doctrine-Repositories: - $myRepository = $this->get('solr')->getRepository('AcmeDemoBundle:Post'); - $result = $myRepository->mySpecialFindMethod(); - +```php +$myRepository = $this->get('solr')->getRepository('AcmeDemoBundle:Post'); +$result = $myRepository->mySpecialFindMethod(); +``` + If you haven't declared a concrete repository in your entity and you calling `$this->get('solr')->getRepository('AcmeDemoBundle:Post')`, you will get an instance of `FS\SolrBundle\Repository\Repository`. From 20f8c9e5f4cb25048139c9fd8c4e9d4b98190039 Mon Sep 17 00:00:00 2001 From: Rodrigo Prado Date: Fri, 10 Jul 2015 16:08:35 -0300 Subject: [PATCH 026/332] updated syntax highligthing --- README.md | 172 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 89 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index c86b0caf..0eaa491d 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,9 @@ $bundles = array( A. Via composer, add in your composer.json - composer require floriansemm/solr-bundle - +```sh +composer require floriansemm/solr-bundle +``` or "require": { @@ -44,20 +45,24 @@ $bundles = array( i. In symfony 2.1.4 (supposing you clone the bundle in vendor/floriansemm/solr-bundle/FS/, making available vendor/floriansemm/solr-bundle/FS/SolrBundle/FSSolrBundle.php) - $loader->add('FS\\SolrBundle', array(__DIR__.'/../vendor/floriansemm/solr-bundle')); - +```php +$loader->add('FS\\SolrBundle', array(__DIR__.'/../vendor/floriansemm/solr-bundle')); +``` ii. in older version it could be - $loader->registerNamespaces(array( - // ... - 'FS' => __DIR__.'/../vendor/bundles', - // ... - )); +```php +$loader->registerNamespaces(array( + // ... + 'FS' => __DIR__.'/../vendor/bundles', + // ... +)); +``` ## Multiple Indexes You have to setup the connection options +```config # app/config/config.yml fs_solr: endpoints: @@ -73,6 +78,7 @@ You have to setup the connection options path: /solr/core2 core: corename timeout: 5 +``` With this config you can setup two cores: `core1` and `core2`. See section `Specify cores` for more information. @@ -83,49 +89,49 @@ With this config you can setup two cores: `core1` and `core2`. See section `Spec To put an entity to the index, you must add some annotations to your entity: ```php - // your Entity +// your Entity - // .... - use FS\SolrBundle\Doctrine\Annotation as Solr; +// .... +use FS\SolrBundle\Doctrine\Annotation as Solr; - /** - * @Solr\Document(repository="Full\Qualified\Class\Name") - * @ORM\Table() - */ - class Post - { - /** - * @Solr\Id - * - * @ORM\Column(name="id", type="integer") - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - */ - - private $id; - /** - * - * @Solr\Field(type="string") - * - * @ORM\Column(name="title", type="string", length=255) - */ - private $title = ''; - - /** - * - * @Solr\Field(type="string") - * - * @ORM\Column(name="text", type="text") - */ - private $text = ''; - - /** - * @Solr\Field(type="date") - * - * @ORM\Column(name="created_at", type="datetime") - */ - private $created_at = null; - } +/** +* @Solr\Document(repository="Full\Qualified\Class\Name") +* @ORM\Table() +*/ +class Post +{ + /** + * @Solr\Id + * + * @ORM\Column(name="id", type="integer") + * @ORM\Id + * @ORM\GeneratedValue(strategy="AUTO") + */ + + private $id; + /** + * + * @Solr\Field(type="string") + * + * @ORM\Column(name="title", type="string", length=255) + */ + private $title = ''; + + /** + * + * @Solr\Field(type="string") + * + * @ORM\Column(name="text", type="text") + */ + private $text = ''; + + /** + * @Solr\Field(type="date") + * + * @ORM\Column(name="created_at", type="datetime") + */ + private $created_at = null; +} ``` ### Supported field types @@ -148,20 +154,20 @@ It is possible to use custum field types (schema.xml). In some cases a entity should not be index. For this you have the `SynchronizationFilter` Annotation. ```php - /** - * @Solr\Document - * @Solr\SynchronizationFilter(callback="shouldBeIndex") - */ - class SomeEntity - { - /** - * @return boolean - */ - public function shouldBeIndex() - { - // put your logic here - } - } +/** + * @Solr\Document + * @Solr\SynchronizationFilter(callback="shouldBeIndex") + */ +class SomeEntity +{ + /** + * @return boolean + */ + public function shouldBeIndex() + { + // put your logic here + } +} ``` The callback property specifies an callable function, which decides whether the should index or not. @@ -171,31 +177,31 @@ The callback property specifies an callable function, which decides whether the It is possible to specify a core dedicated to a document ```php - /** - * @Solr\Document(index="core0") - */ - class SomeEntity - { - // ... - } +/** + * @Solr\Document(index="core0") + */ +class SomeEntity +{ + // ... +} ``` All documents will be indexed in the core `core0`. If your entities/document have different languages then you can setup a callback method, which returns the preferred core for the entity. ```php - /** - * @Solr\Document(indexHandler="indexHandler") - */ - class SomeEntity - { - public function indexHandler() - { - if ($this->language == 'en') { - return 'core0'; - } - } - } +/** + * @Solr\Document(indexHandler="indexHandler") + */ +class SomeEntity +{ + public function indexHandler() + { + if ($this->language == 'en') { + return 'core0'; + } + } +} ``` Each core must setup up in the config.yml under `endpoints`. If you leave the `index` or `indexHandler` property empty, From 6de71ed35550c8a7b99cec25a47b28ffed272124 Mon Sep 17 00:00:00 2001 From: Rodrigo Prado Date: Sat, 11 Jul 2015 11:47:08 -0300 Subject: [PATCH 027/332] Changed structure readme and install option --- README.md | 115 +++++++++++++++++++++++++++--------------------------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 0eaa491d..35a91482 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,40 @@ - +SolrBundle +========== [![Build Status](https://secure.travis-ci.org/floriansemm/SolrBundle.png?branch=master)](http://travis-ci.org/floriansemm/SolrBundle) [![Latest Stable Version](https://poser.pugx.org/floriansemm/solr-bundle/v/stable.svg)](https://packagist.org/packages/floriansemm/solr-bundle) [![Total Downloads](https://poser.pugx.org/floriansemm/solr-bundle/downloads.svg)](https://packagist.org/packages/floriansemm/solr-bundle) +Introduction +------------ + This Bundle provides a simple API to index and query a Solr Index. And do not forget to join the Gitter chat [![join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -# Configuration +## Installation -The bundle requires a working doctrine-orm or doctrine-mongodb configuration. There are no differences in the use. +Installation is a quick (I promise!) 3 step process: -## Install the Bundle +1. Download SolrBundle +2. Enable the Bundle +3. Configure the SolrBundle -Bundle +### Step 1: Download SolrBundle -1. Register bundle in AppKernel.php +This bundle is available on Packagist. You can install it using Composer: -# app/AppKernel.php +.. code-block:: bash -```php -$bundles = array( - // ... - new FS\SolrBundle\FSSolrBundle(), - // ... -); -``` - -2. Add Bundle to autoload + $ composer require floriansemm/solr-bundle - A. Via composer, add in your composer.json +or manually, in app/autoload.php -```sh -composer require floriansemm/solr-bundle -``` - or - - "require": { - // ... - "floriansemm/solr-bundle": "dev-master" - } - - B. or manually, in app/autoload.php - - i. In symfony 2.1.4 (supposing you clone the bundle in vendor/floriansemm/solr-bundle/FS/, making available vendor/floriansemm/solr-bundle/FS/SolrBundle/FSSolrBundle.php) +i. In symfony 2.1.4 (supposing you clone the bundle in vendor/floriansemm/solr-bundle/FS/, making available vendor/floriansemm/solr-bundle/FS/SolrBundle/FSSolrBundle.php) ```php $loader->add('FS\\SolrBundle', array(__DIR__.'/../vendor/floriansemm/solr-bundle')); ``` - ii. in older version it could be +ii. in older version it could be ```php $loader->registerNamespaces(array( @@ -58,33 +44,48 @@ $loader->registerNamespaces(array( )); ``` -## Multiple Indexes +### Step 2: Enable the bundle + +Finally, enable the bundle in the kernel + +``` php +getResult(); The $result array contains all found entities. The solr-service does all mappings from SolrDocument to your entity for you. -## Query all fields of a document +### Query all fields of a document The pervious examples have queried only the field 'title'. You can also query all fields with a string. @@ -261,7 +262,7 @@ $query->queryAllFields('my title'); $result = $query->getResult(); ``` -## Define Result-Mapping +### Define Result-Mapping To narrow the mapping, you can use the `addField()` method. @@ -277,7 +278,7 @@ $result = $query->getResult(); In this case only the fields id and text will be mapped (addField()), so title and created_at will be empty. If nothing was found $result is empty. -## Configure HydrationModes +### Configure HydrationModes HydrationMode tells the Bundle how to create an entity from a document. @@ -302,7 +303,7 @@ public function find($id) } ``` -## Index manually an entity +### Index manually an entity To index your entities manually, you can do it the following way: @@ -314,7 +315,7 @@ $this->get('solr')->deleteDocument($entity); `deleteDocument()` requires that the entity-id is set. -## Use document repositories +### Use document repositories If you specify your own repository you must extend the `FS\SolrBundle\Repository\Repository` class. The useage is the same like Doctrine-Repositories: @@ -327,7 +328,7 @@ $result = $myRepository->mySpecialFindMethod(); If you haven't declared a concrete repository in your entity and you calling `$this->get('solr')->getRepository('AcmeDemoBundle:Post')`, you will get an instance of `FS\SolrBundle\Repository\Repository`. -## Commands +### Commands There are comming two commands with this bundle: From b64e67e48174ca499839d2b9d3522c7e6965a2b0 Mon Sep 17 00:00:00 2001 From: Rodrigo Prado Date: Sat, 11 Jul 2015 11:50:04 -0300 Subject: [PATCH 028/332] corrected bash syntax --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 35a91482..c033edd4 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,9 @@ Installation is a quick (I promise!) 3 step process: This bundle is available on Packagist. You can install it using Composer: -.. code-block:: bash - +```bash $ composer require floriansemm/solr-bundle +``` or manually, in app/autoload.php From 8bed8e76b403bc960cddfeaa68f1c9cfb87d8baa Mon Sep 17 00:00:00 2001 From: Rodrigo Prado Date: Sat, 11 Jul 2015 11:50:38 -0300 Subject: [PATCH 029/332] remove spaces in line --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c033edd4..e555c751 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Installation is a quick (I promise!) 3 step process: This bundle is available on Packagist. You can install it using Composer: ```bash - $ composer require floriansemm/solr-bundle +$ composer require floriansemm/solr-bundle ``` or manually, in app/autoload.php From c536fe527c5fca280cc21e69268c139ff8e04d16 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 08:07:23 +0200 Subject: [PATCH 030/332] fix field access --- Tests/Integration/Bootstrap/CrudFeatureContext.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Tests/Integration/Bootstrap/CrudFeatureContext.php b/Tests/Integration/Bootstrap/CrudFeatureContext.php index a270b118..538ea512 100644 --- a/Tests/Integration/Bootstrap/CrudFeatureContext.php +++ b/Tests/Integration/Bootstrap/CrudFeatureContext.php @@ -3,6 +3,7 @@ namespace FS\SolrBundle\Tests\Integration\Bootstrap; use Behat\Behat\Context\Context; +use Solarium\QueryType\Update\Query\Document\Document; class CrudFeatureContext extends FeatureContext { @@ -74,8 +75,11 @@ public function theIndexShouldBeUpdated() throw new \RuntimeException(sprintf('could not find document with id %s after update', $entityId)); } + /* @var Document $document */ foreach ($resultset as $document) { - $changedFieldValue = $document['text_t']; + $fields = $document->getFields(); + + $changedFieldValue = $fields['text_t'][0]; if ($changedFieldValue != $this->entity->getText()) { throw new \RuntimeException(sprintf('updated entity with id %s was not updated in solr', $entityId)); From 92c2cbed1498cc6e6b3d8fbff3548143fd73e991 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 08:44:10 +0200 Subject: [PATCH 031/332] verify that document was insert successfully --- .../Bootstrap/CrudFeatureContext.php | 23 +++----- .../Integration/Bootstrap/FeatureContext.php | 53 ++++++++++++++++++- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/Tests/Integration/Bootstrap/CrudFeatureContext.php b/Tests/Integration/Bootstrap/CrudFeatureContext.php index 538ea512..b19e7206 100644 --- a/Tests/Integration/Bootstrap/CrudFeatureContext.php +++ b/Tests/Integration/Bootstrap/CrudFeatureContext.php @@ -48,7 +48,7 @@ public function shouldNoErrorOccurre() throw new \RuntimeException(sprintf('error occurred while indexing: %s', $eventDispatcher->getOccurredErrors())); } - $this->assertInsertSuccessful(); + $this->assertInsertSuccessful($this->entity->getId()); } /** @@ -64,26 +64,15 @@ public function iUpdateOneAttribute() */ public function theIndexShouldBeUpdated() { - $client = $this->getSolrClient(); $entityId = $this->entity->getId(); + $document = $this->findDocumentById($entityId); - $query = $client->createSelect(); - $query->setQuery(sprintf('id:%s', $entityId)); - $resultset = $client->select($query); - - if ($resultset->getNumFound() == 0) { - throw new \RuntimeException(sprintf('could not find document with id %s after update', $entityId)); - } - - /* @var Document $document */ - foreach ($resultset as $document) { - $fields = $document->getFields(); + $fields = $document->getFields(); - $changedFieldValue = $fields['text_t'][0]; + $changedFieldValue = $fields['text_t'][0]; - if ($changedFieldValue != $this->entity->getText()) { - throw new \RuntimeException(sprintf('updated entity with id %s was not updated in solr', $entityId)); - } + if ($changedFieldValue != $this->entity->getText()) { + throw new \RuntimeException(sprintf('updated entity with id %s was not updated in solr', $entityId)); } } diff --git a/Tests/Integration/Bootstrap/FeatureContext.php b/Tests/Integration/Bootstrap/FeatureContext.php index b5021312..33ee1350 100644 --- a/Tests/Integration/Bootstrap/FeatureContext.php +++ b/Tests/Integration/Bootstrap/FeatureContext.php @@ -3,6 +3,7 @@ namespace FS\SolrBundle\Tests\Integration\Bootstrap; use Behat\Behat\Context\Context; +use Solarium\QueryType\Update\Query\Document\Document; /** * Features context. @@ -72,6 +73,9 @@ public function getSolrInstance() return $solr; } + /** + * @return \FS\SolrBundle\Doctrine\Mapper\EntityMapper + */ private function setupEntityMapper() { $registry = new \FS\SolrBundle\Tests\Integration\DoctrineRegistryFake(); @@ -123,6 +127,8 @@ private function setupMetaInformationFactory() } /** + * Solarium Client with one core (core0) + * * @return \Solarium\Client */ private function setupSolrClient() @@ -141,12 +147,57 @@ private function setupSolrClient() return $solrClient; } - public function assertInsertSuccessful() + /** + * @param int $entityId + * + * @throws \RuntimeException if Events::POST_INSERT or Events::PRE_INSERT was fired or $entityId not equal to found document id + */ + public function assertInsertSuccessful($entityId) { if (!$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::POST_INSERT) || !$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::PRE_INSERT) ) { throw new \RuntimeException('Insert was not successful'); } + + $document = $this->findDocumentById($entityId); + $idFieldValue = $document->getFields()['id']; + + if (intval($idFieldValue) !== intval($entityId)) { + throw new \RuntimeException(sprintf('found document has ID %s, expected %s', $idFieldValue, $entityId)); + } + } + + /** + * uses Solarium query to find a document by ID + * + * @return Document + * + * @throws \RuntimeException if resultset is empty, no document with given ID was found + */ + protected function findDocumentById($entityId) + { + $client = $this->getSolrClient(); + + $query = $client->createSelect(); + $query->setQuery(sprintf('id:%s', $entityId)); + $resultset = $client->select($query); + + if ($resultset->getNumFound() == 0) { + throw new \RuntimeException(sprintf('could not find document with id %s after update', $entityId)); + } + + $documents = $resultset->getDocuments(); + + /* @var Document $document */ + foreach ($documents as $document) { + $idFieldValue = $document->getFields()['id']; + + if (intval($idFieldValue) == intval($entityId)) { + return $document; + } + } + + throw new \RuntimeException(sprintf('no document with Id %s was found', $entityId)); } } From 28ff22449c1ad2cb7910598121596694f548567e Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 08:55:40 +0200 Subject: [PATCH 032/332] use behat binary und ./bin --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2495c39a..cc0f822b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ before_script: script: - phpunit - - php behat.phar + - ./bin/behat notifications: email: - fsemm.travis-ci@gmx.de From ec4863990ae28af42b2ce08cba9c0f47105f68c9 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 09:36:20 +0200 Subject: [PATCH 033/332] configure solr-config files --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cc0f822b..319810f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,7 @@ before_script: - echo "extension=mongo.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` - curl -s http://getcomposer.org/installer | php - php composer.phar install --dev - - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_VERSION=4.8.0 bash - + - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_VERSION=4.8.0 SOLR_CONFS="schema.xml solrconfig.xml" bash script: - phpunit From a5d71b6f9631298fce6067321a8f531868eba61b Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 09:45:06 +0200 Subject: [PATCH 034/332] enable solr debug-mode --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 319810f5..1f49b5d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_script: - echo "extension=mongo.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` - curl -s http://getcomposer.org/installer | php - php composer.phar install --dev - - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_VERSION=4.8.0 SOLR_CONFS="schema.xml solrconfig.xml" bash + - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_VERSION=4.8.0 DEBUG=true bash script: - phpunit From 1e43c4cb201a61a77ed31ffcaab2e5fc2ccb9bd2 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 09:56:34 +0200 Subject: [PATCH 035/332] use multicore --- Tests/Integration/Bootstrap/FeatureContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Bootstrap/FeatureContext.php b/Tests/Integration/Bootstrap/FeatureContext.php index 33ee1350..29640a9f 100644 --- a/Tests/Integration/Bootstrap/FeatureContext.php +++ b/Tests/Integration/Bootstrap/FeatureContext.php @@ -137,7 +137,7 @@ private function setupSolrClient() 'default' => array( 'host' => 'localhost', 'port' => 8983, - 'path' => '/solr/core0', + 'path' => '/solr/multicore/core0', ) ); From cb7241401f3465e481bc71210d8f66ee7cbe8e1c Mon Sep 17 00:00:00 2001 From: Rodrigo Prado Date: Mon, 13 Jul 2015 16:15:10 -0300 Subject: [PATCH 036/332] removed instructions to install with symfony 2.1 --- README.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/README.md b/README.md index e555c751..71ee2814 100644 --- a/README.md +++ b/README.md @@ -27,23 +27,6 @@ This bundle is available on Packagist. You can install it using Composer: $ composer require floriansemm/solr-bundle ``` -or manually, in app/autoload.php - -i. In symfony 2.1.4 (supposing you clone the bundle in vendor/floriansemm/solr-bundle/FS/, making available vendor/floriansemm/solr-bundle/FS/SolrBundle/FSSolrBundle.php) - -```php -$loader->add('FS\\SolrBundle', array(__DIR__.'/../vendor/floriansemm/solr-bundle')); -``` -ii. in older version it could be - -```php -$loader->registerNamespaces(array( - // ... - 'FS' => __DIR__.'/../vendor/bundles', - // ... -)); -``` - ### Step 2: Enable the bundle Finally, enable the bundle in the kernel From d7dae0638d472632ba3f75973f8b12a5e37eaa1e Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 21:25:11 +0200 Subject: [PATCH 037/332] fix document field access --- Tests/Integration/Bootstrap/CrudFeatureContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Bootstrap/CrudFeatureContext.php b/Tests/Integration/Bootstrap/CrudFeatureContext.php index b19e7206..f3f98224 100644 --- a/Tests/Integration/Bootstrap/CrudFeatureContext.php +++ b/Tests/Integration/Bootstrap/CrudFeatureContext.php @@ -69,7 +69,7 @@ public function theIndexShouldBeUpdated() $fields = $document->getFields(); - $changedFieldValue = $fields['text_t'][0]; + $changedFieldValue = $fields['text_t']; if ($changedFieldValue != $this->entity->getText()) { throw new \RuntimeException(sprintf('updated entity with id %s was not updated in solr', $entityId)); From 091e2b38f7e831581963c638c7a3a0a2b648f572 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 21:25:27 +0200 Subject: [PATCH 038/332] add solr schema.xml --- Tests/Resources/config/schema.xml | 722 ++++++++++++++++++++++++++++++ 1 file changed, 722 insertions(+) create mode 100644 Tests/Resources/config/schema.xml diff --git a/Tests/Resources/config/schema.xml b/Tests/Resources/config/schema.xml new file mode 100644 index 00000000..8bc7362f --- /dev/null +++ b/Tests/Resources/config/schema.xml @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From dc7264857a90120937e43540b74508921c288864 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 21:25:40 +0200 Subject: [PATCH 039/332] fix solr-core config --- Tests/Integration/Bootstrap/FeatureContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Bootstrap/FeatureContext.php b/Tests/Integration/Bootstrap/FeatureContext.php index 29640a9f..33ee1350 100644 --- a/Tests/Integration/Bootstrap/FeatureContext.php +++ b/Tests/Integration/Bootstrap/FeatureContext.php @@ -137,7 +137,7 @@ private function setupSolrClient() 'default' => array( 'host' => 'localhost', 'port' => 8983, - 'path' => '/solr/multicore/core0', + 'path' => '/solr/core0', ) ); From 910dbd18d0e0502ff3611d33181dddd997fd824a Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 21:27:04 +0200 Subject: [PATCH 040/332] add confs option --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1f49b5d2..a516fc91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_script: - echo "extension=mongo.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` - curl -s http://getcomposer.org/installer | php - php composer.phar install --dev - - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_VERSION=4.8.0 DEBUG=true bash + - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_VERSION=4.8.0 SOLR_CONFS="Tests/Resources/config/schema.xml" DEBUG=true bash script: - phpunit From 818ca897ec81b5b145db5f96ea3d76f06ea81fa6 Mon Sep 17 00:00:00 2001 From: Rodrigo Prado Date: Mon, 13 Jul 2015 16:32:02 -0300 Subject: [PATCH 041/332] corrected call to service solr.client --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 71ee2814..0a18848a 100644 --- a/README.md +++ b/README.md @@ -225,10 +225,10 @@ If you persist this entity, it will put automaticlly to the index. Update and de To query the index you have to call some services. ```php -$query = $this->get('solr')->createQuery('AcmeDemoBundle:Post'); +$query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post'); $query->addSearchTerm('title', 'my title'); -$result = $result = $query->getResult(); +$result = $query->getResult(); ``` The $result array contains all found entities. The solr-service does all mappings from SolrDocument @@ -271,7 +271,7 @@ HydrationMode tells the Bundle how to create an entity from a document. With a custom query: ```php -$query = $this->get('solr')->createQuery('AcmeDemoBundle:Post'); +$query = $this->get('solr.client')->createQuery('AcmeDemoBundle:Post'); $query->setHydrationMode($mode) ``` From 8d2a6af4925d8de0091f11bbf7bc9cce8530ae82 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 21:35:02 +0200 Subject: [PATCH 042/332] remove filter with reference to unknown synonyms.txt --- Tests/Resources/config/schema.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/Resources/config/schema.xml b/Tests/Resources/config/schema.xml index 8bc7362f..0f9a969b 100644 --- a/Tests/Resources/config/schema.xml +++ b/Tests/Resources/config/schema.xml @@ -470,7 +470,6 @@ - From dc1010bf87a82850e57a7f53e898339fa1ba1ec0 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 13 Jul 2015 21:42:44 +0200 Subject: [PATCH 043/332] remove solr-debugging flag --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a516fc91..791d7124 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_script: - echo "extension=mongo.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` - curl -s http://getcomposer.org/installer | php - php composer.phar install --dev - - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_VERSION=4.8.0 SOLR_CONFS="Tests/Resources/config/schema.xml" DEBUG=true bash + - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_VERSION=4.8.0 SOLR_CONFS="Tests/Resources/config/schema.xml" bash script: - phpunit From ee89c6bd9e35dd00af4812528b93562def061d33 Mon Sep 17 00:00:00 2001 From: Rodrigo Prado Date: Mon, 13 Jul 2015 17:05:15 -0300 Subject: [PATCH 044/332] corrected call to service solr.client in other parts --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0a18848a..f1273a3f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ And do not forget to join the Gitter chat [![join the chat at https://gitter.im/ ## Installation Installation is a quick (I promise!) 3 step process: - +up 1. Download SolrBundle 2. Enable the Bundle 3. Configure the SolrBundle @@ -77,7 +77,7 @@ To put an entity to the index, you must add some annotations to your entity: // .... use FS\SolrBundle\Doctrine\Annotation as Solr; - + /** * @Solr\Document(repository="Full\Qualified\Class\Name") * @ORM\Table() @@ -154,7 +154,7 @@ class SomeEntity } ``` -The callback property specifies an callable function, which decides whether the should index or not. +The callback property specifies an callable function, which decides whether the should index or not. ### Specify cores @@ -291,9 +291,9 @@ public function find($id) To index your entities manually, you can do it the following way: ```php -$this->get('solr')->addDocument($entity); -$this->get('solr')->updateDocument($entity); -$this->get('solr')->deleteDocument($entity); +$this->get('solr.client')->addDocument($entity); +$this->get('solr.client')->updateDocument($entity); +$this->get('solr.client')->deleteDocument($entity); ``` `deleteDocument()` requires that the entity-id is set. @@ -304,11 +304,11 @@ If you specify your own repository you must extend the `FS\SolrBundle\Repository like Doctrine-Repositories: ```php -$myRepository = $this->get('solr')->getRepository('AcmeDemoBundle:Post'); +$myRepository = $this->get('solr.client')->getRepository('AcmeDemoBundle:Post'); $result = $myRepository->mySpecialFindMethod(); -``` +``` -If you haven't declared a concrete repository in your entity and you calling `$this->get('solr')->getRepository('AcmeDemoBundle:Post')`, you will +If you haven't declared a concrete repository in your entity and you calling `$this->get('solr.client')->getRepository('AcmeDemoBundle:Post')`, you will get an instance of `FS\SolrBundle\Repository\Repository`. ### Commands From e03a70ecd4286e18ee4c005dc7b926d43c4587f3 Mon Sep 17 00:00:00 2001 From: Rodrigo Prado Date: Tue, 14 Jul 2015 23:34:43 -0300 Subject: [PATCH 045/332] corrected list --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f1273a3f..38c715b9 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ And do not forget to join the Gitter chat [![join the chat at https://gitter.im/ ## Installation Installation is a quick (I promise!) 3 step process: -up + 1. Download SolrBundle 2. Enable the Bundle 3. Configure the SolrBundle From f90c2ae10d815af5750119f9e155bcda28272767 Mon Sep 17 00:00:00 2001 From: Dickriven Chellemboyee Date: Thu, 23 Jul 2015 12:02:38 +0400 Subject: [PATCH 046/332] fix typo in README --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 38c715b9..99107641 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ Currently is a basic set of types implemented. - long - boolean -It is possible to use custum field types (schema.xml). +It is possible to use custom field types (schema.xml). ### Filter annotation @@ -218,7 +218,7 @@ private $category = ''; The field has in this case automaticaly the type "general_text". -If you persist this entity, it will put automaticlly to the index. Update and delete happens automatically too. +If you persist this entity, it will put automatically to the index. Update and delete happens automatically too. ### Query a field of a document @@ -293,14 +293,14 @@ To index your entities manually, you can do it the following way: ```php $this->get('solr.client')->addDocument($entity); $this->get('solr.client')->updateDocument($entity); -$this->get('solr.client')->deleteDocument($entity); +$this->get('solr.client')->removeDocument($entity); ``` -`deleteDocument()` requires that the entity-id is set. +`removeDocument()` requires that the entity-id is set. ### Use document repositories -If you specify your own repository you must extend the `FS\SolrBundle\Repository\Repository` class. The useage is the same +If you specify your own repository you must extend the `FS\SolrBundle\Repository\Repository` class. The usage is the same like Doctrine-Repositories: ```php @@ -313,7 +313,7 @@ get an instance of `FS\SolrBundle\Repository\Repository`. ### Commands -There are comming two commands with this bundle: +There are two commands with this bundle: * `solr:index:clear` - delete all documents in the index * `solr:synchronize` - synchronize the db with the index From 2e310ddf3db1a918389ec37d551766ff364a715e Mon Sep 17 00:00:00 2001 From: Dickriven Chellemboyee Date: Fri, 24 Jul 2015 10:26:53 +0400 Subject: [PATCH 047/332] merge parent properties with child properties --- Doctrine/Annotation/AnnotationReader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doctrine/Annotation/AnnotationReader.php b/Doctrine/Annotation/AnnotationReader.php index cb9987e2..83b814a6 100644 --- a/Doctrine/Annotation/AnnotationReader.php +++ b/Doctrine/Annotation/AnnotationReader.php @@ -236,7 +236,7 @@ private function getClassAnnotation($entity, $annotationName) private function readClassProperties($entity) { $reflectionClass = new \ReflectionClass($entity); - $inheritedProperties = array_merge($reflectionClass->getProperties(), $this->getParentProperties($reflectionClass)); + $inheritedProperties = array_merge($this->getParentProperties($reflectionClass), $reflectionClass->getProperties()); $properties = array(); foreach ($inheritedProperties as $property) { From eb6dbead2c03bf9532e90fdd629b92eef1835237 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 24 Jul 2015 10:39:07 +0200 Subject: [PATCH 048/332] set key-field for documents --- Doctrine/Mapper/Mapping/AbstractDocumentCommand.php | 5 +++-- Tests/Doctrine/Mapper/Mapping/MapIdentifierCommandTest.php | 4 ++-- Tests/Doctrine/Mapper/Mapping/SolrDocumentTest.php | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php b/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php index b4e92b40..b7543981 100644 --- a/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php +++ b/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php @@ -19,8 +19,9 @@ public function createDocument(MetaInformationInterface $meta) { $document = new Document(); - $document->addField('id', $meta->getEntityId()); - $document->addField('document_name_s', $meta->getDocumentName()); + $key = $meta->getDocumentName() . '_' . $meta->getEntityId(); + $document->setKey('id', $key); + $document->setBoost($meta->getBoost()); return $document; diff --git a/Tests/Doctrine/Mapper/Mapping/MapIdentifierCommandTest.php b/Tests/Doctrine/Mapper/Mapping/MapIdentifierCommandTest.php index 1292c2f6..1b007ab9 100644 --- a/Tests/Doctrine/Mapper/Mapping/MapIdentifierCommandTest.php +++ b/Tests/Doctrine/Mapper/Mapping/MapIdentifierCommandTest.php @@ -20,8 +20,8 @@ public function testCreateDocument_DocumentHasOnlyIdAndNameField() $document = $command->createDocument(MetaTestInformationFactory::getMetaInformation()); - $this->assertEquals(2, $document->count(), 'fieldcount is two'); - $this->assertEquals(2, $document->id, 'id is 2'); + $this->assertEquals(1, $document->count(), 'fieldcount is two'); + $this->assertEquals('validtestentity_2', $document->id, 'id is 2'); } diff --git a/Tests/Doctrine/Mapper/Mapping/SolrDocumentTest.php b/Tests/Doctrine/Mapper/Mapping/SolrDocumentTest.php index d819880e..cbb58456 100644 --- a/Tests/Doctrine/Mapper/Mapping/SolrDocumentTest.php +++ b/Tests/Doctrine/Mapper/Mapping/SolrDocumentTest.php @@ -5,7 +5,7 @@ abstract class SolrDocumentTest extends \PHPUnit_Framework_TestCase { - const FIELDS_ALWAYS_MAPPED = 2; + const FIELDS_ALWAYS_MAPPED = 1; protected function assertHasDocumentFields(Document $document, $expectedFields) { From 6b8a79893affd72a0bfacaa4a337840b137346c7 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 25 Jul 2015 18:52:33 +0200 Subject: [PATCH 049/332] set key-field for documents --- Client/Client.php | 4 +++ Doctrine/Hydration/DoctrineHydrator.php | 2 +- Doctrine/Hydration/ValueHydrator.php | 20 +++++++++++ .../Mapping/AbstractDocumentCommand.php | 4 +-- Doctrine/Mapper/MetaInformation.php | 25 +++++++++++-- Doctrine/Mapper/MetaInformationInterface.php | 6 ++++ Query/AbstractQuery.php | 25 +++++++++++++ Query/FindByIdentifierQuery.php | 21 +++++++---- Repository/Repository.php | 5 ++- .../Hydration/DoctrineHydratorTest.php | 10 +++--- .../Doctrine/Hydration/ValueHydratorTest.php | 4 +-- Tests/DocumentStub.php | 12 +++++++ Tests/MulticoreSolrTest.php | 1 + Tests/Query/FindByIdentifierQueryTest.php | 35 +++++-------------- 14 files changed, 126 insertions(+), 48 deletions(-) diff --git a/Client/Client.php b/Client/Client.php index eb9c1042..6a3cb9d3 100644 --- a/Client/Client.php +++ b/Client/Client.php @@ -2,6 +2,7 @@ namespace FS\SolrBundle\Client; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; use FS\SolrBundle\Query\FindByIdentifierQuery; use Solarium\Core\Query\QueryInterface; use Solarium\QueryType\Update\Query\Document\DocumentInterface; @@ -44,8 +45,11 @@ public function update(DocumentInterface $doc, $index) */ public function delete(DocumentInterface $document, $index) { + $documentKey = $document->getField(MetaInformationInterface::DOCUMENT_KEY_FIELD_NAME); + $deleteQuery = new FindByIdentifierQuery(); $deleteQuery->setDocument($document); + $deleteQuery->setDocumentKey($documentKey); $delete = $this->solariumClient->createUpdate(); $delete->addDeleteQuery($deleteQuery->getQuery()); diff --git a/Doctrine/Hydration/DoctrineHydrator.php b/Doctrine/Hydration/DoctrineHydrator.php index 635af9d5..18b69d39 100644 --- a/Doctrine/Hydration/DoctrineHydrator.php +++ b/Doctrine/Hydration/DoctrineHydrator.php @@ -38,7 +38,7 @@ public function __construct(RegistryInterface $doctrine, HydratorInterface $valu */ public function hydrate($document, MetaInformationInterface $metaInformation) { - $entityId = $document->id; + $entityId = $metaInformation->getEntityId(); $doctrineEntity = $this->doctrine ->getManager() ->getRepository($metaInformation->getClassName()) diff --git a/Doctrine/Hydration/ValueHydrator.php b/Doctrine/Hydration/ValueHydrator.php index 466ae8df..2d74331f 100644 --- a/Doctrine/Hydration/ValueHydrator.php +++ b/Doctrine/Hydration/ValueHydrator.php @@ -18,6 +18,10 @@ public function hydrate($document, MetaInformationInterface $metaInformation) $reflectionClass = new \ReflectionClass($targetEntity); foreach ($document as $property => $value) { + if ($property === MetaInformationInterface::DOCUMENT_KEY_FIELD_NAME) { + $value = $this->removePrefixedKeyFieldName($value); + } + try { $classProperty = $reflectionClass->getProperty($this->removeFieldSuffix($property)); } catch (\ReflectionException $e) { @@ -55,6 +59,22 @@ private function removeFieldSuffix($property) return $property; } + /** + * keyfield product_1 becomes 1 + * + * @param string $value + * + * @return string + */ + private function removePrefixedKeyFieldName($value) + { + if (($pos = strrpos($value, '_')) !== false) { + return substr($value, ($pos+1)); + } + + return $value; + } + /** * returns field name camelcased if it has underlines * diff --git a/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php b/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php index b7543981..81159e85 100644 --- a/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php +++ b/Doctrine/Mapper/Mapping/AbstractDocumentCommand.php @@ -19,9 +19,7 @@ public function createDocument(MetaInformationInterface $meta) { $document = new Document(); - $key = $meta->getDocumentName() . '_' . $meta->getEntityId(); - $document->setKey('id', $key); - + $document->setKey(MetaInformationInterface::DOCUMENT_KEY_FIELD_NAME, $meta->getDocumentKey()); $document->setBoost($meta->getBoost()); return $document; diff --git a/Doctrine/Mapper/MetaInformation.php b/Doctrine/Mapper/MetaInformation.php index b411869d..7e364734 100644 --- a/Doctrine/Mapper/MetaInformation.php +++ b/Doctrine/Mapper/MetaInformation.php @@ -59,16 +59,29 @@ class MetaInformation implements MetaInformationInterface */ private $index = ''; + /** + * @var int + */ + private $entityId; + /** * {@inheritdoc} */ public function getEntityId() { - if ($this->entity !== null) { + if ($this->entity !== null && $this->entity->getId()) { return $this->entity->getId(); } - return 0; + return $this->entityId; + } + + /** + * @param int $entityId + */ + public function setEntityId($entityId) + { + $this->entityId = $entityId; } /** @@ -277,4 +290,12 @@ public function getIndex() { return $this->index; } + + /** + * {@inheritdoc} + */ + public function getDocumentKey() + { + return $this->documentName . '_' . $this->getEntityId(); + } } diff --git a/Doctrine/Mapper/MetaInformationInterface.php b/Doctrine/Mapper/MetaInformationInterface.php index 05a6bebb..f48c3610 100644 --- a/Doctrine/Mapper/MetaInformationInterface.php +++ b/Doctrine/Mapper/MetaInformationInterface.php @@ -10,6 +10,8 @@ interface MetaInformationInterface { + const DOCUMENT_KEY_FIELD_NAME = 'id'; + /** * @return int */ @@ -77,4 +79,8 @@ public function hasSynchronizationFilter(); */ public function getIndex(); + /** + * @return string + */ + public function getDocumentKey(); } \ No newline at end of file diff --git a/Query/AbstractQuery.php b/Query/AbstractQuery.php index 6709e3cd..f63d4be1 100644 --- a/Query/AbstractQuery.php +++ b/Query/AbstractQuery.php @@ -1,6 +1,7 @@ metaInformation; + } + + /** + * @param MetaInformationInterface $metaInformation + */ + public function setMetaInformation($metaInformation) + { + $this->metaInformation = $metaInformation; + + $this->entity = $metaInformation->getEntity(); + $this->index = $metaInformation->getIndex(); + } + /** * @return object */ diff --git a/Query/FindByIdentifierQuery.php b/Query/FindByIdentifierQuery.php index e10c7abf..46e2dea1 100644 --- a/Query/FindByIdentifierQuery.php +++ b/Query/FindByIdentifierQuery.php @@ -4,6 +4,18 @@ class FindByIdentifierQuery extends AbstractQuery { + /** + * @var string + */ + private $documentKey; + + /** + * @param string $documentKey + */ + public function setDocumentKey($documentKey) + { + $this->documentKey = $documentKey; + } /** * @return string @@ -12,18 +24,13 @@ class FindByIdentifierQuery extends AbstractQuery */ public function getQuery() { - $idField = $this->document->id; - $documentNameField = $this->document->document_name_s; + $idField = $this->documentKey; if ($idField == null) { throw new \RuntimeException('id should not be null'); } - if ($documentNameField == null) { - throw new \RuntimeException('documentName should not be null'); - } - - $query = sprintf('id:%s AND document_name_s:%s', $idField, $documentNameField); + $query = sprintf('id:%s', $idField); $this->setQuery($query); return parent::getQuery(); diff --git a/Repository/Repository.php b/Repository/Repository.php index 0c267608..bf746535 100644 --- a/Repository/Repository.php +++ b/Repository/Repository.php @@ -48,10 +48,13 @@ public function find($id) $mapper = $this->solr->getMapper(); $mapper->setMappingCommand($this->solr->getCommandFactory()->get('all')); $metaInformation = $this->solr->getMetaFactory()->loadInformation($this->entity); + $metaInformation->setEntityId($id); $document = $mapper->toDocument($metaInformation); $query = new FindByIdentifierQuery(); + $query->setIndex($metaInformation->getIndex()); + $query->setDocumentKey($metaInformation->getDocumentKey()); $query->setDocument($document); $query->setEntity($this->entity); $query->setSolr($this->solr); @@ -82,7 +85,7 @@ public function findAll() $document->removeField('id'); - $query = new FindByDocumentNameQuery(); + $query = new FindByDocumentNameQuery($metaInformation); $query->setDocument($document); $query->setEntity($this->entity); $query->setSolr($this->solr); diff --git a/Tests/Doctrine/Hydration/DoctrineHydratorTest.php b/Tests/Doctrine/Hydration/DoctrineHydratorTest.php index 5375b0c9..10d2334e 100644 --- a/Tests/Doctrine/Hydration/DoctrineHydratorTest.php +++ b/Tests/Doctrine/Hydration/DoctrineHydratorTest.php @@ -30,6 +30,7 @@ public function foundEntityInDbReplacesEntityOldTargetEntity() ->will($this->returnValue($fetchedFromDoctrine)); $entity = new ValidTestEntity(); + $entity->setId(1); $metainformations = new MetaInformationFactory(); $metainformations = $metainformations->loadInformation($entity); @@ -37,7 +38,7 @@ public function foundEntityInDbReplacesEntityOldTargetEntity() $doctrineRegistry = $this->setupDoctrineRegistry($metainformations, $repository); $obj = new SolrDocumentStub(array()); - $obj->id = 1; + $obj->id = 'document_1'; $hydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\HydratorInterface'); $hydrator->expects($this->once()) @@ -56,8 +57,6 @@ public function foundEntityInDbReplacesEntityOldTargetEntity() */ public function entityFromDbNotFoundShouldNotModifyMetainformations() { - $fetchedFromDoctrine = new ValidTestEntity(); - $repository = $this->getMock('Doctrine\Common\Persistence\ObjectRepository'); $repository->expects($this->once()) ->method('find') @@ -65,6 +64,7 @@ public function entityFromDbNotFoundShouldNotModifyMetainformations() ->will($this->returnValue(null)); $entity = new ValidTestEntity(); + $entity->setId(1); $metainformations = new MetaInformationFactory(); $metainformations = $metainformations->loadInformation($entity); @@ -72,13 +72,13 @@ public function entityFromDbNotFoundShouldNotModifyMetainformations() $doctrineRegistry = $this->setupDoctrineRegistry($metainformations, $repository); $obj = new SolrDocumentStub(array()); - $obj->id = 1; + $obj->id = 'document_1'; $hydrator = $this->getMock('FS\SolrBundle\Doctrine\Hydration\HydratorInterface'); $hydrator->expects($this->once()) ->method('hydrate') ->with($obj, $metainformations) - ->will($this->returnValue($fetchedFromDoctrine)); + ->will($this->returnValue($entity)); $doctrine = new DoctrineHydrator($doctrineRegistry, $hydrator); $hydratedDocument = $doctrine->hydrate($obj, $metainformations); diff --git a/Tests/Doctrine/Hydration/ValueHydratorTest.php b/Tests/Doctrine/Hydration/ValueHydratorTest.php index a054aab5..1e62a0d5 100644 --- a/Tests/Doctrine/Hydration/ValueHydratorTest.php +++ b/Tests/Doctrine/Hydration/ValueHydratorTest.php @@ -20,7 +20,7 @@ class ValueHydratorTest extends \PHPUnit_Framework_TestCase public function documentShouldMapToEntity() { $obj = new SolrDocumentStub(array( - 'id' => 1, + 'id' => 'document_1', 'title_t' => 'foo' )); @@ -43,7 +43,7 @@ public function documentShouldMapToEntity() public function underscoreFieldBecomeCamelCase() { $obj = new SolrDocumentStub(array( - 'id' => 1, + 'id' => 'document_1', 'created_at_d' => 12345 )); diff --git a/Tests/DocumentStub.php b/Tests/DocumentStub.php index 6fe17962..fb5b3f73 100644 --- a/Tests/DocumentStub.php +++ b/Tests/DocumentStub.php @@ -19,4 +19,16 @@ public function __construct(array $fields = array(), array $boosts = array(), ar { } + + /** + * @param string $fieldName + * + * @return mixed + */ + public function getField($fieldName) + { + $fields = array('id' => $this->id, 'document_name' => $this->document_name_s); + + return $fields[$fieldName]; + } } \ No newline at end of file diff --git a/Tests/MulticoreSolrTest.php b/Tests/MulticoreSolrTest.php index c6cec110..d4bd1314 100644 --- a/Tests/MulticoreSolrTest.php +++ b/Tests/MulticoreSolrTest.php @@ -112,6 +112,7 @@ public function removeDocumentFromAllCores() { $metaInformation = MetaTestInformationFactory::getMetaInformation(); $metaInformation->setIndex('*'); + $metaInformation->setEntityId(1); $this->setupMetaFactoryLoadOneCompleteInformation($metaInformation); $this->mapper->expects($this->once()) diff --git a/Tests/Query/FindByIdentifierQueryTest.php b/Tests/Query/FindByIdentifierQueryTest.php index 3cdfe7bf..c699ee68 100644 --- a/Tests/Query/FindByIdentifierQueryTest.php +++ b/Tests/Query/FindByIdentifierQueryTest.php @@ -14,11 +14,11 @@ class FindByIdentifierQueryTest extends \PHPUnit_Framework_TestCase public function testGetQuery_SearchInAllFields() { $document = new Document(); - $document->addField('id', '1'); - $document->addField('document_name_s', 'validtestentity'); + $document->setKey('id', 'validtestentity_1'); - $expectedQuery = 'id:1 AND document_name_s:validtestentity'; + $expectedQuery = 'id:validtestentity_1'; $query = new FindByIdentifierQuery(); + $query->setDocumentKey('validtestentity_1'); $query->setDocument($document); $queryString = $query->getQuery(); @@ -26,34 +26,15 @@ public function testGetQuery_SearchInAllFields() $this->assertEquals($expectedQuery, $queryString); } - public function testGetQuery_DocumentNameMissing() - { - $document = new Document(); - $document->addField('id', '1'); - - $query = new FindByIdentifierQuery(); - $query->setDocument($document); - - try { - $query->getQuery(); - - $this->fail('an exception should be thrown'); - } catch (\RuntimeException $e) { - $this->assertEquals('documentName should not be null', $e->getMessage()); - } - } - + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage id should not be null + */ public function testGetQuery_IdMissing() { $query = new FindByIdentifierQuery(); $query->setDocument(new Document()); - try { - $query->getQuery(); - - $this->fail('an exception should be thrown'); - } catch (\RuntimeException $e) { - $this->assertEquals('id should not be null', $e->getMessage()); - } + $query->getQuery(); } } From 48fb2b7272ad5cc5df6187e945bb449739ea669a Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 25 Jul 2015 18:55:13 +0200 Subject: [PATCH 050/332] code cleanup + phpdoc --- Doctrine/Mapper/MetaInformationFactory.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Doctrine/Mapper/MetaInformationFactory.php b/Doctrine/Mapper/MetaInformationFactory.php index d557152f..a24434c6 100644 --- a/Doctrine/Mapper/MetaInformationFactory.php +++ b/Doctrine/Mapper/MetaInformationFactory.php @@ -6,18 +6,10 @@ use FS\SolrBundle\Doctrine\Configuration; /** - * - * @author fs - * + * instantiates a new MetaInformation object by a given entity */ class MetaInformationFactory { - - /** - * @var MetaInformation - */ - private $metaInformations = null; - /** * @var AnnotationReader */ From ba3f0cdb8860ca797c92bdcc46780b99eacb294b Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 25 Jul 2015 19:06:58 +0200 Subject: [PATCH 051/332] find all documents by key-field wildcard query --- Query/FindByDocumentNameQuery.php | 24 ++++++++++++++++++--- Repository/Repository.php | 4 +++- Tests/Query/FindByDocumentNameQueryTest.php | 16 ++++++-------- Tests/SolrTest.php | 3 +++ 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/Query/FindByDocumentNameQuery.php b/Query/FindByDocumentNameQuery.php index 6fa5d428..204397c0 100644 --- a/Query/FindByDocumentNameQuery.php +++ b/Query/FindByDocumentNameQuery.php @@ -2,8 +2,26 @@ namespace FS\SolrBundle\Query; +/** + * Builds a wildcard query to find all documents + * + * Query: id:documentname_* + */ class FindByDocumentNameQuery extends AbstractQuery { + /** + * @var string + */ + private $documentName; + + /** + * @param string $documentName + */ + public function setDocumentName($documentName) + { + $this->documentName = $documentName; + } + /** * @return string * @@ -11,13 +29,13 @@ class FindByDocumentNameQuery extends AbstractQuery */ public function getQuery() { - $documentNameField = $this->document->document_name_s; + $documentName = $this->documentName; - if ($documentNameField == null) { + if ($documentName == null) { throw new \RuntimeException('documentName should not be null'); } - $query = sprintf('document_name_s:%s', $documentNameField); + $query = sprintf('id:%s_*', $documentName); $this->setQuery($query); diff --git a/Repository/Repository.php b/Repository/Repository.php index bf746535..ed68408d 100644 --- a/Repository/Repository.php +++ b/Repository/Repository.php @@ -85,7 +85,9 @@ public function findAll() $document->removeField('id'); - $query = new FindByDocumentNameQuery($metaInformation); + $query = new FindByDocumentNameQuery(); + $query->setDocumentName($metaInformation->getDocumentName()); + $query->setIndex($metaInformation->getIndex()); $query->setDocument($document); $query->setEntity($this->entity); $query->setSolr($this->solr); diff --git a/Tests/Query/FindByDocumentNameQueryTest.php b/Tests/Query/FindByDocumentNameQueryTest.php index 4833b028..fce4f23e 100644 --- a/Tests/Query/FindByDocumentNameQueryTest.php +++ b/Tests/Query/FindByDocumentNameQueryTest.php @@ -16,28 +16,26 @@ class FindByDocumentNameQueryTest extends \PHPUnit_Framework_TestCase public function testGetQuery_SearchInAllFields() { $document = new Document(); - $document->addField('document_name_s', 'validtestentity'); + $document->addField('id', 'validtestentity_1'); $query = new FindByDocumentNameQuery(); + $query->setDocumentName('validtestentity'); $query->setDocument($document); $queryString = $query->getQuery(); - $this->assertEquals('document_name_s:validtestentity', $queryString, 'filter query'); + $this->assertEquals('id:validtestentity_*', $queryString, 'filter query'); } + /** + * @expectedException \RuntimeException + */ public function testGetQuery_DocumentnameMissing() { $query = new FindByDocumentNameQuery(); $query->setDocument(new Document()); - try { - $query->getQuery(); - - $this->fail('an exception should be thrown'); - } catch (\RuntimeException $e) { - $this->assertTrue(true); - } + $query->getQuery(); } } diff --git a/Tests/SolrTest.php b/Tests/SolrTest.php index 111fa81c..0f2a54ce 100644 --- a/Tests/SolrTest.php +++ b/Tests/SolrTest.php @@ -152,7 +152,9 @@ public function testQuery_NoResponseKeyInResponseSet() { $document = new Document(); $document->addField('document_name_s', 'name'); + $query = new FindByDocumentNameQuery(); + $query->setDocumentName('name'); $query->setDocument($document); $query->setIndex('index0'); @@ -173,6 +175,7 @@ public function testQuery_OneDocumentFound() $document->addField('document_name_s', 'name'); $query = new FindByDocumentNameQuery(); + $query->setDocumentName('name'); $query->setDocument($document); $query->setEntity(new ValidTestEntity()); $query->setIndex('index0'); From 374817b1831662428a53b2981798bfd5c67ffb09 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 25 Jul 2015 19:16:49 +0200 Subject: [PATCH 052/332] increase row limit for Repository:findAll() --- README.md | 6 ++++++ Repository/Repository.php | 1 + 2 files changed, 7 insertions(+) diff --git a/README.md b/README.md index 99107641..db5f294f 100644 --- a/README.md +++ b/README.md @@ -261,6 +261,12 @@ $result = $query->getResult(); In this case only the fields id and text will be mapped (addField()), so title and created_at will be empty. If nothing was found $result is empty. +The result contains by default 10 rows. You can increase this value: + +```php +$query->setRows(1000000); +``` + ### Configure HydrationModes HydrationMode tells the Bundle how to create an entity from a document. diff --git a/Repository/Repository.php b/Repository/Repository.php index ed68408d..38c4c820 100644 --- a/Repository/Repository.php +++ b/Repository/Repository.php @@ -86,6 +86,7 @@ public function findAll() $document->removeField('id'); $query = new FindByDocumentNameQuery(); + $query->setRows(1000000); $query->setDocumentName($metaInformation->getDocumentName()); $query->setIndex($metaInformation->getIndex()); $query->setDocument($document); From 80f98d47c120500ada18a63bf383a703f3a5a7bb Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 25 Jul 2015 20:07:57 +0200 Subject: [PATCH 053/332] add progress bar --- Command/SynchronizeIndexCommand.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Command/SynchronizeIndexCommand.php b/Command/SynchronizeIndexCommand.php index f4e23948..5098fb71 100644 --- a/Command/SynchronizeIndexCommand.php +++ b/Command/SynchronizeIndexCommand.php @@ -4,6 +4,7 @@ use Doctrine\Common\Persistence\AbstractManagerRegistry; use FS\SolrBundle\Console\ConsoleErrorListOutput; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -58,13 +59,25 @@ protected function execute(InputInterface $input, OutputInterface $output) $solr = $this->getContainer()->get('solr.client'); + $output->writeln(sprintf('Synchronize %s entities', count($entities))); + $output->writeln(''); + + $progress = new ProgressBar($output, count($entities)); + $progress->start(); + foreach ($entities as $entity) { try { $solr->synchronizeIndex($entity); + + $progress->advance(); } catch (\Exception $e) { } } + $progress->finish(); + $output->writeln(''); + $output->writeln(''); + $results = $this->getContainer()->get('solr.console.command.results'); if ($results->hasErrors()) { $output->writeln('Synchronization finished with errors!'); @@ -73,11 +86,10 @@ protected function execute(InputInterface $input, OutputInterface $output) } $output->writeln(''); - $output->writeln(sprintf('Synchronized Documents: %s', $results->getSucceed())); - $output->writeln(sprintf('Not Synchronized Documents: %s', $results->getErrored())); + $output->writeln(sprintf('Synchronized Documents: %s', $results->getSucceed())); + $output->writeln(sprintf('Not Synchronized Documents: %s', $results->getErrored())); $output->writeln(''); - $output->writeln(sprintf('Overall: %s', $results->getOverall())); if ($results->hasErrors()) { $errorList = new ConsoleErrorListOutput($output, $this->getHelper('table'), $results->getErrors()); $errorList->render(); From bba8901a253ee7af4dcd3563774cb519c5d94039 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 25 Jul 2015 20:09:51 +0200 Subject: [PATCH 054/332] show used index --- Command/SynchronizeIndexCommand.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Command/SynchronizeIndexCommand.php b/Command/SynchronizeIndexCommand.php index 5098fb71..0d1f9c29 100644 --- a/Command/SynchronizeIndexCommand.php +++ b/Command/SynchronizeIndexCommand.php @@ -59,7 +59,10 @@ protected function execute(InputInterface $input, OutputInterface $output) $solr = $this->getContainer()->get('solr.client'); + $metaInformation = $solr->getMetaFactory()->loadInformation($entity); + $output->writeln(sprintf('Synchronize %s entities', count($entities))); + $output->writeln(sprintf('Use index %s', $metaInformation->getIndex())); $output->writeln(''); $progress = new ProgressBar($output, count($entities)); From 73f1dfc92c726be9b684def091b2eea968edb301 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 26 Jul 2015 11:56:04 +0200 Subject: [PATCH 055/332] fix behat-tests --- Client/Client.php | 3 ++- Tests/DocumentStub.php | 8 +++++++ .../Bootstrap/CrudFeatureContext.php | 6 +++-- .../Integration/Bootstrap/FeatureContext.php | 22 +++++++++++++------ 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/Client/Client.php b/Client/Client.php index 6a3cb9d3..ec74da1b 100644 --- a/Client/Client.php +++ b/Client/Client.php @@ -45,7 +45,8 @@ public function update(DocumentInterface $doc, $index) */ public function delete(DocumentInterface $document, $index) { - $documentKey = $document->getField(MetaInformationInterface::DOCUMENT_KEY_FIELD_NAME); + $documentFields = $document->getFields(); + $documentKey = $documentFields[MetaInformationInterface::DOCUMENT_KEY_FIELD_NAME]; $deleteQuery = new FindByIdentifierQuery(); $deleteQuery->setDocument($document); diff --git a/Tests/DocumentStub.php b/Tests/DocumentStub.php index fb5b3f73..b134b8ce 100644 --- a/Tests/DocumentStub.php +++ b/Tests/DocumentStub.php @@ -31,4 +31,12 @@ public function getField($fieldName) return $fields[$fieldName]; } + + /** + * @return array + */ + public function getFields() + { + return array('id' => $this->id, 'document_name' => $this->document_name_s); + } } \ No newline at end of file diff --git a/Tests/Integration/Bootstrap/CrudFeatureContext.php b/Tests/Integration/Bootstrap/CrudFeatureContext.php index f3f98224..9483ec3c 100644 --- a/Tests/Integration/Bootstrap/CrudFeatureContext.php +++ b/Tests/Integration/Bootstrap/CrudFeatureContext.php @@ -17,6 +17,8 @@ class CrudFeatureContext extends FeatureContext */ private $solr; + const DOCUMENT_NAME = 'validtestentity'; + /** * @Given /^I have a Doctrine entity$/ */ @@ -48,7 +50,7 @@ public function shouldNoErrorOccurre() throw new \RuntimeException(sprintf('error occurred while indexing: %s', $eventDispatcher->getOccurredErrors())); } - $this->assertInsertSuccessful($this->entity->getId()); + $this->assertInsertSuccessful($this->entity->getId(), self::DOCUMENT_NAME); } /** @@ -65,7 +67,7 @@ public function iUpdateOneAttribute() public function theIndexShouldBeUpdated() { $entityId = $this->entity->getId(); - $document = $this->findDocumentById($entityId); + $document = $this->findDocumentById($entityId, self::DOCUMENT_NAME); $fields = $document->getFields(); diff --git a/Tests/Integration/Bootstrap/FeatureContext.php b/Tests/Integration/Bootstrap/FeatureContext.php index 33ee1350..df4511cd 100644 --- a/Tests/Integration/Bootstrap/FeatureContext.php +++ b/Tests/Integration/Bootstrap/FeatureContext.php @@ -148,11 +148,12 @@ private function setupSolrClient() } /** - * @param int $entityId + * @param int $entityId + * @param string $documentName * * @throws \RuntimeException if Events::POST_INSERT or Events::PRE_INSERT was fired or $entityId not equal to found document id */ - public function assertInsertSuccessful($entityId) + public function assertInsertSuccessful($entityId, $documentName) { if (!$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::POST_INSERT) || !$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::PRE_INSERT) @@ -160,14 +161,19 @@ public function assertInsertSuccessful($entityId) throw new \RuntimeException('Insert was not successful'); } - $document = $this->findDocumentById($entityId); + $document = $this->findDocumentById($entityId, $documentName); $idFieldValue = $document->getFields()['id']; - if (intval($idFieldValue) !== intval($entityId)) { + if (intval($this->removeKeyFieldNameSuffix($idFieldValue)) !== intval($entityId)) { throw new \RuntimeException(sprintf('found document has ID %s, expected %s', $idFieldValue, $entityId)); } } + private function removeKeyFieldNameSuffix($keyField) + { + return substr($keyField, strpos($keyField, '_') + 1); + } + /** * uses Solarium query to find a document by ID * @@ -175,12 +181,14 @@ public function assertInsertSuccessful($entityId) * * @throws \RuntimeException if resultset is empty, no document with given ID was found */ - protected function findDocumentById($entityId) + protected function findDocumentById($entityId, $documentName) { $client = $this->getSolrClient(); + $identifier = $documentName . '_' . $entityId; + $query = $client->createSelect(); - $query->setQuery(sprintf('id:%s', $entityId)); + $query->setQuery(sprintf('id:%s', $identifier)); $resultset = $client->select($query); if ($resultset->getNumFound() == 0) { @@ -193,7 +201,7 @@ protected function findDocumentById($entityId) foreach ($documents as $document) { $idFieldValue = $document->getFields()['id']; - if (intval($idFieldValue) == intval($entityId)) { + if (intval($idFieldValue) == intval($identifier)) { return $document; } } From 00b6fd2044fcc54fe1110762d9542f4abf630302 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 26 Jul 2015 12:10:47 +0200 Subject: [PATCH 056/332] move solr-setup to dedicated setup-feature-context --- .../Integration/Bootstrap/FeatureContext.php | 150 ++---------------- .../Bootstrap/SolrSetupFeatureContext.php | 150 ++++++++++++++++++ 2 files changed, 160 insertions(+), 140 deletions(-) create mode 100644 Tests/Integration/Bootstrap/SolrSetupFeatureContext.php diff --git a/Tests/Integration/Bootstrap/FeatureContext.php b/Tests/Integration/Bootstrap/FeatureContext.php index df4511cd..5af15049 100644 --- a/Tests/Integration/Bootstrap/FeatureContext.php +++ b/Tests/Integration/Bootstrap/FeatureContext.php @@ -8,145 +8,8 @@ /** * Features context. */ -class FeatureContext implements Context +class FeatureContext extends SolrSetupFeatureContext { - - /** - * @var \FS\SolrBundle\Tests\Integration\EventDispatcherFake - */ - private $eventDispatcher; - - /** - * @var \Solarium\Client - */ - private $solrClient; - - public function __construct() - { - $autoload = __DIR__ . '/../vendor/autoload.php'; - if (file_exists($autoload)) { - require_once $autoload; - } else { - require_once 'vendor/autoload.php'; - } - - $this->eventDispatcher = new \FS\SolrBundle\Tests\Integration\EventDispatcherFake(); - } - - /** - * @return \FS\SolrBundle\Tests\Integration\EventDispatcherFake - */ - public function getEventDispatcher() - { - return $this->eventDispatcher; - } - - /** - * @return \Solarium\Client - */ - public function getSolrClient() - { - return $this->solrClient; - } - - /** - * @return \FS\SolrBundle\Solr - */ - public function getSolrInstance() - { - \Doctrine\Common\Annotations\AnnotationRegistry::registerLoader('class_exists'); - \Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver::registerAnnotationClasses(); - - $this->solrClient = $this->setupSolrClient(); - $factory = $this->setupCommandFactory(); - $metaFactory = $this->setupMetaInformationFactory(); - $entityMapper = $this->setupEntityMapper(); - - $solr = new \FS\SolrBundle\Solr( - $this->solrClient, - $factory, - $this->eventDispatcher, - $metaFactory, - $entityMapper - ); - - return $solr; - } - - /** - * @return \FS\SolrBundle\Doctrine\Mapper\EntityMapper - */ - private function setupEntityMapper() - { - $registry = new \FS\SolrBundle\Tests\Integration\DoctrineRegistryFake(); - - $entityMapper = new \FS\SolrBundle\Doctrine\Mapper\EntityMapper( - new \FS\SolrBundle\Doctrine\Hydration\DoctrineHydrator( - $registry, - new \FS\SolrBundle\Doctrine\Hydration\ValueHydrator() - ), - new \FS\SolrBundle\Doctrine\Hydration\IndexHydrator( - new \FS\SolrBundle\Doctrine\Hydration\ValueHydrator() - ) - ); - - return $entityMapper; - } - - /** - * @return \FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory - */ - private function setupCommandFactory() - { - $factory = new \FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory(); - $factory->add(new \FS\SolrBundle\Doctrine\Mapper\Mapping\MapAllFieldsCommand(), 'all'); - $factory->add(new \FS\SolrBundle\Doctrine\Mapper\Mapping\MapIdentifierCommand(), 'identifier'); - - return $factory; - } - - /** - * @return \FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory - */ - private function setupMetaInformationFactory() - { - $ormConfiguration = new \Doctrine\ORM\Configuration(); - $ormConfiguration->addEntityNamespace('FSTest:ValidTestEntity', 'FS\SolrBundle\Tests\Doctrine\Mapper'); - - $knowNamespaces = new \FS\SolrBundle\Doctrine\ClassnameResolver\KnownNamespaceAliases(); - $knowNamespaces->addEntityNamespaces($ormConfiguration); - - $classnameResolver = new \FS\SolrBundle\Doctrine\ClassnameResolver\ClassnameResolver($knowNamespaces); - - $metaFactory = new \FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory(); - $metaFactory->setClassnameResolver( - $classnameResolver - ); - - return $metaFactory; - } - - /** - * Solarium Client with one core (core0) - * - * @return \Solarium\Client - */ - private function setupSolrClient() - { - $config = array( - 'default' => array( - 'host' => 'localhost', - 'port' => 8983, - 'path' => '/solr/core0', - ) - ); - - $builder = new \FS\SolrBundle\Client\SolrBuilder($config); - $solrClient = $builder->build(); - - return $solrClient; - } - /** * @param int $entityId * @param string $documentName @@ -155,8 +18,8 @@ private function setupSolrClient() */ public function assertInsertSuccessful($entityId, $documentName) { - if (!$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::POST_INSERT) || - !$this->eventDispatcher->eventOccurred(\FS\SolrBundle\Event\Events::PRE_INSERT) + if (!$this->getEventDispatcher()->eventOccurred(\FS\SolrBundle\Event\Events::POST_INSERT) || + !$this->getEventDispatcher()->eventOccurred(\FS\SolrBundle\Event\Events::PRE_INSERT) ) { throw new \RuntimeException('Insert was not successful'); } @@ -169,6 +32,13 @@ public function assertInsertSuccessful($entityId, $documentName) } } + /** + * Field value documentname_1 becomes 1 + * + * @param string $keyField + * + * @return string + */ private function removeKeyFieldNameSuffix($keyField) { return substr($keyField, strpos($keyField, '_') + 1); diff --git a/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php b/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php new file mode 100644 index 00000000..e723f696 --- /dev/null +++ b/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php @@ -0,0 +1,150 @@ +eventDispatcher = new \FS\SolrBundle\Tests\Integration\EventDispatcherFake(); + } + + /** + * @return \FS\SolrBundle\Tests\Integration\EventDispatcherFake + */ + public function getEventDispatcher() + { + return $this->eventDispatcher; + } + + /** + * @return \Solarium\Client + */ + public function getSolrClient() + { + return $this->solrClient; + } + + + /** + * @return \FS\SolrBundle\Solr + */ + public function getSolrInstance() + { + \Doctrine\Common\Annotations\AnnotationRegistry::registerLoader('class_exists'); + \Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver::registerAnnotationClasses(); + + $this->solrClient = $this->setupSolrClient(); + $factory = $this->setupCommandFactory(); + $metaFactory = $this->setupMetaInformationFactory(); + $entityMapper = $this->setupEntityMapper(); + + $solr = new \FS\SolrBundle\Solr( + $this->solrClient, + $factory, + $this->eventDispatcher, + $metaFactory, + $entityMapper + ); + + return $solr; + } + + /** + * @return \FS\SolrBundle\Doctrine\Mapper\EntityMapper + */ + private function setupEntityMapper() + { + $registry = new \FS\SolrBundle\Tests\Integration\DoctrineRegistryFake(); + + $entityMapper = new \FS\SolrBundle\Doctrine\Mapper\EntityMapper( + new \FS\SolrBundle\Doctrine\Hydration\DoctrineHydrator( + $registry, + new \FS\SolrBundle\Doctrine\Hydration\ValueHydrator() + ), + new \FS\SolrBundle\Doctrine\Hydration\IndexHydrator( + new \FS\SolrBundle\Doctrine\Hydration\ValueHydrator() + ) + ); + + return $entityMapper; + } + + /** + * @return \FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory + */ + private function setupCommandFactory() + { + $factory = new \FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory(); + $factory->add(new \FS\SolrBundle\Doctrine\Mapper\Mapping\MapAllFieldsCommand(), 'all'); + $factory->add(new \FS\SolrBundle\Doctrine\Mapper\Mapping\MapIdentifierCommand(), 'identifier'); + + return $factory; + } + + /** + * @return \FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory + */ + private function setupMetaInformationFactory() + { + $ormConfiguration = new \Doctrine\ORM\Configuration(); + $ormConfiguration->addEntityNamespace('FSTest:ValidTestEntity', 'FS\SolrBundle\Tests\Doctrine\Mapper'); + + $knowNamespaces = new \FS\SolrBundle\Doctrine\ClassnameResolver\KnownNamespaceAliases(); + $knowNamespaces->addEntityNamespaces($ormConfiguration); + + $classnameResolver = new \FS\SolrBundle\Doctrine\ClassnameResolver\ClassnameResolver($knowNamespaces); + + $metaFactory = new \FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory(); + $metaFactory->setClassnameResolver( + $classnameResolver + ); + + return $metaFactory; + } + + /** + * Solarium Client with two cores (core0, core1) + * + * @return \Solarium\Client + */ + private function setupSolrClient() + { + $config = array( + 'core0' => array( + 'host' => 'localhost', + 'port' => 8983, + 'path' => '/solr/core0', + ), + 'core1' => array( + 'host' => 'localhost', + 'port' => 8983, + 'path' => '/solr/core1', + ), + ); + + $builder = new \FS\SolrBundle\Client\SolrBuilder($config); + $solrClient = $builder->build(); + + return $solrClient; + } +} \ No newline at end of file From 8c61836d5cbad4b25d0682323c440bd22eb71d7e Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 26 Jul 2015 13:11:27 +0200 Subject: [PATCH 057/332] add behat test for multicore indexing --- Tests/Doctrine/Mapper/EntityCore0.php | 58 ++++++++++++ Tests/Doctrine/Mapper/EntityCore1.php | 58 ++++++++++++ .../Integration/Bootstrap/FeatureContext.php | 10 +-- .../Bootstrap/MulticoreFeatureContext.php | 89 +++++++++++++++++++ .../Bootstrap/SolrSetupFeatureContext.php | 2 + Tests/Integration/Features/multicore.feature | 8 ++ behat.yml | 2 + 7 files changed, 220 insertions(+), 7 deletions(-) create mode 100644 Tests/Doctrine/Mapper/EntityCore0.php create mode 100644 Tests/Doctrine/Mapper/EntityCore1.php create mode 100644 Tests/Integration/Bootstrap/MulticoreFeatureContext.php create mode 100644 Tests/Integration/Features/multicore.feature diff --git a/Tests/Doctrine/Mapper/EntityCore0.php b/Tests/Doctrine/Mapper/EntityCore0.php new file mode 100644 index 00000000..ca14b273 --- /dev/null +++ b/Tests/Doctrine/Mapper/EntityCore0.php @@ -0,0 +1,58 @@ +id; + } + + /** + * @return string + */ + public function getText() + { + return $this->text; + } + + /** + * @param mixed $id + */ + public function setId($id) + { + $this->id = $id; + } + + /** + * @param string $text + */ + public function setText($text) + { + $this->text = $text; + } + + +} \ No newline at end of file diff --git a/Tests/Doctrine/Mapper/EntityCore1.php b/Tests/Doctrine/Mapper/EntityCore1.php new file mode 100644 index 00000000..fc2fcc3e --- /dev/null +++ b/Tests/Doctrine/Mapper/EntityCore1.php @@ -0,0 +1,58 @@ +id; + } + + /** + * @return string + */ + public function getText() + { + return $this->text; + } + + /** + * @param mixed $id + */ + public function setId($id) + { + $this->id = $id; + } + + /** + * @param string $text + */ + public function setText($text) + { + $this->text = $text; + } + + +} \ No newline at end of file diff --git a/Tests/Integration/Bootstrap/FeatureContext.php b/Tests/Integration/Bootstrap/FeatureContext.php index 5af15049..a3638bff 100644 --- a/Tests/Integration/Bootstrap/FeatureContext.php +++ b/Tests/Integration/Bootstrap/FeatureContext.php @@ -51,7 +51,7 @@ private function removeKeyFieldNameSuffix($keyField) * * @throws \RuntimeException if resultset is empty, no document with given ID was found */ - protected function findDocumentById($entityId, $documentName) + protected function findDocumentById($entityId, $documentName, $index = null) { $client = $this->getSolrClient(); @@ -59,11 +59,7 @@ protected function findDocumentById($entityId, $documentName) $query = $client->createSelect(); $query->setQuery(sprintf('id:%s', $identifier)); - $resultset = $client->select($query); - - if ($resultset->getNumFound() == 0) { - throw new \RuntimeException(sprintf('could not find document with id %s after update', $entityId)); - } + $resultset = $client->select($query, $index); $documents = $resultset->getDocuments(); @@ -76,6 +72,6 @@ protected function findDocumentById($entityId, $documentName) } } - throw new \RuntimeException(sprintf('no document with Id %s was found', $entityId)); + return null; } } diff --git a/Tests/Integration/Bootstrap/MulticoreFeatureContext.php b/Tests/Integration/Bootstrap/MulticoreFeatureContext.php new file mode 100644 index 00000000..3759bd41 --- /dev/null +++ b/Tests/Integration/Bootstrap/MulticoreFeatureContext.php @@ -0,0 +1,89 @@ +solr = $this->getSolrInstance(); + + $this->entities = array( + 'core0' => new EntityCore0(), + 'core1' => new EntityCore1() + ); + } + + /** + * @Given /^I have a Doctrine entity for "([^"]*)"$/ + */ + public function iHaveADoctrineEntity($core) + { + $entity = $this->entities[$core]; + + $entity->setId(\FS\SolrBundle\Tests\Util\EntityIdentifier::generate()); + $entity->setText('a Text'); + + $this->entities[$core] = $entity; + } + + /** + * @When /^I add these entities to Solr$/ + */ + public function iAddThisEntityToSolr() + { + foreach ($this->entities as $entity) { + $this->solr->addDocument($entity); + } + } + + /** + * @When /^both entities should be in different cores$/ + */ + public function bothEntitiesShouldBeInDifferentCores() + { + /* @var EntityCore0 $core0Entity */ + $core0Entity = $this->entities['core0']; + + /* @var EntityCore1 $core1Entity */ + $core1Entity = $this->entities['core1']; + + // check if core0 contains only one entity + $document1 = $this->findDocumentById($core0Entity->getId(), 'entitycore0', 'core0'); + $document2 = $this->findDocumentById($core1Entity->getId(), 'entitycore1', 'core0'); + + if ($document1 === null) { + throw new \Exception('entity "entitycore0" should be indexed to core0'); + } + + if ($document2 !== null) { + throw new \Exception('entity "entitycore1" should not be indexed to core0'); + } + + // check if core1 contains only one entity + $document1 = $this->findDocumentById($core0Entity->getId(), 'entitycore0', 'core1'); + $document2 = $this->findDocumentById($core1Entity->getId(), 'entitycore1', 'core1'); + + if ($document1 !== null) { + throw new \Exception('entity "entitycore0" not should be indexed to core1'); + } + + if ($document2 === null) { + throw new \Exception('entity "entitycore1" should be indexed to core0'); + } + } + +} \ No newline at end of file diff --git a/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php b/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php index e723f696..d44b668b 100644 --- a/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php +++ b/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php @@ -108,6 +108,8 @@ private function setupMetaInformationFactory() { $ormConfiguration = new \Doctrine\ORM\Configuration(); $ormConfiguration->addEntityNamespace('FSTest:ValidTestEntity', 'FS\SolrBundle\Tests\Doctrine\Mapper'); + $ormConfiguration->addEntityNamespace('FSTest:EntityCore0', 'FS\SolrBundle\Tests\Doctrine\Mapper'); + $ormConfiguration->addEntityNamespace('FSTest:EntityCore1', 'FS\SolrBundle\Tests\Doctrine\Mapper'); $knowNamespaces = new \FS\SolrBundle\Doctrine\ClassnameResolver\KnownNamespaceAliases(); $knowNamespaces->addEntityNamespaces($ormConfiguration); diff --git a/Tests/Integration/Features/multicore.feature b/Tests/Integration/Features/multicore.feature new file mode 100644 index 00000000..17238bc2 --- /dev/null +++ b/Tests/Integration/Features/multicore.feature @@ -0,0 +1,8 @@ +Feature: I can index entities to different cores + + Scenario: Index entities to two cores + Given I have a Doctrine entity for "core0" + And I have a Doctrine entity for "core1" + When I add these entities to Solr + Then both entities should be in different cores + diff --git a/behat.yml b/behat.yml index 76be48ef..38dce7b9 100644 --- a/behat.yml +++ b/behat.yml @@ -3,5 +3,7 @@ default: crud: paths: [ Tests/Integration/Features ] contexts: + - FS\SolrBundle\Tests\Integration\Bootstrap\SolrSetupFeatureContext - FS\SolrBundle\Tests\Integration\Bootstrap\FeatureContext - FS\SolrBundle\Tests\Integration\Bootstrap\CrudFeatureContext + - FS\SolrBundle\Tests\Integration\Bootstrap\MulticoreFeatureContext From 96c24305f2f5977baa480f3908571e2379844dc4 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 26 Jul 2015 14:23:20 +0200 Subject: [PATCH 058/332] use container --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 791d7124..1aa234af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: php - +sudo: false services: mongodb php: From e68266074d339d64780ac95e3e5fe57483209c69 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 26 Jul 2015 14:40:28 +0200 Subject: [PATCH 059/332] init solr with core0 and core1 --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1aa234af..da06153b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,11 +10,10 @@ before_script: - echo "extension=mongo.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` - curl -s http://getcomposer.org/installer | php - php composer.phar install --dev - - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_VERSION=4.8.0 SOLR_CONFS="Tests/Resources/config/schema.xml" bash + - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_CORE=core0 SOLR_VERSION=4.8.0 SOLR_CONFS="Tests/Resources/config/schema.xml" bash + - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_CORE=core1 SOLR_VERSION=4.8.0 SOLR_CONFS="Tests/Resources/config/schema.xml" bash script: - phpunit - ./bin/behat -notifications: - email: - - fsemm.travis-ci@gmx.de +init \ No newline at end of file From e1d136055b99bc45baff165a2edd56f489130232 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 26 Jul 2015 14:42:12 +0200 Subject: [PATCH 060/332] fix typo --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index da06153b..742fb606 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,4 +16,3 @@ before_script: script: - phpunit - ./bin/behat -init \ No newline at end of file From a79baa5c71e595d678aa7d7cc585bbcff3f2847c Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 26 Jul 2015 14:57:06 +0200 Subject: [PATCH 061/332] use modified solr-setup script --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 742fb606..3104305b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,7 @@ before_script: - echo "extension=mongo.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"` - curl -s http://getcomposer.org/installer | php - php composer.phar install --dev - - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_CORE=core0 SOLR_VERSION=4.8.0 SOLR_CONFS="Tests/Resources/config/schema.xml" bash - - curl -sSL https://raw.githubusercontent.com/moliware/travis-solr/master/travis-solr.sh | SOLR_CORE=core1 SOLR_VERSION=4.8.0 SOLR_CONFS="Tests/Resources/config/schema.xml" bash + - curl -sSL https://raw.githubusercontent.com/floriansemm/travis-solr/master/travis-solr.sh | SOLR_CORE=core0 DEBUG=1 SOLR_VERSION=4.8.0 SOLR_CONFS="Tests/Resources/config/schema.xml" bash script: - phpunit From 46314a555a28ff54793442aad58e44642d5adf21 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 27 Jul 2015 20:54:49 +0200 Subject: [PATCH 062/332] modify test-fixtures to cover #109 --- Tests/Doctrine/Annotation/AnnotationReaderTest.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Tests/Doctrine/Annotation/AnnotationReaderTest.php b/Tests/Doctrine/Annotation/AnnotationReaderTest.php index cac28592..e762cb31 100644 --- a/Tests/Doctrine/Annotation/AnnotationReaderTest.php +++ b/Tests/Doctrine/Annotation/AnnotationReaderTest.php @@ -234,10 +234,9 @@ public function readAnnotationsFromMultipleClassHierarchy() abstract class BaseEntity { /** - * - * @Solr\Field(type="integer") + * @var mixed */ - private $baseField1; + protected $baseField1; /** * @@ -248,6 +247,11 @@ abstract class BaseEntity class ChildEntity extends BaseEntity { + /** + * @Solr\Field(type="integer") + */ + protected $baseField1; + /** * @Solr\Field(type="integer") */ @@ -259,5 +263,5 @@ class ChildEntity2 extends ChildEntity /** * @Solr\Field(type="integer") */ - protected $childField2; + private $childField2; } \ No newline at end of file From f37f1ab2d2076774584955a141cdbda7fc4e1f9b Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 5 Sep 2015 17:01:09 +0200 Subject: [PATCH 063/332] real select-query was not prepared with filter-query, fixes #110 --- Solr.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Solr.php b/Solr.php index ec29d7f2..99da34fc 100644 --- a/Solr.php +++ b/Solr.php @@ -240,8 +240,9 @@ public function query(AbstractQuery $query) $queryString = $query->getQuery(); $runQueryInIndex = $query->getIndex(); - $query = $this->solrClientCore->createSelect($query->getOptions()); - $query->setQuery($queryString); + $selectQuery = $this->solrClientCore->createSelect($query->getOptions()); + $selectQuery->setQuery($queryString); + $selectQuery->setFilterQueries($query->getFilterQueries()); try { $response = $this->solrClientCore->select($query, $runQueryInIndex); From c18c7e943d55d04f9c7a24cfc73275eb1b5d8624 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 5 Sep 2015 17:26:20 +0200 Subject: [PATCH 064/332] use own logging channel --- Resources/config/log_listener.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Resources/config/log_listener.xml b/Resources/config/log_listener.xml index b9799c8b..0e57fc87 100644 --- a/Resources/config/log_listener.xml +++ b/Resources/config/log_listener.xml @@ -17,29 +17,34 @@ + + + + + From 0ce95e08601b5527126731bec78558b775716521 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 5 Sep 2015 17:56:59 +0200 Subject: [PATCH 065/332] add request-debugger --- Client/SolrBuilder.php | 22 +++++++++++- Debug/RequestDebugger.php | 48 +++++++++++++++++++++++++ DependencyInjection/FSSolrExtension.php | 1 + Resources/config/services.xml | 6 ++++ 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 Debug/RequestDebugger.php diff --git a/Client/SolrBuilder.php b/Client/SolrBuilder.php index 22fbec0f..dbd935dc 100644 --- a/Client/SolrBuilder.php +++ b/Client/SolrBuilder.php @@ -3,6 +3,7 @@ namespace FS\SolrBundle\Client; use Solarium\Client; +use Solarium\Core\Plugin\Plugin; /** * Creates an instance of the Solarium Client @@ -14,6 +15,11 @@ class SolrBuilder implements Builder */ private $settings = array(); + /** + * @var Plugin + */ + private $plugins; + /** * @param array $settings */ @@ -22,6 +28,15 @@ public function __construct(array $settings) $this->settings = $settings; } + /** + * @param string $pluginName + * @param Plugin $plugin + */ + public function addPlugin($pluginName, Plugin $plugin) + { + $this->plugins[$pluginName] = $plugin; + } + /** * {@inheritdoc} * @@ -29,6 +44,11 @@ public function __construct(array $settings) */ public function build() { - return new Client(array('endpoint' => $this->settings)); + $solariumClient = new Client(array('endpoint' => $this->settings)); + foreach ($this->plugins as $pluginName => $plugin) { + $solariumClient->registerPlugin($pluginName, $plugin); + } + + return $solariumClient; } } \ No newline at end of file diff --git a/Debug/RequestDebugger.php b/Debug/RequestDebugger.php new file mode 100644 index 00000000..c9a0108b --- /dev/null +++ b/Debug/RequestDebugger.php @@ -0,0 +1,48 @@ +logger = $logger; + } + + /** + * {@inheritdoc} + */ + protected function initPluginType() + { + $this->start = microtime(true); + + $dispatcher = $this->client->getEventDispatcher(); + $dispatcher->addListener(Events::PRE_EXECUTE_REQUEST, array($this, 'preExecuteRequest')); + } + + /** + * @param PreExecuteRequest $event + */ + public function preExecuteRequest(PreExecuteRequest $event) + { + $this->logger->info(sprintf('run request: %s', urldecode($event->getRequest()->getUri()))); + } + +} \ No newline at end of file diff --git a/DependencyInjection/FSSolrExtension.php b/DependencyInjection/FSSolrExtension.php index 607ab573..4a30a416 100644 --- a/DependencyInjection/FSSolrExtension.php +++ b/DependencyInjection/FSSolrExtension.php @@ -46,6 +46,7 @@ private function setupClients(array $config, ContainerBuilder $container) $builderDefinition = $container->getDefinition('solr.client.adapter.builder'); $builderDefinition->replaceArgument(0, $endpoints); + $builderDefinition->addMethodCall('addPlugin', array('request_debugger', new Reference('solr.debug.client_debugger'))); } /** diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 46cbd508..155e0a53 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -39,6 +39,12 @@ + + + + + + From 80e668770a64d5d56a2a5e81d8793d6de02cf58e Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 7 Sep 2015 08:04:33 +0200 Subject: [PATCH 066/332] fix tests --- Tests/AbstractSolrTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/AbstractSolrTest.php b/Tests/AbstractSolrTest.php index d86eb075..0973d7f1 100644 --- a/Tests/AbstractSolrTest.php +++ b/Tests/AbstractSolrTest.php @@ -118,7 +118,6 @@ protected function assertQueryWasExecuted($data = array(), $index) $this->solrClientFake ->expects($this->once()) ->method('select') - ->with($selectQuery, $index) ->will($this->returnValue($queryResult)); } From 45172eacc4d21cf8cfffef06a4689d931250a84c Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 7 Sep 2015 08:09:26 +0200 Subject: [PATCH 067/332] init plugins --- Client/SolrBuilder.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Client/SolrBuilder.php b/Client/SolrBuilder.php index dbd935dc..1b36879f 100644 --- a/Client/SolrBuilder.php +++ b/Client/SolrBuilder.php @@ -26,6 +26,7 @@ class SolrBuilder implements Builder public function __construct(array $settings) { $this->settings = $settings; + $this->plugins = array(); } /** From 36dc389d58c0b69a158097486aea3f7b9528f121 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 7 Sep 2015 08:59:57 +0200 Subject: [PATCH 068/332] increase identifier generator range --- Tests/Util/EntityIdentifier.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Util/EntityIdentifier.php b/Tests/Util/EntityIdentifier.php index 286aeef1..203e1873 100644 --- a/Tests/Util/EntityIdentifier.php +++ b/Tests/Util/EntityIdentifier.php @@ -7,6 +7,6 @@ class EntityIdentifier { public static function generate() { - return rand(1, 15); + return rand(1, 100000000); } } \ No newline at end of file From 47f5eef60957f93d7db756648380d36bc677c64f Mon Sep 17 00:00:00 2001 From: floriansemm Date: Wed, 16 Sep 2015 07:57:44 +0200 Subject: [PATCH 069/332] set default query --- Query/SolrQuery.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Query/SolrQuery.php b/Query/SolrQuery.php index 19ffd25f..9c46797c 100644 --- a/Query/SolrQuery.php +++ b/Query/SolrQuery.php @@ -28,7 +28,7 @@ class SolrQuery extends AbstractQuery /** * @var string */ - private $customQuery = ''; + private $customQuery = '*:*'; /** * @return array From c5f2f7fbb017200750d28392b0858982f982c41b Mon Sep 17 00:00:00 2001 From: floriansemm Date: Wed, 16 Sep 2015 07:58:41 +0200 Subject: [PATCH 070/332] selectQuery was not used --- Solr.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Solr.php b/Solr.php index 99da34fc..0fd0e91f 100644 --- a/Solr.php +++ b/Solr.php @@ -237,15 +237,16 @@ private function addToIndex(MetaInformationInterface $metaInformation, $entity) public function query(AbstractQuery $query) { $entity = $query->getEntity(); - - $queryString = $query->getQuery(); $runQueryInIndex = $query->getIndex(); + $selectQuery = $this->solrClientCore->createSelect($query->getOptions()); - $selectQuery->setQuery($queryString); + + $selectQuery->setQuery($query->getQuery()); $selectQuery->setFilterQueries($query->getFilterQueries()); + $selectQuery->setSorts($query->getSorts()); try { - $response = $this->solrClientCore->select($query, $runQueryInIndex); + $response = $this->solrClientCore->select($selectQuery, $runQueryInIndex); } catch (\Exception $e) { $errorEvent = new ErrorEvent(null, null, 'query solr'); $errorEvent->setException($e); From d513ec2a763097b57330c5096257062878218f91 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Wed, 16 Sep 2015 08:16:49 +0200 Subject: [PATCH 071/332] set default query --- Query/SolrQuery.php | 4 ++-- Tests/Query/SolrQueryTest.php | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Query/SolrQuery.php b/Query/SolrQuery.php index 9c46797c..8cfbde6d 100644 --- a/Query/SolrQuery.php +++ b/Query/SolrQuery.php @@ -28,7 +28,7 @@ class SolrQuery extends AbstractQuery /** * @var string */ - private $customQuery = '*:*'; + private $customQuery; /** * @return array @@ -153,7 +153,7 @@ public function getQuery() $term = ''; if (count($this->searchTerms) == 0) { - return $term; + return '*:*'; } $logicOperator = 'AND'; diff --git a/Tests/Query/SolrQueryTest.php b/Tests/Query/SolrQueryTest.php index 9bc57926..1a3edbc6 100644 --- a/Tests/Query/SolrQueryTest.php +++ b/Tests/Query/SolrQueryTest.php @@ -22,6 +22,9 @@ private function getFieldMapping() ); } + /** + * @return SolrQuery + */ private function createQueryWithFieldMapping() { $solr = $this->getMock('FS\SolrBundle\Solr', array(), array(), '', false); @@ -34,8 +37,7 @@ private function createQueryWithFieldMapping() } /** - * - * @return \FS\SolrBundle\SolrQuery + * @return SolrQuery */ private function createQueryWithSearchTerms() { From 439ed223861f1dadcc6396b1d433ad21d4462484 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Wed, 16 Sep 2015 08:45:31 +0200 Subject: [PATCH 072/332] always quote the search term --- Query/SolrQuery.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Query/SolrQuery.php b/Query/SolrQuery.php index 8cfbde6d..fbdaaf16 100644 --- a/Query/SolrQuery.php +++ b/Query/SolrQuery.php @@ -165,9 +165,9 @@ public function getQuery() foreach ($this->searchTerms as $fieldName => $fieldValue) { if ($this->useWildcards) { - $term .= $fieldName . ':*' . $fieldValue . '*'; + $term .= $fieldName . ':"*' . $fieldValue . '*"'; } else { - $term .= $fieldName . ':' . $fieldValue; + $term .= $fieldName . ':"' . $fieldValue .'"'; } if ($termCount < count($this->searchTerms)) { From f12f25ea5062cad3925a234f947e774e91a6acad Mon Sep 17 00:00:00 2001 From: floriansemm Date: Wed, 16 Sep 2015 08:46:48 +0200 Subject: [PATCH 073/332] always quote the search term --- Tests/Query/SolrQueryTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/Query/SolrQueryTest.php b/Tests/Query/SolrQueryTest.php index 1a3edbc6..795896b9 100644 --- a/Tests/Query/SolrQueryTest.php +++ b/Tests/Query/SolrQueryTest.php @@ -78,7 +78,7 @@ public function testAddField_OneFieldOfTwoNotMapped() public function testGetSolrQuery_QueryTermShouldCorrect() { - $expected = 'title_s:*foo* OR text_t:*bar*'; + $expected = 'title_s:"*foo*" OR text_t:"*bar*"'; $query = $this->createQueryWithSearchTerms(); @@ -125,7 +125,7 @@ public function testAddSearchTerm_UnknownField() public function testGetQuery_TermsConcatWithOr() { - $expected = 'title_s:*foo* OR text_t:*bar*'; + $expected = 'title_s:"*foo*" OR text_t:"*bar*"'; $query = $this->createQueryWithSearchTerms(); @@ -134,7 +134,7 @@ public function testGetQuery_TermsConcatWithOr() public function testGetQuery_TermsConcatWithAnd() { - $expected = 'title_s:*foo* AND text_t:*bar*'; + $expected = 'title_s:"*foo*" AND text_t:"*bar*"'; $query = $this->createQueryWithSearchTerms(); $query->setUseAndOperator(true); @@ -147,7 +147,7 @@ public function testGetQuery_SearchInAllFields() $solrQuery = $this->createQueryWithFieldMapping(); $solrQuery->queryAllFields('foo'); - $expected = 'title_s:*foo* OR text_t:*foo* OR created_at_dt:*foo*'; + $expected = 'title_s:"*foo*" OR text_t:"*foo*" OR created_at_dt:"*foo*"'; $this->assertEquals($expected, $solrQuery->getQuery()); } From 928c789eafcbde3d0cf43536b0bff1e545b02c56 Mon Sep 17 00:00:00 2001 From: Frank Neff Date: Fri, 23 Oct 2015 13:12:29 +0200 Subject: [PATCH 074/332] Adds multivalue field types to annotation --- Doctrine/Annotation/Field.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Doctrine/Annotation/Field.php b/Doctrine/Annotation/Field.php index e3df76c7..665f6d6d 100644 --- a/Doctrine/Annotation/Field.php +++ b/Doctrine/Annotation/Field.php @@ -31,13 +31,21 @@ class Field extends Annotation */ private static $TYP_MAPPING = array( 'string' => '_s', + 'strings' => '_ss', 'text' => '_t', + 'texts' => '_txt', 'date' => '_dt', + 'dates' => '_dts', 'boolean' => '_b', + 'booleans' => '_bs', 'integer' => '_i', + 'integers' => '_is', 'long' => '_l', + 'longs' => '_ls', 'float' => '_f', + 'floats' => '_fs', 'double' => '_d', + 'doubles' => '_ds', ); /** From 4daad006b745b55d1a5cf23a609f91087d593c9c Mon Sep 17 00:00:00 2001 From: Zachary Quintana Date: Mon, 7 Dec 2015 10:27:27 -0800 Subject: [PATCH 075/332] Adding support for related entities --- Doctrine/Annotation/Field.php | 15 +++++++++++++++ .../Mapper/Mapping/MapAllFieldsCommand.php | 18 +++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Doctrine/Annotation/Field.php b/Doctrine/Annotation/Field.php index e3df76c7..304e31cf 100644 --- a/Doctrine/Annotation/Field.php +++ b/Doctrine/Annotation/Field.php @@ -26,6 +26,11 @@ class Field extends Annotation */ public $boost = 0; + /** + * @var string + */ + public $getter; + /** * @var array */ @@ -72,6 +77,16 @@ private function getTypeSuffix($type) return self::$TYP_MAPPING[$this->type]; } + /** + * Related object getter name + * + * @return string + */ + public function getGetterName() + { + return $this->getter; + } + /** * @return string */ diff --git a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php index 548f2016..4eb6927a 100644 --- a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php +++ b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php @@ -3,6 +3,7 @@ use FS\SolrBundle\Doctrine\Annotation\Field; use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; +use Doctrine\Common\Collections\ArrayCollection; /** * command maps all fields of the entity @@ -31,7 +32,22 @@ public function createDocument(MetaInformationInterface $meta) continue; } - $document->addField($field->getNameWithAlias(), $field->getValue(), $field->getBoost()); + $value = $field->getValue(); + $getter = $field->getGetterName(); + if (!empty($getter)) { + if ($value instanceof ArrayCollection) { + $values = array(); + foreach ($value as $relatedObj) { + $values[] = $relatedObj->{$getter}(); + } + + $document->addField($field->getNameWithAlias(), $values, $field->getBoost()); + } else { + $document->addField($field->getNameWithAlias(), $value->{$getter}(), $field->getBoost()); + } + } else { + $document->addField($field->getNameWithAlias(), $field->getValue(), $field->getBoost()); + } } return $document; From 6bad06cc6cd2db89fea8c06fdabc3f5ab68ef9f0 Mon Sep 17 00:00:00 2001 From: Zachary Quintana Date: Mon, 7 Dec 2015 10:28:33 -0800 Subject: [PATCH 076/332] Revert "Adding support for related entities" This reverts commit 4daad006b745b55d1a5cf23a609f91087d593c9c. --- Doctrine/Annotation/Field.php | 15 --------------- .../Mapper/Mapping/MapAllFieldsCommand.php | 18 +----------------- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/Doctrine/Annotation/Field.php b/Doctrine/Annotation/Field.php index 304e31cf..e3df76c7 100644 --- a/Doctrine/Annotation/Field.php +++ b/Doctrine/Annotation/Field.php @@ -26,11 +26,6 @@ class Field extends Annotation */ public $boost = 0; - /** - * @var string - */ - public $getter; - /** * @var array */ @@ -77,16 +72,6 @@ private function getTypeSuffix($type) return self::$TYP_MAPPING[$this->type]; } - /** - * Related object getter name - * - * @return string - */ - public function getGetterName() - { - return $this->getter; - } - /** * @return string */ diff --git a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php index 4eb6927a..548f2016 100644 --- a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php +++ b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php @@ -3,7 +3,6 @@ use FS\SolrBundle\Doctrine\Annotation\Field; use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; -use Doctrine\Common\Collections\ArrayCollection; /** * command maps all fields of the entity @@ -32,22 +31,7 @@ public function createDocument(MetaInformationInterface $meta) continue; } - $value = $field->getValue(); - $getter = $field->getGetterName(); - if (!empty($getter)) { - if ($value instanceof ArrayCollection) { - $values = array(); - foreach ($value as $relatedObj) { - $values[] = $relatedObj->{$getter}(); - } - - $document->addField($field->getNameWithAlias(), $values, $field->getBoost()); - } else { - $document->addField($field->getNameWithAlias(), $value->{$getter}(), $field->getBoost()); - } - } else { - $document->addField($field->getNameWithAlias(), $field->getValue(), $field->getBoost()); - } + $document->addField($field->getNameWithAlias(), $field->getValue(), $field->getBoost()); } return $document; From 8d32b363b9cd3bc2ddd14a1d1b3daf0567f5b129 Mon Sep 17 00:00:00 2001 From: Zachary Quintana Date: Mon, 7 Dec 2015 10:27:27 -0800 Subject: [PATCH 077/332] Adding support for related entities --- Doctrine/Annotation/Field.php | 15 +++++++++++++++ .../Mapper/Mapping/MapAllFieldsCommand.php | 18 +++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Doctrine/Annotation/Field.php b/Doctrine/Annotation/Field.php index e3df76c7..304e31cf 100644 --- a/Doctrine/Annotation/Field.php +++ b/Doctrine/Annotation/Field.php @@ -26,6 +26,11 @@ class Field extends Annotation */ public $boost = 0; + /** + * @var string + */ + public $getter; + /** * @var array */ @@ -72,6 +77,16 @@ private function getTypeSuffix($type) return self::$TYP_MAPPING[$this->type]; } + /** + * Related object getter name + * + * @return string + */ + public function getGetterName() + { + return $this->getter; + } + /** * @return string */ diff --git a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php index 548f2016..4eb6927a 100644 --- a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php +++ b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php @@ -3,6 +3,7 @@ use FS\SolrBundle\Doctrine\Annotation\Field; use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; +use Doctrine\Common\Collections\ArrayCollection; /** * command maps all fields of the entity @@ -31,7 +32,22 @@ public function createDocument(MetaInformationInterface $meta) continue; } - $document->addField($field->getNameWithAlias(), $field->getValue(), $field->getBoost()); + $value = $field->getValue(); + $getter = $field->getGetterName(); + if (!empty($getter)) { + if ($value instanceof ArrayCollection) { + $values = array(); + foreach ($value as $relatedObj) { + $values[] = $relatedObj->{$getter}(); + } + + $document->addField($field->getNameWithAlias(), $values, $field->getBoost()); + } else { + $document->addField($field->getNameWithAlias(), $value->{$getter}(), $field->getBoost()); + } + } else { + $document->addField($field->getNameWithAlias(), $field->getValue(), $field->getBoost()); + } } return $document; From 6486bb8cf366410246e37e6c8b5620b402762cf5 Mon Sep 17 00:00:00 2001 From: Zachary Quintana Date: Mon, 7 Dec 2015 11:57:28 -0800 Subject: [PATCH 078/332] Changed ArrayCollection to Collection to catch other types of Doctrine Collections --- Doctrine/Mapper/Mapping/MapAllFieldsCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php index 4eb6927a..74a9775f 100644 --- a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php +++ b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php @@ -3,7 +3,7 @@ use FS\SolrBundle\Doctrine\Annotation\Field; use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; -use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; /** * command maps all fields of the entity @@ -35,7 +35,7 @@ public function createDocument(MetaInformationInterface $meta) $value = $field->getValue(); $getter = $field->getGetterName(); if (!empty($getter)) { - if ($value instanceof ArrayCollection) { + if ($value instanceof Collection) { $values = array(); foreach ($value as $relatedObj) { $values[] = $relatedObj->{$getter}(); From 60f0ad644b11fc0f81a38686aa84b4d2278d52e7 Mon Sep 17 00:00:00 2001 From: Zachary Quintana Date: Thu, 10 Dec 2015 23:21:08 -0800 Subject: [PATCH 079/332] Refactoring for greater flexibility --- Query/AbstractQuery.php | 20 ++++++ Query/ResultSet.php | 143 ++++++++++++++++++++++++++++++++++++++++ Query/SolrQuery.php | 11 ++-- Solr.php | 44 +++++++------ 4 files changed, 194 insertions(+), 24 deletions(-) create mode 100644 Query/ResultSet.php diff --git a/Query/AbstractQuery.php b/Query/AbstractQuery.php index f63d4be1..273c01d7 100644 --- a/Query/AbstractQuery.php +++ b/Query/AbstractQuery.php @@ -34,6 +34,24 @@ abstract class AbstractQuery extends Query */ private $metaInformation; + /** + * @var \Solarium\QueryType\Select\Query\Query + */ + private $selectQuery; + + + /** + * @return \Solarium\QueryType\Select\Query\Query + */ + public function getSelectQuery() + { + if (!$this->selectQuery) { + $this->selectQuery = $this->solr->getSelectQuery($this); + } + + return $this->selectQuery; + } + /** * @return MetaInformationInterface */ @@ -126,4 +144,6 @@ public function setIndex($index) { $this->index = $index; } + + abstract public function prepareQuery(); } diff --git a/Query/ResultSet.php b/Query/ResultSet.php new file mode 100644 index 00000000..d5e51370 --- /dev/null +++ b/Query/ResultSet.php @@ -0,0 +1,143 @@ +total = $response->getNumFound(); + if ($this->total == 0) { + return $this; + } + + $mappedEntities = array(); + foreach ($response as $document) { + $mappedEntities[] = $mapper->toEntity($document, $entity); + } + + $this->entities = $mappedEntities; + $this->response = $response; + } + + /** + * Response getter + * + * @return Result + */ + public function getResponse() + { + return $this->response; + } + + /** + * Entities getter + * + * @return array + */ + public function getEntities() + { + return $this->entities; + } + + /** + * Entities setter + * + * @param array $entities + * + * @return ResultSet $this + */ + public function setEntities($entities) + { + $this->entities = $entities; + + return $this; + } + + /** + * @param mixed $offset + * @param mixed $value + */ + public function offsetSet($offset, $value) + { + $this->entities[$offset] = $value; + } + + /** + * @param mixed $offset + * @return mixed + */ + public function offsetGet($offset) + { + return $this->entities[$offset]; + } + + /** + * @param mixed $offset + */ + public function offsetUnset($offset) + { + unset($this->entities[$offset]); + } + + /** + * @param mixed $offset + * @return bool + */ + public function offsetExists($offset) + { + return isset($this->entities[$offset]); + } + + /** + * @return array + */ + public function toArray() + { + return $this->entities; + } + + /** + * @return array + */ + public function __toArray() + { + return $this->toArray(); + } +} \ No newline at end of file diff --git a/Query/SolrQuery.php b/Query/SolrQuery.php index fbdaaf16..f76f567f 100644 --- a/Query/SolrQuery.php +++ b/Query/SolrQuery.php @@ -2,6 +2,8 @@ namespace FS\SolrBundle\Query; +use Solarium\Core\Query\Query; + class SolrQuery extends AbstractQuery { @@ -30,8 +32,10 @@ class SolrQuery extends AbstractQuery */ private $customQuery; + + /** - * @return array + * @return ResultSet */ public function getResult() { @@ -144,7 +148,7 @@ public function addField($field) /** * @return string */ - public function getQuery() + public function prepareQuery() { if ($this->customQuery) { $this->setQuery($this->customQuery); @@ -165,7 +169,7 @@ public function getQuery() foreach ($this->searchTerms as $fieldName => $fieldValue) { if ($this->useWildcards) { - $term .= $fieldName . ':"*' . $fieldValue . '*"'; + $term .= $fieldName . ':*' . $fieldValue . '*'; } else { $term .= $fieldName . ':"' . $fieldValue .'"'; } @@ -176,7 +180,6 @@ public function getQuery() $termCount++; } - $this->setQuery($term); return $term; diff --git a/Solr.php b/Solr.php index 0fd0e91f..cb8e1445 100644 --- a/Solr.php +++ b/Solr.php @@ -3,6 +3,9 @@ namespace FS\SolrBundle; use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; +use FS\SolrBundle\Query\ResultSet; +use Solarium\Core\Query\Query; +use Solarium\QueryType\Select\Result\Result; use Solarium\QueryType\Update\Query\Document\Document; use FS\SolrBundle\Doctrine\Mapper\EntityMapper; use FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory; @@ -232,42 +235,43 @@ private function addToIndex(MetaInformationInterface $metaInformation, $entity) } /** - * {@inheritdoc} + * Get select query + * + * @param AbstractQuery $query + * + * @return \Solarium\QueryType\Select\Query\Query */ - public function query(AbstractQuery $query) + public function getSelectQuery(AbstractQuery $query) { - $entity = $query->getEntity(); - $runQueryInIndex = $query->getIndex(); - $selectQuery = $this->solrClientCore->createSelect($query->getOptions()); - $selectQuery->setQuery($query->getQuery()); + $selectQuery->setQuery($query->prepareQuery()); $selectQuery->setFilterQueries($query->getFilterQueries()); $selectQuery->setSorts($query->getSorts()); + return $selectQuery; + } + + /** + * {@inheritdoc} + */ + public function query(AbstractQuery $query) + { + $entity = $query->getEntity(); + $runQueryInIndex = $query->getIndex(); + $selectQuery = $query->getSelectQuery(); + try { $response = $this->solrClientCore->select($selectQuery, $runQueryInIndex); + return new ResultSet($entity, $this->entityMapper, $response); } catch (\Exception $e) { $errorEvent = new ErrorEvent(null, null, 'query solr'); $errorEvent->setException($e); $this->eventManager->dispatch(Events::ERROR, $errorEvent); - return array(); + return new ResultSet($entity, null, null); } - - $this->numberOfFoundDocuments = $response->getNumFound(); - if ($this->numberOfFoundDocuments == 0) { - return array(); - } - - $targetEntity = $entity; - $mappedEntities = array(); - foreach ($response as $document) { - $mappedEntities[] = $this->entityMapper->toEntity($document, $targetEntity); - } - - return $mappedEntities; } /** From 08e974afc96fb36981c822cd737ee4343c5d9f92 Mon Sep 17 00:00:00 2001 From: Zachary Quintana Date: Mon, 14 Dec 2015 18:54:59 -0800 Subject: [PATCH 080/332] Fixes for new Solarium --- Client/SolrBuilder.php | 10 +++++----- Debug/RequestDebugger.php | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Client/SolrBuilder.php b/Client/SolrBuilder.php index 1b36879f..80a1e912 100644 --- a/Client/SolrBuilder.php +++ b/Client/SolrBuilder.php @@ -3,7 +3,7 @@ namespace FS\SolrBundle\Client; use Solarium\Client; -use Solarium\Core\Plugin\Plugin; +use Solarium\Core\Plugin\AbstractPlugin; /** * Creates an instance of the Solarium Client @@ -16,7 +16,7 @@ class SolrBuilder implements Builder private $settings = array(); /** - * @var Plugin + * @var AbstractPlugin */ private $plugins; @@ -30,10 +30,10 @@ public function __construct(array $settings) } /** - * @param string $pluginName - * @param Plugin $plugin + * @param string $pluginName + * @param AbstractPlugin $plugin */ - public function addPlugin($pluginName, Plugin $plugin) + public function addPlugin($pluginName, AbstractPlugin $plugin) { $this->plugins[$pluginName] = $plugin; } diff --git a/Debug/RequestDebugger.php b/Debug/RequestDebugger.php index c9a0108b..23564c57 100644 --- a/Debug/RequestDebugger.php +++ b/Debug/RequestDebugger.php @@ -5,12 +5,12 @@ use Psr\Log\LoggerInterface; use Solarium\Core\Event\Events; use Solarium\Core\Event\PreExecuteRequest; -use Solarium\Core\Plugin\Plugin; +use Solarium\Core\Plugin\AbstractPlugin; /** * Listens on solarium.core.preExecuteRequest event */ -class RequestDebugger extends Plugin +class RequestDebugger extends AbstractPlugin { /** @@ -24,6 +24,8 @@ class RequestDebugger extends Plugin public function __construct(LoggerInterface $logger) { $this->logger = $logger; + + return parent::__construct(); } /** From db780229662c8a7d2264b987b2d807cb06692e95 Mon Sep 17 00:00:00 2001 From: Zachary Quintana Date: Thu, 24 Dec 2015 09:04:57 -0800 Subject: [PATCH 081/332] Fix to the mapper related entities when null --- Doctrine/Mapper/Mapping/MapAllFieldsCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php index 74a9775f..f1e3fe23 100644 --- a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php +++ b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php @@ -42,7 +42,7 @@ public function createDocument(MetaInformationInterface $meta) } $document->addField($field->getNameWithAlias(), $values, $field->getBoost()); - } else { + } elseif (is_object($value) && method_exists($value, $getter)) { $document->addField($field->getNameWithAlias(), $value->{$getter}(), $field->getBoost()); } } else { From 867d73dbd1fa19d168ff19296738b57527ca5156 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 13 Feb 2016 16:34:14 +0100 Subject: [PATCH 082/332] fix tests --- Query/AbstractQuery.php | 20 ------------- Query/ResultSet.php | 54 +++++++++++++++-------------------- Query/SolrQuery.php | 12 +++++--- Solr.php | 6 ++-- Tests/AbstractSolrTest.php | 1 + Tests/Query/SolrQueryTest.php | 8 +++--- Tests/SolrTest.php | 1 - 7 files changed, 39 insertions(+), 63 deletions(-) diff --git a/Query/AbstractQuery.php b/Query/AbstractQuery.php index 273c01d7..f63d4be1 100644 --- a/Query/AbstractQuery.php +++ b/Query/AbstractQuery.php @@ -34,24 +34,6 @@ abstract class AbstractQuery extends Query */ private $metaInformation; - /** - * @var \Solarium\QueryType\Select\Query\Query - */ - private $selectQuery; - - - /** - * @return \Solarium\QueryType\Select\Query\Query - */ - public function getSelectQuery() - { - if (!$this->selectQuery) { - $this->selectQuery = $this->solr->getSelectQuery($this); - } - - return $this->selectQuery; - } - /** * @return MetaInformationInterface */ @@ -144,6 +126,4 @@ public function setIndex($index) { $this->index = $index; } - - abstract public function prepareQuery(); } diff --git a/Query/ResultSet.php b/Query/ResultSet.php index d5e51370..4ab1a089 100644 --- a/Query/ResultSet.php +++ b/Query/ResultSet.php @@ -12,12 +12,7 @@ use FS\SolrBundle\Doctrine\Mapper\EntityMapper; use Solarium\QueryType\Select\Result\Result; -/** - * Class ResultSet - * - * @package FS\SolrBundle\Query - */ -class ResultSet implements \ArrayAccess +class ResultSet implements \ArrayAccess, \Countable { /** @@ -35,30 +30,27 @@ class ResultSet implements \ArrayAccess */ private $total = 0; - - public function __construct($entity, EntityMapper $mapper, Result $response) + /** + * @param object $entity + * @param EntityMapper $mapper + * @param Result $response + */ + public function __construct($entity, EntityMapper $mapper = null, \IteratorAggregate $response = null) { - if ($mapper === null || $response === null) { - return $this; - } - - $this->total = $response->getNumFound(); - if ($this->total == 0) { - return $this; + $this->response = $response; + if ($response !== null) { + $this->total = $response->getNumFound(); } - $mappedEntities = array(); - foreach ($response as $document) { - $mappedEntities[] = $mapper->toEntity($document, $entity); + $this->entities = array(); + if ($response !== null) { + foreach ($response as $document) { + $this->entities[] = $mapper->toEntity($document, $entity); + } } - - $this->entities = $mappedEntities; - $this->response = $response; } /** - * Response getter - * * @return Result */ public function getResponse() @@ -67,8 +59,6 @@ public function getResponse() } /** - * Entities getter - * * @return array */ public function getEntities() @@ -77,17 +67,11 @@ public function getEntities() } /** - * Entities setter - * * @param array $entities - * - * @return ResultSet $this */ public function setEntities($entities) { $this->entities = $entities; - - return $this; } /** @@ -140,4 +124,12 @@ public function __toArray() { return $this->toArray(); } + + /** + * {@inheritdoc} + */ + public function count() + { + return count($this->entities); + } } \ No newline at end of file diff --git a/Query/SolrQuery.php b/Query/SolrQuery.php index f76f567f..9a768272 100644 --- a/Query/SolrQuery.php +++ b/Query/SolrQuery.php @@ -148,16 +148,20 @@ public function addField($field) /** * @return string */ - public function prepareQuery() + public function getQuery() { if ($this->customQuery) { - $this->setQuery($this->customQuery); + parent::setQuery($this->customQuery); + return $this->customQuery; } $term = ''; if (count($this->searchTerms) == 0) { - return '*:*'; + $query = '*:*'; + parent::setQuery($query); + + return $query; } $logicOperator = 'AND'; @@ -180,7 +184,7 @@ public function prepareQuery() $termCount++; } - $this->setQuery($term); + parent::setQuery($term); return $term; } diff --git a/Solr.php b/Solr.php index cb8e1445..7b90f968 100644 --- a/Solr.php +++ b/Solr.php @@ -245,7 +245,7 @@ public function getSelectQuery(AbstractQuery $query) { $selectQuery = $this->solrClientCore->createSelect($query->getOptions()); - $selectQuery->setQuery($query->prepareQuery()); + $selectQuery->setQuery($query->getQuery()); $selectQuery->setFilterQueries($query->getFilterQueries()); $selectQuery->setSorts($query->getSorts()); @@ -257,9 +257,9 @@ public function getSelectQuery(AbstractQuery $query) */ public function query(AbstractQuery $query) { - $entity = $query->getEntity(); + $entity = $query->getEntity(); $runQueryInIndex = $query->getIndex(); - $selectQuery = $query->getSelectQuery(); + $selectQuery = $this->getSelectQuery($query); try { $response = $this->solrClientCore->select($selectQuery, $runQueryInIndex); diff --git a/Tests/AbstractSolrTest.php b/Tests/AbstractSolrTest.php index 0973d7f1..ca475780 100644 --- a/Tests/AbstractSolrTest.php +++ b/Tests/AbstractSolrTest.php @@ -6,6 +6,7 @@ use FS\SolrBundle\Tests\Util\CommandFactoryStub; use FS\SolrBundle\Tests\Util\MetaTestInformationFactory; +use Solarium\QueryType\Select\Result\Result; abstract class AbstractSolrTest extends \PHPUnit_Framework_TestCase { diff --git a/Tests/Query/SolrQueryTest.php b/Tests/Query/SolrQueryTest.php index 795896b9..1a3edbc6 100644 --- a/Tests/Query/SolrQueryTest.php +++ b/Tests/Query/SolrQueryTest.php @@ -78,7 +78,7 @@ public function testAddField_OneFieldOfTwoNotMapped() public function testGetSolrQuery_QueryTermShouldCorrect() { - $expected = 'title_s:"*foo*" OR text_t:"*bar*"'; + $expected = 'title_s:*foo* OR text_t:*bar*'; $query = $this->createQueryWithSearchTerms(); @@ -125,7 +125,7 @@ public function testAddSearchTerm_UnknownField() public function testGetQuery_TermsConcatWithOr() { - $expected = 'title_s:"*foo*" OR text_t:"*bar*"'; + $expected = 'title_s:*foo* OR text_t:*bar*'; $query = $this->createQueryWithSearchTerms(); @@ -134,7 +134,7 @@ public function testGetQuery_TermsConcatWithOr() public function testGetQuery_TermsConcatWithAnd() { - $expected = 'title_s:"*foo*" AND text_t:"*bar*"'; + $expected = 'title_s:*foo* AND text_t:*bar*'; $query = $this->createQueryWithSearchTerms(); $query->setUseAndOperator(true); @@ -147,7 +147,7 @@ public function testGetQuery_SearchInAllFields() $solrQuery = $this->createQueryWithFieldMapping(); $solrQuery->queryAllFields('foo'); - $expected = 'title_s:"*foo*" OR text_t:"*foo*" OR created_at_dt:"*foo*"'; + $expected = 'title_s:*foo* OR text_t:*foo* OR created_at_dt:*foo*'; $this->assertEquals($expected, $solrQuery->getQuery()); } diff --git a/Tests/SolrTest.php b/Tests/SolrTest.php index 0f2a54ce..b8f4fa2b 100644 --- a/Tests/SolrTest.php +++ b/Tests/SolrTest.php @@ -162,7 +162,6 @@ public function testQuery_NoResponseKeyInResponseSet() $solr = new Solr($this->solrClientFake, $this->commandFactory, $this->eventDispatcher, $this->metaFactory, $this->mapper); - $entities = $solr->query($query); $this->assertEquals(0, count($entities)); } From 548f1b242cf86b18e95cf200637ee41dc200ac32 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 13 Feb 2016 17:25:54 +0100 Subject: [PATCH 083/332] disable wildcard search by default, fix query tests --- Query/SolrQuery.php | 16 ++++++++++------ Tests/Query/SolrQueryTest.php | 29 +++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/Query/SolrQuery.php b/Query/SolrQuery.php index 9a768272..287ccf4c 100644 --- a/Query/SolrQuery.php +++ b/Query/SolrQuery.php @@ -25,15 +25,13 @@ class SolrQuery extends AbstractQuery /** * @var bool */ - private $useWildcards = true; + private $useWildcards = false; /** * @var string */ private $customQuery; - - /** * @return ResultSet */ @@ -172,12 +170,18 @@ public function getQuery() $termCount = 1; foreach ($this->searchTerms as $fieldName => $fieldValue) { + if ($this->useWildcards) { - $term .= $fieldName . ':*' . $fieldValue . '*'; - } else { - $term .= $fieldName . ':"' . $fieldValue .'"'; + $fieldValue = '*' . $fieldValue . '*'; } + $termParts = explode(' ', $fieldValue); + if (count($termParts) > 1) { + $fieldValue = '"'.$fieldValue.'"'; + } + + $term .= $fieldName . ':' . $fieldValue; + if ($termCount < count($this->searchTerms)) { $term .= ' ' . $logicOperator . ' '; } diff --git a/Tests/Query/SolrQueryTest.php b/Tests/Query/SolrQueryTest.php index 1a3edbc6..b3941764 100644 --- a/Tests/Query/SolrQueryTest.php +++ b/Tests/Query/SolrQueryTest.php @@ -78,7 +78,7 @@ public function testAddField_OneFieldOfTwoNotMapped() public function testGetSolrQuery_QueryTermShouldCorrect() { - $expected = 'title_s:*foo* OR text_t:*bar*'; + $expected = 'title_s:foo OR text_t:bar'; $query = $this->createQueryWithSearchTerms(); @@ -125,7 +125,7 @@ public function testAddSearchTerm_UnknownField() public function testGetQuery_TermsConcatWithOr() { - $expected = 'title_s:*foo* OR text_t:*bar*'; + $expected = 'title_s:foo OR text_t:bar'; $query = $this->createQueryWithSearchTerms(); @@ -134,7 +134,7 @@ public function testGetQuery_TermsConcatWithOr() public function testGetQuery_TermsConcatWithAnd() { - $expected = 'title_s:*foo* AND text_t:*bar*'; + $expected = 'title_s:foo AND text_t:bar'; $query = $this->createQueryWithSearchTerms(); $query->setUseAndOperator(true); @@ -147,7 +147,28 @@ public function testGetQuery_SearchInAllFields() $solrQuery = $this->createQueryWithFieldMapping(); $solrQuery->queryAllFields('foo'); - $expected = 'title_s:*foo* OR text_t:*foo* OR created_at_dt:*foo*'; + $expected = 'title_s:foo OR text_t:foo OR created_at_dt:foo'; + + $this->assertEquals($expected, $solrQuery->getQuery()); + } + + public function testGetQuery_SurroundTermWithDoubleQuotes() + { + $solrQuery = $this->createQueryWithFieldMapping(); + $solrQuery->queryAllFields('foo 12'); + + $expected = 'title_s:"foo 12" OR text_t:"foo 12" OR created_at_dt:"foo 12"'; + + $this->assertEquals($expected, $solrQuery->getQuery()); + } + + public function testGetQuery_SurroundWildcardTermWithDoubleQuotes() + { + $solrQuery = $this->createQueryWithFieldMapping(); + $solrQuery->queryAllFields('foo 12'); + $solrQuery->setUseWildcard(true); + + $expected = 'title_s:"*foo 12*" OR text_t:"*foo 12*" OR created_at_dt:"*foo 12*"'; $this->assertEquals($expected, $solrQuery->getQuery()); } From a0eb43b1b1dc41c575254685a3ef82d2192ffbce Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 14 Feb 2016 11:06:46 +0100 Subject: [PATCH 084/332] map all fields if no setter is specified --- .../Mapper/Mapping/MapAllFieldsCommand.php | 58 ++++++-- Repository/Repository.php | 1 + Resources/config/services.xml | 1 + Tests/Doctrine/Mapper/EntityMapperTest.php | 3 +- .../Mapping/MapAllFieldsCommandTest.php | 73 +++++++++- .../Mapper/ValidTestEntityWithCollection.php | 128 ++++++++++++++++++ Tests/Util/CommandFactoryStub.php | 3 +- Tests/Util/MetaTestInformationFactory.php | 8 +- 8 files changed, 255 insertions(+), 20 deletions(-) create mode 100644 Tests/Doctrine/Mapper/ValidTestEntityWithCollection.php diff --git a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php index f1e3fe23..c11387e2 100644 --- a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php +++ b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php @@ -2,8 +2,10 @@ namespace FS\SolrBundle\Doctrine\Mapper\Mapping; use FS\SolrBundle\Doctrine\Annotation\Field; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; use Doctrine\Common\Collections\Collection; +use Symfony\Component\Form\Extension\Core\Type\CollectionType; /** * command maps all fields of the entity @@ -12,6 +14,18 @@ */ class MapAllFieldsCommand extends AbstractDocumentCommand { + /** + * @var MetaInformationFactory + */ + private $metaInformationFactory; + + /** + * @param MetaInformationFactory $metaInformationFactory + */ + public function __construct(MetaInformationFactory $metaInformationFactory) + { + $this->metaInformationFactory = $metaInformationFactory; + } /** * @param MetaInformationInterface $meta @@ -33,18 +47,8 @@ public function createDocument(MetaInformationInterface $meta) } $value = $field->getValue(); - $getter = $field->getGetterName(); - if (!empty($getter)) { - if ($value instanceof Collection) { - $values = array(); - foreach ($value as $relatedObj) { - $values[] = $relatedObj->{$getter}(); - } - - $document->addField($field->getNameWithAlias(), $values, $field->getBoost()); - } elseif (is_object($value) && method_exists($value, $getter)) { - $document->addField($field->getNameWithAlias(), $value->{$getter}(), $field->getBoost()); - } + if ($value instanceof Collection) { + $document->addField($field->getNameWithAlias(), $this->mapCollection($field), $field->getBoost()); } else { $document->addField($field->getNameWithAlias(), $field->getValue(), $field->getBoost()); } @@ -52,4 +56,34 @@ public function createDocument(MetaInformationInterface $meta) return $document; } + + private function mapCollection(Field $field) + { + /** @var Collection $value */ + $value = $field->getValue(); + $getter = $field->getGetterName(); + if (!empty($getter)) { + $values = array(); + foreach ($value as $relatedObj) { + $values[] = $relatedObj->{$getter}(); + } + + return $values; + } + + $collection = array(); + foreach ($value as $object) { + $metaInformation = $this->metaInformationFactory->loadInformation($object); + + $field = array(); + $document = $this->createDocument($metaInformation); + foreach ($document as $fieldName => $value) { + $field[$fieldName] = $value; + } + + $collection[] = $field; + } + + return $collection; + } } diff --git a/Repository/Repository.php b/Repository/Repository.php index 38c4c820..63563aa2 100644 --- a/Repository/Repository.php +++ b/Repository/Repository.php @@ -103,6 +103,7 @@ public function findAll() public function findBy(array $args) { $query = $this->solr->createQuery($this->entity); + $query->setHydrationMode($this->hydrationMode); foreach ($args as $fieldName => $fieldValue) { $query->addSearchTerm($fieldName, $fieldValue); diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 155e0a53..b40df4e1 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -56,6 +56,7 @@ + diff --git a/Tests/Doctrine/Mapper/EntityMapperTest.php b/Tests/Doctrine/Mapper/EntityMapperTest.php index c9b0cd1a..109f2cc0 100644 --- a/Tests/Doctrine/Mapper/EntityMapperTest.php +++ b/Tests/Doctrine/Mapper/EntityMapperTest.php @@ -6,6 +6,7 @@ use FS\SolrBundle\Doctrine\Hydration\HydrationModes; use FS\SolrBundle\Doctrine\Mapper\EntityMapper; use FS\SolrBundle\Doctrine\Mapper\Mapping\MapAllFieldsCommand; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; use FS\SolrBundle\Tests\Util\MetaTestInformationFactory; use Solarium\QueryType\Update\Query\Document\Document; @@ -36,7 +37,7 @@ public function testToDocument_EntityMayNotIndexed() public function testToDocument_DocumentIsUpdated() { $mapper = new \FS\SolrBundle\Doctrine\Mapper\EntityMapper($this->doctrineHydrator, $this->indexHydrator); - $mapper->setMappingCommand(new MapAllFieldsCommand(new AnnotationReader())); + $mapper->setMappingCommand(new MapAllFieldsCommand(new MetaInformationFactory())); $actual = $mapper->toDocument(MetaTestInformationFactory::getMetaInformation()); $this->assertTrue($actual instanceof Document); diff --git a/Tests/Doctrine/Mapper/Mapping/MapAllFieldsCommandTest.php b/Tests/Doctrine/Mapper/Mapping/MapAllFieldsCommandTest.php index 85a6ec55..4a35b053 100644 --- a/Tests/Doctrine/Mapper/Mapping/MapAllFieldsCommandTest.php +++ b/Tests/Doctrine/Mapper/Mapping/MapAllFieldsCommandTest.php @@ -2,7 +2,12 @@ namespace FS\SolrBundle\Tests\Doctrine\Mapper\Mapping; +use Doctrine\Common\Collections\ArrayCollection; +use FS\SolrBundle\Doctrine\Annotation\Field; use FS\SolrBundle\Doctrine\Mapper\Mapping\MapAllFieldsCommand; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; +use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntity; +use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntityWithCollection; use FS\SolrBundle\Tests\Util\MetaTestInformationFactory; use Solarium\QueryType\Update\Query\Document\Document; @@ -14,12 +19,9 @@ class MapAllFieldsCommandTest extends SolrDocumentTest public static $MAPPED_FIELDS = array('title_s', 'text_t', 'created_at_dt'); - /** - * @group foo - */ public function testMapEntity_DocumentShouldContainThreeFields() { - $command = new MapAllFieldsCommand(); + $command = new MapAllFieldsCommand(new MetaInformationFactory()); $actual = $command->createDocument(MetaTestInformationFactory::getMetaInformation()); @@ -33,5 +35,68 @@ public function testMapEntity_DocumentShouldContainThreeFields() $this->assertHasDocumentFields($actual, self::$MAPPED_FIELDS); } + + /** + * @test + */ + public function mapRelationFieldByGetter() + { + $command = new MapAllFieldsCommand(new MetaInformationFactory()); + + $entity1 = new ValidTestEntity(); + $entity1->setTitle('title 1'); + + $entity2 = new ValidTestEntity(); + $entity2->setTitle('title 2'); + + $collection = new ArrayCollection(); + $collection->add($entity1); + $collection->add($entity2); + + $metaInformation = MetaTestInformationFactory::getMetaInformation(new ValidTestEntityWithCollection()); + $fields = $metaInformation->getFields(); + $fields[] = new Field(array('name' => 'collection', 'type' => 'strings', 'boost' => '1', 'value' => $collection, 'getter'=>'getTitle')); + $metaInformation->setFields($fields); + + $actual = $command->createDocument($metaInformation); + + $this->assertArrayHasKey('collection_ss', $actual->getFields()); + $collectionField = $actual->getFields()['collection_ss']; + + $this->assertEquals(2, count($collectionField)); + } + + /** + * @test + */ + public function mapRelationFieldAllFields() + { + $command = new MapAllFieldsCommand(new MetaInformationFactory()); + + $entity1 = new ValidTestEntity(); + $entity1->setTitle('title 1'); + $entity1->setText('text 1'); + + $entity2 = new ValidTestEntity(); + $entity2->setTitle('title 2'); + $entity1->setText('text 2'); + + $collection = new ArrayCollection(); + $collection->add($entity1); + $collection->add($entity2); + + $metaInformation = MetaTestInformationFactory::getMetaInformation(new ValidTestEntityWithCollection()); + $fields = $metaInformation->getFields(); + $fields[] = new Field(array('name' => 'collection', 'type' => 'strings', 'boost' => '1', 'value' => $collection)); + $metaInformation->setFields($fields); + + $actual = $command->createDocument($metaInformation); + + $this->assertArrayHasKey('collection_ss', $actual->getFields()); + $collectionField = $actual->getFields()['collection_ss']; + + $this->assertEquals(2, count($collectionField), 'collection contains 2 fields'); + $this->assertEquals(3, count($collectionField[0]), 'field has 2 properties'); + } } diff --git a/Tests/Doctrine/Mapper/ValidTestEntityWithCollection.php b/Tests/Doctrine/Mapper/ValidTestEntityWithCollection.php new file mode 100644 index 00000000..75643c3e --- /dev/null +++ b/Tests/Doctrine/Mapper/ValidTestEntityWithCollection.php @@ -0,0 +1,128 @@ +id; + } + + public function setId($id) + { + $this->id = $id; + } + + /** + * @return the $text + */ + public function getText() + { + return $this->text; + } + + /** + * @return the $title + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param \FS\BlogBundle\Tests\Solr\Doctrine\Mapper\text $text + */ + public function setText($text) + { + $this->text = $text; + } + + /** + * @param \FS\BlogBundle\Tests\Solr\Doctrine\Mapper\text $title + */ + public function setTitle($title) + { + $this->title = $title; + } + + /** + * @param string $costomField + */ + public function setCostomField($costomField) + { + $this->costomField = $costomField; + } + + /** + * @return string + */ + public function getCostomField() + { + return $this->costomField; + } + + /** + * @return \FS\SolrBundle\Tests\Doctrine\Mapper\date + */ + public function getCreatedAt() + { + return $this->created_at; + } + + /** + * @param \FS\SolrBundle\Tests\Doctrine\Mapper\date $created_at + */ + public function setCreatedAt($created_at) + { + $this->created_at = $created_at; + } +} + diff --git a/Tests/Util/CommandFactoryStub.php b/Tests/Util/CommandFactoryStub.php index d907b7b3..41086a69 100644 --- a/Tests/Util/CommandFactoryStub.php +++ b/Tests/Util/CommandFactoryStub.php @@ -5,6 +5,7 @@ use FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory; use FS\SolrBundle\Doctrine\Mapper\Mapping\MapAllFieldsCommand; use FS\SolrBundle\Doctrine\Mapper\Mapping\MapIdentifierCommand; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; class CommandFactoryStub { @@ -15,7 +16,7 @@ class CommandFactoryStub public static function getFactoryWithAllMappingCommand() { $commandFactory = new CommandFactory(); - $commandFactory->add(new MapAllFieldsCommand(), 'all'); + $commandFactory->add(new MapAllFieldsCommand(new MetaInformationFactory()), 'all'); $commandFactory->add(new MapIdentifierCommand(), 'identifier'); return $commandFactory; diff --git a/Tests/Util/MetaTestInformationFactory.php b/Tests/Util/MetaTestInformationFactory.php index 6d40955e..775cd84d 100644 --- a/Tests/Util/MetaTestInformationFactory.php +++ b/Tests/Util/MetaTestInformationFactory.php @@ -8,11 +8,15 @@ class MetaTestInformationFactory { /** + * @param object $entity + * * @return MetaInformation */ - public static function getMetaInformation() + public static function getMetaInformation($entity = null) { - $entity = new ValidTestEntity(); + if ($entity === null) { + $entity = new ValidTestEntity(); + } $entity->setId(2); $metaInformation = new MetaInformation(); From c8577ba3c8a900e834df129633363d57a4873346 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 14 Feb 2016 11:26:15 +0100 Subject: [PATCH 085/332] map embedded object by setter-option or map all fields --- .../Mapper/Mapping/MapAllFieldsCommand.php | 26 ++++ .../Mapping/MapAllFieldsCommandTest.php | 57 +++++++ .../Mapper/ValidTestEntityWithRelation.php | 145 ++++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 Tests/Doctrine/Mapper/ValidTestEntityWithRelation.php diff --git a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php index c11387e2..4374de8d 100644 --- a/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php +++ b/Doctrine/Mapper/Mapping/MapAllFieldsCommand.php @@ -49,6 +49,8 @@ public function createDocument(MetaInformationInterface $meta) $value = $field->getValue(); if ($value instanceof Collection) { $document->addField($field->getNameWithAlias(), $this->mapCollection($field), $field->getBoost()); + } elseif (is_object($value)) { + $document->addField($field->getNameWithAlias(), $this->mapObject($field), $field->getBoost()); } else { $document->addField($field->getNameWithAlias(), $field->getValue(), $field->getBoost()); } @@ -57,6 +59,30 @@ public function createDocument(MetaInformationInterface $meta) return $document; } + private function mapObject(Field $field) + { + $value = $field->getValue(); + $getter = $field->getGetterName(); + if (!empty($getter)) { + return $value->{$getter}(); + } + + $metaInformation = $this->metaInformationFactory->loadInformation($value); + + $field = array(); + $document = $this->createDocument($metaInformation); + foreach ($document as $fieldName => $value) { + $field[$fieldName] = $value; + } + + return $field; + } + + /** + * @param Field $field + * + * @return array + */ private function mapCollection(Field $field) { /** @var Collection $value */ diff --git a/Tests/Doctrine/Mapper/Mapping/MapAllFieldsCommandTest.php b/Tests/Doctrine/Mapper/Mapping/MapAllFieldsCommandTest.php index 4a35b053..bab40657 100644 --- a/Tests/Doctrine/Mapper/Mapping/MapAllFieldsCommandTest.php +++ b/Tests/Doctrine/Mapper/Mapping/MapAllFieldsCommandTest.php @@ -8,6 +8,7 @@ use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntity; use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntityWithCollection; +use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntityWithRelation; use FS\SolrBundle\Tests\Util\MetaTestInformationFactory; use Solarium\QueryType\Update\Query\Document\Document; @@ -98,5 +99,61 @@ public function mapRelationFieldAllFields() $this->assertEquals(2, count($collectionField), 'collection contains 2 fields'); $this->assertEquals(3, count($collectionField[0]), 'field has 2 properties'); } + + /** + * @test + */ + public function mapRelationField_AllFields() + { + $command = new MapAllFieldsCommand(new MetaInformationFactory()); + + $entity2 = new ValidTestEntity(); + $entity2->setTitle('embbeded object'); + + $entity1 = new ValidTestEntityWithRelation(); + $entity1->setTitle('title 1'); + $entity1->setText('text 1'); + $entity1->setRelation($entity2); + + $metaInformation = MetaTestInformationFactory::getMetaInformation($entity1); + $fields = $metaInformation->getFields(); + $fields[] = new Field(array('name' => 'relation', 'type' => 'strings', 'boost' => '1', 'value' => $entity1)); + $metaInformation->setFields($fields); + + $actual = $command->createDocument($metaInformation); + + $this->assertArrayHasKey('relation_ss', $actual->getFields()); + $collectionField = $actual->getFields()['relation_ss']; + + $this->assertEquals(4, count($collectionField), 'collection contains 4 fields'); + } + + /** + * @test + */ + public function mapRelationField_Getter() + { + $command = new MapAllFieldsCommand(new MetaInformationFactory()); + + $entity2 = new ValidTestEntity(); + $entity2->setTitle('embedded object'); + + $entity1 = new ValidTestEntityWithRelation(); + $entity1->setTitle('title 1'); + $entity1->setText('text 1'); + $entity1->setRelation($entity2); + + $metaInformation = MetaTestInformationFactory::getMetaInformation($entity1); + $fields = $metaInformation->getFields(); + $fields[] = new Field(array('name' => 'relation', 'type' => 'strings', 'boost' => '1', 'value' => $entity2, 'getter'=>'getTitle')); + $metaInformation->setFields($fields); + + $actual = $command->createDocument($metaInformation); + + $this->assertArrayHasKey('relation_ss', $actual->getFields()); + $collectionField = $actual->getFields()['relation_ss']; + + $this->assertEquals('embedded object', $collectionField); + } } diff --git a/Tests/Doctrine/Mapper/ValidTestEntityWithRelation.php b/Tests/Doctrine/Mapper/ValidTestEntityWithRelation.php new file mode 100644 index 00000000..6b90762a --- /dev/null +++ b/Tests/Doctrine/Mapper/ValidTestEntityWithRelation.php @@ -0,0 +1,145 @@ +id; + } + + public function setId($id) + { + $this->id = $id; + } + + /** + * @return the $text + */ + public function getText() + { + return $this->text; + } + + /** + * @return the $title + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param \FS\BlogBundle\Tests\Solr\Doctrine\Mapper\text $text + */ + public function setText($text) + { + $this->text = $text; + } + + /** + * @param \FS\BlogBundle\Tests\Solr\Doctrine\Mapper\text $title + */ + public function setTitle($title) + { + $this->title = $title; + } + + /** + * @param string $costomField + */ + public function setCostomField($costomField) + { + $this->costomField = $costomField; + } + + /** + * @return string + */ + public function getCostomField() + { + return $this->costomField; + } + + /** + * @return \FS\SolrBundle\Tests\Doctrine\Mapper\date + */ + public function getCreatedAt() + { + return $this->created_at; + } + + /** + * @param \FS\SolrBundle\Tests\Doctrine\Mapper\date $created_at + */ + public function setCreatedAt($created_at) + { + $this->created_at = $created_at; + } + + /** + * @return object + */ + public function getRelation() + { + return $this->relation; + } + + /** + * @param object $relation + */ + public function setRelation($relation) + { + $this->relation = $relation; + } + + +} + From 999c06e0173e879167cdd0cc62ce29a562ce861a Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 14 Feb 2016 13:01:45 +0100 Subject: [PATCH 086/332] complex fields (collections / relation) of the target-entity will not overwritten --- Doctrine/Annotation/Field.php | 40 ++++++++--- Doctrine/Hydration/ValueHydrator.php | 29 ++++++++ Query/ResultSet.php | 4 ++ .../Doctrine/Hydration/ValueHydratorTest.php | 66 +++++++++++++++++++ .../Mapper/ValidTestEntityWithCollection.php | 18 +++++ 5 files changed, 148 insertions(+), 9 deletions(-) diff --git a/Doctrine/Annotation/Field.php b/Doctrine/Annotation/Field.php index 160e8421..40d1397a 100644 --- a/Doctrine/Annotation/Field.php +++ b/Doctrine/Annotation/Field.php @@ -2,6 +2,7 @@ namespace FS\SolrBundle\Doctrine\Annotation; use Doctrine\Common\Annotations\Annotation; +use phpDocumentor\Reflection\DocBlock\Type\Collection; /** * Defines a field of a solr-document @@ -34,23 +35,34 @@ class Field extends Annotation /** * @var array */ - private static $TYP_MAPPING = array( + private static $TYP_MAPPING = array(); + + /** + * @var array + */ + private static $TYP_SIMPLE_MAPPING = array( 'string' => '_s', - 'strings' => '_ss', 'text' => '_t', - 'texts' => '_txt', 'date' => '_dt', - 'dates' => '_dts', 'boolean' => '_b', - 'booleans' => '_bs', 'integer' => '_i', - 'integers' => '_is', 'long' => '_l', - 'longs' => '_ls', 'float' => '_f', - 'floats' => '_fs', - 'double' => '_d', + 'double' => '_d' + ); + + /** + * @var array + */ + private static $TYP_COMPLEX_MAPPING = array( 'doubles' => '_ds', + 'floats' => '_fs', + 'longs' => '_ls', + 'integers' => '_is', + 'booleans' => '_bs', + 'dates' => '_dts', + 'texts' => '_txt', + 'strings' => '_ss', ); /** @@ -74,6 +86,8 @@ public function getNameWithAlias() */ private function getTypeSuffix($type) { + self::$TYP_MAPPING = array_merge(self::$TYP_COMPLEX_MAPPING, self::$TYP_SIMPLE_MAPPING); + if ($type == '') { return ''; } @@ -151,4 +165,12 @@ function ($value) { return implode('_', $words); } + + /** + * @return array + */ + public static function getComplexFieldMapping() + { + return self::$TYP_COMPLEX_MAPPING; + } } diff --git a/Doctrine/Hydration/ValueHydrator.php b/Doctrine/Hydration/ValueHydrator.php index 2d74331f..a9e74eeb 100644 --- a/Doctrine/Hydration/ValueHydrator.php +++ b/Doctrine/Hydration/ValueHydrator.php @@ -2,6 +2,8 @@ namespace FS\SolrBundle\Doctrine\Hydration; +use Doctrine\Common\Collections\Collection; +use FS\SolrBundle\Doctrine\Annotation\Field; use FS\SolrBundle\Doctrine\Mapper\MetaInformationInterface; /** @@ -22,6 +24,12 @@ public function hydrate($document, MetaInformationInterface $metaInformation) $value = $this->removePrefixedKeyFieldName($value); } + // skip field if value is array or "flat" object + // hydrated object should contain a list of real entities / entity + if ($this->isComplexValue($property, $value)) { + continue; + } + try { $classProperty = $reflectionClass->getProperty($this->removeFieldSuffix($property)); } catch (\ReflectionException $e) { @@ -92,4 +100,25 @@ private function toCamelCase($fieldname) return lcfirst($pascalCased); } + + /** + * @return bool + */ + public function isComplexValue($fieldName, $value) + { + if (is_array($value)) { + return true; + } + + $fieldSuffix = $this->removePrefixedKeyFieldName($fieldName); + if ($fieldSuffix === false) { + return false; + } + + if (array_key_exists($fieldSuffix, Field::getComplexFieldMapping())) { + return true; + } + + return false; + } } \ No newline at end of file diff --git a/Query/ResultSet.php b/Query/ResultSet.php index 4ab1a089..8a97a7d4 100644 --- a/Query/ResultSet.php +++ b/Query/ResultSet.php @@ -89,6 +89,10 @@ public function offsetSet($offset, $value) */ public function offsetGet($offset) { + if (count($this->entities) === 0) { + throw new \OutOfBoundsException(sprintf('Index %s is not defined', $offset)); + } + return $this->entities[$offset]; } diff --git a/Tests/Doctrine/Hydration/ValueHydratorTest.php b/Tests/Doctrine/Hydration/ValueHydratorTest.php index 1e62a0d5..33241d9b 100644 --- a/Tests/Doctrine/Hydration/ValueHydratorTest.php +++ b/Tests/Doctrine/Hydration/ValueHydratorTest.php @@ -3,11 +3,14 @@ namespace FS\SolrBundle\Tests\Doctrine\Hydration; +use Doctrine\Common\Collections\ArrayCollection; use FS\SolrBundle\Doctrine\Hydration\ValueHydrator; use FS\SolrBundle\Doctrine\Hydration\ValueHydratorInterface; use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; use FS\SolrBundle\Tests\Doctrine\Mapper\SolrDocumentStub; use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntity; +use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntityWithCollection; +use FS\SolrBundle\Tests\Doctrine\Mapper\ValidTestEntityWithRelation; /** * @group hydration @@ -59,5 +62,68 @@ public function underscoreFieldBecomeCamelCase() $this->assertEquals(1, $entity->getId()); $this->assertEquals(12345, $entity->getCreatedAt()); } + + /** + * @test + */ + public function doNotOverwriteComplexTypes_Collection() + { + $obj = new SolrDocumentStub(array( + 'id' => 'document_1', + 'title_t' => 'foo', + 'posts_ss' => array('title 1', 'title 2') + )); + + $entity1 = new ValidTestEntity(); + $entity1->setTitle('title 1'); + + $entity2 = new ValidTestEntity(); + $entity2->setTitle('title 2'); + + $entity = new ValidTestEntityWithCollection(); + $entity->setCollection(new ArrayCollection(array($entity1, $entity2))); + + $metainformations = new MetaInformationFactory(); + $metainformations = $metainformations->loadInformation($entity); + + $hydrator = new ValueHydrator(); + $hydratedDocument = $hydrator->hydrate($obj, $metainformations); + + $this->assertTrue($hydratedDocument instanceof $entity); + $this->assertEquals(1, $entity->getId()); + $this->assertEquals('foo', $entity->getTitle()); + + $this->assertTrue($hydratedDocument->getCollection()[0] === $entity1); + } + + /** + * @test + */ + public function doNotOverwriteComplexTypes_Relation() + { + $obj = new SolrDocumentStub(array( + 'id' => 'document_1', + 'title_t' => 'foo', + 'posts_ss' => 'title 1' + )); + + $entity1 = new ValidTestEntity(); + $entity1->setTitle('title 1'); + + $entity = new ValidTestEntityWithRelation(); + $entity->setRelation($entity1); + + $metainformations = new MetaInformationFactory(); + $metainformations = $metainformations->loadInformation($entity); + + $hydrator = new ValueHydrator(); + $hydratedDocument = $hydrator->hydrate($obj, $metainformations); + + $this->assertTrue($hydratedDocument instanceof $entity); + $this->assertEquals(1, $entity->getId()); + $this->assertEquals('foo', $entity->getTitle()); + + $this->assertTrue($hydratedDocument->getRelation() === $entity1); + } } \ No newline at end of file diff --git a/Tests/Doctrine/Mapper/ValidTestEntityWithCollection.php b/Tests/Doctrine/Mapper/ValidTestEntityWithCollection.php index 75643c3e..1aa209a6 100644 --- a/Tests/Doctrine/Mapper/ValidTestEntityWithCollection.php +++ b/Tests/Doctrine/Mapper/ValidTestEntityWithCollection.php @@ -124,5 +124,23 @@ public function setCreatedAt($created_at) { $this->created_at = $created_at; } + + /** + * @return ArrayCollection + */ + public function getCollection() + { + return $this->collection; + } + + /** + * @param ArrayCollection $collection + */ + public function setCollection($collection) + { + $this->collection = $collection; + } + + } From 650e8c3bff75552413dd9c6ab9b772e49c35f7af Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 14 Feb 2016 13:02:51 +0100 Subject: [PATCH 087/332] fix behat setup --- Tests/Integration/Bootstrap/SolrSetupFeatureContext.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php b/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php index d44b668b..e3b03fbf 100644 --- a/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php +++ b/Tests/Integration/Bootstrap/SolrSetupFeatureContext.php @@ -3,6 +3,7 @@ namespace FS\SolrBundle\Tests\Integration\Bootstrap; use Behat\Behat\Context\Context; +use FS\SolrBundle\Doctrine\Mapper\MetaInformationFactory; class SolrSetupFeatureContext implements Context { @@ -95,7 +96,7 @@ private function setupEntityMapper() private function setupCommandFactory() { $factory = new \FS\SolrBundle\Doctrine\Mapper\Mapping\CommandFactory(); - $factory->add(new \FS\SolrBundle\Doctrine\Mapper\Mapping\MapAllFieldsCommand(), 'all'); + $factory->add(new \FS\SolrBundle\Doctrine\Mapper\Mapping\MapAllFieldsCommand(new MetaInformationFactory()), 'all'); $factory->add(new \FS\SolrBundle\Doctrine\Mapper\Mapping\MapIdentifierCommand(), 'identifier'); return $factory; From eba130c1ebf8c1320c0528149c37066bfe8c1c36 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 14 Feb 2016 13:56:00 +0100 Subject: [PATCH 088/332] symfony2 + symfony 3 support --- composer.json | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index c497db1c..a75a8b65 100644 --- a/composer.json +++ b/composer.json @@ -12,17 +12,16 @@ "license": "MIT", "require": { "php": ">=5.4.5", - "solarium/solarium": "*" - }, - "require-dev": { - "doctrine/doctrine-module": "*", - "doctrine/doctrine-orm-module": "*", + "solarium/solarium": "^3.5", + "symfony/dependency-injection": "^2.3|^3.0", + "symfony/http-kernel": "^2.3|^3.0", + "symfony/config": "^2.3|^3.0", + "symfony/doctrine-bridge": "^2.3|^3.0", "doctrine/mongodb": "*", "doctrine/mongodb-odm": "*", - "symfony/dependency-injection": "*", - "symfony/http-kernel": "*", - "symfony/config": "*", - "symfony/doctrine-bridge": "*", + "doctrine/orm": "^2.3" + }, + "require-dev": { "behat/behat": "3.*" }, "minimum-stability": "alpha", From 9b582a3aae46c8b9b0b7007fe6303cdfbc21a486 Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sun, 14 Feb 2016 14:32:30 +0100 Subject: [PATCH 089/332] use develop branch --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a75a8b65..bf5db550 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "license": "MIT", "require": { "php": ">=5.4.5", - "solarium/solarium": "^3.5", + "solarium/solarium": "dev-develop", "symfony/dependency-injection": "^2.3|^3.0", "symfony/http-kernel": "^2.3|^3.0", "symfony/config": "^2.3|^3.0", From fbf76c7782aa81625c3c6ca8b9638ddc10df37bd Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sun, 14 Feb 2016 14:36:36 +0100 Subject: [PATCH 090/332] use develop branch --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index bf5db550..a2e562b5 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "license": "MIT", "require": { "php": ">=5.4.5", - "solarium/solarium": "dev-develop", + "solarium/solarium": "3.3.x-dev", "symfony/dependency-injection": "^2.3|^3.0", "symfony/http-kernel": "^2.3|^3.0", "symfony/config": "^2.3|^3.0", From 4fa47d056419b9fc80fd2903d28f8b887c720b30 Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sun, 14 Feb 2016 14:42:44 +0100 Subject: [PATCH 091/332] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a2e562b5..bf5db550 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "license": "MIT", "require": { "php": ">=5.4.5", - "solarium/solarium": "3.3.x-dev", + "solarium/solarium": "dev-develop", "symfony/dependency-injection": "^2.3|^3.0", "symfony/http-kernel": "^2.3|^3.0", "symfony/config": "^2.3|^3.0", From de9b311d9d367a226cd0060ed9e2e5df364864b0 Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sun, 14 Feb 2016 14:46:54 +0100 Subject: [PATCH 092/332] Update composer.json --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index bf5db550..fcde602e 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,6 @@ "require-dev": { "behat/behat": "3.*" }, - "minimum-stability": "alpha", "autoload": { "psr-0": { "FS\\SolrBundle": "" From 2a24c90a43d959a58c9cc766cfcb8fd4e4267f78 Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sun, 14 Feb 2016 15:00:34 +0100 Subject: [PATCH 093/332] Update composer.json --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index fcde602e..fda9f11a 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "FS\\SolrBundle": "" } }, + "minimum-stability": "dev", "config": { "bin-dir": "bin" }, From 820b17f1dc545ced55705c4282b362f80c4b225d Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sun, 14 Feb 2016 15:24:56 +0100 Subject: [PATCH 094/332] remove mini. version --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index fda9f11a..fcde602e 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,6 @@ "FS\\SolrBundle": "" } }, - "minimum-stability": "dev", "config": { "bin-dir": "bin" }, From f870b49491b80022cb26dfb8669e21b9d61b4eab Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sun, 14 Feb 2016 15:35:53 +0100 Subject: [PATCH 095/332] Update composer.json --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index fcde602e..a2fb407d 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ "require-dev": { "behat/behat": "3.*" }, + "minimum-stability": "alpha" "autoload": { "psr-0": { "FS\\SolrBundle": "" From e287ea9adac9ba1d5a6312aaa3d357beb917b62a Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sun, 14 Feb 2016 15:36:56 +0100 Subject: [PATCH 096/332] Update composer.json --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index a2fb407d..c32bac4e 100644 --- a/composer.json +++ b/composer.json @@ -22,9 +22,9 @@ "doctrine/orm": "^2.3" }, "require-dev": { - "behat/behat": "3.*" + "behat/behat": "dev-master" }, - "minimum-stability": "alpha" + "minimum-stability": "alpha", "autoload": { "psr-0": { "FS\\SolrBundle": "" From b445cb9eeb7ddd88eb6405d78e06ea4b665db001 Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Sun, 14 Feb 2016 15:38:41 +0100 Subject: [PATCH 097/332] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c32bac4e..39b2236b 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "require-dev": { "behat/behat": "dev-master" }, - "minimum-stability": "alpha", + "minimum-stability": "beta", "autoload": { "psr-0": { "FS\\SolrBundle": "" From a92fb7f522db4f797043168eee718dbfc0155ae9 Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Mon, 15 Feb 2016 15:57:59 +0100 Subject: [PATCH 098/332] revert symfony3 dependencies --- composer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 39b2236b..0246dc4f 100644 --- a/composer.json +++ b/composer.json @@ -12,17 +12,17 @@ "license": "MIT", "require": { "php": ">=5.4.5", - "solarium/solarium": "dev-develop", - "symfony/dependency-injection": "^2.3|^3.0", - "symfony/http-kernel": "^2.3|^3.0", - "symfony/config": "^2.3|^3.0", - "symfony/doctrine-bridge": "^2.3|^3.0", + "solarium/solarium": "^3.5", + "symfony/dependency-injection": "^2.3", + "symfony/http-kernel": "^2.3", + "symfony/config": "^2.3", + "symfony/doctrine-bridge": "^2.3", "doctrine/mongodb": "*", "doctrine/mongodb-odm": "*", "doctrine/orm": "^2.3" }, "require-dev": { - "behat/behat": "dev-master" + "behat/behat": "^3.0" }, "minimum-stability": "beta", "autoload": { From 1833fff2c747ccb8d5db3b078b941b594a8c5e0b Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Mon, 15 Feb 2016 16:09:05 +0100 Subject: [PATCH 099/332] revert symfony3 dependencies --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index fcde602e..66c30a9f 100644 --- a/composer.json +++ b/composer.json @@ -12,11 +12,11 @@ "license": "MIT", "require": { "php": ">=5.4.5", - "solarium/solarium": "dev-develop", - "symfony/dependency-injection": "^2.3|^3.0", - "symfony/http-kernel": "^2.3|^3.0", - "symfony/config": "^2.3|^3.0", - "symfony/doctrine-bridge": "^2.3|^3.0", + "solarium/solarium": "^3.5", + "symfony/dependency-injection": "^2.3", + "symfony/http-kernel": "^2.3", + "symfony/config": "^2.3", + "symfony/doctrine-bridge": "^2.3", "doctrine/mongodb": "*", "doctrine/mongodb-odm": "*", "doctrine/orm": "^2.3" From 574f5c6d546ee571dded2c0a4ee6fedf9ff345b4 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 15 Feb 2016 16:54:37 +0100 Subject: [PATCH 100/332] throw exception if requested field is unknown to avoid issues like #114 --- Query/Exception/UnknownFieldException.php | 8 ++++++++ Query/SolrQuery.php | 8 ++++++++ Tests/Query/SolrQueryTest.php | 21 ++++----------------- 3 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 Query/Exception/UnknownFieldException.php diff --git a/Query/Exception/UnknownFieldException.php b/Query/Exception/UnknownFieldException.php new file mode 100644 index 00000000..98bb0dff --- /dev/null +++ b/Query/Exception/UnknownFieldException.php @@ -0,0 +1,8 @@ +mappedFields); + if (!array_key_exists($field, $documentFieldsAsValues)) { + throw new UnknownFieldException(sprintf('Entity %s has no mapping for field %s', get_class($this->getEntity()), $field)); + } + if (array_key_exists($field, $documentFieldsAsValues)) { $documentFieldName = $documentFieldsAsValues[$field]; diff --git a/Tests/Query/SolrQueryTest.php b/Tests/Query/SolrQueryTest.php index 795896b9..15b038a0 100644 --- a/Tests/Query/SolrQueryTest.php +++ b/Tests/Query/SolrQueryTest.php @@ -3,6 +3,7 @@ namespace FS\SolrBundle\Tests\Query; use FS\SolrBundle\Doctrine\Annotation\AnnotationReader; +use FS\SolrBundle\Query\Exception\UnknownFieldException; use FS\SolrBundle\Query\SolrQuery; use FS\SolrBundle\SolrQueryFacade; @@ -99,28 +100,14 @@ public function testAddSearchTerm_AllFieldsAreMapped() $this->assertTrue(array_key_exists('text_t', $terms), 'text_t not in terms'); } - public function testAddSearchTerm_OneFieldOfTwoNotMapped() - { - $solrQuery = $this->createQueryWithFieldMapping(); - - $solrQuery->addSearchTerm('title', 'foo') - ->addSearchTerm('foo', 'bar'); - - $terms = $solrQuery->getSearchTerms(); - - $this->assertTrue(array_key_exists('title_s', $terms), 'title_s not in terms'); - $this->assertEquals(1, count($terms)); - } - + /** + * @expectedException \FS\SolrBundle\Query\Exception\UnknownFieldException + */ public function testAddSearchTerm_UnknownField() { $solrQuery = $this->createQueryWithFieldMapping(); $solrQuery->addSearchTerm('unknownfield', 'foo'); - - $terms = $solrQuery->getSearchTerms(); - - $this->assertEquals(0, count($terms)); } public function testGetQuery_TermsConcatWithOr() From 6da3bf991663ea8d9bcf34614e69f2f4333e7c36 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Mon, 15 Feb 2016 16:56:45 +0100 Subject: [PATCH 101/332] remove unnecessary if statement --- Query/SolrQuery.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Query/SolrQuery.php b/Query/SolrQuery.php index d5d93c89..3013254f 100644 --- a/Query/SolrQuery.php +++ b/Query/SolrQuery.php @@ -125,11 +125,8 @@ public function addSearchTerm($field, $value) throw new UnknownFieldException(sprintf('Entity %s has no mapping for field %s', get_class($this->getEntity()), $field)); } - if (array_key_exists($field, $documentFieldsAsValues)) { - $documentFieldName = $documentFieldsAsValues[$field]; - - $this->searchTerms[$documentFieldName] = $value; - } + $documentFieldName = $documentFieldsAsValues[$field]; + $this->searchTerms[$documentFieldName] = $value; return $this; } From 7a88a751e9bacb46b3c8c10f4ca4dc0deedb2842 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 20 Feb 2016 16:51:51 +0100 Subject: [PATCH 102/332] set selected fields from incoming query, #116 --- Solr.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Solr.php b/Solr.php index 0fd0e91f..e776a01d 100644 --- a/Solr.php +++ b/Solr.php @@ -244,6 +244,7 @@ public function query(AbstractQuery $query) $selectQuery->setQuery($query->getQuery()); $selectQuery->setFilterQueries($query->getFilterQueries()); $selectQuery->setSorts($query->getSorts()); + $selectQuery->setFields($query->getFields()); try { $response = $this->solrClientCore->select($selectQuery, $runQueryInIndex); From 5eb5fe98ceee33b64a7df0fbebef8a8d3c8ec2fe Mon Sep 17 00:00:00 2001 From: Florian Semm Date: Mon, 22 Feb 2016 17:37:20 +0100 Subject: [PATCH 103/332] remove gitter --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index db5f294f..5e3671ea 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,6 @@ Introduction This Bundle provides a simple API to index and query a Solr Index. -And do not forget to join the Gitter chat [![join the chat at https://gitter.im/floriansemm/SolrBundle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/floriansemm/SolrBundle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - ## Installation Installation is a quick (I promise!) 3 step process: From 74ca4b4bc4018fbab5eec3d9589b77a0c44d9866 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Tue, 23 Feb 2016 11:17:07 +0100 Subject: [PATCH 104/332] improve test-coverage of getQuery --- Tests/Query/SolrQueryTest.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Tests/Query/SolrQueryTest.php b/Tests/Query/SolrQueryTest.php index 15b038a0..a1add733 100644 --- a/Tests/Query/SolrQueryTest.php +++ b/Tests/Query/SolrQueryTest.php @@ -138,4 +138,34 @@ public function testGetQuery_SearchInAllFields() $this->assertEquals($expected, $solrQuery->getQuery()); } + + public function testGetQuery_NoWildcard_Word() + { + $solrQuery = $this->createQueryWithFieldMapping(); + $solrQuery->setUseWildcard(false); + $solrQuery->addSearchTerm('title', 'a_word'); + + $expected = 'title_s:"a_word"'; + + $this->assertEquals($expected, $solrQuery->getQuery()); + } + + public function testGetQuery_NoSearchTerm() + { + $solrQuery = $this->createQueryWithFieldMapping(); + + $expected = '*:*'; + + $this->assertEquals($expected, $solrQuery->getQuery()); + } + + public function testGetQuery_CustomQuery() + { + $solrQuery = $this->createQueryWithFieldMapping(); + $solrQuery->setCustomQuery('title_s:[*:*]'); + + $expected = 'title_s:[*:*]'; + + $this->assertEquals($expected, $solrQuery->getQuery()); + } } From 98bfab1fd9b36b84258b128f28e19c3f0a62de8e Mon Sep 17 00:00:00 2001 From: floriansemm Date: Wed, 24 Feb 2016 10:19:42 +0100 Subject: [PATCH 105/332] fix hasField/getField --- Doctrine/Mapper/MetaInformation.php | 35 +++++++++---- Doctrine/Mapper/MetaInformationInterface.php | 4 +- .../Mapper/MetaInformationFactoryTest.php | 6 +++ Tests/Doctrine/Mapper/MetaInformationTest.php | 49 ------------------- 4 files changed, 33 insertions(+), 61 deletions(-) diff --git a/Doctrine/Mapper/MetaInformation.php b/Doctrine/Mapper/MetaInformation.php index 7e364734..692bd8b2 100644 --- a/Doctrine/Mapper/MetaInformation.php +++ b/Doctrine/Mapper/MetaInformation.php @@ -165,38 +165,53 @@ public function setFields($fields) } /** - * @param string $field + * @param string $fieldName * * @return boolean */ - public function hasField($field) + public function hasField($fieldName) { - if (count($this->fields) == 0) { + $fields = array_filter($this->fields, function(Field $field) use ($fieldName) { + return $field->name == $fieldName || $field->getNameWithAlias() == $fieldName; + }); + + if (count($fields) == 0) { return false; } - return isset($this->fields[$field]); + return true; } /** - * @param string $field + * @param string $fieldName * @param string $value + * + * @throws \InvalidArgumentException if $fieldName does not exist */ - public function setFieldValue($field, $value) + public function setFieldValue($fieldName, $value) { - $this->fields[$field]->value = $value; + if ($this->hasField($fieldName) == false) { + throw new \InvalidArgumentException(sprintf('Field %s does not exist', $fieldName)); + } + + $field = $this->getField($fieldName); + $field->value = $value; } /** * {@inheritdoc} */ - public function getField($field) + public function getField($fieldName) { - if (!$this->hasField($field)) { + if (!$this->hasField($fieldName)) { return null; } - return $this->fields[$field]; + $fields = array_filter($this->fields, function(Field $field) use ($fieldName) { + return $field->name == $fieldName || $field->getNameWithAlias() == $fieldName; + }); + + return array_pop($fields); } /** diff --git a/Doctrine/Mapper/MetaInformationInterface.php b/Doctrine/Mapper/MetaInformationInterface.php index f48c3610..a89fa15c 100644 --- a/Doctrine/Mapper/MetaInformationInterface.php +++ b/Doctrine/Mapper/MetaInformationInterface.php @@ -48,11 +48,11 @@ public function getRepository(); public function getEntity(); /** - * @param string $field + * @param string $fieldName * * @return Field|null */ - public function getField($field); + public function getField($fieldName); /** * @return array diff --git a/Tests/Doctrine/Mapper/MetaInformationFactoryTest.php b/Tests/Doctrine/Mapper/MetaInformationFactoryTest.php index a98c9a3c..52d9f32b 100644 --- a/Tests/Doctrine/Mapper/MetaInformationFactoryTest.php +++ b/Tests/Doctrine/Mapper/MetaInformationFactoryTest.php @@ -1,6 +1,7 @@ assertEquals($expectedClassName, $actual->getClassName(), 'wrong classname'); $this->assertEquals($expectedDocumentName, $actual->getDocumentName(), 'wrong documentname'); $this->assertEquals(4, count($actual->getFields()), '4 fields are mapped'); + + $this->assertTrue($actual->hasField('title'), 'field should be able to located by field-name'); + $this->assertTrue($actual->hasField('text_t'), 'field should be able to located by field-name with suffix'); + + $this->assertTrue($actual->getField('title') instanceof Field); } /** diff --git a/Tests/Doctrine/Mapper/MetaInformationTest.php b/Tests/Doctrine/Mapper/MetaInformationTest.php index 339d9fdf..f50e2ab4 100644 --- a/Tests/Doctrine/Mapper/MetaInformationTest.php +++ b/Tests/Doctrine/Mapper/MetaInformationTest.php @@ -18,55 +18,6 @@ private function createFieldObject($name, $value) return $value; } - public function testHasField_FieldExists() - { - $value1 = $this->createFieldObject('field1', 'oldfieldvalue'); - $value2 = $this->createFieldObject('field2', true); - - $fields = array( - 'field1' => $value1, - 'field2' => $value2 - ); - - $information = new MetaInformation(); - $information->setFields($fields); - - $this->assertTrue($information->hasField('field2'), 'metainformation should have field2'); - } - - public function testHasField_FieldNotExists() - { - $value1 = $this->createFieldObject('field1', 'oldfieldvalue'); - - $fields = array( - 'field1' => $value1, - ); - - $information = new MetaInformation(); - $information->setFields($fields); - - $this->assertFalse($information->hasField('field2'), 'unknown field field2'); - } - - public function testSetFieldValue() - { - $value1 = $this->createFieldObject('field1', 'oldfieldvalue'); - $value2 = $this->createFieldObject('field2', true); - - $fields = array( - 'field1' => $value1, - 'field2' => $value2 - ); - - $information = new MetaInformation(); - $information->setFields($fields); - - $expectedValue = 'newFieldValue'; - $information->setFieldValue('field2', $expectedValue); - - $this->assertEquals($expectedValue, $information->getField('field2')->value, 'field2 should have new value'); - } - public function testHasCallback_CallbackSet() { $information = new MetaInformation(); From 9457e896cfc51118d12d838c340cdbfecb8bad23 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Wed, 24 Feb 2016 10:20:03 +0100 Subject: [PATCH 106/332] add command to show document-mappings --- Command/ShowSchemaCommand.php | 54 +++++++++++++++++++ .../KnownNamespaceAliases.php | 13 ++++- Resources/config/services.xml | 2 +- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 Command/ShowSchemaCommand.php diff --git a/Command/ShowSchemaCommand.php b/Command/ShowSchemaCommand.php new file mode 100644 index 00000000..09996bed --- /dev/null +++ b/Command/ShowSchemaCommand.php @@ -0,0 +1,54 @@ +setName('solr:schema:show') + ->setDescription('Index all entities'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $namespaces = $this->getContainer()->get('solr.doctrine.classnameresolver.known_entity_namespaces'); + $metaInformationFactory = $this->getContainer()->get('solr.meta.information.factory'); + + foreach ($namespaces->getEntityClassnames() as $classname) { + $metaInformation = $metaInformationFactory->loadInformation($classname); + + $output->writeln(sprintf('%s', $classname)); + $output->writeln(sprintf('Documentname: %s', $metaInformation->getDocumentName())); + $output->writeln(sprintf('Document Boost: %s', $metaInformation->getBoost()?$metaInformation->getBoost(): '-')); + + $table = new Table($output); + $table->setHeaders(array('Property', 'Document Fieldname', 'Boost')); + + foreach ($metaInformation->getFieldMapping() as $documentField => $property) { + $field = $metaInformation->getField($documentField); + + if ($field === null) { + continue; + } + + $table->addRow(array($property, $documentField, $field->boost)); + } + $table->render(); + } + + } + + +} \ No newline at end of file diff --git a/Doctrine/ClassnameResolver/KnownNamespaceAliases.php b/Doctrine/ClassnameResolver/KnownNamespaceAliases.php index d27cdb25..5ca050be 100644 --- a/Doctrine/ClassnameResolver/KnownNamespaceAliases.php +++ b/Doctrine/ClassnameResolver/KnownNamespaceAliases.php @@ -15,6 +15,8 @@ class KnownNamespaceAliases */ private $knownNamespaceAlias = array(); + private $entityClassnames = array(); + /** * @param OdmConfiguration $configuration */ @@ -29,6 +31,7 @@ public function addDocumentNamespaces(OdmConfiguration $configuration) public function addEntityNamespaces(OrmConfiguration $configuration) { $this->knownNamespaceAlias = array_merge($this->knownNamespaceAlias, $configuration->getEntityNamespaces()); + $this->entityClassnames = array_merge($this->entityClassnames, $configuration->getMetadataDriverImpl()->getAllClassNames()); } /** @@ -62,4 +65,12 @@ public function getAllNamespaceAliases() { return array_keys($this->knownNamespaceAlias); } -} \ No newline at end of file + + /** + * @return array + */ + public function getEntityClassnames() + { + return $this->entityClassnames; + } +} \ No newline at end of file diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 155e0a53..25da1c6e 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -45,7 +45,7 @@ - + From ff9aa5522f29f055317311f9c4a6fe6707d93678 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Wed, 24 Feb 2016 10:35:36 +0100 Subject: [PATCH 107/332] add null check --- Doctrine/ClassnameResolver/KnownNamespaceAliases.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Doctrine/ClassnameResolver/KnownNamespaceAliases.php b/Doctrine/ClassnameResolver/KnownNamespaceAliases.php index 5ca050be..1f83bd60 100644 --- a/Doctrine/ClassnameResolver/KnownNamespaceAliases.php +++ b/Doctrine/ClassnameResolver/KnownNamespaceAliases.php @@ -31,7 +31,10 @@ public function addDocumentNamespaces(OdmConfiguration $configuration) public function addEntityNamespaces(OrmConfiguration $configuration) { $this->knownNamespaceAlias = array_merge($this->knownNamespaceAlias, $configuration->getEntityNamespaces()); - $this->entityClassnames = array_merge($this->entityClassnames, $configuration->getMetadataDriverImpl()->getAllClassNames()); + + if ($configuration->getMetadataDriverImpl()) { + $this->entityClassnames = array_merge($this->entityClassnames, $configuration->getMetadataDriverImpl()->getAllClassNames()); + } } /** From eb4b58abb5e581f2c5c86dd9e22cfcc19da6be03 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 25 Mar 2016 10:03:06 +0100 Subject: [PATCH 108/332] ResultSet breaks old behavior --- Solr.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Solr.php b/Solr.php index 7b90f968..39b9a202 100644 --- a/Solr.php +++ b/Solr.php @@ -263,14 +263,20 @@ public function query(AbstractQuery $query) try { $response = $this->solrClientCore->select($selectQuery, $runQueryInIndex); - return new ResultSet($entity, $this->entityMapper, $response); + + $entities = array(); + foreach ($response as $document) { + $entities[] = $this->entityMapper->toEntity($document, $entity); + } + + return $entities; } catch (\Exception $e) { $errorEvent = new ErrorEvent(null, null, 'query solr'); $errorEvent->setException($e); $this->eventManager->dispatch(Events::ERROR, $errorEvent); - return new ResultSet($entity, null, null); + return array(); } } From 2cde6f3093be9f39d14d21a787e2575c5e66e253 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 25 Mar 2016 11:40:58 +0100 Subject: [PATCH 109/332] use doctrine value if property is a relation --- Doctrine/Hydration/ValueHydrator.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Doctrine/Hydration/ValueHydrator.php b/Doctrine/Hydration/ValueHydrator.php index a9e74eeb..8b82509a 100644 --- a/Doctrine/Hydration/ValueHydrator.php +++ b/Doctrine/Hydration/ValueHydrator.php @@ -26,7 +26,7 @@ public function hydrate($document, MetaInformationInterface $metaInformation) // skip field if value is array or "flat" object // hydrated object should contain a list of real entities / entity - if ($this->isComplexValue($property, $value)) { + if ($this->isComplexValue($property, $value, $metaInformation)) { continue; } @@ -104,12 +104,16 @@ private function toCamelCase($fieldname) /** * @return bool */ - public function isComplexValue($fieldName, $value) + public function isComplexValue($fieldName, $value, MetaInformationInterface $metaInformation) { if (is_array($value)) { return true; } + if ($metaInformation->getField($fieldName) && $metaInformation->getField($fieldName)->getter) { + return true; + } + $fieldSuffix = $this->removePrefixedKeyFieldName($fieldName); if ($fieldSuffix === false) { return false; From 1ccc4a8bdfeeaef1864fd4ae4f41470e583364cc Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 25 Mar 2016 11:43:21 +0100 Subject: [PATCH 110/332] fix query test --- Tests/Query/SolrQueryTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Query/SolrQueryTest.php b/Tests/Query/SolrQueryTest.php index 111892d5..543ceb3d 100644 --- a/Tests/Query/SolrQueryTest.php +++ b/Tests/Query/SolrQueryTest.php @@ -166,7 +166,7 @@ public function testGetQuery_NoWildcard_Word() $solrQuery->setUseWildcard(false); $solrQuery->addSearchTerm('title', 'a_word'); - $expected = 'title_s:"a_word"'; + $expected = 'title_s:a_word'; $this->assertEquals($expected, $solrQuery->getQuery()); } From 271a18c448f3152d663c54da457bfa31f7f56468 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 25 Mar 2016 13:06:43 +0100 Subject: [PATCH 111/332] consistent command naming --- Command/SynchronizeIndexCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Command/SynchronizeIndexCommand.php b/Command/SynchronizeIndexCommand.php index 0d1f9c29..79f1cd0f 100644 --- a/Command/SynchronizeIndexCommand.php +++ b/Command/SynchronizeIndexCommand.php @@ -19,7 +19,7 @@ class SynchronizeIndexCommand extends ContainerAwareCommand */ protected function configure() { - $this->setName('solr:synchronize') + $this->setName('solr:input:populate') ->addArgument('entity', InputArgument::REQUIRED, 'The entity you want to index') ->addOption( 'source', From e6b61be475f7e9335168d0358f592afd2ae157de Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 25 Mar 2016 13:07:07 +0100 Subject: [PATCH 112/332] consistent command naming --- Command/SynchronizeIndexCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Command/SynchronizeIndexCommand.php b/Command/SynchronizeIndexCommand.php index 79f1cd0f..8ba78493 100644 --- a/Command/SynchronizeIndexCommand.php +++ b/Command/SynchronizeIndexCommand.php @@ -19,7 +19,7 @@ class SynchronizeIndexCommand extends ContainerAwareCommand */ protected function configure() { - $this->setName('solr:input:populate') + $this->setName('solr:index:populate') ->addArgument('entity', InputArgument::REQUIRED, 'The entity you want to index') ->addOption( 'source', From f7d0af5806b7cb7b5c52f6c2fc1cda8141d88f5c Mon Sep 17 00:00:00 2001 From: floriansemm Date: Fri, 25 Mar 2016 13:54:37 +0100 Subject: [PATCH 113/332] cleanup document, add description for new features --- README.md | 188 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 110 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 5e3671ea..761c5325 100644 --- a/README.md +++ b/README.md @@ -48,21 +48,15 @@ public function registerBundles() # app/config/config.yml fs_solr: endpoints: - core1: + core0: host: host port: 8983 - path: /solr/core1 - core: corename - timeout: 5 - core2: - host: host - port: 8983 - path: /solr/core2 + path: /solr/core0 core: corename timeout: 5 ``` -With this config you can setup two cores: `core1` and `core2`. See section `Specify cores` for more information. +See section `Specify cores` for more detaild information about how to setup cores. ## Usage @@ -116,45 +110,26 @@ class Post } ``` -### Supported field types - -Currently is a basic set of types implemented. - -- string -- text -- date -- integer -- float -- double -- long -- boolean +## `@Solr\Document` annotation -It is possible to use custom field types (schema.xml). +Entities must have this annotation to mark them as document. -### Filter annotation +### Setup custom repository class -In some cases a entity should not be index. For this you have the `SynchronizationFilter` Annotation. +If you specify your own repository you must extend the `FS\SolrBundle\Repository\Repository` class. ```php /** - * @Solr\Document - * @Solr\SynchronizationFilter(callback="shouldBeIndex") + * @Solr\Document(repository="My/Custom/Repository") */ class SomeEntity { - /** - * @return boolean - */ - public function shouldBeIndex() - { - // put your logic here - } + // ... } ``` -The callback property specifies an callable function, which decides whether the should index or not. -### Specify cores +### Specify a core for a document It is possible to specify a core dedicated to a document @@ -189,34 +164,110 @@ class SomeEntity Each core must setup up in the config.yml under `endpoints`. If you leave the `index` or `indexHandler` property empty, then a default core will be used (first in the `endpoints` list). To index a document in all cores use `*` as index value: +## `@Solr\Field` annotation + +Add this annotation with a type to a property an the value will be indexed. + +### Supported simple field types + +Currently is a basic set of types implemented. + +- string(s) +- text(s) +- date(s) +- integer(s) +- float(s) +- double(s) +- long(s) +- boolean(s) + +### Object relations + +Indexing of relations works in simplified way. Related entities will not indexed as a new document only a searchable value. +Related entity do not need a `@Solr\Document` annotation. + +#### ManyToOne relation + ```php -@Solr\Document(index="*") +/** + * @var Category + * + * @Solr\Field(type="string", getter="getTitle") + * + * @ORM\ManyToOne(targetEntity="Acme\DemoBundle\Entity\Category", inversedBy="posts", cascade={"persist"}) + * @ORM\JoinColumn(name="category_id", referencedColumnName="id") + */ +private $category; ``` -### Solr field configuration +Related entity: + +```php +class Category +{ + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } +} +``` + +#### OneToMany relation + +To index a set of objects it is important to use the fieldtype `strings`. -Solr comes with a set of predefined field-name/field-types mapping: +```php +/** + * @var Tag[] + * + * @Solr\Field(type="strings", getter="getName") + * @ORM\OneToMany(targetEntity="Acme\DemoBundle\Entity\Tag", mappedBy="post", cascade={"persist"}) + */ +private $tags; +``` + +Related entity: -- title (solr-type: general_text) -- text (solr-type: general_text) -- category (solr-type: general_text) -- content_type (solr-type: string) +```php +class Tag +{ + /** + * @return string + */ + public function getName() + { + return $this->name; + } +} +``` -For details have a look into your schema.xml. +### `@Solr\SynchronizationFilter(callback="shouldBeIndex")` annotation -So if you have an entity with a property "category", then you don't need a type-declaration in the annotation: +In some cases a entity should not be index. For this you have the `SynchronizationFilter` annotation to run a filter-callback. ```php /** - * @Solr\Field - * @ORM\Column(name="category", type="text") + * // .... + * @Solr\SynchronizationFilter(callback="shouldBeIndex") */ -private $category = ''; +class SomeEntity +{ + /** + * @return boolean + */ + public function shouldBeIndex() + { + // put your logic here + } +} ``` -The field has in this case automaticaly the type "general_text". +The callback property specifies an callable function, which decides whether the should index or not. -If you persist this entity, it will put automatically to the index. Update and delete happens automatically too. +## Queries ### Query a field of a document @@ -229,8 +280,13 @@ $query->addSearchTerm('title', 'my title'); $result = $query->getResult(); ``` -The $result array contains all found entities. The solr-service does all mappings from SolrDocument -to your entity for you. +or + +```php +$posts = $this->get('solr.client')->getRepository('AcmeDemoBundle:Post')->findOneBy(array( + 'title' => 'my title' +)); +``` ### Query all fields of a document @@ -290,34 +346,10 @@ public function find($id) } ``` -### Index manually an entity - -To index your entities manually, you can do it the following way: - -```php -$this->get('solr.client')->addDocument($entity); -$this->get('solr.client')->updateDocument($entity); -$this->get('solr.client')->removeDocument($entity); -``` - -`removeDocument()` requires that the entity-id is set. - -### Use document repositories - -If you specify your own repository you must extend the `FS\SolrBundle\Repository\Repository` class. The usage is the same -like Doctrine-Repositories: - -```php -$myRepository = $this->get('solr.client')->getRepository('AcmeDemoBundle:Post'); -$result = $myRepository->mySpecialFindMethod(); -``` - -If you haven't declared a concrete repository in your entity and you calling `$this->get('solr.client')->getRepository('AcmeDemoBundle:Post')`, you will -get an instance of `FS\SolrBundle\Repository\Repository`. - -### Commands +## Commands There are two commands with this bundle: * `solr:index:clear` - delete all documents in the index -* `solr:synchronize` - synchronize the db with the index +* `solr:index:populate` - synchronize the db with the index +* `solr:schema:show` - shows your configured documents From 983bb549899c0bdd45d1dbbf10444cb5a33f84ff Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 26 Mar 2016 13:56:02 +0100 Subject: [PATCH 114/332] more docu cleanup --- README.md | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 761c5325..81771b43 100644 --- a/README.md +++ b/README.md @@ -56,22 +56,17 @@ fs_solr: timeout: 5 ``` -See section `Specify cores` for more detaild information about how to setup cores. +### Step 4: Configure your entities -## Usage - -### Annotations - -To put an entity to the index, you must add some annotations to your entity: +To put an entity to the index, you must add some annotations to your entity. Basic configuration requires two annoations: +`@Solr\Document()`, `@Solr\Id()`. This two annotations makes a entity indexable. To index data add `@Solr\Field()` to your properties. ```php -// your Entity - // .... use FS\SolrBundle\Doctrine\Annotation as Solr; /** -* @Solr\Document(repository="Full\Qualified\Class\Name") +* @Solr\Document() * @ORM\Table() */ class Post @@ -83,10 +78,9 @@ class Post * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ - private $id; + /** - * * @Solr\Field(type="string") * * @ORM\Column(name="title", type="string", length=255) @@ -94,7 +88,6 @@ class Post private $title = ''; /** - * * @Solr\Field(type="string") * * @ORM\Column(name="text", type="text") @@ -110,6 +103,8 @@ class Post } ``` +# Annotation reference + ## `@Solr\Document` annotation Entities must have this annotation to mark them as document. @@ -128,8 +123,7 @@ class SomeEntity } ``` - -### Specify a core for a document +### `index` property It is possible to specify a core dedicated to a document @@ -143,6 +137,8 @@ class SomeEntity } ``` +### `indexHandler` property + All documents will be indexed in the core `core0`. If your entities/document have different languages then you can setup a callback method, which returns the preferred core for the entity. @@ -164,6 +160,25 @@ class SomeEntity Each core must setup up in the config.yml under `endpoints`. If you leave the `index` or `indexHandler` property empty, then a default core will be used (first in the `endpoints` list). To index a document in all cores use `*` as index value: +## `@Solr\Id` annotation + +This is required for entites to index them. The annotation has no futher properties. + +```php +class Post +{ + /** + * @Solr\Id + * + * @ORM\Column(name="id", type="integer") + * @ORM\Id + * @ORM\GeneratedValue(strategy="AUTO") + */ + + private $id; +} +``` + ## `@Solr\Field` annotation Add this annotation with a type to a property an the value will be indexed. @@ -224,6 +239,7 @@ To index a set of objects it is important to use the fieldtype `strings`. * @var Tag[] * * @Solr\Field(type="strings", getter="getName") + * * @ORM\OneToMany(targetEntity="Acme\DemoBundle\Entity\Tag", mappedBy="post", cascade={"persist"}) */ private $tags; From 66329f0cc8d46c4f812cb191ddad6717bac60182 Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 26 Mar 2016 13:58:45 +0100 Subject: [PATCH 115/332] more docu cleanup --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 81771b43..dccd9152 100644 --- a/README.md +++ b/README.md @@ -107,9 +107,9 @@ class Post ## `@Solr\Document` annotation -Entities must have this annotation to mark them as document. +Entities must have this annotation to mark them as document. It has two optional properties: `repository`, `index`, `indexHandler` -### Setup custom repository class +### Setup custom repository class with `repository` option If you specify your own repository you must extend the `FS\SolrBundle\Repository\Repository` class. From b893fa29bca25988d9d70952feb1a5f2f8ca707b Mon Sep 17 00:00:00 2001 From: Zachary Quintana Date: Thu, 28 Jan 2016 13:51:29 -0800 Subject: [PATCH 116/332] added DataCollector support from #117 --- DataCollector/RequestCollector.php | 100 +++++++++++ Logging/DebugLogger.php | 62 +++++++ Logging/LoggerChain.php | 52 ++++++ Logging/SolrLoggerInterface.php | 34 ++++ Plugin/LoggerPlugin.php | 89 ++++++++++ Query/ResultSet.php | 58 +++--- Resources/config/services.xml | 34 +++- Resources/views/Profiler/icon.svg | 1 + Resources/views/Profiler/solr.html.twig | 227 ++++++++++++++++++++++++ 9 files changed, 629 insertions(+), 28 deletions(-) create mode 100644 DataCollector/RequestCollector.php create mode 100644 Logging/DebugLogger.php create mode 100644 Logging/LoggerChain.php create mode 100644 Logging/SolrLoggerInterface.php create mode 100644 Plugin/LoggerPlugin.php create mode 100644 Resources/views/Profiler/icon.svg create mode 100644 Resources/views/Profiler/solr.html.twig diff --git a/DataCollector/RequestCollector.php b/DataCollector/RequestCollector.php new file mode 100644 index 00000000..0b468fb4 --- /dev/null +++ b/DataCollector/RequestCollector.php @@ -0,0 +1,100 @@ +logger = $logger; + } + + /** + * @param Request $request + * @param Response $response + * @param \Exception|null $exception + */ + public function collect(Request $request, Response $response, \Exception $exception = null) + { + $this->data = [ + 'queries' => array_map(function ($query) { + return $this->parseQuery($query); + }, $this->logger->getQueries()) + ]; + } + + /** + * @return int + */ + public function getQueryCount() + { + return count($this->data['queries']); + } + + /** + * @return array + */ + public function getQueries() + { + return $this->data['queries']; + } + + /** + * @return int + */ + public function getTime() + { + $time = 0; + foreach ($this->data['queries'] as $query) { + $time += $query['executionMS']; + } + + return $time; + } + + /** + * @param array $request + * + * @return array + */ + public function parseQuery($request) + { + list($endpoint, $params) = explode('?', $request['request']); + + return array_merge($request, [ + 'endpoint' => $endpoint, + 'params' => $params + ]); + } + + /** + * @param DebugLogger $logger + */ + public function setLogger(DebugLogger $logger) + { + $this->logger = $logger; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'solr'; + } +} \ No newline at end of file diff --git a/Logging/DebugLogger.php b/Logging/DebugLogger.php new file mode 100644 index 00000000..b657f96e --- /dev/null +++ b/Logging/DebugLogger.php @@ -0,0 +1,62 @@ +queries; + } + + /** + * {@inheritdoc} + */ + public function startRequest($request) + { + $this->start = microtime(true); + $this->queries[++$this->currentQuery] = [ + 'request' => $request, + 'executionMS' => 0 + ]; + } + + /** + * {@inheritdoc} + */ + public function stopRequest() + { + $this->queries[$this->currentQuery]['executionMS'] = microtime(true) - $this->start; + } +} \ No newline at end of file diff --git a/Logging/LoggerChain.php b/Logging/LoggerChain.php new file mode 100644 index 00000000..e100bfd6 --- /dev/null +++ b/Logging/LoggerChain.php @@ -0,0 +1,52 @@ +loggers, $logger); + } + + /** + * {@inheritdoc} + */ + public function startRequest($request) + { + foreach ($this->loggers as $logger) { + $logger->startRequest($request); + } + } + + /** + * {@inheritdoc} + */ + public function stopRequest() + { + foreach ($this->loggers as $logger) { + $logger->stopRequest(); + } + } +} \ No newline at end of file diff --git a/Logging/SolrLoggerInterface.php b/Logging/SolrLoggerInterface.php new file mode 100644 index 00000000..04bb3619 --- /dev/null +++ b/Logging/SolrLoggerInterface.php @@ -0,0 +1,34 @@ +client->getEventDispatcher(); + $dispatcher->addListener(Events::PRE_EXECUTE_REQUEST, [$this, 'preExecuteRequest']); + $dispatcher->addListener(Events::POST_EXECUTE_REQUEST, [$this, 'postExecuteRequest']); + } + + /** + * @param PreExecuteRequest $event + */ + public function preExecuteRequest(PreExecuteRequest $event) + { + $this->getLogger()->startRequest($event->getRequest()->getUri()); + } + + /** + * Issue stop logger + */ + public function postExecuteRequest() + { + $this->getLogger()->stopRequest(); + } + + /** + * Client getter + * + * @return \Solarium\Core\Client\Client + */ + public function getClient() + { + return $this->client; + } + + /** + * @param SolrLoggerInterface $logger + * + * @return $this + */ + public function setLogger(SolrLoggerInterface $logger) + { + $this->logger = $logger; + + return $this; + } + + /** + * Logger getter + * + * @return SolrLoggerInterface + */ + public function getLogger() + { + return $this->logger; + } +} \ No newline at end of file diff --git a/Query/ResultSet.php b/Query/ResultSet.php index 8a97a7d4..d705bbb2 100644 --- a/Query/ResultSet.php +++ b/Query/ResultSet.php @@ -12,7 +12,12 @@ use FS\SolrBundle\Doctrine\Mapper\EntityMapper; use Solarium\QueryType\Select\Result\Result; -class ResultSet implements \ArrayAccess, \Countable +/** + * Class ResultSet + * + * @package FS\SolrBundle\Query + */ +class ResultSet implements \ArrayAccess { /** @@ -30,27 +35,30 @@ class ResultSet implements \ArrayAccess, \Countable */ private $total = 0; - /** - * @param object $entity - * @param EntityMapper $mapper - * @param Result $response - */ - public function __construct($entity, EntityMapper $mapper = null, \IteratorAggregate $response = null) + + public function __construct($entity, EntityMapper $mapper=null, Result $response=null) { - $this->response = $response; - if ($response !== null) { - $this->total = $response->getNumFound(); + if ($mapper === null || $response === null) { + return $this; + } + + $this->total = $response->getNumFound(); + if ($this->total == 0) { + return $this; } - $this->entities = array(); - if ($response !== null) { - foreach ($response as $document) { - $this->entities[] = $mapper->toEntity($document, $entity); - } + $mappedEntities = array(); + foreach ($response as $document) { + $mappedEntities[] = $mapper->toEntity($document, $entity); } + + $this->entities = $mappedEntities; + $this->response = $response; } /** + * Response getter + * * @return Result */ public function getResponse() @@ -59,6 +67,8 @@ public function getResponse() } /** + * Entities getter + * * @return array */ public function getEntities() @@ -67,11 +77,17 @@ public function getEntities() } /** + * Entities setter + * * @param array $entities + * + * @return ResultSet $this */ public function setEntities($entities) { $this->entities = $entities; + + return $this; } /** @@ -89,10 +105,6 @@ public function offsetSet($offset, $value) */ public function offsetGet($offset) { - if (count($this->entities) === 0) { - throw new \OutOfBoundsException(sprintf('Index %s is not defined', $offset)); - } - return $this->entities[$offset]; } @@ -128,12 +140,4 @@ public function __toArray() { return $this->toArray(); } - - /** - * {@inheritdoc} - */ - public function count() - { - return count($this->entities); - } } \ No newline at end of file diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 5cc8b46e..b6232d0a 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -22,6 +22,11 @@ FS\SolrBundle\Console\ConsoleCommandResults FS\SolrBundle\Event\Listener\SynchronizationSummaryListener FS\SolrBundle\Console\ConsoleResultFactory + + FS\SolrBundle\Plugin\LoggerPlugin + FS\SolrBundle\Logging\LoggerChain + FS\SolrBundle\Logging\DebugLogger + FS\SolrBundle\DataCollector\SolrRequestCollector @@ -33,10 +38,33 @@ - + + + SolrBundleLogger + + + + + + + + + + + + + + + + + + + + + @@ -95,5 +123,9 @@ + + + + diff --git a/Resources/views/Profiler/icon.svg b/Resources/views/Profiler/icon.svg new file mode 100644 index 00000000..7ca1aeca --- /dev/null +++ b/Resources/views/Profiler/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Resources/views/Profiler/solr.html.twig b/Resources/views/Profiler/solr.html.twig new file mode 100644 index 00000000..599ae903 --- /dev/null +++ b/Resources/views/Profiler/solr.html.twig @@ -0,0 +1,227 @@ +{% extends app.request.isXmlHttpRequest ? '@WebProfiler/Profiler/ajax_layout.html.twig' : '@WebProfiler/Profiler/layout.html.twig' %} + +{% block toolbar %} + {% set profiler_markup_version = profiler_markup_version|default(1) %} + + {% set icon %} + {% if profiler_markup_version == 1 %} + + Solr + {{ collector.querycount }} + {% if collector.querycount > 0 %} + in {{ '%0.2f'|format(collector.time * 1000) }} ms + {% endif %} + + {% else %} + + {% if collector.querycount > 0 %} + {% set status = collector.querycount > 50 ? 'yellow' %} + + {{ include('@FSSolrBundle/Collector/icon.svg') }} + + {{ collector.querycount }} + + in + {{ '%0.2f'|format(collector.time * 1000) }} + ms + + {% endif %} + + {% endif %} + {% endset %} + + {% set text %} +

+
+ Query time + {{ '%0.2f'|format(collector.time * 1000) }} ms +
+ {% endset %} + + {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status|default('') }) }} +{% endblock %} + +{% block menu %} + {% set profiler_markup_version = profiler_markup_version|default(1) %} + + {% if profiler_markup_version == 1 %} + + + + Solr + + {{ collector.querycount }} + {{ '%0.0f'|format(collector.time * 1000) }} ms + + + + {% else %} + + + {{ include('@FSSolrBundle/Collector/icon.svg') }} + Solr + + + {% endif %} +{% endblock %} + +{% block panel %} + {% set profiler_markup_version = profiler_markup_version|default(1) %} + + {{ block('queries') }} +{% endblock %} + +{% block queries %} + {% if profiler_markup_version == 1 %} + + {% endif %} + +

Queries

+ + {% if collector.queries is empty %} +
+

No solr queries were performed.

+
+ {% else %} + + + + + + + + + + + {% for i, query in collector.queries %} + + + + + + + {% endfor %} + +
#Time + End Point + Parameters
{{ loop.index }}{{ '%0.2f'|format(query.executionMS * 1000) }} ms + {{ query.endpoint }} + + {{ query.params | solr_pretty_params }} +
+ {% endif %} + + {#

Entities Mapping

#} + + {#{% for manager, classes in collector.entities %}#} + {#{% if collector.managers|length > 1 %}#} + {#

{{ manager }} entity manager

#} + {#{% endif %}#} + + {#{% if classes is empty %}#} + {#
#} + {#

No loaded entities.

#} + {#
#} + {#{% else %}#} + {##} + {##} + {##} + {##} + {##} + {##} + {##} + {##} + {#{% for class in classes %}#} + {#{% set contains_errors = collector.mappingErrors[manager] is defined and collector.mappingErrors[manager][class] is defined %}#} + {##} + {##} + {##} + {##} + {#{% endfor %}#} + {##} + {#
ClassMapping errors
{{ class }}#} + {#{% if contains_errors %}#} + {#
    #} + {#{% for error in collector.mappingErrors[manager][class] %}#} + {#
  • {{ error }}
  • #} + {#{% endfor %}#} + {#
#} + {#{% else %}#} + {#No errors.#} + {#{% endif %}#} + {#
#} + {#{% endif %}#} + {#{% endfor %}#} + + +{% endblock %} From 806f0ae0cda5cbefe985ee7739ee1267ca788b4e Mon Sep 17 00:00:00 2001 From: floriansemm Date: Sat, 26 Mar 2016 16:29:55 +0100 Subject: [PATCH 117/332] added DataCollector support from #117 --- Logging/DebugLogger.php | 13 ------ Logging/LoggerChain.php | 13 ------ Logging/SolrLoggerInterface.php | 12 ------ Plugin/LoggerPlugin.php | 29 +++---------- Resources/config/services.xml | 6 +-- Resources/views/Profiler/icon.svg | 8 +++- Resources/views/Profiler/solr.html.twig | 54 +++---------------------- 7 files changed, 19 insertions(+), 116 deletions(-) diff --git a/Logging/DebugLogger.php b/Logging/DebugLogger.php index b657f96e..abdc0dfd 100644 --- a/Logging/DebugLogger.php +++ b/Logging/DebugLogger.php @@ -1,19 +1,7 @@ getLogger()->startRequest($event->getRequest()->getUri()); + $endpoint = $event->getEndpoint(); + $uri = $event->getRequest()->getUri(); + + $path = sprintf('%s://%s:%s%s/%s', $endpoint->getScheme(), $endpoint->getHost(), $endpoint->getPort(), $endpoint->getPath(), urldecode($uri)); + + $this->getLogger()->startRequest($path); } /** @@ -56,8 +47,6 @@ public function postExecuteRequest() } /** - * Client getter - * * @return \Solarium\Core\Client\Client */ public function getClient() @@ -67,19 +56,13 @@ public function getClient() /** * @param SolrLoggerInterface $logger - * - * @return $this */ public function setLogger(SolrLoggerInterface $logger) { $this->logger = $logger; - - return $this; } /** - * Logger getter - * * @return SolrLoggerInterface */ public function getLogger() diff --git a/Resources/config/services.xml b/Resources/config/services.xml index b6232d0a..763a2b5d 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -26,7 +26,7 @@ FS\SolrBundle\Plugin\LoggerPlugin FS\SolrBundle\Logging\LoggerChain FS\SolrBundle\Logging\DebugLogger - FS\SolrBundle\DataCollector\SolrRequestCollector + FS\SolrBundle\DataCollector\RequestCollector @@ -123,9 +123,5 @@ - - - - diff --git a/Resources/views/Profiler/icon.svg b/Resources/views/Profiler/icon.svg index 7ca1aeca..3567873c 100644 --- a/Resources/views/Profiler/icon.svg +++ b/Resources/views/Profiler/icon.svg @@ -1 +1,7 @@ - \ No newline at end of file + + + + + + + \ No newline at end of file diff --git a/Resources/views/Profiler/solr.html.twig b/Resources/views/Profiler/solr.html.twig index 599ae903..ce17dbfd 100644 --- a/Resources/views/Profiler/solr.html.twig +++ b/Resources/views/Profiler/solr.html.twig @@ -17,7 +17,7 @@ {% if collector.querycount > 0 %} {% set status = collector.querycount > 50 ? 'yellow' %} - {{ include('@FSSolrBundle/Collector/icon.svg') }} + {{ include('@FSSolr/Profiler/icon.svg') }} {{ collector.querycount }} @@ -61,7 +61,7 @@ {% else %} - {{ include('@FSSolrBundle/Collector/icon.svg') }} + {{ include('@FSSolr/Profiler/icon.svg') }} Solr @@ -105,10 +105,8 @@ # Time - - End Point - - Parameters + End Point + Parameters @@ -120,7 +118,7 @@ {{ query.endpoint }} - {{ query.params | solr_pretty_params }} + {{ query.params | replace({'&': "
"}) | raw }} {% endfor %} @@ -128,48 +126,6 @@ {% endif %} - {#

Entities Mapping

#} - - {#{% for manager, classes in collector.entities %}#} - {#{% if collector.managers|length > 1 %}#} - {#

{{ manager }} entity manager

#} - {#{% endif %}#} - - {#{% if classes is empty %}#} - {#
#} - {#

No loaded entities.

#} - {#
#} - {#{% else %}#} - {##} - {##} - {##} - {##} - {##} - {##} - {##} - {##} - {#{% for class in classes %}#} - {#{% set contains_errors = collector.mappingErrors[manager] is defined and collector.mappingErrors[manager][class] is defined %}#} - {##} - {##} - {##} - {##} - {#{% endfor %}#} - {##} - {#
ClassMapping errors
{{ class }}#} - {#{% if contains_errors %}#} - {#
    #} - {#{% for error in collector.mappingErrors[manager][class] %}#} - {#
  • {{ error }}
  • #} - {#{% endfor %}#} - {#
#} - {#{% else %}#} - {#No errors.#} - {#{% endif %}#} - {#
#} - {#{% endif %}#} - {#{% endfor %}#} -