Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
33.33% |
4 / 12 |
CRAP | |
44.78% |
30 / 67 |
| QueryFactory | |
0.00% |
0 / 1 |
|
33.33% |
4 / 12 |
160.04 | |
44.78% |
30 / 67 |
| __construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
5 / 5 |
|||
| get | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getAggregate | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getConfigKeyStore | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| updateConfigKeyStore | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 8 |
|||
| deleteConfigKeyStore | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 11 |
|||
| getKeys | |
100.00% |
1 / 1 |
3 | |
100.00% |
7 / 7 |
|||
| anonymous function | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
| getValues | |
100.00% |
1 / 1 |
5 | |
100.00% |
13 / 13 |
|||
| onConfigSave | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| onConfigDelete | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| getSubscribedEvents | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\Core\Config\Entity\Query\QueryFactory. | |
| */ | |
| namespace Drupal\Core\Config\Entity\Query; | |
| use Drupal\Core\Config\Config; | |
| use Drupal\Core\Config\ConfigCrudEvent; | |
| use Drupal\Core\Config\ConfigEvents; | |
| use Drupal\Core\Config\ConfigFactoryInterface; | |
| use Drupal\Core\Config\ConfigManagerInterface; | |
| use Drupal\Core\Config\Entity\ConfigEntityTypeInterface; | |
| use Drupal\Core\Entity\EntityTypeInterface; | |
| use Drupal\Core\Entity\Query\QueryBase; | |
| use Drupal\Core\Entity\Query\QueryException; | |
| use Drupal\Core\Entity\Query\QueryFactoryInterface; | |
| use Drupal\Core\KeyValueStore\KeyValueFactoryInterface; | |
| use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
| /** | |
| * Provides a factory for creating entity query objects for the config backend. | |
| */ | |
| class QueryFactory implements QueryFactoryInterface, EventSubscriberInterface { | |
| /** | |
| * The prefix for the key value collection for fast lookups. | |
| */ | |
| const CONFIG_LOOKUP_PREFIX = 'config.entity.key_store.'; | |
| /** | |
| * The config factory used by the config entity query. | |
| * | |
| * @var \Drupal\Core\Config\ConfigFactoryInterface; | |
| */ | |
| protected $configFactory; | |
| /** | |
| * The namespace of this class, the parent class etc. | |
| * | |
| * @var array | |
| */ | |
| protected $namespaces; | |
| /** | |
| * Constructs a QueryFactory object. | |
| * | |
| * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory | |
| * The config storage used by the config entity query. | |
| * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value | |
| * The key value factory. | |
| * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager | |
| * The configuration manager. | |
| */ | |
| public function __construct(ConfigFactoryInterface $config_factory, KeyValueFactoryInterface $key_value, ConfigManagerInterface $config_manager) { | |
| $this->configFactory = $config_factory; | |
| $this->keyValueFactory = $key_value; | |
| $this->configManager = $config_manager; | |
| $this->namespaces = QueryBase::getNamespaces($this); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function get(EntityTypeInterface $entity_type, $conjunction) { | |
| return new Query($entity_type, $conjunction, $this->configFactory, $this->keyValueFactory, $this->namespaces); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function getAggregate(EntityTypeInterface $entity_type, $conjunction) { | |
| throw new QueryException('Aggregation over configuration entities is not supported'); | |
| } | |
| /** | |
| * Gets the key value store used to store fast lookups. | |
| * | |
| * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type | |
| * The entity type. | |
| * | |
| * @return \Drupal\Core\KeyValueStore\KeyValueStoreInterface | |
| * The key value store used to store fast lookups. | |
| */ | |
| protected function getConfigKeyStore(EntityTypeInterface $entity_type) { | |
| return $this->keyValueFactory->get(static::CONFIG_LOOKUP_PREFIX . $entity_type->id()); | |
| } | |
| /** | |
| * Updates or adds lookup data. | |
| * | |
| * @param \Drupal\Core\Config\Entity\ConfigEntityTypeInterface $entity_type | |
| * The entity type. | |
| * @param \Drupal\Core\Config\Config $config | |
| * The configuration object that is being saved. | |
| */ | |
| protected function updateConfigKeyStore(ConfigEntityTypeInterface $entity_type, Config $config) { | |
| $config_key_store = $this->getConfigKeyStore($entity_type); | |
| foreach ($entity_type->getLookupKeys() as $lookup_key) { | |
| foreach ($this->getKeys($config, $lookup_key, 'get', $entity_type) as $key) { | |
| $values = $config_key_store->get($key, []); | |
| if (!in_array($config->getName(), $values, TRUE)) { | |
| $values[] = $config->getName(); | |
| $config_key_store->set($key, $values); | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Deletes lookup data. | |
| * | |
| * @param \Drupal\Core\Config\Entity\ConfigEntityTypeInterface $entity_type | |
| * The entity type. | |
| * @param \Drupal\Core\Config\Config $config | |
| * The configuration object that is being deleted. | |
| */ | |
| protected function deleteConfigKeyStore(ConfigEntityTypeInterface $entity_type, Config $config) { | |
| $config_key_store = $this->getConfigKeyStore($entity_type); | |
| foreach ($entity_type->getLookupKeys() as $lookup_key) { | |
| foreach ($this->getKeys($config, $lookup_key, 'getOriginal', $entity_type) as $key) { | |
| $values = $config_key_store->get($key, []); | |
| $pos = array_search($config->getName(), $values, TRUE); | |
| if ($pos !== FALSE) { | |
| unset($values[$pos]); | |
| } | |
| if (empty($values)) { | |
| $config_key_store->delete($key); | |
| } | |
| else { | |
| $config_key_store->set($key, $values); | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Creates lookup keys for configuration data. | |
| * | |
| * @param \Drupal\Core\Config\Config $config | |
| * The configuration object. | |
| * @param string $key | |
| * The configuration key to look for. | |
| * @param string $get_method | |
| * Which method on the config object to call to get the value. Either 'get' | |
| * or 'getOriginal'. | |
| * @param \Drupal\Core\Config\Entity\ConfigEntityTypeInterface $entity_type | |
| * The configuration entity type. | |
| * | |
| * @return array | |
| * An array of lookup keys concatenated to the configuration values. | |
| * | |
| * @throws \Drupal\Core\Config\Entity\Query\InvalidLookupKeyException | |
| * The provided $key cannot end with a wildcard. This makes no sense since | |
| * you cannot do fast lookups against this. | |
| */ | |
| protected function getKeys(Config $config, $key, $get_method, ConfigEntityTypeInterface $entity_type) { | |
| if (substr($key, -1) == '*') { | |
| throw new InvalidLookupKeyException(strtr('%entity_type lookup key %key ends with a wildcard this can not be used as a lookup', ['%entity_type' => $entity_type->id(), '%key' => $key])); | |
| } | |
| $parts = explode('.*', $key); | |
| // Remove leading dots. | |
| array_walk($parts, function (&$value) { | |
| $value = trim($value, '.'); | |
| }); | |
| $values = (array) $this->getValues($config, $parts[0], $get_method, $parts); | |
| $output = array(); | |
| // Flatten the array to a single dimension and add the key to all the | |
| // values. | |
| array_walk_recursive($values, function ($current) use (&$output, $key) { | |
| if (is_scalar($current)) { | |
| $current = $key . ':' . $current; | |
| } | |
| $output[] = $current; | |
| }); | |
| return $output; | |
| } | |
| /** | |
| * Finds all the values for a configuration key in a configuration object. | |
| * | |
| * @param \Drupal\Core\Config\Config $config | |
| * The configuration object. | |
| * @param string $key | |
| * The current key being checked. | |
| * @param string $get_method | |
| * Which method on the config object to call to get the value. | |
| * @param array $parts | |
| * All the parts of a configuration key we are checking. | |
| * @param int $start | |
| * Which position of $parts we are processing. Defaults to 0. | |
| * | |
| * @return array|NULL | |
| * The array of configuration values the match the provided key. NULL if | |
| * the configuration object does not have a value that corresponds to the | |
| * key. | |
| */ | |
| protected function getValues(Config $config, $key, $get_method, array $parts, $start = 0) { | |
| $value = $config->$get_method($key); | |
| if (is_array($value)) { | |
| $new_value = []; | |
| $start++; | |
| if (!isset($parts[$start])) { | |
| // The configuration object does not have a value that corresponds to | |
| // the key. | |
| return NULL; | |
| } | |
| foreach (array_keys($value) as $key_bit) { | |
| $new_key = $key . '.' . $key_bit; | |
| if (!empty($parts[$start])) { | |
| $new_key .= '.' . $parts[$start]; | |
| } | |
| $new_value[] = $this->getValues($config, $new_key, $get_method, $parts, $start); | |
| } | |
| $value = $new_value; | |
| } | |
| return $value; | |
| } | |
| /** | |
| * Updates configuration entity in the key store. | |
| * | |
| * @param ConfigCrudEvent $event | |
| * The configuration event. | |
| */ | |
| public function onConfigSave(ConfigCrudEvent $event) { | |
| $saved_config = $event->getConfig(); | |
| $entity_type_id = $this->configManager->getEntityTypeIdByName($saved_config->getName()); | |
| if ($entity_type_id) { | |
| $entity_type = $this->configManager->getEntityManager()->getDefinition($entity_type_id); | |
| $this->updateConfigKeyStore($entity_type, $saved_config); | |
| } | |
| } | |
| /** | |
| * Removes configuration entity from key store. | |
| * | |
| * @param \Drupal\Core\Config\ConfigCrudEvent $event | |
| * The configuration event. | |
| */ | |
| public function onConfigDelete(ConfigCrudEvent $event) { | |
| $saved_config = $event->getConfig(); | |
| $entity_type_id = $this->configManager->getEntityTypeIdByName($saved_config->getName()); | |
| if ($entity_type_id) { | |
| $entity_type = $this->configManager->getEntityManager()->getDefinition($entity_type_id); | |
| $this->deleteConfigKeyStore($entity_type, $saved_config); | |
| } | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| static function getSubscribedEvents() { | |
| $events[ConfigEvents::SAVE][] = array('onConfigSave', 128); | |
| $events[ConfigEvents::DELETE][] = array('onConfigDelete', 128); | |
| return $events; | |
| } | |
| } |