Merge remote-tracking branch 'upstream/master'

This commit is contained in:
nurikabe 2014-01-11 16:38:29 +00:00
commit 4a4716a55b
44 changed files with 920 additions and 106 deletions

View file

@ -6,4 +6,4 @@ php:
before_script:
- echo "extension = mongo.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- composer install --dev
- composer install --dev --prefer-source

View file

@ -4,6 +4,7 @@ namespace FOS\ElasticaBundle;
use Elastica\Client as ElasticaClient;
use Elastica\Request;
use FOS\ElasticaBundle\Logger\ElasticaLogger;
/**
* @author Gordon Franke <info@nevalon.de>
@ -15,9 +16,18 @@ class Client extends ElasticaClient
$start = microtime(true);
$response = parent::request($path, $method, $data, $query);
if (null !== $this->_logger) {
if (null !== $this->_logger and $this->_logger instanceof ElasticaLogger) {
$time = microtime(true) - $start;
$this->_logger->logQuery($path, $method, $data, $time);
$connection = $this->getLastRequest()->getConnection();
$connection_array = array(
'host' => $connection->getHost(),
'port' => $connection->getPort(),
'transport' => $connection->getTransport(),
);
$this->_logger->logQuery($path, $method, $data, $time, $connection_array);
}
return $response;

View file

@ -4,11 +4,9 @@ namespace FOS\ElasticaBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use FOS\ElasticaBundle\IndexManager;
use FOS\ElasticaBundle\Provider\ProviderRegistry;
use FOS\ElasticaBundle\Resetter;

View file

@ -3,11 +3,9 @@
namespace FOS\ElasticaBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use FOS\ElasticaBundle\IndexManager;
use FOS\ElasticaBundle\Resetter;
@ -62,7 +60,7 @@ class ResetCommand extends ContainerAwareCommand
if (null !== $type) {
$output->writeln(sprintf('<info>Resetting</info> <comment>%s/%s</comment>', $index, $type));
$this->resetter->resetIndex($index, $type);
$this->resetter->resetIndexType($index, $type);
} else {
$indexes = null === $index
? array_keys($this->indexManager->getAllIndexes())

View file

@ -7,7 +7,6 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use Elastica\Query;
use Elastica\Result;

View file

@ -11,8 +11,6 @@ namespace FOS\ElasticaBundle\Configuration;
*/
class Search
{
/** @var string */
public $repositoryClass;
}

View file

@ -76,8 +76,9 @@ class Configuration implements ConfigurationInterface
return array(
'servers' => array(
array(
'host' => $v['host'],
'port' => $v['port'],
'host' => $v['host'],
'port' => $v['port'],
'logger' => isset($v['logger']) ? $v['logger'] : null
)
)
);
@ -89,7 +90,8 @@ class Configuration implements ConfigurationInterface
return array(
'servers' => array(
array(
'url' => $v['url'],
'url' => $v['url'],
'logger' => isset($v['logger']) ? $v['logger'] : null
)
)
);
@ -102,6 +104,11 @@ class Configuration implements ConfigurationInterface
->scalarNode('url')->end()
->scalarNode('host')->end()
->scalarNode('port')->end()
->scalarNode('logger')
->defaultValue('fos_elastica.logger')
->treatNullLike('fos_elastica.logger')
->treatTrueLike('fos_elastica.logger')
->end()
->end()
->end()
->end()
@ -293,6 +300,7 @@ class Configuration implements ConfigurationInterface
->append($this->getBoostNode())
->append($this->getRoutingNode())
->append($this->getParentNode())
->append($this->getAllNode())
->end()
;
@ -333,18 +341,13 @@ class Configuration implements ConfigurationInterface
->useAttributeAsKey('name')
->prototype('array')
->children()
->scalarNode('match')->isRequired()->end()
->scalarNode('match')->end()
->scalarNode('unmatch')->end()
->scalarNode('match_mapping_type')->end()
->arrayNode('mapping')
->isRequired()
->children()
->scalarNode('type')->end()
->scalarNode('index')->end()
->arrayNode('fields')
->children()
->end()
->end()
->end()
->scalarNode('path_match')->end()
->scalarNode('path_unmatch')->end()
->scalarNode('match_pattern')->end()
->append($this->getDynamicTemplateMapping())
->end()
->end()
;
@ -352,6 +355,21 @@ class Configuration implements ConfigurationInterface
return $node;
}
/**
* @return the array node used for mapping in dynamic templates
*/
protected function getDynamicTemplateMapping()
{
$builder = new TreeBuilder();
$node = $builder->root('mapping');
$nestings = $this->getNestingsForDynamicTemplates();
$this->addFieldConfig($node->children(), $nestings);
return $node;
}
/**
* @param \Symfony\Component\Config\Definition\Builder\NodeBuilder $node The node to which to attach the field config to
* @param array $nestings the nested mappings for the current field level
@ -369,6 +387,7 @@ class Configuration implements ConfigurationInterface
->scalarNode('term_vector')->end()
->scalarNode('null_value')->end()
->booleanNode('include_in_all')->defaultValue(true)->end()
->booleanNode('enabled')->defaultValue(true)->end()
->scalarNode('lat_lon')->end()
->scalarNode('index_name')->end()
->booleanNode('omit_norms')->end()
@ -434,12 +453,51 @@ class Configuration implements ConfigurationInterface
}
foreach ($index['types'] as $type) {
if (empty($type['mappings'])) {
continue;
}
$nestings = array_merge_recursive($nestings, $this->getNestingsForType($type['mappings'], $nestings));
}
}
return $nestings;
}
/**
* @return array The unique nested mappings for all dynamic templates
*/
protected function getNestingsForDynamicTemplates()
{
if (!isset($this->configArray[0]['indexes'])) {
return array();
}
$nestings = array();
foreach ($this->configArray[0]['indexes'] as $index) {
if (empty($index['types'])) {
continue;
}
foreach ($index['types'] as $type) {
if (empty($type['dynamic_templates'])) {
continue;
}
foreach ($type['dynamic_templates'] as $definition) {
$field = $definition['mapping'];
if (isset($field['fields'])) {
$this->addPropertyNesting($field, $nestings, 'fields');
} else if (isset($field['properties'])) {
$this->addPropertyNesting($field, $nestings, 'properties');
}
}
}
}
return $nestings;
}
/**
* @param array $mappings The mappings for the current type
* @return array The nested mappings defined for this type
@ -574,4 +632,21 @@ class Configuration implements ConfigurationInterface
return $node;
}
/**
* Returns the array node used for "_all"
*/
protected function getAllNode()
{
$builder = new TreeBuilder();
$node = $builder->root('_all');
$node
->children()
->scalarNode('enabled')->defaultValue(true)->end()
->end()
;
return $node;
}
}

View file

@ -16,6 +16,7 @@ class FOSElasticaExtension extends Extension
protected $indexConfigs = array();
protected $typeFields = array();
protected $loadedDrivers = array();
protected $serializerConfig = array();
public function load(array $configs, ContainerBuilder $container)
{
@ -40,8 +41,8 @@ class FOSElasticaExtension extends Extension
}
$clientIdsByName = $this->loadClients($config['clients'], $container);
$serializerConfig = isset($config['serializer']) ? $config['serializer'] : null;
$indexIdsByName = $this->loadIndexes($config['indexes'], $container, $clientIdsByName, $config['default_client'], $serializerConfig);
$this->serializerConfig = isset($config['serializer']) ? $config['serializer'] : null;
$indexIdsByName = $this->loadIndexes($config['indexes'], $container, $clientIdsByName, $config['default_client']);
$indexRefsByName = array_map(function($id) {
return new Reference($id);
}, $indexIdsByName);
@ -73,7 +74,10 @@ class FOSElasticaExtension extends Extension
foreach ($clients as $name => $clientConfig) {
$clientId = sprintf('fos_elastica.client.%s', $name);
$clientDef = new Definition('%fos_elastica.client.class%', array($clientConfig));
$clientDef->addMethodCall('setLogger', array(new Reference('fos_elastica.logger')));
$logger = $clientConfig['servers'][0]['logger'];
if (false !== $logger) {
$clientDef->addMethodCall('setLogger', array(new Reference($logger)));
}
$clientDef->addTag('fos_elastica.client');
$container->setDefinition($clientId, $clientDef);
@ -91,10 +95,11 @@ class FOSElasticaExtension extends Extension
* @param ContainerBuilder $container A ContainerBuilder instance
* @param array $clientIdsByName
* @param $defaultClientName
* @param $serializerConfig
* @throws \InvalidArgumentException
* @return array
*/
protected function loadIndexes(array $indexes, ContainerBuilder $container, array $clientIdsByName, $defaultClientName, $serializerConfig)
protected function loadIndexes(array $indexes, ContainerBuilder $container, array $clientIdsByName, $defaultClientName)
{
$indexIds = array();
foreach ($indexes as $name => $index) {
@ -129,7 +134,7 @@ class FOSElasticaExtension extends Extension
if (!empty($index['settings'])) {
$this->indexConfigs[$name]['config']['settings'] = $index['settings'];
}
$this->loadTypes(isset($index['types']) ? $index['types'] : array(), $container, $name, $indexId, $typePrototypeConfig, $serializerConfig);
$this->loadTypes(isset($index['types']) ? $index['types'] : array(), $container, $name, $indexId, $typePrototypeConfig);
}
return $indexIds;
@ -170,8 +175,9 @@ class FOSElasticaExtension extends Extension
* @param $indexName
* @param $indexId
* @param array $typePrototypeConfig
* @param $serializerConfig
*/
protected function loadTypes(array $types, ContainerBuilder $container, $indexName, $indexId, array $typePrototypeConfig, $serializerConfig)
protected function loadTypes(array $types, ContainerBuilder $container, $indexName, $indexId, array $typePrototypeConfig)
{
foreach ($types as $name => $type) {
$type = self::deepArrayUnion($typePrototypeConfig, $type);
@ -180,12 +186,12 @@ class FOSElasticaExtension extends Extension
$typeDef = new Definition('%fos_elastica.type.class%', $typeDefArgs);
$typeDef->setFactoryService($indexId);
$typeDef->setFactoryMethod('getType');
if ($serializerConfig) {
$callbackDef = new Definition($serializerConfig['callback_class']);
if ($this->serializerConfig) {
$callbackDef = new Definition($this->serializerConfig['callback_class']);
$callbackId = sprintf('%s.%s.serializer.callback', $indexId, $name);
$typeDef->addMethodCall('setSerializer', array(array(new Reference($callbackId), 'serialize')));
$callbackDef->addMethodCall('setSerializer', array(new Reference($serializerConfig['serializer'])));
$callbackDef->addMethodCall('setSerializer', array(new Reference($this->serializerConfig['serializer'])));
if (isset($type['serializer']['groups'])) {
$callbackDef->addMethodCall('setGroups', array($type['serializer']['groups']));
}
@ -198,6 +204,11 @@ class FOSElasticaExtension extends Extension
$typeDef->addMethodCall('setSerializer', array(array(new Reference($callbackId), 'serialize')));
}
$container->setDefinition($typeId, $typeDef);
$this->indexConfigs[$indexName]['config']['mappings'][$name] = array(
"_source" => array("enabled" => true), // Add a default setting for empty mapping settings
);
if (isset($type['_id'])) {
$this->indexConfigs[$indexName]['config']['mappings'][$name]['_id'] = $type['_id'];
}
@ -210,7 +221,7 @@ class FOSElasticaExtension extends Extension
if (isset($type['_routing'])) {
$this->indexConfigs[$indexName]['config']['mappings'][$name]['_routing'] = $type['_routing'];
}
if (isset($type['mappings'])) {
if (isset($type['mappings']) && !empty($type['mappings'])) {
$this->indexConfigs[$indexName]['config']['mappings'][$name]['properties'] = $type['mappings'];
$typeName = sprintf('%s/%s', $indexName, $name);
$this->typeFields[$typeName] = $type['mappings'];
@ -232,6 +243,9 @@ class FOSElasticaExtension extends Extension
if (isset($type['index'])) {
$this->indexConfigs[$indexName]['config']['mappings'][$name]['index'] = $type['index'];
}
if (isset($type['_all'])) {
$this->indexConfigs[$indexName]['config']['mappings'][$name]['_all'] = $type['_all'];
}
if (!empty($type['dynamic_templates'])) {
$this->indexConfigs[$indexName]['config']['mappings'][$name]['dynamic_templates'] = array();
foreach ($type['dynamic_templates'] as $templateName => $templateData) {
@ -324,8 +338,14 @@ class FOSElasticaExtension extends Extension
return $typeConfig['model_to_elastica_transformer']['service'];
}
if ($this->serializerConfig) {
$abstractId = sprintf('fos_elastica.model_to_elastica_identifier_transformer');
} else {
$abstractId = sprintf('fos_elastica.model_to_elastica_transformer');
}
$serviceId = sprintf('fos_elastica.model_to_elastica_transformer.%s.%s', $indexName, $typeName);
$serviceDef = new DefinitionDecorator('fos_elastica.model_to_elastica_transformer');
$serviceDef = new DefinitionDecorator($abstractId);
$serviceDef->replaceArgument(0, array(
'identifier' => $typeConfig['identifier']
));
@ -336,12 +356,26 @@ class FOSElasticaExtension extends Extension
protected function loadObjectPersister(array $typeConfig, Definition $typeDef, ContainerBuilder $container, $indexName, $typeName, $transformerId)
{
$arguments = array(
$typeDef,
new Reference($transformerId),
$typeConfig['model'],
);
if ($this->serializerConfig) {
$abstractId = 'fos_elastica.object_serializer_persister';
$callbackId = sprintf('%s.%s.serializer.callback', $this->indexConfigs[$indexName]['index'], $typeName);
$arguments[] = array(new Reference($callbackId), 'serialize');
} else {
$abstractId = 'fos_elastica.object_persister';
$arguments[] = $this->typeFields[sprintf('%s/%s', $indexName, $typeName)];
}
$serviceId = sprintf('fos_elastica.object_persister.%s.%s', $indexName, $typeName);
$serviceDef = new DefinitionDecorator('fos_elastica.object_persister');
$serviceDef->replaceArgument(0, $typeDef);
$serviceDef->replaceArgument(1, new Reference($transformerId));
$serviceDef->replaceArgument(2, $typeConfig['model']);
$serviceDef->replaceArgument(3, $this->typeFields[sprintf('%s/%s', $indexName, $typeName)]);
$serviceDef = new DefinitionDecorator($abstractId);
foreach ($arguments as $i => $argument) {
$serviceDef->replaceArgument($i, $argument);
}
$container->setDefinition($serviceId, $serviceDef);
return $serviceId;

View file

@ -40,5 +40,4 @@ class RepositoryManager extends BaseManager
return parent::getRepository($realEntityName);
}
}

View file

@ -97,6 +97,7 @@ class TransformedFinder implements PaginatedFinderInterface
public function createPaginatorAdapter($query)
{
$query = Query::create($query);
return new TransformedPaginatorAdapter($this->searchable, $query, $this->transformer);
}
}

View file

@ -38,15 +38,17 @@ class ElasticaLogger implements LoggerInterface
* @param string $method Rest method to use (GET, POST, DELETE, PUT)
* @param array $data arguments
* @param float $time execution time
* @param array $connection host, port and transport of the query
*/
public function logQuery($path, $method, $data, $time)
public function logQuery($path, $method, $data, $time, $connection = array())
{
if ($this->debug) {
$this->queries[] = array(
'path' => $path,
'method' => $method,
'data' => $data,
'executionMS' => $time
'executionMS' => $time,
'connection' => $connection
);
}
@ -145,6 +147,6 @@ class ElasticaLogger implements LoggerInterface
*/
public function log($level, $message, array $context = array())
{
return $this->logger->log($message, $context);
return $this->logger->log($level, $message, $context);
}
}

View file

@ -5,6 +5,7 @@ namespace FOS\ElasticaBundle\Manager;
use Doctrine\Common\Annotations\Reader;
use FOS\ElasticaBundle\Finder\FinderInterface;
use RuntimeException;
/**
* @author Richard Miller <info@limethinking.co.uk>
*
@ -70,11 +71,10 @@ class RepositoryManager implements RepositoryManagerInterface
private function createRepository($entityName)
{
$repositoryName = $this->getRepositoryName($entityName);
if (!class_exists($repositoryName)) {
if (!class_exists($repositoryName = $this->getRepositoryName($entityName))) {
throw new RuntimeException(sprintf('%s repository for %s does not exist', $repositoryName, $entityName));
}
return new $repositoryName($this->entities[$entityName]['finder']);
}
}

View file

@ -32,5 +32,4 @@ interface RepositoryManagerInterface
* @param string $entityName
*/
public function getRepository($entityName);
}

View file

@ -3,14 +3,13 @@
namespace FOS\ElasticaBundle\Paginator;
use Pagerfanta\Adapter\AdapterInterface;
use FOS\ElasticaBundle\Paginator\PaginatorAdapterInterface;
class FantaPaginatorAdapter implements AdapterInterface
{
private $adapter;
/**
* @param PaginatorAdapterInterface $adapter
* @param \FOS\ElasticaBundle\Paginator\PaginatorAdapterInterface $adapter
*/
public function __construct(PaginatorAdapterInterface $adapter)
{
@ -42,7 +41,7 @@ class FantaPaginatorAdapter implements AdapterInterface
}
/**
* Returns an slice of the results.
* Returns a slice of the results.
*
* @param integer $offset The offset.
* @param integer $length The length.

View file

@ -2,8 +2,6 @@
namespace FOS\ElasticaBundle\Paginator;
use FOS\ElasticaBundle\Paginator\PartialResultsInterface;
interface PaginatorAdapterInterface
{
/**

View file

@ -5,9 +5,6 @@ namespace FOS\ElasticaBundle\Paginator;
use Elastica\SearchableInterface;
use Elastica\Query;
use Elastica\ResultSet;
use FOS\ElasticaBundle\Paginator\PaginatorAdapterInterface;
use FOS\ElasticaBundle\Paginator\RawPartialResults;
use FOS\ElasticaBundle\Paginator\PartialResultsInterface;
use InvalidArgumentException;
/**
@ -52,6 +49,7 @@ class RawPaginatorAdapter implements PaginatorAdapterInterface
*
* @param $offset
* @param $itemCountPerPage
* @throws \InvalidArgumentException
* @return ResultSet
*/
protected function getElasticaResults($offset, $itemCountPerPage)

View file

@ -2,7 +2,6 @@
namespace FOS\ElasticaBundle\Paginator;
use FOS\ElasticaBundle\Paginator\PartialResultsInterface;
use Elastica\ResultSet;
use Elastica\Result;

View file

@ -3,7 +3,6 @@
namespace FOS\ElasticaBundle\Paginator;
use FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
use FOS\ElasticaBundle\Paginator\TransformedPartialResults;
use Elastica\SearchableInterface;
use Elastica\Query;

View file

@ -3,7 +3,6 @@
namespace FOS\ElasticaBundle\Paginator;
use FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface;
use FOS\ElasticaBundle\Paginator\RawPartialResults;
use Elastica\ResultSet;
/**

View file

@ -0,0 +1,42 @@
<?php
namespace FOS\ElasticaBundle\Persister;
use Elastica\Document;
use Elastica\Type;
use FOS\ElasticaBundle\Transformer\ModelToElasticaTransformerInterface;
/**
* Inserts, replaces and deletes single objects in an elastica type, making use
* of elastica's serializer support to convert objects in to elastica documents.
* Accepts domain model objects and passes them directly to elastica
*
* @author Lea Haensenberber <lea.haensenberger@gmail.com>
*/
class ObjectSerializerPersister extends ObjectPersister
{
protected $serializer;
public function __construct(Type $type, ModelToElasticaTransformerInterface $transformer, $objectClass, $serializer)
{
parent::__construct($type, $transformer, $objectClass, array());
$this->serializer = $serializer;
}
/**
* Transforms an object to an elastica document
* with just the identifier set
*
* @param object $object
* @return Document the elastica document
*/
public function transformToElasticaDocument($object)
{
$document = $this->transformer->transform($object, array());
$data = call_user_func($this->serializer, $object);
$document->setData($data);
return $document;
}
}

View file

@ -3,7 +3,6 @@
namespace FOS\ElasticaBundle\Provider;
use FOS\ElasticaBundle\Persister\ObjectPersisterInterface;
use FOS\ElasticaBundle\Provider\ProviderInterface;
abstract class AbstractProvider implements ProviderInterface
{

View file

@ -2,8 +2,6 @@
namespace FOS\ElasticaBundle\Provider;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

View file

@ -182,17 +182,19 @@ per type.
content: ~
_parent: { type: "post", property: "post", identifier: "id" }
The parent filed declaration has the following values:
The parent field declaration has the following values:
* `type`: The parent type.
* `property`: The property in the child entity where to look for the parent entity. It may be ignored if is equal to the parent type.
* `identifier`: The property in the parent entity which have the parent identifier. Defaults to `id`.
* `identifier`: The property in the parent entity which has the parent identifier. Defaults to `id`.
Note that to create a document with a parent, you need to call `setParent` on the document rather than setting a _parent field.
If you do this wrong, you will see a `RoutingMissingException` as elasticsearch does not know where to store a document that should have a parent but does not specify it.
### Declaring `nested` or `object`
Note that object can autodetect properties
fos_elastica:
clients:
default: { host: localhost, port: 9200 }
@ -213,6 +215,12 @@ If you do this wrong, you will see a `RoutingMissingException` as elasticsearch
properties:
date: { boost: 5 }
content: ~
user:
type: "object"
approver:
type: "object"
properties:
date: { boost: 5 }
#### Doctrine ORM and `object` mappings
@ -230,7 +238,7 @@ It applies the configured mappings to the types.
This command needs providers to insert new documents in the elasticsearch types.
There are 2 ways to create providers.
If your elasticsearch type matches a Doctrine repository or a Propel query, go for the persistence automatic provider.
Or, for complete flexibility, go for manual provider.
Or, for complete flexibility, go for a manual provider.
#### Persistence automatic provider
@ -495,7 +503,7 @@ If you use multiple drivers then you can choose which one is aliased to `fos_ela
using the `default_manager` parameter:
fos_elastica:
default_manager: mongodb #defauults to orm
default_manager: mongodb #defaults to orm
clients:
default: { host: localhost, port: 9200 }
#--

View file

@ -49,6 +49,13 @@
<argument /> <!-- transformer -->
</service>
<service id="fos_elastica.object_serializer_persister" class="FOS\ElasticaBundle\Persister\ObjectSerializerPersister" abstract="true">
<argument /> <!-- type -->
<argument /> <!-- model to elastica transformer -->
<argument /> <!-- model -->
<argument /> <!-- serializer -->
</service>
<service id="fos_elastica.model_to_elastica_transformer" class="FOS\ElasticaBundle\Transformer\ModelToElasticaAutoTransformer" public="false" abstract="true">
<argument /> <!-- options -->
<call method="setPropertyAccessor">
@ -56,6 +63,13 @@
</call>
</service>
<service id="fos_elastica.model_to_elastica_identifier_transformer" class="FOS\ElasticaBundle\Transformer\ModelToElasticaIdentifierTransformer" public="false" abstract="true">
<argument /> <!-- options -->
<call method="setPropertyAccessor">
<argument type="service" id="fos_elastica.property_accessor" />
</call>
</service>
<service id="fos_elastica.elastica_to_model_transformer.collection" class="%fos_elastica.elastica_to_model_transformer.collection.class%" public="true" abstract="true">
<argument type="collection" /> <!-- transformers -->
</service>

View file

@ -19,13 +19,13 @@
{% endblock %}
{% block menu %}
<span class="label">
<span class="icon"><img src="{{ asset('bundles/foselastica/images/elastica.png') }}" alt="" /></span>
<strong>Elastica</strong>
<span class="count">
<span>{{ collector.querycount }}</span>
<span class="label">
<span class="icon"><img src="{{ asset('bundles/foselastica/images/elastica.png') }}" alt="" /></span>
<strong>Elastica</strong>
<span class="count">
<span>{{ collector.querycount }}</span>
</span>
</span>
</span>
{% endblock %}
{% block panel %}
@ -41,18 +41,52 @@
</p>
{% else %}
<ul class="alt">
{% for query in collector.queries %}
{% for key, query in collector.queries %}
<li class="{{ cycle(['odd', 'even'], loop.index) }}">
<strong>Path</strong>: {{ query.path }}<br />
<strong>Method</strong>: {{ query.method }}
<strong>Method</strong>: {{ query.method }} <small>({{ query.connection.transport }} on {{ query.connection.host }}:{{ query.connection.port }})</small>
<div>
<code>{{ query.data|json_encode }}</code>
</div>
<small>
<strong>Time</strong>: {{ '%0.2f'|format(query.executionMS * 1000) }} ms
</small>
{% if query.connection.transport in ['Http', 'Https'] %}{# cURL support only HTTP #}
<a href="#elastica_curl_query_{{ key }}" onclick="return curl_version(this);" style="text-decoration: none;" title="Get the cURL repeatable query">
<img alt="+" src="{{ asset('bundles/framework/images/blue_picto_more.gif') }}" style="display: inline; width: 12px; height: 12px; vertical-align: bottom;" />
<img alt="-" src="{{ asset('bundles/framework/images/blue_picto_less.gif') }}" style="display: none; width: 12px; height: 12px; vertical-align: bottom;" />
<small>Display cURL query</small>
</a>
<div style="display: none;" id="elastica_curl_query_{{ key }}">
<code>curl -X{{ query.method }} '{{ query.connection.transport|lower }}://{{ query.connection.host }}:{{ query.connection.port }}/{{ query.path }}' -d '{{ query.data|json_encode }}'</code>
</div>
{% endif %}
</li>
{% endfor %}
</ul>
<script type="text/javascript">//<![CDATA[
function curl_version(link) {
"use strict";
var sections = link.children;
if (sections[0].style.display != 'none') {
sections[0].style.display = 'none';
sections[1].style.display = 'inline';
document.getElementById(link.hash.replace("#", "")).style.display = 'block';
} else {
sections[0].style.display = 'inline';
sections[1].style.display = 'none';
document.getElementById(link.hash.replace("#", "")).style.display = 'none';
}
return false;
}
</script>
{% endif %}
{% endblock %}

View file

@ -8,9 +8,7 @@ use JMS\Serializer\SerializerInterface;
class Callback
{
protected $serializer;
protected $groups;
protected $version;
public function setSerializer($serializer)

42
Tests/ClientTest.php Normal file
View file

@ -0,0 +1,42 @@
<?php
namespace FOS\ElasticaBundle\Tests\Resetter;
use Elastica\Request;
use Elastica\Transport\Null as NullTransport;
class ClientTest extends \PHPUnit_Framework_TestCase
{
public function testRequestsAreLogged()
{
$transport = new NullTransport;
$connection = $this->getMock('Elastica\Connection');
$connection->expects($this->any())->method('getTransportObject')->will($this->returnValue($transport));
$connection->expects($this->any())->method('toArray')->will($this->returnValue(array()));
$logger = $this->getMock('FOS\ElasticaBundle\Logger\ElasticaLogger');
$logger
->expects($this->once())
->method('logQuery')
->with(
'foo',
Request::GET,
$this->isType('array'),
$this->isType('float'),
$this->isType('array')
);
$client = $this->getMockBuilder('FOS\ElasticaBundle\Client')
->setMethods(array('getConnection'))
->getMock();
$client->expects($this->any())->method('getConnection')->will($this->returnValue($connection));
$client->setLogger($logger);
$response = $client->request('foo');
$this->assertInstanceOf('Elastica\Response', $response);
}
}

View file

@ -0,0 +1,91 @@
<?php
namespace FOS\ElasticaBundle\Tests\Command;
use FOS\ElasticaBundle\Command\ResetCommand;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\DependencyInjection\Container;
class ResetCommandTest extends \PHPUnit_Framework_TestCase
{
private $resetter;
private $indexManager;
public function setup()
{
$container = new Container();
$this->resetter = $this->getMockBuilder('\FOS\ElasticaBundle\Resetter')
->disableOriginalConstructor()
->setMethods(array('resetIndex', 'resetIndexType'))
->getMock();
$container->set('fos_elastica.resetter', $this->resetter);
$this->indexManager = $this->getMockBuilder('\FOS\ElasticaBundle\IndexManager')
->disableOriginalConstructor()
->setMethods(array('getAllIndexes'))
->getMock();
$container->set('fos_elastica.index_manager', $this->indexManager);
$this->command = new ResetCommand();
$this->command->setContainer($container);
}
public function testResetAllIndexes()
{
$this->indexManager->expects($this->any())
->method('getAllIndexes')
->will($this->returnValue(array('index1' => true, 'index2' => true)));
$this->resetter->expects($this->at(0))
->method('resetIndex')
->with($this->equalTo('index1'));
$this->resetter->expects($this->at(1))
->method('resetIndex')
->with($this->equalTo('index2'));
$this->command->run(
new ArrayInput(array()),
new NullOutput()
);
}
public function testResetIndex()
{
$this->indexManager->expects($this->never())
->method('getAllIndexes');
$this->resetter->expects($this->at(0))
->method('resetIndex')
->with($this->equalTo('index1'));
$this->command->run(
new ArrayInput(array('--index' => 'index1')),
new NullOutput()
);
}
public function testResetIndexType()
{
$this->indexManager->expects($this->never())
->method('getAllIndexes');
$this->resetter->expects($this->never())
->method('resetIndex');
$this->resetter->expects($this->at(0))
->method('resetIndexType')
->with($this->equalTo('index1'), $this->equalTo('type1'));
$this->command->run(
new ArrayInput(array('--index' => 'index1', '--type' => 'type1')),
new NullOutput()
);
}
}

View file

@ -9,7 +9,6 @@ use FOS\ElasticaBundle\DataCollector\ElasticaDataCollector;
*/
class ElasticaDataCollectorTest extends \PHPUnit_Framework_TestCase
{
public function testCorrectAmountOfQueries()
{
/** @var $requestMock \PHPUnit_Framework_MockObject_MockObject|\Symfony\Component\HttpFoundation\Request */
@ -93,5 +92,4 @@ class ElasticaDataCollectorTest extends \PHPUnit_Framework_TestCase
$elasticaDataCollector->collect($requestMock, $responseMock);
$this->assertEquals(30, $elasticaDataCollector->getTime());
}
}

View file

@ -48,6 +48,22 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase
$this->assertInstanceOf('Symfony\Component\Config\Definition\ScalarNode', $dynamicTemplates['match_mapping_type']);
$this->assertNull($dynamicTemplates['match_mapping_type']->getDefaultValue());
$this->assertArrayHasKey('unmatch', $dynamicTemplates);
$this->assertInstanceOf('Symfony\Component\Config\Definition\ScalarNode', $dynamicTemplates['unmatch']);
$this->assertNull($dynamicTemplates['unmatch']->getDefaultValue());
$this->assertArrayHasKey('path_match', $dynamicTemplates);
$this->assertInstanceOf('Symfony\Component\Config\Definition\ScalarNode', $dynamicTemplates['path_match']);
$this->assertNull($dynamicTemplates['path_match']->getDefaultValue());
$this->assertArrayHasKey('path_unmatch', $dynamicTemplates);
$this->assertInstanceOf('Symfony\Component\Config\Definition\ScalarNode', $dynamicTemplates['path_unmatch']);
$this->assertNull($dynamicTemplates['path_unmatch']->getDefaultValue());
$this->assertArrayHasKey('match_pattern', $dynamicTemplates);
$this->assertInstanceOf('Symfony\Component\Config\Definition\ScalarNode', $dynamicTemplates['match_pattern']);
$this->assertNull($dynamicTemplates['match_pattern']->getDefaultValue());
$this->assertArrayHasKey('mapping', $dynamicTemplates);
$this->assertInstanceOf('Symfony\Component\Config\Definition\ArrayNode', $dynamicTemplates['mapping']);
}
@ -63,13 +79,10 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase
$this->assertArrayHasKey('type', $mapping);
$this->assertInstanceOf('Symfony\Component\Config\Definition\ScalarNode', $mapping['type']);
$this->assertNull($mapping['type']->getDefaultValue());
$this->assertSame('string', $mapping['type']->getDefaultValue());
$this->assertArrayHasKey('index', $mapping);
$this->assertInstanceOf('Symfony\Component\Config\Definition\ScalarNode', $mapping['index']);
$this->assertNull($mapping['index']->getDefaultValue());
$this->assertArrayHasKey('fields', $mapping);
$this->assertInstanceOf('Symfony\Component\Config\Definition\ArrayNode', $mapping['fields']);
}
}

View file

@ -156,5 +156,4 @@ class RepositoryManagerTest extends \PHPUnit_Framework_TestCase
$repository = $manager->getRepository($shortEntityName);
$this->assertInstanceOf('FOS\ElasticaBundle\Repository', $repository);
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace FOS\ElasticaBundle\Tests\Resetter;
use FOS\ElasticaBundle\FOSElasticaBundle;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
class FOSElasticaBundleTest extends \PHPUnit_Framework_TestCase
{
public function testCompilerPassesAreRegistered()
{
$passes = array(
array (
'FOS\ElasticaBundle\DependencyInjection\Compiler\RegisterProvidersPass',
PassConfig::TYPE_BEFORE_REMOVING
),
array (
'FOS\ElasticaBundle\DependencyInjection\Compiler\TransformerPass'
),
);
$container = $this
->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$container
->expects($this->at(0))
->method('addCompilerPass')
->with($this->isInstanceOf($passes[0][0]), $passes[0][1]);
$container
->expects($this->at(1))
->method('addCompilerPass')
->with($this->isInstanceOf($passes[1][0]));
$bundle = new FOSElasticaBundle();
$bundle->build($container);
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace FOS\ElasticaBundle\Tests\Resetter;
use Elastica\Result;
use FOS\ElasticaBundle\HybridResult;
class HybridResultTest extends \PHPUnit_Framework_TestCase
{
public function testTransformedResultDefaultsToNull()
{
$result = new Result(array());
$hybridResult = new HybridResult($result);
$this->assertSame($result, $hybridResult->getResult());
$this->assertNull($hybridResult->getTransformed());
}
}

View file

@ -9,6 +9,39 @@ use FOS\ElasticaBundle\Logger\ElasticaLogger;
*/
class ElasticaLoggerTest extends \PHPUnit_Framework_TestCase
{
/**
* @return \PHPUnit_Framework_MockObject_MockObject|\Symfony\Component\HttpKernel\Log\LoggerInterface
*/
private function getMockLogger()
{
return $this->getMockBuilder('Symfony\Component\HttpKernel\Log\LoggerInterface')
->disableOriginalConstructor()
->getMock();
}
/**
* @param string $level
* @param string $message
* @param array $context
* @return ElasticaLogger
*/
private function getMockLoggerForLevelMessageAndContext($level, $message, $context)
{
$loggerMock = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\LoggerInterface')
->disableOriginalConstructor()
->getMock();
$loggerMock->expects($this->once())
->method($level)
->with(
$this->equalTo($message),
$this->equalTo($context)
);
$elasticaLogger = new ElasticaLogger($loggerMock);
return $elasticaLogger;
}
public function testGetZeroIfNoQueriesAdded()
{
@ -36,15 +69,17 @@ class ElasticaLoggerTest extends \PHPUnit_Framework_TestCase
$method = 'testMethod';
$data = array('data');
$time = 12;
$connection = array('host' => 'localhost', 'port' => '8999', 'transport' => 'https');
$expected = array(
'path' => $path,
'method' => $method,
'data' => $data,
'executionMS' => $time
'executionMS' => $time,
'connection' => $connection,
);
$elasticaLogger->logQuery($path, $method, $data, $time);
$elasticaLogger->logQuery($path, $method, $data, $time, $connection);
$returnedQueries = $elasticaLogger->getQueries();
$this->assertEquals($expected, $returnedQueries[0]);
}
@ -63,10 +98,7 @@ class ElasticaLoggerTest extends \PHPUnit_Framework_TestCase
public function testQueryIsLogged()
{
/** @var $loggerMock \PHPUnit_Framework_MockObject_MockObject|\Symfony\Component\HttpKernel\Log\LoggerInterface */
$loggerMock = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\LoggerInterface')
->disableOriginalConstructor()
->getMock();
$loggerMock = $this->getMockLogger();
$elasticaLogger = new ElasticaLogger($loggerMock);
@ -87,4 +119,54 @@ class ElasticaLoggerTest extends \PHPUnit_Framework_TestCase
$elasticaLogger->logQuery($path, $method, $data, $time);
}
/**
* @return array
*/
public function logLevels()
{
return array(
array('emergency'),
array('alert'),
array('critical'),
array('error'),
array('warning'),
array('notice'),
array('info'),
array('debug'),
);
}
/**
* @dataProvider logLevels
*/
public function testMessagesCanBeLoggedAtSpecificLogLevels($level)
{
$message = 'foo';
$context = array('data');
$loggerMock = $this->getMockLoggerForLevelMessageAndContext($level, $message, $context);
call_user_func(array($loggerMock, $level), $message, $context);
}
public function testMessagesCanBeLoggedToArbitraryLevels()
{
$loggerMock = $this->getMockLogger();
$level = 'info';
$message = 'foo';
$context = array('data');
$loggerMock->expects($this->once())
->method('log')
->with(
$level,
$message,
$context
);
$elasticaLogger = new ElasticaLogger($loggerMock);
$elasticaLogger->log($level, $message, $context);
}
}

View file

@ -97,5 +97,4 @@ class RepositoryManagerTest extends \PHPUnit_Framework_TestCase
$manager->addEntity($entityName, $finderMock, 'FOS\ElasticaBundle\Tests\MissingRepository');
$manager->getRepository('Missing Entity');
}
}

View file

@ -0,0 +1,131 @@
<?php
namespace FOS\ElasticaBundle\Tests\ObjectSerializerPersister;
use FOS\ElasticaBundle\Persister\ObjectPersister;
use FOS\ElasticaBundle\Persister\ObjectSerializerPersister;
use FOS\ElasticaBundle\Transformer\ModelToElasticaAutoTransformer;
use FOS\ElasticaBundle\Transformer\ModelToElasticaIdentifierTransformer;
use Symfony\Component\PropertyAccess\PropertyAccess;
class POPO
{
public $id = 123;
public $name = 'popoName';
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
}
class ObjectSerializerPersisterTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
if (!class_exists('Elastica\Type')) {
$this->markTestSkipped('The Elastica library classes are not available');
}
}
public function testThatCanReplaceObject()
{
$transformer = $this->getTransformer();
/** @var $typeMock \PHPUnit_Framework_MockObject_MockObject|\Elastica\Type */
$typeMock = $this->getMockBuilder('Elastica\Type')
->disableOriginalConstructor()
->getMock();
$typeMock->expects($this->once())
->method('deleteById')
->with($this->equalTo(123));
$typeMock->expects($this->once())
->method('addDocument');
$serializerMock = $this->getMockBuilder('FOS\ElasticaBundle\Serializer\Callback')->getMock();
$serializerMock->expects($this->once())->method('serialize');
$objectPersister = new ObjectSerializerPersister($typeMock, $transformer, 'SomeClass', array($serializerMock, 'serialize'));
$objectPersister->replaceOne(new POPO());
}
public function testThatCanInsertObject()
{
$transformer = $this->getTransformer();
/** @var $typeMock \PHPUnit_Framework_MockObject_MockObject|\Elastica\Type */
$typeMock = $this->getMockBuilder('Elastica\Type')
->disableOriginalConstructor()
->getMock();
$typeMock->expects($this->never())
->method('deleteById');
$typeMock->expects($this->once())
->method('addDocument');
$serializerMock = $this->getMockBuilder('FOS\ElasticaBundle\Serializer\Callback')->getMock();
$serializerMock->expects($this->once())->method('serialize');
$objectPersister = new ObjectSerializerPersister($typeMock, $transformer, 'SomeClass', array($serializerMock, 'serialize'));
$objectPersister->insertOne(new POPO());
}
public function testThatCanDeleteObject()
{
$transformer = $this->getTransformer();
/** @var $typeMock \PHPUnit_Framework_MockObject_MockObject|\Elastica\Type */
$typeMock = $this->getMockBuilder('Elastica\Type')
->disableOriginalConstructor()
->getMock();
$typeMock->expects($this->once())
->method('deleteById');
$typeMock->expects($this->never())
->method('addDocument');
$serializerMock = $this->getMockBuilder('FOS\ElasticaBundle\Serializer\Callback')->getMock();
$serializerMock->expects($this->once())->method('serialize');
$objectPersister = new ObjectSerializerPersister($typeMock, $transformer, 'SomeClass', array($serializerMock, 'serialize'));
$objectPersister->deleteOne(new POPO());
}
public function testThatCanInsertManyObjects()
{
$transformer = $this->getTransformer();
/** @var $typeMock \PHPUnit_Framework_MockObject_MockObject|\Elastica\Type */
$typeMock = $this->getMockBuilder('Elastica\Type')
->disableOriginalConstructor()
->getMock();
$typeMock->expects($this->never())
->method('deleteById');
$typeMock->expects($this->never())
->method('addObject');
$typeMock->expects($this->never())
->method('addObjects');
$typeMock->expects($this->once())
->method('addDocuments');
$serializerMock = $this->getMockBuilder('FOS\ElasticaBundle\Serializer\Callback')->getMock();
$serializerMock->expects($this->exactly(2))->method('serialize');
$objectPersister = new ObjectSerializerPersister($typeMock, $transformer, 'SomeClass', array($serializerMock, 'serialize'));
$objectPersister->insertMany(array(new POPO(), new POPO()));
}
/**
* @return ModelToElasticaIdentifierTransformer
*/
private function getTransformer()
{
$transformer = new ModelToElasticaIdentifierTransformer();
$transformer->setPropertyAccessor(PropertyAccess::getPropertyAccessor());
return $transformer;
}
}

View file

@ -9,7 +9,6 @@ use FOS\ElasticaBundle\Repository;
*/
class RepositoryTest extends \PHPUnit_Framework_TestCase
{
public function testThatFindCallsFindOnFinder()
{
$testQuery = 'Test Query';
@ -59,6 +58,22 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase
$repository->findPaginated($testQuery);
}
public function testThatCreatePaginatorCreatesAPaginatorViaFinder()
{
$testQuery = 'Test Query';
/** @var $typeMock \PHPUnit_Framework_MockObject_MockObject|\FOS\ElasticaBundle\Finder\TransformedFinder */
$finderMock = $this->getMockBuilder('FOS\ElasticaBundle\Finder\TransformedFinder')
->disableOriginalConstructor()
->getMock();
$finderMock->expects($this->once())
->method('createPaginatorAdapter')
->with($this->equalTo($testQuery));
$repository = new Repository($finderMock);
$repository->createPaginatorAdapter($testQuery);
}
public function testThatFindHybridCallsFindHybridOnFinder()
{
$testQuery = 'Test Query';
@ -75,5 +90,4 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase
$repository = new Repository($finderMock);
$repository->findHybrid($testQuery, $testLimit);
}
}

View file

@ -3,6 +3,7 @@
namespace FOS\ElasticaBundle\Tests\Transformer;
use Elastica\Document;
use Elastica\Result;
use FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerCollection;
class ElasticaToModelTransformerCollectionTest extends \PHPUnit_Framework_TestCase
@ -98,6 +99,57 @@ class ElasticaToModelTransformerCollectionTest extends \PHPUnit_Framework_TestCa
$result2,
), $results);
}
public function testGetIdentifierFieldReturnsAMapOfIdentifiers()
{
$collection = new ElasticaToModelTransformerCollection(array());
$identifiers = $collection->getIdentifierField();
$this->assertInternalType('array', $identifiers);
$this->assertEmpty($identifiers);
$this->collectionSetup();
$identifiers = $this->collection->getIdentifierField();
$this->assertInternalType('array', $identifiers);
$this->assertEquals(array('type1' => 'id', 'type2' => 'id'), $identifiers);
}
public function elasticaResults()
{
$result = new Result(array('_id' => 123, '_type' => 'type1'));
$transformedObject = new POPO(123, array());
return array(
array(
$result, $transformedObject
)
);
}
/**
* @dataProvider elasticaResults
*/
public function testHybridTransformDecoratesResultsWithHybridResultObjects($result, $transformedObject)
{
$transformer = $this->getMock('FOS\ElasticaBundle\Transformer\ElasticaToModelTransformerInterface');
$transformer->expects($this->any())->method('getIdentifierField')->will($this->returnValue('id'));
$transformer
->expects($this->any())
->method('transform')
->will($this->returnValue(array($transformedObject)));
$collection = new ElasticaToModelTransformerCollection(array('type1' => $transformer));
$hybridResults = $collection->hybridTransform(array($result));
$this->assertInternalType('array', $hybridResults);
$this->assertNotEmpty($hybridResults);
$this->assertContainsOnlyInstancesOf('FOS\ElasticaBundle\HybridResult', $hybridResults);
$hybridResult = array_pop($hybridResults);
$this->assertEquals($result, $hybridResult->getResult());
$this->assertEquals($transformedObject, $hybridResult->getTransformed());
}
}
class POPO
@ -119,5 +171,4 @@ class POPO
class POPO2 extends POPO
{
}

View file

@ -102,6 +102,11 @@ class POPO
);
}
public function getObj()
{
return array('foo' => 'foo', 'bar' => 'foo', 'id' => 1);
}
public function getUpper()
{
return (object) array('id' => 'parent', 'name' => 'a random name');
@ -118,7 +123,6 @@ class ModelToElasticaAutoTransformerTest extends \PHPUnit_Framework_TestCase
public function setUp()
{
if (!class_exists('Elastica\Document')) {
;
$this->markTestSkipped('The Elastica library classes are not available');
}
}
@ -273,6 +277,25 @@ class ModelToElasticaAutoTransformerTest extends \PHPUnit_Framework_TestCase
), $data['sub']);
}
public function testObjectDoesNotRequireProperties()
{
$transformer = $this->getTransformer();
$document = $transformer->transform(new POPO(), array(
'obj' => array(
'type' => 'object'
)
));
$data = $document->getData();
$this->assertTrue(array_key_exists('obj', $data));
$this->assertInternalType('array', $data['obj']);
$this->assertEquals(array(
'foo' => 'foo',
'bar' => 'foo',
'id' => 1
), $data['obj']);
}
public function testParentMapping()
{
$transformer = $this->getTransformer();

View file

@ -0,0 +1,65 @@
<?php
namespace FOS\ElasticaBundle\Tests\Transformer\ModelToElasticaIdentifierTransformer;
use FOS\ElasticaBundle\Transformer\ModelToElasticaIdentifierTransformer;
use Symfony\Component\PropertyAccess\PropertyAccess;
class POPO
{
protected $id = 123;
protected $name = 'Name';
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
}
class ModelToElasticaIdentifierTransformerTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
if (!class_exists('Elastica\Document')) {
$this->markTestSkipped('The Elastica library classes are not available');
}
}
public function testGetDocumentWithIdentifierOnly()
{
$transformer = $this->getTransformer();
$document = $transformer->transform(new POPO(), array());
$data = $document->getData();
$this->assertInstanceOf('Elastica\Document', $document);
$this->assertEquals(123, $document->getId());
$this->assertCount(0, $data);
}
public function testGetDocumentWithIdentifierOnlyWithFields()
{
$transformer = $this->getTransformer();
$document = $transformer->transform(new POPO(), array('name' => array()));
$data = $document->getData();
$this->assertInstanceOf('Elastica\Document', $document);
$this->assertEquals(123, $document->getId());
$this->assertCount(0, $data);
}
/**
* @return ModelToElasticaIdentifierTransformer
*/
private function getTransformer()
{
$transformer = new ModelToElasticaIdentifierTransformer();
$transformer->setPropertyAccessor(PropertyAccess::getPropertyAccessor());
return $transformer;
}
}

View file

@ -84,11 +84,4 @@ class ElasticaToModelTransformerCollection implements ElasticaToModelTransformer
return $result;
}
protected function getTypeToClassMap()
{
return array_map(function (ElasticaToModelTransformerInterface $transformer) {
return $transformer->getObjectClass();
}, $this->transformers);
}
}

View file

@ -71,11 +71,11 @@ class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterf
$value = $this->propertyAccessor->getValue($object, $key);
if (isset($mapping['type']) && in_array($mapping['type'], array('nested', 'object'))) {
if (isset($mapping['type']) && in_array($mapping['type'], array('nested', 'object')) && isset($mapping['properties'])) {
/* $value is a nested document or object. Transform $value into
* an array of documents, respective the mapped properties.
*/
$document->add($key, $this->transformNested($value, $mapping['properties']));
$document->set($key, $this->transformNested($value, $mapping['properties']));
continue;
}
@ -89,7 +89,7 @@ class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterf
continue;
}
$document->add($key, $this->normalizeValue($value));
$document->set($key, $this->normalizeValue($value));
}
return $document;
@ -149,5 +149,4 @@ class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterf
return $value;
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace FOS\ElasticaBundle\Transformer;
use Elastica\Document;
/**
* Creates an Elastica document with the ID of
* the Doctrine object as Elastica document ID
*/
class ModelToElasticaIdentifierTransformer extends ModelToElasticaAutoTransformer
{
/**
* Creates an elastica document with the id of the doctrine object as id
*
* @param object $object the object to convert
* @param array $fields the keys we want to have in the returned array
*
* @return Document
**/
public function transform($object, array $fields)
{
$identifier = $this->propertyAccessor->getValue($object, $this->options['identifier']);
return new Document($identifier);
}
}

32
UPGRADE-3.0.md Normal file
View file

@ -0,0 +1,32 @@
UPGRADE FROM 2.1 to 3.0
=======================
### Serialization
* you can now define a Serializer service and callback for indexing. All providers and listeners will use it.
```yml
serializer:
callback_class: FOS\ElasticaBundle\Serializer\Callback
serializer: serializer
```
### Mapping
* you do not have to setup any mapping anymore if you use a Serializer, properties are no more indexed only if
they are mapped. So this kind of configuration became valid:
```yml
serializer:
callback_class: FOS\ElasticaBundle\Serializer\Callback
serializer: serializer
indexes:
acme:
client: default
types:
Article:
persistence:
driver: orm
model: Acme\Bundle\CoreBundle\Entity\Article
provider: ~
```