cms_content_sync-3.0.x-dev/modules/cms_content_sync_developer/src/EventSubscriber/VersionComparison.php
modules/cms_content_sync_developer/src/EventSubscriber/VersionComparison.php
<?php
namespace Drupal\cms_content_sync_developer\EventSubscriber;
use Drupal\cms_content_sync\Entity\Flow;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* A subscriber triggering a config when certain configuration changes.
*/
class VersionComparison implements EventSubscriberInterface {
/**
* The config Factory.
*
* @var \Drupal\Core\Config\ConfigFactory
*/
protected $configFactory;
/**
* The Core EntityTypeManager.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/**
* MyModuleService constructor.
*
* @param \Drupal\Core\Config\ConfigFactory $configFactory
* The config factory.
* @param Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* Drupals Entity Type Manager interface.
*/
public function __construct(ConfigFactory $configFactory, EntityTypeManagerInterface $entityTypeManager) {
$this->configFactory = $configFactory;
$this->entityTypeManager = $entityTypeManager;
}
/**
* Check for config changes on create.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
* The Event to process.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function doComparisonOnCreate(ConfigCrudEvent $event) {
// Comparison is not done if config got changed by CLI.
if (in_array(PHP_SAPI, ['cli', 'cli-server', 'phpdbg'])) {
return;
}
$saved_config = $event->getConfig();
$new_config = $saved_config->getRawData();
$old_config = $saved_config->getOriginal();
// Check if the config has changed and that we got a new configuration.
if ($new_config === $old_config || empty($new_config)) {
return;
}
// Entity Type and bundle are not set consistent between the entity types.
$entity_type = $this->getEntityTypeFromConfig($new_config);
$bundle = $this->getBundleFromConfig($new_config);
if (!isset($entity_type) || !isset($bundle)) {
return;
}
$flows = Flow::getAll();
$mismatching_flows = [];
foreach ($flows as $flow_id => $flow) {
// We only need to compare the version for the effected entity type.
$entity_type_config = $flow->getController()->getEntityTypeConfig($entity_type, $bundle);
if ($entity_type_config && Flow::HANDLER_IGNORE != $entity_type_config['handler']) {
$current_version = $entity_type_config['version'];
$new_version = $flow->getEntityTypeVersion($entity_type, $bundle);
if ($current_version != $new_version) {
$mismatching_flows[$flow_id] = $flow->label();
}
}
else {
// We can ignore variant Simple because it will set this automatically
// based on whether the target entity type is enabled or not.
if (Flow::VARIANT_PER_BUNDLE === $flow->variant) {
// If no entity type config exists for now, we assume that it is a new
// entity type.
$types = $flow->per_bundle_settings;
foreach ($types as $entity_type_name => $bundles) {
foreach ($bundles as $bundle) {
foreach ($bundle['properties'] as $field_name => $config) {
if (isset($config['handler_settings']['export_referenced_entities']) && $config['handler_settings']['export_referenced_entities']) {
// Check if there is a reference field handler that
// automatically pushes other bundles of this entity type.
$field_storage = $this->entityTypeManager->getStorage('field_storage_config')->load($entity_type_name . '.' . $field_name);
if ($field_storage instanceof FieldStorageConfig) {
$settings = $field_storage->get('settings');
if ($settings['target_type'] == $entity_type) {
$mismatching_flows[$flow_id] = $flow->label();
}
}
}
}
}
}
}
}
}
// Set the mismatching flows.
if (!empty($mismatching_flows)) {
$this->setMismatchingFlows($mismatching_flows);
}
}
/**
* Check for config changes on delete.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
* The Event to process.
*/
public function doComparisonOnDelete(ConfigCrudEvent $event) {
// Very comparison is not done if config got changed by CLI.
if (!in_array(PHP_SAPI, ['cli', 'cli-server', 'phpdbg'])) {
$saved_config = $event->getConfig();
$old_config = $saved_config->getOriginal();
if (isset($old_config['entity_type'], $old_config['bundle'])) {
$flows = Flow::getAll();
$mismatching_flows = [];
foreach ($flows as $flow_id => $flow) {
// Entity Type and bundle are not set consistent between the
// entity types.
$entity_type = $this->getEntityTypeFromConfig($old_config);
$bundle = $this->getBundleFromConfig($old_config);
if (isset($entity_type, $bundle)) {
$entity_type_config = $flow->getController()->getEntityTypeConfig($entity_type, $bundle);
if (isset($entity_type_config['handler'])) {
$mismatching_flows[$flow_id] = $flow->label();
$this->setMismatchingFlows($mismatching_flows);
}
}
}
}
}
}
/**
* Set current mismatching flows.
*
* @param array $mismatching_flows
* The flows the version mismatch message should be set for.
*/
public function setMismatchingFlows(array $mismatching_flows) {
$config = $this->configFactory;
$developer_config = $config->getEditable('cms_content_sync.developer');
$version_mismatch_config = $developer_config->get('version_mismatch');
if (empty($version_mismatch_config)) {
$developer_config->set('version_mismatch', $mismatching_flows);
}
else {
$new_mismatching_config = array_unique(array_merge($mismatching_flows, $version_mismatch_config));
$developer_config->set('version_mismatch', $new_mismatching_config);
}
$developer_config->save();
}
/**
* Get the entity type.
*
* The entity type is not set consistent between the entity types.
*
* @param mixed $config
* The entity type configuration.
*
* @return entity_type|null
* Returns the entity type from the configuration if it is available.
*/
public function getEntityTypeFromConfig(mixed $config) {
if (isset($config['entity_type'])) {
$entity_type = $config['entity_type'];
}
elseif (isset($config['target_entity_type_id'])) {
$entity_type = $config['target_entity_type_id'];
}
return $entity_type ?? NULL;
}
/**
* Get the bundle.
*
* The bundle is not set consistent between the entity types.
*
* @param mixed $config
* The entity type configuration.
*
* @return bundle|null
* Returns the bundle from the configuration if it is available.
*/
public function getBundleFromConfig(mixed $config) {
if (isset($config['bundle'])) {
$bundle = $config['bundle'];
}
elseif (isset($config['target_bundle'])) {
$bundle = $config['target_bundle'];
}
return $bundle ?? NULL;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
$events[ConfigEvents::SAVE][] = ['doComparisonOnCreate'];
$events[ConfigEvents::DELETE][] = ['doComparisonOnDelete'];
return $events;
}
}
