association-1.0.0-alpha2/src/Entity/AssociationType.php
src/Entity/AssociationType.php
<?php namespace Drupal\association\Entity; use Drupal\association\Plugin\BehaviorInterface; use Drupal\association\Plugin\BehaviorPluginManagerInterface; use Drupal\association\Plugin\LandingPagePluginInterface; use Drupal\association\Plugin\LandingPagePluginManagerInterface; use Drupal\association\Plugin\RevisionablePagePluginInterface; use Drupal\Component\Plugin\Exception\PluginException; use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\Component\Plugin\FallbackPluginManagerInterface; use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Entity\RevisionableEntityBundleInterface; use Drupal\Core\Logger\LoggerChannelTrait; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Utility\Error; use Drupal\toolshed\Entity\EntityBundleBase; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; /** * Configuration entity to be used as the bundle type for association entities. * * @ConfigEntityType( * id = "association_type", * label = @Translation("Association type"), * label_plural = @Translation("Association types"), * config_prefix = "type", * admin_permission = "administer association configurations", * bundle_of = "association", * entity_keys = { * "id" = "id", * "label" = "label", * "uuid" = "uuid", * }, * handlers = { * "list_builder" = "Drupal\association\Entity\Controller\AssociationTypeListBuilder", * "form" = { * "default" = "Drupal\association\Entity\Form\AssociationTypeForm", * "edit" = "Drupal\association\Entity\Form\AssociationTypeForm", * "delete" = "Drupal\toolshed\Entity\Form\EntityBundleDeleteConfirm", * }, * "route_provider" = { * "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider", * }, * }, * links = { * "collection" = "/admin/structure/association", * "add-form" = "/admin/structure/association/add", * "edit-form" = "/admin/structure/association/manage/{association_type}", * "delete-form" = "/admin/structure/association/manage/{association_type}/delete", * }, * config_export = { * "id", * "label", * "searchable", * "behavior", * "landingPage", * }, * ) */ class AssociationType extends EntityBundleBase implements AssociationTypeInterface, ConfigEntityInterface, RevisionableEntityBundleInterface { use StringTranslationTrait; use LoggerChannelTrait; /** * The entity ID. * * @var string */ protected $id; /** * The human friendly display name for the association type. * * @var string */ protected $label; /** * Indicates if content for associations of this type should be searchable. * * @var bool */ protected $searchable; /** * Does this association type already have data? * * @var bool */ protected $hasData; /** * The behavior plugin definition. * * Definition is just the stored config entity values which consist of a 'id' * and 'config' keys, which are the plugin ID and configurations respectively. * * @var array */ protected $behavior; /** * The landing page plugin definition. * * Definition is just the stored config entity values which consist of a 'id' * and 'config' keys, which are the plugin ID and configurations respectively. * * @var array */ protected $landingPage; /** * The loaded association bundle plugin instances. * * @var \Drupal\Component\Plugin\PluginInspectionInterface[] */ protected $plugins; /** * Get the plugin manager for managing association behaviors. * * @return \Drupal\association\Plugin\BehaviorPluginManagerInterface * Plugin manager for creating and managing association behavior plugins. */ protected static function getBehaviorManager(): BehaviorPluginManagerInterface { return \Drupal::service('plugin.manager.association.behavior'); } /** * Get the plugin manager for managing landing page handlers. * * @return \Drupal\association\Plugin\LandingPagePluginManagerInterface * Plugin manager for instatiating and managing landing page plugins. */ protected static function getLandingPageManager(): LandingPagePluginManagerInterface { return \Drupal::service('plugin.manager.association.landing_page'); } /** * {@inheritdoc} */ public function set($property_name, $value) { parent::set($property_name, $value); // Ensure that if the behavior configurations are updated, the loaded // plugin behavior will get rebuilt. if ($property_name === 'behavior') { unset($this->plugins['behavior']); } elseif ($property_name === 'landingPage') { unset($this->plugins['landing_page']); } return $this; } /** * {@inheritdoc} */ public function isContentSearchable(): bool { return $this->searchable ?? FALSE; } /** * {@inheritdoc} */ public function hasData(): bool { if (!isset($this->hasData)) { $this->hasData = parent::hasData(); } return $this->hasData; } /** * {@inheritdoc} */ public function shouldCreateNewRevision(): bool { $plugin = $this->getLandingPageHandler(); if ($plugin instanceof RevisionablePagePluginInterface) { return $plugin->shouldCreateNewRevision(); } return FALSE; } /** * {@inheritdoc} */ public function getPlugin($plugin_type, $force_rebuild = FALSE): ?PluginInspectionInterface { if (!isset($this->plugins[$plugin_type]) || $force_rebuild) { try { switch ($plugin_type) { case 'behavior': $pluginDef = $this->behavior; $pluginManager = static::getBehaviorManager(); break; case 'landing_page': $pluginDef = $this->landingPage; $pluginManager = static::getLandingPageManager(); break; default: throw new \InvalidArgumentException(); } if (empty($pluginDef['id'])) { if ($pluginManager instanceof FallbackPluginManagerInterface) { $pluginDef['id'] = $pluginManager->getFallbackPluginId('', []); } else { throw new PluginNotFoundException(sprintf('No %s plugin specified.', $plugin_type)); } } $pluginDef += ['config' => []]; $this->plugins[$plugin_type] = $pluginManager->createInstance($pluginDef['id'], $pluginDef['config']); } catch (ServiceNotFoundException | PluginException $e) { $this->plugins[$plugin_type] = FALSE; // If we are creating a new bundle, this is still under construction // and should not be logged. If not new this could mean a missing plugin // or module and should be logged. if (!$this->isNew()) { Error::logException($this->getLogger('association'), $e); } } } return $this->plugins[$plugin_type] ?: NULL; } /** * {@inheritdoc} */ public function getBehavior($force_rebuild = FALSE): ?BehaviorInterface { return $this->getPlugin('behavior', $force_rebuild); } /** * {@inheritdoc} */ public function getLandingPageHandler($force_rebuild = FALSE): LandingPagePluginInterface { return $this->getPlugin('landing_page', $force_rebuild); } /** * {@inheritdoc} */ public function validateConfigChanges(array $updates): array { $errors = []; // These configurations are only locked if association type has data. if ($this->hasData()) { if ($this->landingPage['id'] !== $updates['landingPage']['id']) { $errors[] = $this->t('Association type %id cannot change its page settings after association entities have been created', [ '%id' => $this->id(), ]); } // Check for plugin behavior changes. if ($this->behavior['id'] !== $updates['behavior']['id']) { $errors[] = $this->t('Association type %id cannot change its behavior plugin after association entities have been created', [ '%id' => $this->id(), ]); } elseif ($behavior = $this->getBehavior()) { $errors = array_merge($errors, $behavior->validateConfigUpdate($this, $updates['behavior']['config'])); } } return $errors; } }