PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/web/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php

https://gitlab.com/mohamed_hussein/prodt
PHP | 318 lines | 188 code | 28 blank | 102 comment | 14 complexity | 58ca5bcb8359418d5e60f0b84fcdc5b6 MD5 | raw file
  1. <?php
  2. namespace Drupal\content_moderation\Plugin\WorkflowType;
  3. use Drupal\content_moderation\ModerationInformationInterface;
  4. use Drupal\Core\Entity\ContentEntityInterface;
  5. use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
  6. use Drupal\Core\Entity\EntityTypeManagerInterface;
  7. use Drupal\Core\Entity\EntityPublishedInterface;
  8. use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
  9. use Drupal\Core\StringTranslation\StringTranslationTrait;
  10. use Drupal\content_moderation\ContentModerationState;
  11. use Drupal\workflows\Plugin\WorkflowTypeBase;
  12. use Drupal\workflows\StateInterface;
  13. use Drupal\workflows\WorkflowInterface;
  14. use Symfony\Component\DependencyInjection\ContainerInterface;
  15. /**
  16. * Attaches workflows to content entity types and their bundles.
  17. *
  18. * @WorkflowType(
  19. * id = "content_moderation",
  20. * label = @Translation("Content moderation"),
  21. * required_states = {
  22. * "draft",
  23. * "published",
  24. * },
  25. * forms = {
  26. * "configure" = "\Drupal\content_moderation\Form\ContentModerationConfigureForm",
  27. * "state" = "\Drupal\content_moderation\Form\ContentModerationStateForm"
  28. * },
  29. * )
  30. */
  31. class ContentModeration extends WorkflowTypeBase implements ContentModerationInterface, ContainerFactoryPluginInterface {
  32. use StringTranslationTrait;
  33. /**
  34. * The entity type manager.
  35. *
  36. * @var \Drupal\Core\Entity\EntityTypeManagerInterface
  37. */
  38. protected $entityTypeManager;
  39. /**
  40. * The entity type bundle info service.
  41. *
  42. * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
  43. */
  44. protected $entityTypeBundleInfo;
  45. /**
  46. * The moderation information service.
  47. *
  48. * @var \Drupal\content_moderation\ModerationInformationInterface
  49. */
  50. protected $moderationInfo;
  51. /**
  52. * Constructs a ContentModeration object.
  53. *
  54. * @param array $configuration
  55. * A configuration array containing information about the plugin instance.
  56. * @param string $plugin_id
  57. * The plugin_id for the plugin instance.
  58. * @param mixed $plugin_definition
  59. * The plugin implementation definition.
  60. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
  61. * The entity type manager.
  62. * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
  63. * The entity type bundle info.
  64. * @param \Drupal\content_moderation\ModerationInformationInterface $moderation_info
  65. * Moderation information service.
  66. */
  67. public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, ModerationInformationInterface $moderation_info) {
  68. parent::__construct($configuration, $plugin_id, $plugin_definition);
  69. $this->entityTypeManager = $entity_type_manager;
  70. $this->entityTypeBundleInfo = $entity_type_bundle_info;
  71. $this->moderationInfo = $moderation_info;
  72. }
  73. /**
  74. * {@inheritdoc}
  75. */
  76. public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  77. return new static(
  78. $configuration,
  79. $plugin_id,
  80. $plugin_definition,
  81. $container->get('entity_type.manager'),
  82. $container->get('entity_type.bundle.info'),
  83. $container->get('content_moderation.moderation_information')
  84. );
  85. }
  86. /**
  87. * {@inheritdoc}
  88. */
  89. public function getState($state_id) {
  90. $state = parent::getState($state_id);
  91. if (isset($this->configuration['states'][$state->id()]['published']) && isset($this->configuration['states'][$state->id()]['default_revision'])) {
  92. $state = new ContentModerationState($state, $this->configuration['states'][$state->id()]['published'], $this->configuration['states'][$state->id()]['default_revision']);
  93. }
  94. else {
  95. $state = new ContentModerationState($state);
  96. }
  97. return $state;
  98. }
  99. /**
  100. * {@inheritdoc}
  101. */
  102. public function workflowHasData(WorkflowInterface $workflow) {
  103. return (bool) $this->entityTypeManager
  104. ->getStorage('content_moderation_state')
  105. ->getQuery()
  106. ->condition('workflow', $workflow->id())
  107. ->count()
  108. ->accessCheck(FALSE)
  109. ->range(0, 1)
  110. ->execute();
  111. }
  112. /**
  113. * {@inheritdoc}
  114. */
  115. public function workflowStateHasData(WorkflowInterface $workflow, StateInterface $state) {
  116. return (bool) $this->entityTypeManager
  117. ->getStorage('content_moderation_state')
  118. ->getQuery()
  119. ->condition('workflow', $workflow->id())
  120. ->condition('moderation_state', $state->id())
  121. ->count()
  122. ->accessCheck(FALSE)
  123. ->range(0, 1)
  124. ->execute();
  125. }
  126. /**
  127. * {@inheritdoc}
  128. */
  129. public function getEntityTypes() {
  130. return array_keys($this->configuration['entity_types']);
  131. }
  132. /**
  133. * {@inheritdoc}
  134. */
  135. public function getBundlesForEntityType($entity_type_id) {
  136. return $this->configuration['entity_types'][$entity_type_id] ?? [];
  137. }
  138. /**
  139. * {@inheritdoc}
  140. */
  141. public function appliesToEntityTypeAndBundle($entity_type_id, $bundle_id) {
  142. return in_array($bundle_id, $this->getBundlesForEntityType($entity_type_id), TRUE);
  143. }
  144. /**
  145. * {@inheritdoc}
  146. */
  147. public function removeEntityTypeAndBundle($entity_type_id, $bundle_id) {
  148. if (!isset($this->configuration['entity_types'][$entity_type_id])) {
  149. return;
  150. }
  151. $key = array_search($bundle_id, $this->configuration['entity_types'][$entity_type_id], TRUE);
  152. if ($key !== FALSE) {
  153. unset($this->configuration['entity_types'][$entity_type_id][$key]);
  154. if (empty($this->configuration['entity_types'][$entity_type_id])) {
  155. unset($this->configuration['entity_types'][$entity_type_id]);
  156. }
  157. else {
  158. $this->configuration['entity_types'][$entity_type_id] = array_values($this->configuration['entity_types'][$entity_type_id]);
  159. }
  160. }
  161. }
  162. /**
  163. * {@inheritdoc}
  164. */
  165. public function addEntityTypeAndBundle($entity_type_id, $bundle_id) {
  166. if (!$this->appliesToEntityTypeAndBundle($entity_type_id, $bundle_id)) {
  167. $this->configuration['entity_types'][$entity_type_id][] = $bundle_id;
  168. sort($this->configuration['entity_types'][$entity_type_id]);
  169. ksort($this->configuration['entity_types']);
  170. }
  171. }
  172. /**
  173. * {@inheritdoc}
  174. */
  175. public function defaultConfiguration() {
  176. return [
  177. 'states' => [
  178. 'draft' => [
  179. 'label' => 'Draft',
  180. 'published' => FALSE,
  181. 'default_revision' => FALSE,
  182. 'weight' => 0,
  183. ],
  184. 'published' => [
  185. 'label' => 'Published',
  186. 'published' => TRUE,
  187. 'default_revision' => TRUE,
  188. 'weight' => 1,
  189. ],
  190. ],
  191. 'transitions' => [
  192. 'create_new_draft' => [
  193. 'label' => 'Create New Draft',
  194. 'to' => 'draft',
  195. 'weight' => 0,
  196. 'from' => [
  197. 'draft',
  198. 'published',
  199. ],
  200. ],
  201. 'publish' => [
  202. 'label' => 'Publish',
  203. 'to' => 'published',
  204. 'weight' => 1,
  205. 'from' => [
  206. 'draft',
  207. 'published',
  208. ],
  209. ],
  210. ],
  211. 'entity_types' => [],
  212. ];
  213. }
  214. /**
  215. * {@inheritdoc}
  216. */
  217. public function calculateDependencies() {
  218. $dependencies = parent::calculateDependencies();
  219. foreach ($this->getEntityTypes() as $entity_type_id) {
  220. $entity_definition = $this->entityTypeManager->getDefinition($entity_type_id);
  221. foreach ($this->getBundlesForEntityType($entity_type_id) as $bundle) {
  222. $dependency = $entity_definition->getBundleConfigDependency($bundle);
  223. $dependencies[$dependency['type']][] = $dependency['name'];
  224. }
  225. }
  226. return $dependencies;
  227. }
  228. /**
  229. * {@inheritdoc}
  230. */
  231. public function onDependencyRemoval(array $dependencies) {
  232. $changed = parent::onDependencyRemoval($dependencies);
  233. // When bundle config entities are removed, ensure they are cleaned up from
  234. // the workflow.
  235. foreach ($dependencies['config'] as $removed_config) {
  236. if ($entity_type_id = $removed_config->getEntityType()->getBundleOf()) {
  237. $bundle_id = $removed_config->id();
  238. $this->removeEntityTypeAndBundle($entity_type_id, $bundle_id);
  239. $changed = TRUE;
  240. }
  241. }
  242. // When modules that provide entity types are removed, ensure they are also
  243. // removed from the workflow.
  244. if (!empty($dependencies['module'])) {
  245. // Gather all entity definitions provided by the dependent modules which
  246. // are being removed.
  247. $module_entity_definitions = [];
  248. foreach ($this->entityTypeManager->getDefinitions() as $entity_definition) {
  249. if (in_array($entity_definition->getProvider(), $dependencies['module'])) {
  250. $module_entity_definitions[] = $entity_definition;
  251. }
  252. }
  253. // For all entity types provided by the uninstalled modules, remove any
  254. // configuration for those types.
  255. foreach ($module_entity_definitions as $module_entity_definition) {
  256. foreach ($this->getBundlesForEntityType($module_entity_definition->id()) as $bundle) {
  257. $this->removeEntityTypeAndBundle($module_entity_definition->id(), $bundle);
  258. $changed = TRUE;
  259. }
  260. }
  261. }
  262. return $changed;
  263. }
  264. /**
  265. * {@inheritdoc}
  266. */
  267. public function getConfiguration() {
  268. $configuration = parent::getConfiguration();
  269. // Ensure that states and entity types are ordered consistently.
  270. ksort($configuration['states']);
  271. ksort($configuration['entity_types']);
  272. return $configuration;
  273. }
  274. /**
  275. * {@inheritdoc}
  276. */
  277. public function getInitialState($entity = NULL) {
  278. // Workflows are not tied to entities, but Content Moderation adds the
  279. // relationship between Workflows and entities. Content Moderation needs the
  280. // entity object to be able to determine the initial state based on
  281. // publishing status.
  282. if (!($entity instanceof ContentEntityInterface)) {
  283. throw new \InvalidArgumentException('A content entity object must be supplied.');
  284. }
  285. if ($entity instanceof EntityPublishedInterface && !$entity->isNew()) {
  286. return $this->getState($entity->isPublished() ? 'published' : 'draft');
  287. }
  288. return $this->getState(!empty($this->configuration['default_moderation_state']) ? $this->configuration['default_moderation_state'] : 'draft');
  289. }
  290. }