Skip to content
Browse files

Merge pull request #80 from MrHash/master

Update to documentation and minor serialization update
  • Loading branch information...
2 parents 35e1ecc + 36165ce commit 8b761a81045e659dcd88fbc6f62e629079c06a48 @Baachi Baachi committed Sep 22, 2013
View
218 README.markdown
@@ -1,56 +1,204 @@
# Doctrine Search #
-Note: This project is a prototype at the moment.
+Note: This project is a prototype at the moment.
__Supported search engines__
-* [ElasticSearch](http://www.elasticsearch.org/)
-* [Solr](http://lucene.apache.org/solr/)
-* [ZendLucene](http://framework.zend.com/manual/en/zend.search.lucene.html)
+* [ElasticSearch](http://www.elasticsearch.org/) (functional)
+* [Solr](http://lucene.apache.org/solr/) (partial implementation)
+* [ZendLucene](http://framework.zend.com/manual/en/zend.search.lucene.html) (partial implementation)
-## Todo convert this into items ##
-* SearchService
- * aggregates a ObjectManager instance: $searchManager = new SearchManager($objectManager);
- * supports direct API calls (Solr, Lucene, ... Adapter useable)
- * transforms returned ID"s via batch operation into objects
-* EventListener for indexing, new SearchIndexListener($backendAdapter);
-* uses ObjectManager::getClassMetadata() as the base structure
-* adds new Annotationen for more complexe configuration needs
+__Features__
+* SearchManager
+ * Can be used stand-alone or in a hybrid configuration
+ * Configurable search manager supports aggregate entity manager
+ * supports direct API calls through search engine adapters such as Elastica
+ * transforms returned ID's via batch operation into hydrated objects as required
+* Support for indexing through event listeners via JMS Serializer or simple entity callback.
+* Annotations for index and data type creation using ObjectManager::getClassMetadata() as the base structure
-## Usage ##
+#Usage#
+## Configuration ##
+The search manager connection can be configured as shown in the following example:
+```php
+$config = new Doctrine\Search\Configuration();
+$config->setMetadataCacheImpl(new Doctrine\Common\Cache\ArrayCache());
+$config->setEntitySerializer(
+ new Doctrine\Search\Serializer\JMSSerializer(
+ JMS\Serializer\SerializationContext::create()->setGroups('search')
+ )
+);
+
+$searchManager = new Doctrine\Search\SearchManager(
+ $config,
+ new Doctrine\Search\ElasticSearch\Client(
+ new Elastica\Client(array(
+ array('host' => 'localhost', 'port' => '9200')
+ )
+ )
+);
+```
+
+## Mappings ##
+Basic entity mappings for index and type generation can be annotated as shown in the following example. Mappings
+can be rendered into a format suitable for automatically generating indexes and types using a build script
+(advanced setup required).
```php
<?php
namespace Entities;
-use Doctrine\Search\Mapping\Annotation as Search;
+use Doctrine\Search\Mapping\Annotations as MAP;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
- * @Search\Searchable
+ * @MAP\ElasticSearchable(index="indexname", type="post", source=true)
*/
class Post
{
- /**
- * @var integer
- * @ORM\Id @ORM\GeneratedValue(strategy="AUTO")
- */
- public $id;
-
- /**
- * @var string
- * @ORM\Column(type="string")
- * @Search\Field
- */
- public $title;
-
- /**
- * @var string
- * @ORM\Column(type="text")
- * @Search\Field
- * @Search\SolrField
- */
- public $content;
+ /**
+ * @ORM\Id
+ * @ORM\GeneratedValue(strategy="AUTO")
+ * @MAP\ElasticField(type="integer", includeInAll=false)
+ */
+ private $id;
+
+ /**
+ * @ORM\Column(type="string")
+ * @MAP\ElasticField(type="string", includeInAll=true, boost=5.0)
+ */
+ private $title;
+
+ /**
+ * @ORM\Column(type="text")
+ * @MAP\ElasticField(type="string", includeInAll=true)
+ */
+ private $content;
+
+ /**
+ * @MAP\ElasticField(name="tags", type="string", includeInAll=false, index="not_analyzed")
+ */
+ public function getTags() {
+ return $this->tags->slice(0,3);
+ }
}
+```
+
+## Indexing ##
+Documents can be serialized for indexing currently in the following ways. If required an event listener can
+be used with your ORM as shown in this example. If an event listener is not needed, entities can be persisted
+or removed directly using the search manager.
+```php
+<?php
+namespace Entities\Listener;
+
+use Doctrine\ORM\Event\LifecycleEventArgs;
+use Entities\Behaviour\SearchableEntityInterface;
+
+class SearchableListener implements
+{
+ protected function getSearchManager() {
+ return $this->getDatabaseConnection('elasticsearch');
+ }
+
+ public function postPersist(LifecycleEventArgs $oArgs) {
+ $oEntity = $oArgs->getEntity();
+ if($oEntity instanceof SearchableEntityInterface) {
+ $this->getSearchManager()->persist($oEntity);
+ }
+ }
+
+ public function postRemove(LifecycleEventArgs $oArgs) {
+ $oEntity = $oArgs->getEntity();
+ if($oEntity instanceof SearchableEntityInterface) {
+ $this->getSearchManager()->remove($oEntity);
+ }
+ }
+}
+```
+
+### CallbackSerializer ###
+This approach simply expects a `toArray()` method on the entity, although this method be configured as required.
+The interface suggested in this example can be any interface you desire, as long as your event listener can identify
+entities that need to be persisted to the search engine (see above example).
+```php
+...
+use Entities\Behaviour\SearchableEntityInterface
+
+class Post implements SearchableEntityInterface
+{
+ ...
+ public function toArray() {
+ return array(
+ 'id' => $this->id,
+ 'title' => $this->title,
+ 'content' => $this->content
+ ...
+ );
+ }
+}
+```
+
+### JMS Serializer ###
+You can alternatively use the advanced serialization power of the `JMS Serializer` to automatically handle
+serialization for you based on annotations such as those shown in this example.
+```php
+...
+use JMS\Serializer\Annotation as JMS;
+use Entities\Behaviour\SearchableEntityInterface
+
+/**
+ * @ORM\Entity
+ * @MAP\ElasticSearchable(index="indexname", type="post", source=true)
+ * @JMS\ExclusionPolicy("all")
+ */
+class Post implements SearchableEntityInterface
+{
+ ...
+ /**
+ * @ORM\Column(type="string")
+ * @MAP\ElasticField(type="string", includeInAll=true, boost=5.0)
+ * @JMS\Expose
+ * @JMS\Groups({"public", "search"})
+ */
+ private $title;
+
+ /**
+ * @ORM\Column(type="text")
+ * @MAP\ElasticField(type="string", includeInAll=true)
+ * @JMS\Expose
+ * @JMS\Groups({"public", "search"})
+ */
+ private $content;
+ ...
+}
+```
+
+### AnnotationSerializer ###
+Not yet available.
+
+
+## Queries ##
+Queries can be executed through the search manager as shown below. Use of the result cache refers to using the
+cache for the hydration query. Search engine specific adapter interfaces are exposed magically so as in this
+example, `Elastica\Query::addSort` method is amalgamated with `Doctrine\Search\Query` methods. Thus any complexity
+of query supported by the search engine client library is supported.
+```php
+$hydrationQuery = $entityManager->createQueryBuilder()
+ ->select(array('p', 'field(p.id, :ids) as HIDDEN field'))
+ ->from('Entities\Post', 'p')
+ ->where('p.id IN (:ids)')
+ ->orderBy('field')
+ ->getQuery();
+
+$query = $searchManager->createQuery()
+ ->from('Entities\Post')
+ ->searchWith(new Elastica\Query())
+ ->hydrateWith($hydrationQuery)
+ ->addSort('_score')
+ ->setFrom(0)
+ ->setLimit(10)
+ ->getResult();
+```
View
24 lib/Doctrine/Search/Configuration.php
@@ -82,7 +82,9 @@ public function setMetadataCacheImpl(Cache $concreteCache)
*/
public function getMetadataCacheImpl()
{
- return isset($this->attributes['metadataCacheImpl']) ? $this->attributes['metadataCacheImpl'] : new ArrayCache();
+ return isset($this->attributes['metadataCacheImpl'])
+ ? $this->attributes['metadataCacheImpl']
+ : new ArrayCache();
}
/**
@@ -139,40 +141,42 @@ public function getClassMetadataFactory()
/**
* Sets an entity serializer
- *
+ *
* @param SerializerInterface $serializer
*/
public function setEntitySerializer(SerializerInterface $serializer)
{
$this->attributes['serializer'] = $serializer;
}
-
+
/**
* Gets the entity serializer or provides a default if not set
- *
+ *
* @return SerializerInterface
*/
public function getEntitySerializer()
{
- if(isset($this->attributes['serializer'])) {
- return $this->attributes['serializer'];
+ if (isset($this->attributes['serializer'])) {
+ return $this->attributes['serializer'];
}
return new CallbackSerializer();
}
-
+
/**
* @param ObjectManager $entityManager
*/
public function setEntityManager(ObjectManager $entityManager)
{
$this->attributes['entityManager'] = $serializer;
}
-
+
/**
* @return ObjectManager
*/
public function getEntityManager()
{
- if(isset($this->attributes['entityManager'])) return $this->attributes['entityManager'];
+ if (isset($this->attributes['entityManager'])) {
+ return $this->attributes['entityManager'];
+ }
}
-}
+}
View
122 lib/Doctrine/Search/ElasticSearch/Client.php
@@ -57,34 +57,33 @@ public function __construct(ElasticaClient $client)
public function addDocuments($index, $type, array $documents)
{
$type = $this->getIndex($index)->getType($type);
-
+
$batch = array();
- foreach($documents as $id => $document)
- {
+ foreach ($documents as $id => $document) {
$batch[] = new Document($id, $document);
}
-
+
$type->addDocuments($batch);
}
-
- /**
- * {@inheritDoc}
- */
- public function removeDocuments($index, $type, array $documents)
- {
- $type = $this->getIndex($index)->getType($type);
- $type->deleteIds(array_keys($documents));
+
+ /**
+ * {@inheritDoc}
+ */
+ public function removeDocuments($index, $type, array $documents)
+ {
+ $type = $this->getIndex($index)->getType($type);
+ $type->deleteIds(array_keys($documents));
}
-
- /**
- * {@inheritDoc}
- */
- public function removeAll($index, $type)
- {
+
+ /**
+ * {@inheritDoc}
+ */
+ public function removeAll($index, $type)
+ {
$type = $this->getIndex($index)->getType($type);
- $type->deleteByQuery(new MatchAll());
- }
-
+ $type->deleteByQuery(new MatchAll());
+ }
+
/**
* {@inheritDoc}
*/
@@ -103,67 +102,76 @@ public function createIndex($name, array $config = array())
$index->create($config, true);
return $index;
}
-
+
/**
* {@inheritDoc}
*/
public function getIndex($name)
{
return $this->client->getIndex($name);
}
-
- /**
- * {@inheritDoc}
- */
- public function deleteIndex($index)
- {
- $this->getIndex($index)->delete();
- }
-
+
+ /**
+ * {@inheritDoc}
+ */
+ public function deleteIndex($index)
+ {
+ $this->getIndex($index)->delete();
+ }
+
/**
* {@inheritDoc}
*/
public function createType(ClassMetadata $metadata)
{
- $type = $this->getIndex($metadata->index)->getType($metadata->type);
+ $type = $this->getIndex($metadata->index)->getType($metadata->type);
$properties = $this->getMapping($metadata->fieldMappings);
- $mapping = new Mapping($type, $properties);
+ $mapping = new Mapping($type, $properties);
$mapping->disableSource($metadata->source);
- $mapping->setParam('_boost', array('name' => '_boost', 'null_value' => $metadata->boost));
+ $mapping->setParam('_boost', array('name' => '_boost', 'null_value' => $metadata->boost));
$mapping->send();
-
+
return $type;
}
-
+
/**
* Generates property mapping from entity annotations
- *
+ *
* @param array $fieldMapping
*/
protected function getMapping($fieldMapping)
{
$properties = array();
-
- foreach($fieldMapping as $propertyName => $fieldMapping)
- {
- if(isset($fieldMapping->name)) $propertyName = $fieldMapping->name;
- $properties[$propertyName]['type'] = $fieldMapping->type;
- if(isset($fieldMapping->includeInAll)) $properties[$propertyName]['include_in_all'] = $fieldMapping->includeInAll;
- if(isset($fieldMapping->index)) $properties[$propertyName]['index'] = $fieldMapping->index;
- if(isset($fieldMapping->boost)) $properties[$propertyName]['boost'] = $fieldMapping->boost;
-
- if($fieldMapping->type == 'multi_field' && isset($fieldMapping->fields))
- {
- $properties[$propertyName]['fields'] = $this->getMapping($fieldMapping->fields);
- }
-
- if(in_array($fieldMapping->type, array('nested', 'object')) && isset($fieldMapping->properties))
- {
- $properties[$propertyName]['properties'] = $this->getMapping($fieldMapping->properties);
- }
+
+ foreach ($fieldMapping as $propertyName => $fieldMapping) {
+ if (isset($fieldMapping->name)) {
+ $propertyName = $fieldMapping->name;
+ }
+
+ $properties[$propertyName]['type'] = $fieldMapping->type;
+
+ if (isset($fieldMapping->includeInAll)) {
+ $properties[$propertyName]['include_in_all'] = $fieldMapping->includeInAll;
+ }
+
+ if (isset($fieldMapping->index)) {
+ $properties[$propertyName]['index'] = $fieldMapping->index;
+ }
+
+ if (isset($fieldMapping->boost)) {
+ $properties[$propertyName]['boost'] = $fieldMapping->boost;
+ }
+
+ if ($fieldMapping->type == 'multi_field' && isset($fieldMapping->fields)) {
+ $properties[$propertyName]['fields'] = $this->getMapping($fieldMapping->fields);
+ }
+
+ if (in_array($fieldMapping->type, array('nested', 'object')) && isset($fieldMapping->properties)) {
+ $properties[$propertyName]['properties'] = $this->getMapping($fieldMapping->properties);
+ }
}
-
+
return $properties;
}
-}
+}
View
1 lib/Doctrine/Search/Event/LoadClassMetadataEventArgs.php
@@ -42,5 +42,4 @@ public function getClassMetadata()
{
return $this->classMetadata;
}
-
}
View
1 lib/Doctrine/Search/Exception/Driver/ClassIsNotAValidDocumentException.php
@@ -1,5 +1,6 @@
<?php
namespace Doctrine\Search\Exception\Driver;
+
use Doctrine\Search\Exception\DoctrineSearchException;
class ClassIsNotAValidDocumentException extends DoctrineSearchException
View
1 lib/Doctrine/Search/Exception/Driver/PropertyDoesNotExistsInMetadataException.php
@@ -1,5 +1,6 @@
<?php
namespace Doctrine\Search\Exception\Driver;
+
use Doctrine\Search\Exception\DoctrineSearchException;
class PropertyDoesNotExistsInMetadataException extends DoctrineSearchException
View
3 lib/Doctrine/Search/Exception/UnexpectedTypeException.php
@@ -1,7 +1,7 @@
<?php
namespace Doctrine\Search\Exception;
-use \Doctrine\Search\Exception\DoctrineSearchException;
+use Doctrine\Search\Exception\DoctrineSearchException;
class UnexpectedTypeException extends DoctrineSearchException
{
@@ -16,5 +16,4 @@ public function __construct($value, $expected)
)
);
}
-
}
View
21 lib/Doctrine/Search/Mapping/ClassMetadata.php
@@ -81,17 +81,17 @@ class ClassMetadata implements ClassMetadataInterface
* @var int
*/
public $value = 1;
-
+
/**
* @var boolean
*/
public $source = true;
- /**
- * @var float
- */
- public $boost = 1.0;
-
+ /**
+ * @var float
+ */
+ public $boost = 1.0;
+
/**
* @var string
*/
@@ -140,7 +140,7 @@ public function __sleep()
{
// This metadata is always serialized/cached.
return array(
- 'boost',
+ 'boost',
'className',
'fieldMappings',
'index',
@@ -357,7 +357,7 @@ public function getAssociationMappedByTargetField($assocName)
* @param object $object
* @return array
*/
- function getIdentifierValues($object)
+ public function getIdentifierValues($object)
{
// TODO: Implement getIdentifierValues() method.
}
@@ -367,9 +367,8 @@ function getIdentifierValues($object)
*
* @return array
*/
- function getIdentifierFieldNames()
+ public function getIdentifierFieldNames()
{
// TODO: Implement getIdentifierFieldNames() method.
}
-
-}
+}
View
27 lib/Doctrine/Search/Mapping/Driver/AnnotationDriver.php
@@ -19,12 +19,11 @@
namespace Doctrine\Search\Mapping\Driver;
-use Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver,
- Doctrine\Search\Mapping\Annotations as Search,
- Doctrine\Search\Mapping\ClassMetadata as SearchMetadata,
- Doctrine\Common\Persistence\Mapping\ClassMetadata,
- Doctrine\Search\Exception\Driver as DriverException;
-
+use Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver;
+use Doctrine\Search\Mapping\Annotations as Search;
+use Doctrine\Search\Mapping\ClassMetadata as SearchMetadata;
+use Doctrine\Common\Persistence\Mapping\ClassMetadata;
+use Doctrine\Search\Exception\Driver as DriverException;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
/**
@@ -40,15 +39,15 @@ class AnnotationDriver extends AbstractAnnotationDriver
/**
* Document annotation classes, ordered by precedence.
*/
- static private $documentAnnotationClasses = array(
+ private static $documentAnnotationClasses = array(
'Doctrine\\Search\\Mapping\\Annotations\\Searchable',
'Doctrine\\Search\\Mapping\\Annotations\\ElasticSearchable',
);
/**
* Document fields annotation classes, ordered by precedence.
*/
- static private $documentFieldAnnotationClasses = array(
+ private static $documentFieldAnnotationClasses = array(
'Doctrine\\Search\\Mapping\\Annotations\\Field',
'Doctrine\\Search\\Mapping\\Annotations\\ElasticField',
'Doctrine\\Search\\Mapping\\Annotations\\SolrField',
@@ -107,9 +106,11 @@ private function extractClassAnnotations(\ReflectionClass $reflClass, ClassMetad
//choose only one (the first one)
$annotationClass = $documentsClassAnnotations[0];
$reflClassAnnotations = new \ReflectionClass($annotationClass);
- $metadata = $this->addValuesToMetadata($reflClassAnnotations->getProperties(),
+ $metadata = $this->addValuesToMetadata(
+ $reflClassAnnotations->getProperties(),
$metadata,
- $annotationClass);
+ $annotationClass
+ );
return $metadata;
}
@@ -138,7 +139,7 @@ private function extractPropertiesAnnotations(array $reflProperties, ClassMetada
return $metadata;
}
-
+
/**
* Extract the methods annotations.
*
@@ -163,7 +164,7 @@ private function extractMethodsAnnotations(array $reflMethods, ClassMetadata $me
return $metadata;
}
-
+
/**
* @param \ReflectionProperty[] $reflectedClassProperties
* @param ClassMetadata $metadata
@@ -181,7 +182,7 @@ private function addValuesToMetadata(array $reflectedClassProperties, ClassMetad
if (false === property_exists($metadata, $propertyName)) {
throw new DriverException\PropertyDoesNotExistsInMetadataException($reflectedProperty->getName());
} else {
- if(!is_null($class->$propertyName)) {
+ if (!is_null($class->$propertyName)) {
$metadata->$propertyName = $class->$propertyName;
}
}
View
118 lib/Doctrine/Search/Query.php
@@ -7,63 +7,63 @@
class Query
{
const HYDRATE_BYPASS = -1;
-
+
const HYDRATION_PARAMETER = 'ids';
-
- /**
- * @var SearchManager
+
+ /**
+ * @var SearchManager
*/
- protected $_sm;
-
- /**
- * @var object
+ protected $sm;
+
+ /**
+ * @var object
*/
protected $query;
-
- /**
+
+ /**
* @var object
*/
protected $hydrationQuery;
-
- /**
+
+ /**
* @var string
*/
protected $hydrationParameter = self::HYDRATION_PARAMETER;
- /**
- * @var string
+ /**
+ * @var string
*/
protected $entityClass;
-
- /**
- * @var integer
+
+ /**
+ * @var integer
*/
protected $hydrationMode;
-
- /**
- * @var boolean
+
+ /**
+ * @var boolean
*/
protected $useResultCache;
-
- /**
- * @var integer
+
+ /**
+ * @var integer
*/
protected $cacheLifetime;
-
- /**
- * @var integer
+
+ /**
+ * @var integer
*/
protected $count;
-
+
public function __construct(SearchManager $sm)
{
- $this->_sm = $sm;
+ $this->sm = $sm;
}
-
+
/**
* Magic method to pass query building to the underlying query
* object, saving the need to abstract.
- *
+ *
* @param string $method
* @param array $arguments
*/
@@ -72,21 +72,21 @@ public function __call($method, $arguments)
call_user_func_array(array($this->query, $method), $arguments);
return $this;
}
-
+
/**
* Specifies the searchable entity class to search against.
- *
+ *
* @param string $entityClass
*/
public function from($entityClass)
{
$this->entityClass = $entityClass;
return $this;
}
-
+
/**
* Set the query object to be executed on the search engine
- *
+ *
* @param mixes $query
*/
public function searchWith($query)
@@ -97,25 +97,25 @@ public function searchWith($query)
protected function getSearchManager()
{
- return $this->_sm;
+ return $this->sm;
}
-
+
/**
* Set the hydration mode from the underlying query modes
* or bypass and return search result directly from the client
- *
+ *
* @param integer $mode
*/
public function setHydrationMode($mode)
{
$this->hydrationMode = $mode;
return $this;
}
-
+
/**
* If hydrating with Doctrine then you can use the result cache
* on the default or provided query
- *
+ *
* @param boolean $useCache
* @param integer $cacheLifetime
*/
@@ -125,7 +125,7 @@ public function useResultCache($useCache, $cacheLifetime = null)
$this->cacheLifetime = $cacheLifetime;
return $this;
}
-
+
/**
* Return the total hit count for the given query as provided by
* the search engine.
@@ -134,72 +134,76 @@ public function count()
{
return $this->count;
}
-
+
/**
* Set a custom Doctrine Query to execute in order to hydrate the search
* engine results into required entities. The assumption is made the the
* search engine result id is correlated to the entity id. An optional
* query parameter override can be specified.
- *
+ *
* @param object $hydrationQuery
* @param string $parameter
*/
public function hydrateWith($hydrationQuery, $parameter = null)
{
$this->hydrationQuery = $hydrationQuery;
- if($parameter) {
+ if ($parameter) {
$this->hydrationParameter = $parameter;
}
return $this;
}
-
+
/**
* Return a provided hydration query
- *
+ *
* @return object
*/
protected function getHydrationQuery()
{
- if(!$this->hydrationQuery) {
+ if (!$this->hydrationQuery) {
throw new DoctrineSearchException('A hydration query is required for hydrating results to entities.');
}
-
+
return $this->hydrationQuery;
}
-
+
/**
* Execute search and hydrate results if required.
- *
+ *
* @param integer $hydrationMode
* @throws DoctrineSearchException
* @return mixed
*/
public function getResult($hydrationMode = null)
{
- if($hydrationMode) {
+ if ($hydrationMode) {
$this->hydrationMode = $hydrationMode;
}
-
+
$classMetadata = $this->getSearchManager()->getClassMetadata($this->entityClass);
$resultSet = $this->getSearchManager()->find($classMetadata->index, $classMetadata->type, $this->query);
-
+
switch(get_class($resultSet)) {
case 'Elastica\ResultSet':
$this->count = $resultSet->getTotalHits();
$results = $resultSet->getResults();
- break;
+ break;
default:
throw new DoctrineSearchException('Unknown result set class');
}
-
- if($this->hydrationMode == self::HYDRATE_BYPASS) {
+
+ if ($this->hydrationMode == self::HYDRATE_BYPASS) {
return $resultSet;
}
- $ids = array_map(function($result) { return $result->getId(); }, $results);
+ $fn = function ($result) {
+ return $result->getId();
+ };
+
+ $ids = array_map($fn, $results);
return $this->getHydrationQuery()
->setParameter($this->hydrationParameter, $ids ?: null)
->useResultCache($this->useResultCache, $this->cacheLifetime)
->getResult($this->hydrationMode);
}
-}
+}
View
78 lib/Doctrine/Search/SearchClientInterface.php
@@ -38,62 +38,62 @@
* @param String $type
* @param String $query
*/
- function find($index, $type, $query);
+ public function find($index, $type, $query);
/**
* Creates a document index
*
* @param string $name The name of the index.
* @param string $config The configuration of the index.
*/
- function createIndex($name, array $config = array());
-
+ public function createIndex($name, array $config = array());
+
/**
* Gets a document index reference
*
* @param string $name The name of the index.
*/
- function getIndex($name);
+ public function getIndex($name);
/**
* Deletes an index and its types and documents
- *
+ *
* @param string $index
*/
- function deleteIndex($index);
-
- /**
+ public function deleteIndex($index);
+
+ /**
* Create a document type mapping as defined in the
- * class annotations
- *
- * @param ClassMetadata $metadata
- */
- function createType(ClassMetadata $metadata);
-
- /**
- * Adds documents of a given type to the specified index
- *
- * @param string $index
- * @param string $type
- * @param array $documents Indexed by document id
- */
- function addDocuments($index, $type, array $documents);
-
- /**
- * Remove documents of a given type from the specified index
- *
- * @param string $index
- * @param string $type
- * @param array $documents Indexed by document id
+ * class annotations
+ *
+ * @param ClassMetadata $metadata
+ */
+ public function createType(ClassMetadata $metadata);
+
+ /**
+ * Adds documents of a given type to the specified index
+ *
+ * @param string $index
+ * @param string $type
+ * @param array $documents Indexed by document id
*/
- function removeDocuments($index, $type, array $documents);
-
- /**
- * Remove all documents of a given type from the specified index
- * without deleting the index itself
- *
- * @param string $index
- * @param string $type
+ public function addDocuments($index, $type, array $documents);
+
+ /**
+ * Remove documents of a given type from the specified index
+ *
+ * @param string $index
+ * @param string $type
+ * @param array $documents Indexed by document id
+ */
+ public function removeDocuments($index, $type, array $documents);
+
+ /**
+ * Remove all documents of a given type from the specified index
+ * without deleting the index itself
+ *
+ * @param string $index
+ * @param string $type
*/
- function removeAll($index, $type);
-}
+ public function removeAll($index, $type);
+}
View
147 lib/Doctrine/Search/SearchManager.php
@@ -39,39 +39,39 @@
*/
class SearchManager
{
- /**
- * @var SearchClientInterface
+ /**
+ * @var SearchClientInterface
*/
private $searchClient;
- /**
- * @var Configuration $configuration
+ /**
+ * @var Configuration $configuration
*/
private $configuration;
- /**
- * @var ClassMetadataFactory
+ /**
+ * @var ClassMetadataFactory
*/
private $metadataFactory;
-
- /**
- * @var SerializerInterface
+
+ /**
+ * @var SerializerInterface
*/
private $serializer;
-
- /**
- * @var array
+
+ /**
+ * @var array
*/
private $scheduledForPersist = array();
-
- /**
- * @var array
+
+ /**
+ * @var array
*/
private $scheduledForDelete = array();
-
+
/** @var EntityManager */
private $entityManager;
-
+
/**
* Constructor
*
@@ -87,29 +87,29 @@ public function __construct(Configuration $config, SearchClientInterface $sc)
$this->metadataFactory->setSearchManager($this);
$this->metadataFactory->setConfiguration($this->configuration);
$this->metadataFactory->setCacheDriver($this->configuration->getMetadataCacheImpl());
-
+
$this->serializer = $this->configuration->getEntitySerializer();
- $this->entityManager = $this->configuration->getEntityManager();
+ $this->entityManager = $this->configuration->getEntityManager();
}
/**
* Inject a Doctrine 2 entity manager
- *
+ *
* @param EntityManager $em
*/
public function setEntityManager(EntityManager $em)
{
- $this->entityManager = $em;
+ $this->entityManager = $em;
}
-
- /**
- * @return EntityManager
+
+ /**
+ * @return EntityManager
*/
public function getEntityManager()
{
- return $this->entityManager;
+ return $this->entityManager;
}
-
+
/**
* @return Configuration
*/
@@ -120,26 +120,26 @@ public function getConfiguration()
/**
* Loads class metadata for the given class
- *
+ *
* @param string $className
- *
+ *
* @return ClassMetadata
*/
public function getClassMetadata($className)
{
return $this->metadataFactory->getMetadataFor($className);
}
-
- /**
- * @return SearchClientInterface
+
+ /**
+ * @return SearchClientInterface
*/
public function getClient()
{
return $this->searchClient;
}
- /**
- * @return mixed
+ /**
+ * @return mixed
*/
public function getIndex($name)
{
@@ -162,7 +162,7 @@ public function getClassMetadataFactory()
*/
public function find($index, $type, $query)
{
- return $this->searchClient->find($index, $type, $query);
+ return $this->searchClient->find($index, $type, $query);
}
/**
@@ -177,7 +177,7 @@ public function persist($object)
if (!is_object($object)) {
throw new UnexpectedTypeException($object, 'object');
}
-
+
$this->scheduledForPersist[] = $object;
}
@@ -193,7 +193,7 @@ public function remove($object)
if (!is_object($object)) {
throw new UnexpectedTypeException($object, 'object');
}
-
+
$this->scheduledForDelete[] = $object;
}
@@ -205,53 +205,48 @@ public function commit()
$this->commitPersisted();
$this->commitRemoved();
}
-
- private function commitPersisted()
- {
- $documents = $this->sortObjects($this->scheduledForPersist);
-
- foreach($documents as $index => $documentTypes)
- {
- foreach($documentTypes as $type => $documents)
- {
- $this->searchClient->addDocuments($index, $type, $documents);
- }
- }
- }
-
- private function commitRemoved()
- {
- $documents = $this->sortObjects($this->scheduledForDelete, false);
-
- foreach($documents as $index => $documentTypes)
- {
- foreach($documentTypes as $type => $documents)
- {
- $this->searchClient->removeDocuments($index, $type, $documents);
- }
- }
- }
-
- private function sortObjects(array $objects, $serialize = true)
- {
- $documents = array();
- foreach($objects as $object)
- {
- $metadata = $this->getClassMetadata(get_class($object));
- $document = $serialize ? $this->serializer->serialize($object) : $object;
- $documents[$metadata->index][$metadata->type][$object->getId()] = $document;
- }
- return $documents;
- }
+
+ private function commitPersisted()
+ {
+ $documents = $this->sortObjects($this->scheduledForPersist);
+
+ foreach ($documents as $index => $documentTypes) {
+ foreach ($documentTypes as $type => $documents) {
+ $this->searchClient->addDocuments($index, $type, $documents);
+ }
+ }
+ }
+
+ private function commitRemoved()
+ {
+ $documents = $this->sortObjects($this->scheduledForDelete, false);
+
+ foreach ($documents as $index => $documentTypes) {
+ foreach ($documentTypes as $type => $documents) {
+ $this->searchClient->removeDocuments($index, $type, $documents);
+ }
+ }
+ }
+
+ private function sortObjects(array $objects, $serialize = true)
+ {
+ $documents = array();
+ foreach ($objects as $object) {
+ $metadata = $this->getClassMetadata(get_class($object));
+ $document = $serialize ? $this->serializer->serialize($object) : $object;
+ $documents[$metadata->index][$metadata->type][$object->getId()] = $document;
+ }
+ return $documents;
+ }
/**
* Returns a search engine Query wrapper which can be executed
* to retrieve results;
- *
+ *
* @return Query
*/
public function createQuery()
{
return new Query($this);
}
-}
+}
View
2 lib/Doctrine/Search/Serializer/AnnotationSerializer.php
@@ -7,4 +7,4 @@
class AnnotationSerializer implements SerializerInterface
{
-}
+}
View
4 lib/Doctrine/Search/Serializer/CallbackSerializer.php
@@ -7,7 +7,7 @@
class CallbackSerializer implements SerializerInterface
{
protected $callback;
-
+
public function __construct($callback = 'toArray')
{
$this->callback = $callback;
@@ -17,4 +17,4 @@ public function serialize($object)
{
return $object->{$this->callback}();
}
-}
+}
View
11 lib/Doctrine/Search/Serializer/JMSSerializer.php
@@ -5,6 +5,8 @@
use Doctrine\Search\SerializerInterface;
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\SerializationContext;
+use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
+use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy;
class JMSSerializer implements SerializerInterface
{
@@ -14,12 +16,15 @@ class JMSSerializer implements SerializerInterface
public function __construct(SerializationContext $context = null)
{
$this->context = $context;
- $this->serializer = SerializerBuilder::create()->addDefaultHandlers()->build();
+ $this->serializer = SerializerBuilder::create()
+ ->setPropertyNamingStrategy(new SerializedNameAnnotationStrategy(new IdenticalPropertyNamingStrategy()))
+ ->addDefaultHandlers()
+ ->build();
}
public function serialize($object)
{
- $context = $this->context ? clone $this->context : null;
+ $context = $this->context ? clone $this->context : null;
return json_decode($this->serializer->serialize($object, 'json', $context), true);
}
-}
+}
View
4 lib/Doctrine/Search/SerializerInterface.php
@@ -4,5 +4,5 @@
interface SerializerInterface
{
- public function serialize($object);
-}
+ public function serialize($object);
+}
View
24 lib/Doctrine/Search/Solr/Client.php
@@ -55,34 +55,34 @@ public function createIndex($index, array $data)
{
}
-
- public function createType(ClassMetadata $metadata)
- {
-
+
+ public function createType(ClassMetadata $metadata)
+ {
+
}
-
+
public function getIndex($index)
{
}
public function deleteIndex($index)
{
-
+
}
public function addDocuments($index, $type, array $documents)
{
-
+
}
-
+
public function removeDocuments($index, $type, array $documents)
{
-
+
}
-
+
public function removeAll($index, $type)
{
-
+
}
-}
+}
View
2 lib/Doctrine/Search/Solr/Configuration.php
@@ -33,4 +33,4 @@ public function __construct()
{
}
-}
+}
View
4 lib/Doctrine/Search/Solr/Connection.php
@@ -37,7 +37,7 @@ class Connection
private $httpClient;
- public function __construct($host = null, $port = null, $path = null, HttpClientInterface $httpClient)
+ public function __construct(HttpClientInterface $httpClient, $host = null, $port = null, $path = null)
{
$this->host = $host;
$this->port = $port;
@@ -49,4 +49,4 @@ public function initialize()
{
}
-}
+}
View
4 lib/Doctrine/Search/Version.php
@@ -7,7 +7,7 @@
/**
* @var string
*/
- static $version = '0.1-alpha';
+ public static $version = '0.1-alpha';
/**
* Compare a given version with the current version
@@ -17,7 +17,7 @@
*
* @return integer Return -1 if it older, 0 if it the same, 1 if $version is newer
*/
- static public function compare($version)
+ public static function compare($version)
{
return version_compare($version, static::$version);
}
View
34 lib/Doctrine/Search/ZendLucene/Client.php
@@ -56,34 +56,34 @@ public function createIndex($index, array $data)
{
}
-
+
public function createType(ClassMetadata $metadata)
{
}
-
+
public function getIndex($index)
{
}
public function deleteIndex($index)
{
-
+
}
-
- public function addDocuments($index, $type, array $documents)
- {
-
- }
-
- public function removeDocuments($index, $type, array $documents)
- {
-
+
+ public function addDocuments($index, $type, array $documents)
+ {
+
}
-
- public function removeAll($index, $type)
- {
-
+
+ public function removeDocuments($index, $type, array $documents)
+ {
+
+ }
+
+ public function removeAll($index, $type)
+ {
+
}
-}
+}
View
2 lib/Doctrine/Search/ZendLucene/Configuration.php
@@ -33,4 +33,4 @@ public function __construct()
{
}
-}
+}
View
4 lib/Doctrine/Search/ZendLucene/Connection.php
@@ -37,7 +37,7 @@ class Connection
private $httpClient;
- public function __construct($host = null, $port = null, $path = null, HttpClientInterface $httpClient)
+ public function __construct(HttpClientInterface $httpClient, $host = null, $port = null, $path = null)
{
$this->host = $host;
$this->port = $port;
@@ -49,4 +49,4 @@ public function initialize()
{
}
-}
+}

0 comments on commit 8b761a8

Please sign in to comment.
Something went wrong with that request. Please try again.