View source
<?php
namespace Drupal\Tests\search_api\Kernel\ConfigEntity;
use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\KernelTests\KernelTestBase;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\search_api\Entity\Index;
use Drupal\search_api\Entity\Server;
use Drupal\search_api_test\PluginTestTrait;
class DependencyRemovalTest extends KernelTestBase {
use EntityReferenceTestTrait;
use PluginTestTrait;
protected $index;
protected $dependency;
public static $modules = [
'user',
'system',
'field',
'search_api',
'search_api_test',
];
public function setUp() {
parent::setUp();
$this
->installEntitySchema('user');
$this
->installEntitySchema('search_api_task');
$this
->installConfig('search_api');
$this->index = Index::create([
'id' => 'test_index',
'name' => 'Test index',
'tracker_settings' => [
'default' => [],
],
'datasource_settings' => [
'entity:user' => [],
],
]);
$this->dependency = Server::create([
'id' => 'dependency',
'name' => 'Test dependency',
'backend' => 'search_api_test',
]);
$this->dependency
->save();
}
public function testFieldDependency() {
$this
->createEntityReferenceField('user', 'user', 'parent', 'Parent', 'user');
$parent_field_storage = FieldStorageConfig::loadByName('user', 'parent');
$field_storage = FieldStorageConfig::create([
'field_name' => 'field_search',
'type' => 'string',
'entity_type' => 'user',
]);
$field_storage
->save();
$field_search = FieldConfig::create([
'field_name' => 'field_search',
'field_type' => 'string',
'entity_type' => 'user',
'bundle' => 'user',
'label' => 'Search Field',
]);
$field_search
->save();
$fields_helper = \Drupal::getContainer()
->get('search_api.fields_helper');
$field = $fields_helper
->createFieldFromProperty($this->index, $field_storage
->getPropertyDefinition('value'), 'entity:user', 'field_search', 'search', 'string');
$this->index
->addField($field);
$field = $fields_helper
->createFieldFromProperty($this->index, $field_storage
->getPropertyDefinition('value'), 'entity:user', 'parent:entity:field_search', 'parent_search', 'string');
$this->index
->addField($field);
$field = $fields_helper
->createFieldFromProperty($this->index, $parent_field_storage
->getPropertyDefinition('target_id'), 'entity:user', 'parent', 'parent', 'string');
$this->index
->addField($field);
$this->index
->save();
$config_dependencies = \Drupal::config('search_api.index.' . $this->index
->id())
->get('dependencies.config');
$this
->assertContains($parent_field_storage
->getConfigDependencyName(), $config_dependencies);
$this
->assertContains($field_storage
->getConfigDependencyName(), $config_dependencies);
$parent_field_storage
->delete();
$this
->reloadIndex();
$index = \Drupal::config('search_api.index.' . $this->index
->id());
$dependencies = $index
->get('dependencies');
$this
->assertFalse(isset($dependencies['config'][$parent_field_storage
->getConfigDependencyName()]));
$this
->assertContains($field_storage
->getConfigDependencyName(), $config_dependencies);
$this
->assertEquals([
'search',
], array_keys($index
->get('field_settings')));
$field_storage
->delete();
$this
->reloadIndex();
$dependencies = \Drupal::config('search_api.index.' . $this->index
->id())
->get('dependencies');
$this
->assertFalse(isset($dependencies['config'][$field_storage
->getConfigDependencyName()]));
$this
->assertEquals([], array_keys($index
->get('field_settings')));
}
public function testBackendDependency($remove_dependency) {
$dependency_key = $this->dependency
->getConfigDependencyKey();
$dependency_name = $this->dependency
->getConfigDependencyName();
$server = Server::create([
'id' => 'test_server',
'name' => 'Test server',
'backend' => 'search_api_test',
'backend_config' => [
'dependencies' => [
$dependency_key => [
$dependency_name,
],
],
],
]);
$server
->save();
$server_dependency_key = $server
->getConfigDependencyKey();
$server_dependency_name = $server
->getConfigDependencyName();
$this->index
->setServer($server);
$this->index
->disable();
$this->index
->save();
$server_dependencies = $server
->getDependencies();
$this
->assertContains($dependency_name, $server_dependencies[$dependency_key], 'Backend dependency correctly inserted');
$index_dependencies = $this->index
->getDependencies();
$this
->assertContains($server_dependency_name, $index_dependencies[$server_dependency_key], 'Server dependency correctly inserted');
$this
->setReturnValue('backend', 'onDependencyRemoval', $remove_dependency);
$this->dependency
->delete();
$this
->reloadIndex();
$this
->assertInstanceOf('Drupal\\search_api\\IndexInterface', $this->index, 'Index not removed');
$storage = \Drupal::entityTypeManager()
->getStorage('search_api_server');
$storage
->resetCache();
$server = $storage
->load($server
->id());
if ($remove_dependency) {
$this
->assertInstanceOf('Drupal\\search_api\\ServerInterface', $server, 'Server was not removed');
$this
->assertArrayNotHasKey('dependencies', $server
->get('backend_config'), 'Backend config was adapted');
}
else {
$this
->assertNull($server, 'Server was removed');
$this
->assertEquals(NULL, $this->index
->getServerId(), 'Index server was changed');
}
}
public function testDatasourceDependency($remove_dependency) {
$dependency_key = $this->dependency
->getConfigDependencyKey();
$dependency_name = $this->dependency
->getConfigDependencyName();
$datasources = \Drupal::getContainer()
->get('search_api.plugin_helper')
->createDatasourcePlugins($this->index, [
'entity:user',
'search_api_test',
], [
'search_api_test' => [
$dependency_key => [
$dependency_name,
],
],
]);
$this->index
->setDatasources($datasources);
$this->index
->save();
$dependencies = $this->index
->getDependencies();
$this
->assertContains($dependency_name, $dependencies[$dependency_key], 'Datasource dependency correctly inserted');
$this
->setReturnValue('datasource', 'onDependencyRemoval', $remove_dependency);
$this->dependency
->delete();
$this
->reloadIndex();
$this
->assertInstanceOf('Drupal\\search_api\\IndexInterface', $this->index, 'Index not removed');
$dependencies = $this->index
->getDependencies();
$dependencies += [
$dependency_key => [],
];
$this
->assertNotContains($dependency_name, $dependencies[$dependency_key], 'Datasource dependency removed from index');
$datasources = $this->index
->getDatasources();
if ($remove_dependency) {
$this
->assertArrayHasKey('search_api_test', $datasources, 'Datasource not removed');
$this
->assertEmpty($datasources['search_api_test']
->getConfiguration(), 'Datasource settings adapted');
}
else {
$this
->assertArrayNotHasKey('search_api_test', $datasources, 'Datasource removed');
}
}
public function testSingleDatasourceDependency() {
$dependency_key = $this->dependency
->getConfigDependencyKey();
$dependency_name = $this->dependency
->getConfigDependencyName();
$datasources['search_api_test'] = \Drupal::getContainer()
->get('search_api.plugin_helper')
->createDatasourcePlugin($this->index, 'search_api_test', [
$dependency_key => [
$dependency_name,
],
]);
$this->index
->setDatasources($datasources);
$this->index
->save();
$mock = $this
->createMock(KeyValueStoreExpirableInterface::class);
$mock_factory = $this
->createMock(KeyValueExpirableFactoryInterface::class);
$mock_factory
->method('get')
->willReturn($mock);
$this->container
->set('keyvalue.expirable', $mock_factory);
$this->dependency
->delete();
$this
->reloadIndex();
$this
->assertNull($this->index, 'Index was removed');
}
public function testProcessorDependency($remove_dependency) {
$dependency_key = $this->dependency
->getConfigDependencyKey();
$dependency_name = $this->dependency
->getConfigDependencyName();
$processor = \Drupal::getContainer()
->get('search_api.plugin_helper')
->createProcessorPlugin($this->index, 'search_api_test', [
$dependency_key => [
$dependency_name,
],
]);
$this->index
->addProcessor($processor);
$this->index
->save();
$dependencies = $this->index
->getDependencies();
$this
->assertContains($dependency_name, $dependencies[$dependency_key], 'Processor dependency correctly inserted');
$this
->setReturnValue('processor', 'onDependencyRemoval', $remove_dependency);
$this->dependency
->delete();
$this
->reloadIndex();
$this
->assertInstanceOf('Drupal\\search_api\\IndexInterface', $this->index, 'Index not removed');
$dependencies = $this->index
->getDependencies();
$dependencies += [
$dependency_key => [],
];
$this
->assertNotContains($dependency_name, $dependencies[$dependency_key], 'Processor dependency removed from index');
$processors = $this->index
->getProcessors();
if ($remove_dependency) {
$this
->assertArrayHasKey('search_api_test', $processors, 'Processor not removed');
$this
->assertEmpty($processors['search_api_test']
->getConfiguration(), 'Processor settings adapted');
}
else {
$this
->assertArrayNotHasKey('search_api_test', $processors, 'Processor removed');
}
}
public function testTrackerDependency($remove_dependency) {
$dependency_key = $this->dependency
->getConfigDependencyKey();
$dependency_name = $this->dependency
->getConfigDependencyName();
$tracker = \Drupal::getContainer()
->get('search_api.plugin_helper')
->createTrackerPlugin($this->index, 'search_api_test', [
'dependencies' => [
$dependency_key => [
$dependency_name,
],
],
]);
$this->index
->setTracker($tracker);
$this->index
->save();
$dependencies = $this->index
->getDependencies();
$this
->assertContains($dependency_name, $dependencies[$dependency_key], 'Tracker dependency correctly inserted');
$this
->setReturnValue('tracker', 'onDependencyRemoval', $remove_dependency);
$this->dependency
->delete();
$this
->reloadIndex();
$this
->assertInstanceOf('Drupal\\search_api\\IndexInterface', $this->index, 'Index not removed');
$dependencies = $this->index
->getDependencies();
$dependencies += [
$dependency_key => [],
];
$this
->assertNotContains($dependency_name, $dependencies[$dependency_key], 'Tracker dependency removed from index');
$tracker_instance = $this->index
->getTrackerInstance();
$tracker_id = $tracker_instance
->getPluginId();
$tracker_config = $tracker_instance
->getConfiguration();
if ($remove_dependency) {
$this
->assertEquals('search_api_test', $tracker_id, 'Tracker not reset');
$this
->assertEmpty($tracker_config['dependencies'], 'Tracker settings adapted');
}
else {
$this
->assertEquals('default', $tracker_id, 'Tracker was reset');
$this
->assertEquals($tracker_instance
->defaultConfiguration(), $tracker_config, 'Tracker settings were cleared');
}
}
public function dependencyTestDataProvider() {
return [
'Remove dependency' => [
TRUE,
],
'Keep dependency' => [
FALSE,
],
];
}
public function testModuleDependency() {
$datasource = \Drupal::getContainer()
->get('search_api.plugin_helper')
->createDatasourcePlugin($this->index, 'search_api_test');
$this->index
->addDatasource($datasource);
$datasource = \Drupal::getContainer()
->get('search_api.plugin_helper')
->createDatasourcePlugin($this->index, 'entity:user');
$this->index
->addDatasource($datasource);
$processor = \Drupal::getContainer()
->get('search_api.plugin_helper')
->createProcessorPlugin($this->index, 'search_api_test');
$this->index
->addProcessor($processor);
$tracker = \Drupal::getContainer()
->get('search_api.plugin_helper')
->createTrackerPlugin($this->index, 'search_api_test');
$this->index
->setTracker($tracker);
$this->index
->save();
$dependencies = $this->index
->getDependencies();
$this
->assertContains('search_api_test', $dependencies['module'], 'Module dependency correctly inserted');
$this
->installConfig('search_api');
\Drupal::getContainer()
->get('config.manager')
->uninstall('module', 'search_api_test');
$this
->reloadIndex();
$this
->assertInstanceOf('Drupal\\search_api\\IndexInterface', $this->index, 'Index not removed');
$dependencies = $this->index
->getDependencies();
$dependencies += [
'module' => [],
];
$this
->assertNotContains('search_api_test', $dependencies['module'], 'Module dependency removed from index');
$this
->assertNotContains('search_api_test', $this->index
->getDatasources(), 'Datasource was removed');
$this
->assertArrayNotHasKey('search_api_test', $this->index
->getProcessors(), 'Processor was removed');
$this
->assertEquals('default', $this->index
->getTrackerId(), 'Tracker was reset');
}
public function testDataTypeDependency($dependency_type) {
switch ($dependency_type) {
case 'module':
$type = 'search_api_test';
$config_dependency_key = 'module';
$config_dependency_name = 'search_api_test';
break;
case 'config':
$type = 'search_api_test_altering';
$config_dependency_key = $this->dependency
->getConfigDependencyKey();
$config_dependency_name = $this->dependency
->getConfigDependencyName();
\Drupal::state()
->set('search_api_test.data_type.dependencies', [
$config_dependency_key => [
$config_dependency_name,
],
]);
break;
default:
$this
->fail();
return;
}
$datasources = \Drupal::getContainer()
->get('search_api.plugin_helper')
->createDatasourcePlugins($this->index, [
'entity:user',
]);
$this->index
->setDatasources($datasources);
$field = \Drupal::getContainer()
->get('search_api.fields_helper')
->createField($this->index, 'uid', [
'label' => 'ID',
'datasource_id' => 'entity:user',
'property_path' => 'uid',
'type' => $type,
]);
$this->index
->addField($field);
$this->index
->setServer(NULL);
$this->index
->save();
$dependencies = $this->index
->getDependencies();
$dependencies += [
$config_dependency_key => [],
];
$this
->assertContains($config_dependency_name, $dependencies[$config_dependency_key], 'Data type dependency correctly inserted');
switch ($dependency_type) {
case 'module':
\Drupal::getContainer()
->get('config.manager')
->uninstall('module', 'search_api_test');
break;
case 'config':
$this->dependency
->delete();
break;
}
$this
->reloadIndex();
$this
->assertInstanceOf('Drupal\\search_api\\IndexInterface', $this->index, 'Index not removed');
$dependencies = $this->index
->getDependencies();
$dependencies += [
$config_dependency_key => [],
];
$this
->assertNotContains($config_dependency_name, $dependencies[$config_dependency_key], 'Data type dependency correctly removed');
$field = $this->index
->getField('uid');
$this
->assertNotNull($field, 'Field was not removed');
$this
->assertEquals('string', $field
->getType(), 'Field type was changed to fallback type');
}
public function dataTypeDependencyTestDataProvider() {
return [
'Module dependency' => [
'module',
],
'Config dependency' => [
'config',
],
];
}
protected function reloadIndex() {
$storage = \Drupal::entityTypeManager()
->getStorage('search_api_index');
$storage
->resetCache();
$this->index = $storage
->load($this->index
->id());
}
}