diff --git a/search_api.services.yml b/search_api.services.yml index 1b7dc72..279b0b0 100644 --- a/search_api.services.yml +++ b/search_api.services.yml @@ -51,11 +51,11 @@ services: - { name: event_subscriber } search_api.data_type_helper: - class: \Drupal\search_api\Utility\Utility\DataTypeHelper + class: \Drupal\search_api\Utility\DataTypeHelper arguments: ['@module_handler', '@plugin.manager.search_api.data_type'] search_api.fields_helper: - class: \Drupal\search_api\Utility\Utility\FieldsHelper + class: \Drupal\search_api\Utility\FieldsHelper arguments: ['@entity_field.manager', '@entity_type.bundle.info', '@search_api.data_type_helper'] search_api.index_task_manager: @@ -64,9 +64,9 @@ services: tags: - { name: event_subscriber } - search_api.results_static_cache: - class: Drupal\search_api\Query\ResultsCache - arguments: ['@request_stack'] + search_api.query_helper: + class: Drupal\search_api\Utility\QueryHelper + arguments: ['@request_stack', '@module_handler', '@plugin.manager.search_api.parse_mode'] search_api.server_task_manager: class: Drupal\search_api\Task\ServerTaskManager diff --git a/src/Plugin/views/cache/SearchApiCache.php b/src/Plugin/views/cache/SearchApiCache.php index 18c1580..6867bca 100644 --- a/src/Plugin/views/cache/SearchApiCache.php +++ b/src/Plugin/views/cache/SearchApiCache.php @@ -66,9 +66,9 @@ public function cacheGet($type) { // et al. work. /** @var \Drupal\search_api\Query\ResultSetInterface $results */ $results = $cache->data['search_api results']; - /** @var \Drupal\search_api\Query\ResultsCacheInterface $static_results_cache */ - $static_results_cache = \Drupal::service('search_api.results_static_cache'); - $static_results_cache->addResults($results); + \Drupal::getContainer() + ->get('search_api.query_helper') + ->addResults($results); try { $this->getQuery()->setSearchApiResults($results); diff --git a/src/Processor/FieldsProcessorPluginBase.php b/src/Processor/FieldsProcessorPluginBase.php index c139959..bbe6c82 100644 --- a/src/Processor/FieldsProcessorPluginBase.php +++ b/src/Processor/FieldsProcessorPluginBase.php @@ -7,7 +7,7 @@ use Drupal\Core\Plugin\PluginFormInterface; use Drupal\Core\Render\Element; use Drupal\search_api\Item\FieldInterface; -use Drupal\search_api\Utility\FieldsHelperInterface; +use Drupal\search_api\Utility\DataTypeHelperInterface; use Drupal\search_api\Plugin\PluginFormTrait; use Drupal\search_api\Plugin\search_api\data_type\value\TextValueInterface; use Drupal\search_api\Query\ConditionGroupInterface; @@ -40,11 +40,11 @@ use PluginFormTrait; /** - * The field helper. + * The data type helper. * - * @var \Drupal\search_api\Utility\FieldsHelperInterface|null + * @var \Drupal\search_api\Utility\DataTypeHelperInterface|null */ - protected $fieldHelper; + protected $dataTypeHelper; // @todo Add defaultConfiguration() implementation and find a cleaner solution // for all the isset($this->configuration['fields']) checks. @@ -56,31 +56,31 @@ public static function create(ContainerInterface $container, array $configuratio /** @var static $processor */ $processor = parent::create($container, $configuration, $plugin_id, $plugin_definition); - $processor->setFieldHelper($container->get('search_api.fields_helper')); + $processor->setDataTypeHelper($container->get('search_api.data_type_helper')); return $processor; } /** - * Retrieves the field helper. + * Retrieves the data type helper. * - * @return \Drupal\search_api\Utility\FieldsHelperInterface - * The field helper. + * @return \Drupal\search_api\Utility\DataTypeHelperInterface + * The data type helper. */ - public function getFieldHelper() { - return $this->fieldHelper ?: \Drupal::service('search_api.fields_helper'); + public function getDataTypeHelper() { + return $this->dataTypeHelper ?: \Drupal::service('search_api.data_type_helper'); } /** - * Sets the field helper. + * Sets the data type helper. * - * @param \Drupal\search_api\Utility\FieldsHelperInterface $field_helper - * The new field helper. + * @param \Drupal\search_api\Utility\DataTypeHelperInterface $data_type_helper + * The new data type helper. * * @return $this */ - public function setFieldHelper(FieldsHelperInterface $field_helper) { - $this->fieldHelper = $field_helper; + public function setDataTypeHelper(DataTypeHelperInterface $data_type_helper) { + $this->dataTypeHelper = $data_type_helper; return $this; } @@ -330,7 +330,7 @@ protected function testField($name, FieldInterface $field) { * TRUE if fields of that type should be processed, FALSE otherwise. */ protected function testType($type) { - return $this->getFieldHelper()->isTextType($type, array('text', 'string')); + return $this->getDataTypeHelper()->isTextType($type, array('text', 'string')); } /** diff --git a/src/Query/Query.php b/src/Query/Query.php index f6f34d4..6c409bc 100644 --- a/src/Query/Query.php +++ b/src/Query/Query.php @@ -3,10 +3,13 @@ namespace Drupal\search_api\Query; use Drupal\Core\DependencyInjection\DependencySerializationTrait; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\search_api\IndexInterface; use Drupal\search_api\ParseMode\ParseModeInterface; +use Drupal\search_api\ParseMode\ParseModePluginManager; use Drupal\search_api\SearchApiException; +use Drupal\search_api\Utility\QueryHelperInterface; /** * Provides a standard implementation for a Search API query. @@ -43,13 +46,6 @@ class Query implements QueryInterface { protected $results; /** - * The result cache service. - * - * @var \Drupal\search_api\Query\ResultsCacheInterface - */ - protected $resultsCache; - - /** * The parse mode to use for fulltext search keys. * * @var \Drupal\search_api\ParseMode\ParseModeInterface|null @@ -145,12 +141,31 @@ class Query implements QueryInterface { protected $executed = FALSE; /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface|null + */ + protected $moduleHandler; + + /** + * The parse mode manager. + * + * @var \Drupal\search_api\ParseMode\ParseModePluginManager|null + */ + protected $parseModeManager; + + /** + * The result cache service. + * + * @var \Drupal\search_api\Utility\QueryHelperInterface + */ + protected $queryHelper; + + /** * Constructs a Query object. * * @param \Drupal\search_api\IndexInterface $index * The index the query should be executed on. - * @param \Drupal\search_api\Query\ResultsCacheInterface $results_cache - * The results cache that should be used for this query. * @param array $options * (optional) Associative array of options configuring this query. See * \Drupal\search_api\Query\QueryInterface::setOption() for a list of @@ -160,14 +175,13 @@ class Query implements QueryInterface { * Thrown if a search on that index (or with those options) won't be * possible. */ - public function __construct(IndexInterface $index, ResultsCacheInterface $results_cache, array $options = array()) { + public function __construct(IndexInterface $index, array $options = array()) { if (!$index->status()) { $index_label = $index->label(); throw new SearchApiException("Can't search on index '$index_label' which is disabled."); } $this->index = $index; $this->results = new ResultSet($this); - $this->resultsCache = $results_cache; $this->options = $options + array( 'conjunction' => 'AND', 'search id' => __CLASS__, @@ -178,8 +192,77 @@ public function __construct(IndexInterface $index, ResultsCacheInterface $result /** * {@inheritdoc} */ - public static function create(IndexInterface $index, ResultsCacheInterface $results_cache, array $options = array()) { - return new static($index, $results_cache, $options); + public static function create(IndexInterface $index, array $options = array()) { + return new static($index, $options); + } + + /** + * Retrieves the module handler. + * + * @return \Drupal\Core\Extension\ModuleHandlerInterface + * The module handler. + */ + public function getModuleHandler() { + return $this->moduleHandler ?: \Drupal::moduleHandler(); + } + + /** + * Sets the module handler. + * + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The new module handler. + * + * @return $this + */ + public function setModuleHandler(ModuleHandlerInterface $module_handler) { + $this->moduleHandler = $module_handler; + return $this; + } + + /** + * Retrieves the parse mode manager. + * + * @return \Drupal\search_api\ParseMode\ParseModePluginManager + * The parse mode manager. + */ + public function getParseModeManager() { + return $this->parseModeManager ?: \Drupal::service('plugin.manager.search_api.parse_mode'); + } + + /** + * Sets the parse mode manager. + * + * @param \Drupal\search_api\ParseMode\ParseModePluginManager $parse_mode_manager + * The new parse mode manager. + * + * @return $this + */ + public function setParseModeManager(ParseModePluginManager $parse_mode_manager) { + $this->parseModeManager = $parse_mode_manager; + return $this; + } + + /** + * Retrieves the query helper. + * + * @return \Drupal\search_api\Utility\QueryHelperInterface + * The query helper. + */ + public function getQueryHelper() { + return $this->queryHelper ?: \Drupal::service('search_api.query_helper'); + } + + /** + * Sets the query helper. + * + * @param \Drupal\search_api\Utility\QueryHelperInterface $query_helper + * The new query helper. + * + * @return $this + */ + public function setQueryHelper(QueryHelperInterface $query_helper) { + $this->queryHelper = $query_helper; + return $this; } /** @@ -187,10 +270,8 @@ public static function create(IndexInterface $index, ResultsCacheInterface $resu */ public function getParseMode() { if (!$this->parseMode) { - $this->parseMode = \Drupal::getContainer() - ->get('plugin.manager.search_api.parse_mode') - ->createInstance('terms') - ->setConjunction($this->options['conjunction']); + $this->parseMode = $this->getParseModeManager()->createInstance('terms'); + $this->parseMode->setConjunction($this->options['conjunction']); } return $this->parseMode; } @@ -384,7 +465,7 @@ public function preExecute() { foreach ($this->tags as $tag) { $hooks[] = "search_api_query_$tag"; } - \Drupal::moduleHandler()->alter($hooks, $this); + $this->getModuleHandler()->alter($hooks, $this); } } @@ -404,10 +485,10 @@ public function postExecute() { foreach ($this->tags as $tag) { $hooks[] = "search_api_results_$tag"; } - \Drupal::moduleHandler()->alter($hooks, $this->results); + $this->getModuleHandler()->alter($hooks, $this->results); // Store the results in the static cache. - $this->resultsCache->addResults($this->results); + $this->getQueryHelper()->addResults($this->results); } /** diff --git a/src/Query/QueryInterface.php b/src/Query/QueryInterface.php index fc0db7b..fb8778e 100644 --- a/src/Query/QueryInterface.php +++ b/src/Query/QueryInterface.php @@ -2,8 +2,10 @@ namespace Drupal\search_api\Query; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\search_api\IndexInterface; use Drupal\search_api\ParseMode\ParseModeInterface; +use Drupal\search_api\ParseMode\ParseModePluginManager; /** * Represents a search query on a Search API index. @@ -55,8 +57,6 @@ * * @param \Drupal\search_api\IndexInterface $index * The index for which the query should be created. - * @param \Drupal\search_api\Query\ResultsCacheInterface $results_cache - * The results cache that should be used for this query. * @param array $options * (optional) The options to set for the query. * @@ -67,7 +67,7 @@ * Thrown if a search on that index (or with those options) won't be * possible. */ - public static function create(IndexInterface $index, ResultsCacheInterface $results_cache, array $options = array()); + public static function create(IndexInterface $index, array $options = array()); /** * Retrieves the parse mode. diff --git a/src/Query/ResultsCache.php b/src/Utility/QueryHelper.php similarity index 65% rename from src/Query/ResultsCache.php rename to src/Utility/QueryHelper.php index be92bf5..c4d7d17 100644 --- a/src/Query/ResultsCache.php +++ b/src/Utility/QueryHelper.php @@ -1,14 +1,18 @@ requestStack = $request_stack; + public function __construct(RequestStack $requestStack, ModuleHandlerInterface $moduleHandler, ParseModePluginManager $parseModeManager) { + $this->requestStack = $requestStack; + $this->moduleHandler = $moduleHandler; + $this->parseModeManager = $parseModeManager; $this->results = new \SplObjectStorage(); $this->null = (object) array(); } @@ -47,14 +71,20 @@ public function __construct(RequestStack $request_stack) { * {@inheritdoc} */ public function createQuery(IndexInterface $index, array $options = array()) { - return Query::create($index, $this, $options); + $query = Query::create($index, $options); + + $query->setModuleHandler($this->moduleHandler); + $query->setParseModeManager($this->parseModeManager); + $query->setQueryHelper($this); + + return $query; } /** * {@inheritdoc} */ public function addResults(ResultSetInterface $results) { - // @todo Create getter and setter methods for the search ID. + // @todo Create getter and setter methods for the search ID. See #2772829. $search_id = $results->getQuery()->getOption('search id', ''); $request = $this->getCurrentRequest(); if (!isset($this->results[$request])) { diff --git a/src/Query/ResultsCacheInterface.php b/src/Utility/QueryHelperInterface.php similarity index 88% rename from src/Query/ResultsCacheInterface.php rename to src/Utility/QueryHelperInterface.php index 6782235..8268f5d 100644 --- a/src/Query/ResultsCacheInterface.php +++ b/src/Utility/QueryHelperInterface.php @@ -1,13 +1,14 @@ get('search_api.results_static_cache') + ->get('search_api.query_helper') ->createQuery($index, $options); } diff --git a/tests/src/Kernel/QueryTest.php b/tests/src/Kernel/QueryTest.php index 035665c..f94399b 100644 --- a/tests/src/Kernel/QueryTest.php +++ b/tests/src/Kernel/QueryTest.php @@ -172,8 +172,7 @@ public function testQueryCloning() { * Tests that serialization of queries works correctly. */ public function testQuerySerialization() { - $results_cache = $this->container->get('search_api.results_static_cache'); - $query = Query::create($this->index, $results_cache); + $query = Query::create($this->index); $tags = array('tag1', 'tag2'); $query->keys('foo bar') ->addCondition('field1', 'value', '<') diff --git a/tests/src/Unit/Plugin/Processor/TestItemsTrait.php b/tests/src/Unit/Plugin/Processor/TestItemsTrait.php index 9a1ce10..50326cc 100644 --- a/tests/src/Unit/Plugin/Processor/TestItemsTrait.php +++ b/tests/src/Unit/Plugin/Processor/TestItemsTrait.php @@ -5,7 +5,9 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\TypedData\ComplexDataInterface; use Drupal\search_api\IndexInterface; +use Drupal\search_api\Item\Field; use Drupal\search_api\Item\FieldInterface; +use Drupal\search_api\Utility\DataTypeHelper; use Drupal\search_api\Utility\FieldsHelper; use Drupal\search_api\Item\Item; use Drupal\search_api\Query\Query; @@ -50,8 +52,8 @@ */ public function createSingleFieldItem(IndexInterface $index, $fieldType, $fieldValue, FieldInterface &$field = NULL, $fieldId = 'field_test') { $this->itemIds[0] = $itemId = Utility::createCombinedId('entity:node', '1:en'); - $item = Utility::createItem($index, $itemId); - $field = Utility::createField($index, $fieldId); + $item = new Item($index, $itemId); + $field = new Field($index, $fieldId); $field->setType($fieldType); $field->addValue($fieldValue); $item->setField($fieldId, $field); @@ -90,13 +92,17 @@ public function createItems(IndexInterface $index, $count, array $fields, Comple $item->setOriginalObject($object); } foreach ($fields as $combined_property_path => $field_info) { - list($field_info['datasource_id'], $field_info['property_path']) = Utility::splitCombinedId($combined_property_path); + list($field_datasource_id, $property_path) = Utility::splitCombinedId($combined_property_path); // Only add fields of the right datasource. - if (isset($field_info['datasource_id']) && $field_info['datasource_id'] != $datasource_id) { + if (isset($field_datasource_id) && $field_datasource_id != $datasource_id) { continue; } - $field_id = Utility::getNewFieldId($index, $field_info['property_path']); - $field = Utility::createField($index, $field_id, $field_info); + $field_id = \Drupal::getContainer() + ->get('search_api.fields_helper') + ->getNewFieldId($index, $property_path); + $field = new Field($index, $field_id); + $field->setDatasourceId($field_datasource_id) + ->setPropertyPath($property_path); $item->setField($field_id, $field); } $item->setFieldsExtracted(TRUE); @@ -106,7 +112,7 @@ public function createItems(IndexInterface $index, $count, array $fields, Comple } /** - * Adds mock data type plugin manager and results cache services to \Drupal. + * Adds a container with several mock services commonly needed by our tests. */ protected function setUpMockContainer() { /** @var \Drupal\Tests\UnitTestCase|\Drupal\Tests\search_api\Unit\Plugin\Processor\TestItemsTrait $this */ @@ -116,31 +122,32 @@ protected function setUpMockContainer() { $dataTypeManager->method('getInstances') ->will($this->returnValue(array())); - $entityFieldManager = $this->getMockBuilder('Drupal\Core\Entity\EntityFieldManagerInterface') + $moduleHandler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandlerInterface') ->disableOriginalConstructor() ->getMock(); - $entityBundleInfo = $this->getMockBuilder('Drupal\Core\Entity\EntityTypeBundleInfoInterface') + $dataTypeHelper = new DataTypeHelper($moduleHandler, $dataTypeManager); + + $entityFieldManager = $this->getMockBuilder('Drupal\Core\Entity\EntityFieldManagerInterface') ->disableOriginalConstructor() ->getMock(); - $moduleHandler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandlerInterface') + $entityBundleInfo = $this->getMockBuilder('Drupal\Core\Entity\EntityTypeBundleInfoInterface') ->disableOriginalConstructor() ->getMock(); - $fieldsHelper = new FieldsHelper($entityFieldManager, $entityBundleInfo, $moduleHandler, $dataTypeManager); + $fieldsHelper = new FieldsHelper($entityFieldManager, $entityBundleInfo, $dataTypeHelper); - $resultsStaticCache = $this->getMockBuilder('Drupal\search_api\Query\ResultsCache') - ->disableOriginalConstructor() - ->getMock(); - $resultsStaticCache->method('createQuery') - ->willReturnCallback(function (IndexInterface $index, array $options = array()) use ($resultsStaticCache) { - return Query::create($index, $resultsStaticCache, $options); + $queryHelper = $this->getMock('Drupal\search_api\Utility\QueryHelperInterface'); + $queryHelper->method('createQuery') + ->willReturnCallback(function (IndexInterface $index, array $options = array()) { + return Query::create($index, $options); }); - $resultsStaticCache->method('getResults') + $queryHelper->method('getResults') ->will($this->returnValue(array())); $this->container = new ContainerBuilder(); $this->container->set('plugin.manager.search_api.data_type', $dataTypeManager); + $this->container->set('search_api.data_type_helper', $dataTypeHelper); $this->container->set('search_api.fields_helper', $fieldsHelper); - $this->container->set('search_api.results_static_cache', $resultsStaticCache); + $this->container->set('search_api.query_helper', $queryHelper); \Drupal::setContainer($this->container); }