diff --git a/composer.json b/composer.json index 375e036..a7911d8 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "wikimedia/composer-merge-plugin": "~1.3" }, "replace": { - "drupal/core": "~8.4" + "drupal/core": "~8.3" }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/composer.lock b/composer.lock index d3ea225..93962cd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "324eae1731d25ba58e17ce0c32be7d02", + "hash": "1167766f8eca494239cc8a1baa1ea6bb", + "content-hash": "0cfc95231ad5eb3f8d306e45c9cc92d9", "packages": [ { "name": "asm89/stack-cors", @@ -47,7 +48,7 @@ "cors", "stack" ], - "time": "2016-08-01T12:05:04+00:00" + "time": "2016-08-01 12:05:04" }, { "name": "composer/installers", @@ -142,7 +143,7 @@ "zend", "zikula" ], - "time": "2015-02-18T17:17:01+00:00" + "time": "2015-02-18 17:17:01" }, { "name": "composer/semver", @@ -203,7 +204,7 @@ "validation", "versioning" ], - "time": "2015-09-21T09:42:36+00:00" + "time": "2015-09-21 09:42:36" }, { "name": "doctrine/annotations", @@ -271,7 +272,7 @@ "docblock", "parser" ], - "time": "2015-08-31T12:32:49+00:00" + "time": "2015-08-31 12:32:49" }, { "name": "doctrine/cache", @@ -341,7 +342,7 @@ "cache", "caching" ], - "time": "2015-08-31T12:36:41+00:00" + "time": "2015-08-31 12:36:41" }, { "name": "doctrine/collections", @@ -407,7 +408,7 @@ "collections", "iterator" ], - "time": "2015-04-14T22:21:58+00:00" + "time": "2015-04-14 22:21:58" }, { "name": "doctrine/common", @@ -480,7 +481,7 @@ "persistence", "spl" ], - "time": "2015-08-31T13:00:22+00:00" + "time": "2015-08-31 13:00:22" }, { "name": "doctrine/inflector", @@ -547,7 +548,7 @@ "singularize", "string" ], - "time": "2014-12-20T21:24:13+00:00" + "time": "2014-12-20 21:24:13" }, { "name": "doctrine/lexer", @@ -601,7 +602,7 @@ "lexer", "parser" ], - "time": "2014-09-09T13:34:57+00:00" + "time": "2014-09-09 13:34:57" }, { "name": "easyrdf/easyrdf", @@ -663,7 +664,7 @@ "rdfa", "sparql" ], - "time": "2015-02-27T09:45:49+00:00" + "time": "2015-02-27 09:45:49" }, { "name": "egulias/email-validator", @@ -716,7 +717,7 @@ "validation", "validator" ], - "time": "2015-06-22T21:07:51+00:00" + "time": "2015-06-22 21:07:51" }, { "name": "guzzlehttp/guzzle", @@ -778,7 +779,7 @@ "rest", "web service" ], - "time": "2016-07-15T17:22:37+00:00" + "time": "2016-07-15 17:22:37" }, { "name": "guzzlehttp/promises", @@ -829,7 +830,7 @@ "keywords": [ "promise" ], - "time": "2016-05-18T16:56:05+00:00" + "time": "2016-05-18 16:56:05" }, { "name": "guzzlehttp/psr7", @@ -887,7 +888,7 @@ "stream", "uri" ], - "time": "2016-06-24T23:00:38+00:00" + "time": "2016-06-24 23:00:38" }, { "name": "ircmaxell/password-compat", @@ -929,7 +930,7 @@ "hashing", "password" ], - "time": "2014-11-20T16:49:30+00:00" + "time": "2014-11-20 16:49:30" }, { "name": "masterminds/html5", @@ -994,7 +995,7 @@ "serializer", "xml" ], - "time": "2016-05-10T14:11:45+00:00" + "time": "2016-05-10 14:11:45" }, { "name": "paragonie/random_compat", @@ -1042,7 +1043,7 @@ "pseudorandom", "random" ], - "time": "2016-04-03T06:00:07+00:00" + "time": "2016-04-03 06:00:07" }, { "name": "psr/http-message", @@ -1091,7 +1092,7 @@ "request", "response" ], - "time": "2015-05-04T20:22:00+00:00" + "time": "2015-05-04 20:22:00" }, { "name": "psr/log", @@ -1129,7 +1130,7 @@ "psr", "psr-3" ], - "time": "2012-12-21T11:40:51+00:00" + "time": "2012-12-21 11:40:51" }, { "name": "stack/builder", @@ -1178,7 +1179,7 @@ "keywords": [ "stack" ], - "time": "2016-06-02T06:58:42+00:00" + "time": "2016-06-02 06:58:42" }, { "name": "symfony-cmf/routing", @@ -1237,7 +1238,7 @@ "database", "routing" ], - "time": "2016-03-31T09:11:39+00:00" + "time": "2016-03-31 09:11:39" }, { "name": "symfony/class-loader", @@ -1290,7 +1291,7 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2017-01-10T14:03:07+00:00" + "time": "2017-01-10 14:03:07" }, { "name": "symfony/console", @@ -1351,7 +1352,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-01-08T20:43:03+00:00" + "time": "2017-01-08 20:43:03" }, { "name": "symfony/debug", @@ -1408,7 +1409,7 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/dependency-injection", @@ -1471,7 +1472,7 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2017-01-10T14:27:01+00:00" + "time": "2017-01-10 14:27:01" }, { "name": "symfony/dom-crawler", @@ -1527,7 +1528,7 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/event-dispatcher", @@ -1587,7 +1588,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/http-foundation", @@ -1642,7 +1643,7 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2017-01-08T20:43:03+00:00" + "time": "2017-01-08 20:43:03" }, { "name": "symfony/http-kernel", @@ -1724,7 +1725,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2017-01-12T20:27:24+00:00" + "time": "2017-01-12 20:27:24" }, { "name": "symfony/polyfill-apcu", @@ -1777,7 +1778,7 @@ "portable", "shim" ], - "time": "2016-11-14T01:06:16+00:00" + "time": "2016-11-14 01:06:16" }, { "name": "symfony/polyfill-iconv", @@ -1836,7 +1837,7 @@ "portable", "shim" ], - "time": "2016-11-14T01:06:16+00:00" + "time": "2016-11-14 01:06:16" }, { "name": "symfony/polyfill-mbstring", @@ -1895,7 +1896,7 @@ "portable", "shim" ], - "time": "2016-11-14T01:06:16+00:00" + "time": "2016-11-14 01:06:16" }, { "name": "symfony/polyfill-php54", @@ -1953,7 +1954,7 @@ "portable", "shim" ], - "time": "2016-11-14T01:06:16+00:00" + "time": "2016-11-14 01:06:16" }, { "name": "symfony/polyfill-php55", @@ -2009,7 +2010,7 @@ "portable", "shim" ], - "time": "2016-11-14T01:06:16+00:00" + "time": "2016-11-14 01:06:16" }, { "name": "symfony/process", @@ -2058,7 +2059,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/psr-http-message-bridge", @@ -2112,7 +2113,7 @@ "http-message", "psr-7" ], - "time": "2015-05-29T17:57:12+00:00" + "time": "2015-05-29 17:57:12" }, { "name": "symfony/routing", @@ -2187,7 +2188,7 @@ "uri", "url" ], - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/serializer", @@ -2251,7 +2252,7 @@ ], "description": "Symfony Serializer Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/translation", @@ -2315,7 +2316,7 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/validator", @@ -2388,7 +2389,7 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2017-01-12T19:24:25+00:00" + "time": "2017-01-12 19:24:25" }, { "name": "symfony/yaml", @@ -2437,7 +2438,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-01-03T13:49:52+00:00" + "time": "2017-01-03 13:49:52" }, { "name": "twig/twig", @@ -2498,7 +2499,7 @@ "keywords": [ "templating" ], - "time": "2016-09-21T23:05:12+00:00" + "time": "2016-09-21 23:05:12" }, { "name": "wikimedia/composer-merge-plugin", @@ -2547,7 +2548,7 @@ } ], "description": "Composer plugin to merge multiple composer.json files", - "time": "2016-03-08T17:11:37+00:00" + "time": "2016-03-08 17:11:37" }, { "name": "zendframework/zend-diactoros", @@ -2597,7 +2598,7 @@ "psr", "psr-7" ], - "time": "2015-08-10T20:04:20+00:00" + "time": "2015-08-10 20:04:20" }, { "name": "zendframework/zend-escaper", @@ -2641,7 +2642,7 @@ "escaper", "zf2" ], - "time": "2015-06-03T14:05:37+00:00" + "time": "2015-06-03 14:05:37" }, { "name": "zendframework/zend-feed", @@ -2700,7 +2701,7 @@ "feed", "zf2" ], - "time": "2015-08-04T21:39:18+00:00" + "time": "2015-08-04 21:39:18" }, { "name": "zendframework/zend-hydrator", @@ -2756,7 +2757,7 @@ "hydrator", "zf2" ], - "time": "2015-09-17T14:06:43+00:00" + "time": "2015-09-17 14:06:43" }, { "name": "zendframework/zend-stdlib", @@ -2814,7 +2815,7 @@ "stdlib", "zf2" ], - "time": "2015-09-25T04:06:33+00:00" + "time": "2015-09-25 04:06:33" } ], "packages-dev": [ @@ -2874,7 +2875,7 @@ "testing", "web" ], - "time": "2016-10-17T08:31:38+00:00" + "time": "2016-10-17 08:31:38" }, { "name": "behat/mink-browserkit-driver", @@ -2930,7 +2931,7 @@ "browser", "testing" ], - "time": "2016-03-05T08:59:47+00:00" + "time": "2016-03-05 08:59:47" }, { "name": "behat/mink-goutte-driver", @@ -2985,7 +2986,7 @@ "headless", "testing" ], - "time": "2016-03-05T09:04:22+00:00" + "time": "2016-03-05 09:04:22" }, { "name": "doctrine/instantiator", @@ -3039,7 +3040,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2015-06-14 21:17:01" }, { "name": "drupal/coder", @@ -3124,7 +3125,7 @@ "keywords": [ "scraper" ], - "time": "2015-11-05T12:58:44+00:00" + "time": "2015-11-05 12:58:44" }, { "name": "jcalderonzumba/gastonjs", @@ -3181,7 +3182,7 @@ "headless", "phantomjs" ], - "time": "2016-01-18T09:21:03+00:00" + "time": "2016-01-18 09:21:03" }, { "name": "jcalderonzumba/mink-phantomjs-driver", @@ -3242,7 +3243,7 @@ "phantomjs", "testing" ], - "time": "2015-12-04T13:55:02+00:00" + "time": "2015-12-04 13:55:02" }, { "name": "mikey179/vfsStream", @@ -3288,7 +3289,7 @@ ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", - "time": "2015-10-06T16:59:57+00:00" + "time": "2015-10-06 16:59:57" }, { "name": "phpdocumentor/reflection-docblock", @@ -3337,7 +3338,7 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2015-02-03T12:10:50+00:00" + "time": "2015-02-03 12:10:50" }, { "name": "phpspec/prophecy", @@ -3397,7 +3398,7 @@ "spy", "stub" ], - "time": "2015-08-13T10:07:40+00:00" + "time": "2015-08-13 10:07:40" }, { "name": "phpunit/php-code-coverage", @@ -3459,7 +3460,7 @@ "testing", "xunit" ], - "time": "2015-10-06T15:47:00+00:00" + "time": "2015-10-06 15:47:00" }, { "name": "phpunit/php-file-iterator", @@ -3506,7 +3507,7 @@ "filesystem", "iterator" ], - "time": "2015-06-21T13:08:43+00:00" + "time": "2015-06-21 13:08:43" }, { "name": "phpunit/php-text-template", @@ -3547,7 +3548,7 @@ "keywords": [ "template" ], - "time": "2015-06-21T13:50:34+00:00" + "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", @@ -3588,7 +3589,7 @@ "keywords": [ "timer" ], - "time": "2015-06-21T08:01:12+00:00" + "time": "2015-06-21 08:01:12" }, { "name": "phpunit/php-token-stream", @@ -3637,7 +3638,7 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15T10:49:45+00:00" + "time": "2015-09-15 10:49:45" }, { "name": "phpunit/phpunit", @@ -3709,7 +3710,7 @@ "testing", "xunit" ], - "time": "2016-07-21T06:48:14+00:00" + "time": "2016-07-21 06:48:14" }, { "name": "phpunit/phpunit-mock-objects", @@ -3765,7 +3766,7 @@ "mock", "xunit" ], - "time": "2015-10-02T06:51:40+00:00" + "time": "2015-10-02 06:51:40" }, { "name": "sebastian/comparator", @@ -3829,7 +3830,7 @@ "compare", "equality" ], - "time": "2015-07-26T15:48:44+00:00" + "time": "2015-07-26 15:48:44" }, { "name": "sebastian/diff", @@ -3881,7 +3882,7 @@ "keywords": [ "diff" ], - "time": "2015-02-22T15:13:53+00:00" + "time": "2015-02-22 15:13:53" }, { "name": "sebastian/environment", @@ -3931,7 +3932,7 @@ "environment", "hhvm" ], - "time": "2015-08-03T06:14:51+00:00" + "time": "2015-08-03 06:14:51" }, { "name": "sebastian/exporter", @@ -3997,7 +3998,7 @@ "export", "exporter" ], - "time": "2015-06-21T07:55:53+00:00" + "time": "2015-06-21 07:55:53" }, { "name": "sebastian/global-state", @@ -4048,7 +4049,7 @@ "keywords": [ "global state" ], - "time": "2014-10-06T09:23:50+00:00" + "time": "2014-10-06 09:23:50" }, { "name": "sebastian/recursion-context", @@ -4101,7 +4102,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-06-21T08:04:50+00:00" + "time": "2015-06-21 08:04:50" }, { "name": "sebastian/version", @@ -4136,7 +4137,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21T13:59:46+00:00" + "time": "2015-06-21 13:59:46" }, { "name": "squizlabs/php_codesniffer", @@ -4271,7 +4272,7 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-01-02 20:30:24" }, { "name": "symfony/css-selector", @@ -4324,7 +4325,7 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-01-02 20:30:24" } ], "aliases": [], diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php index 5002739..443bf45 100644 --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -81,7 +81,7 @@ class Drupal { /** * The current system version. */ - const VERSION = '8.4.0-dev'; + const VERSION = '8.3.0-dev'; /** * Core API compatibility. diff --git a/core/lib/Drupal/Core/Render/Element/Details.php b/core/lib/Drupal/Core/Render/Element/Details.php index 2ae6f1d..ae25d34 100644 --- a/core/lib/Drupal/Core/Render/Element/Details.php +++ b/core/lib/Drupal/Core/Render/Element/Details.php @@ -75,9 +75,7 @@ public static function preRenderDetails($element) { // Collapsible details. $element['#attached']['library'][] = 'core/drupal.collapse'; - - // Open the detail if specified or if a child has an error. - if (!empty($element['#open']) || !empty($element['#children_errors'])) { + if (!empty($element['#open'])) { $element['#attributes']['open'] = 'open'; } diff --git a/core/modules/content_moderation/content_moderation.module b/core/modules/content_moderation/content_moderation.module index 7345e93..7260eab 100644 --- a/core/modules/content_moderation/content_moderation.module +++ b/core/modules/content_moderation/content_moderation.module @@ -64,15 +64,6 @@ function content_moderation_entity_type_alter(array &$entity_types) { } /** - * Implements hook_entity_operation(). - */ -function content_moderation_entity_operation(EntityInterface $entity) { - return \Drupal::service('class_resolver') - ->getInstanceFromDefinition(EntityTypeInfo::class) - ->entityOperation($entity); -} - -/** * Implements hook_entity_presave(). */ function content_moderation_entity_presave(EntityInterface $entity) { diff --git a/core/modules/content_moderation/src/EntityTypeInfo.php b/core/modules/content_moderation/src/EntityTypeInfo.php index f11e471..1ccfbf5 100644 --- a/core/modules/content_moderation/src/EntityTypeInfo.php +++ b/core/modules/content_moderation/src/EntityTypeInfo.php @@ -21,9 +21,7 @@ use Drupal\content_moderation\Entity\Handler\BlockContentModerationHandler; use Drupal\content_moderation\Entity\Handler\ModerationHandler; use Drupal\content_moderation\Entity\Handler\NodeModerationHandler; -use Drupal\content_moderation\Form\BundleModerationConfigurationForm; use Drupal\content_moderation\Routing\EntityModerationRouteProvider; -use Drupal\content_moderation\Routing\EntityTypeModerationRouteProvider; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -127,11 +125,6 @@ public function entityTypeAlter(array &$entity_types) { // The ContentModerationState entity type should never be moderated. if ($entity_type->isRevisionable() && $entity_type_id != 'content_moderation_state') { $entity_types[$entity_type_id] = $this->addModerationToEntityType($entity_type); - // Add additional moderation support to entity types whose bundles are - // managed by a config entity type. - if ($entity_type->getBundleEntityType()) { - $entity_types[$entity_type->getBundleEntityType()] = $this->addModerationToBundleEntityType($entity_types[$entity_type->getBundleEntityType()]); - } } } } @@ -170,67 +163,6 @@ protected function addModerationToEntityType(ContentEntityTypeInterface $type) { } /** - * Configures moderation configuration support on a entity type definition. - * - * That "configuration support" includes a configuration form, a hypermedia - * link, and a route provider to tie it all together. There's also a - * moderation handler for per-entity-type variation. - * - * @param \Drupal\Core\Config\Entity\ConfigEntityTypeInterface $type - * The config entity definition to modify. - * - * @return \Drupal\Core\Config\Entity\ConfigEntityTypeInterface - * The modified config entity definition. - */ - protected function addModerationToBundleEntityType(ConfigEntityTypeInterface $type) { - if ($type->hasLinkTemplate('edit-form') && !$type->hasLinkTemplate('moderation-form')) { - $type->setLinkTemplate('moderation-form', $type->getLinkTemplate('edit-form') . '/moderation'); - } - - if (!$type->getFormClass('moderation')) { - $type->setFormClass('moderation', BundleModerationConfigurationForm::class); - } - - // @todo Core forgot to add a direct way to manipulate route_provider, so - // we have to do it the sloppy way for now. - $providers = $type->getRouteProviderClasses() ?: []; - if (empty($providers['moderation'])) { - $providers['moderation'] = EntityTypeModerationRouteProvider::class; - $type->setHandlerClass('route_provider', $providers); - } - - return $type; - } - - /** - * Adds an operation on bundles that should have a Moderation form. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity on which to define an operation. - * - * @return array - * An array of operation definitions. - * - * @see hook_entity_operation() - */ - public function entityOperation(EntityInterface $entity) { - $operations = []; - $type = $entity->getEntityType(); - $bundle_of = $type->getBundleOf(); - if ($this->currentUser->hasPermission('administer content moderation') && $bundle_of && - $this->moderationInfo->canModerateEntitiesOfEntityType($this->entityTypeManager->getDefinition($bundle_of)) - ) { - $operations['manage-moderation'] = [ - 'title' => t('Manage moderation'), - 'weight' => 27, - 'url' => Url::fromRoute("entity.{$type->id()}.moderation", [$entity->getEntityTypeId() => $entity->id()]), - ]; - } - - return $operations; - } - - /** * Gets the "extra fields" for a bundle. * * This is a hook bridge. diff --git a/core/modules/content_moderation/src/Form/BundleModerationConfigurationForm.php b/core/modules/content_moderation/src/Form/BundleModerationConfigurationForm.php deleted file mode 100644 index 917ec5d..0000000 --- a/core/modules/content_moderation/src/Form/BundleModerationConfigurationForm.php +++ /dev/null @@ -1,155 +0,0 @@ -entityTypeManager = $entity_type_manager; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static($container->get('entity_type.manager')); - } - - /** - * {@inheritdoc} - * - * Blank out the base form ID so that form alters that use the base form ID to - * target both add and edit forms don't pick up this form. - */ - public function getBaseFormId() { - return NULL; - } - - /** - * {@inheritdoc} - */ - public function form(array $form, FormStateInterface $form_state) { - /* @var \Drupal\Core\Config\Entity\ConfigEntityInterface $bundle */ - $bundle = $this->getEntity(); - $bundle_of_entity_type = $this->entityTypeManager->getDefinition($bundle->getEntityType()->getBundleOf()); - /* @var \Drupal\workflows\WorkflowInterface[] $workflows */ - $workflows = $this->entityTypeManager->getStorage('workflow')->loadMultiple(); - - $options = array_map(function (WorkflowInterface $workflow) { - return $workflow->label(); - }, array_filter($workflows, function (WorkflowInterface $workflow) { - return $workflow->status() && $workflow->getTypePlugin() instanceof ContentModeration; - })); - - $selected_workflow = array_reduce($workflows, function ($carry, WorkflowInterface $workflow) use ($bundle_of_entity_type, $bundle) { - $plugin = $workflow->getTypePlugin(); - if ($plugin instanceof ContentModeration && $plugin->appliesToEntityTypeAndBundle($bundle_of_entity_type->id(), $bundle->id())) { - return $workflow->id(); - } - return $carry; - }); - $form['workflow'] = [ - '#type' => 'select', - '#title' => $this->t('Select the workflow to apply'), - '#default_value' => $selected_workflow, - '#options' => $options, - '#required' => FALSE, - '#empty_value' => '', - ]; - - $form['original_workflow'] = [ - '#type' => 'value', - '#value' => $selected_workflow, - ]; - - $form['bundle'] = [ - '#type' => 'value', - '#value' => $bundle->id(), - ]; - - $form['entity_type'] = [ - '#type' => 'value', - '#value' => $bundle_of_entity_type->id(), - ]; - - // Add a special message when moderation is being disabled. - if ($selected_workflow) { - $form['enable_workflow_note'] = [ - '#type' => 'item', - '#description' => $this->t('After disabling moderation, any existing forward drafts will be accessible via the "Revisions" tab.'), - '#access' => !empty($selected_workflow) - ]; - } - - return parent::form($form, $form_state); - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // If moderation is enabled, revisions MUST be enabled as well. Otherwise we - // can't have forward revisions. - drupal_set_message($this->t('Your settings have been saved.')); - } - - /** - * {@inheritdoc} - */ - public function save(array $form, FormStateInterface $form_state) { - $entity_type_id = $form_state->getValue('entity_type'); - $bundle_id = $form_state->getValue('bundle'); - $new_workflow_id = $form_state->getValue('workflow'); - $original_workflow_id = $form_state->getValue('original_workflow'); - if ($new_workflow_id === $original_workflow_id) { - // Nothing to do. - return; - } - if ($original_workflow_id) { - /* @var \Drupal\workflows\WorkflowInterface $workflow */ - $workflow = $this->entityTypeManager->getStorage('workflow')->load($original_workflow_id); - $workflow->getTypePlugin()->removeEntityTypeAndBundle($entity_type_id, $bundle_id); - $workflow->save(); - } - if ($new_workflow_id) { - /* @var \Drupal\workflows\WorkflowInterface $workflow */ - $workflow = $this->entityTypeManager->getStorage('workflow')->load($new_workflow_id); - $workflow->getTypePlugin()->addEntityTypeAndBundle($entity_type_id, $bundle_id); - $workflow->save(); - } - } - - /** - * {@inheritdoc} - */ - protected function actions(array $form, FormStateInterface $form_state) { - $actions['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Save'), - '#submit' => ['::submitForm', '::save'], - ]; - - return $actions; - } - -} diff --git a/core/modules/content_moderation/src/Plugin/Derivative/DynamicLocalTasks.php b/core/modules/content_moderation/src/Plugin/Derivative/DynamicLocalTasks.php index 7ff1fa5..9f09a9a 100644 --- a/core/modules/content_moderation/src/Plugin/Derivative/DynamicLocalTasks.php +++ b/core/modules/content_moderation/src/Plugin/Derivative/DynamicLocalTasks.php @@ -76,19 +76,6 @@ public static function create(ContainerInterface $container, $base_plugin_id) { public function getDerivativeDefinitions($base_plugin_definition) { $this->derivatives = []; - foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) { - if ($this->moderationInfo->canModerateEntitiesOfEntityType($entity_type)) { - $bundle_id = $entity_type->getBundleEntityType(); - $this->derivatives["$bundle_id.moderation_tab"] = [ - 'route_name' => "entity.$bundle_id.moderation", - 'title' => $this->t('Manage moderation'), - // @todo - are we sure they all have an edit_form? - 'base_route' => "entity.$bundle_id.edit_form", - 'weight' => 30, - ] + $base_plugin_definition; - } - } - $latest_version_entities = array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $type) { return $this->moderationInfo->canModerateEntitiesOfEntityType($type) && $type->hasLinkTemplate('latest-version'); }); diff --git a/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php b/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php index e61f25e..9f5c9a2 100644 --- a/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php +++ b/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php @@ -2,14 +2,18 @@ namespace Drupal\content_moderation\Plugin\WorkflowType; +use Drupal\content_moderation\ModerationInformationInterface; use Drupal\Core\Access\AccessResult; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\content_moderation\ContentModerationState; use Drupal\workflows\Plugin\WorkflowTypeBase; use Drupal\workflows\StateInterface; use Drupal\workflows\WorkflowInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Attaches workflows to content entity types and their bundles. @@ -19,11 +23,58 @@ * label = @Translation("Content moderation"), * ) */ -class ContentModeration extends WorkflowTypeBase { +class ContentModeration extends WorkflowTypeBase implements ContainerFactoryPluginInterface { use StringTranslationTrait; /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * The moderation information service. + * + * @var \Drupal\content_moderation\ModerationInformationInterface + */ + protected $moderationInfo; + + /** + * Constructs an ContentModeration object. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. + * @param \Drupal\content_moderation\ModerationInformationInterface $moderation_info + * Moderation information service. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModerationInformationInterface $moderation_info) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->entityTypeManager = $entity_type_manager; + $this->moderationInfo = $moderation_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager'), + $container->get('content_moderation.moderation_information') + ); + } + + /** * {@inheritdoc} */ public function checkWorkflowAccess(WorkflowInterface $entity, $operation, AccountInterface $account) { @@ -145,7 +196,7 @@ public function addEntityTypeAndBundle($entity_type_id, $bundle_id) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function defaultConfiguration() { // This plugin does not store anything per transition. @@ -156,11 +207,75 @@ public function defaultConfiguration() { } /** - * @inheritDoc + * {@inheritdoc} */ public function calculateDependencies() { // @todo : Implement calculateDependencies() method. return []; } + /** + * {@inheritdoc} + */ + public function editForm(WorkflowInterface $workflow) { + $form['attachments'] = [ + '#type' => 'details', + '#title' => $this->t('Select types to use this workflow'), + '#open' => TRUE, + '#tree' => TRUE, + ]; + + $entity_types = $this->entityTypeManager->getDefinitions(); + foreach ($entity_types as $entity_type) { + if ($this->moderationInfo->canModerateEntitiesOfEntityType($entity_type)) { + $options = []; + $defaults = []; + if ($entity_type->getBundleEntityType()) { + $bundles = $this->entityTypeManager->getStorage($entity_type->getBundleEntityType()) + ->loadMultiple(); + foreach ($bundles as $bundle) { + if (!$this->moderationInfo->shouldModerateEntitiesOfBundle($entity_type, $bundle->id()) || $this->appliesToEntityTypeAndBundle($entity_type->id(), $bundle->id())) { + $options[$bundle->id()] = $bundle->label(); + $defaults[$bundle->id()] = $this->appliesToEntityTypeAndBundle($entity_type->id(), $bundle->id()); + } + } + } + else { + if (!$this->moderationInfo->shouldModerateEntitiesOfBundle($entity_type, $entity_type->id()) || $this->appliesToEntityTypeAndBundle($entity_type->id(), $entity_type->id())) { + $options[$entity_type->id()] = $entity_type->getLabel(); + $defaults[$entity_type->id()] = $this->appliesToEntityTypeAndBundle($entity_type->id(), $entity_type->id()); + } + } + + if (!empty($options)) { + $form['attachments'][$entity_type->id()] = [ + '#type' => 'checkboxes', + '#title' => $entity_type->getLabel()->render(), + '#options' => $options, + '#default_value' => array_keys(array_filter($defaults)), + ]; + } + } + } + + return $form; + } + + /** + * {@inheritdoc} + */ + public function editFormSave(WorkflowInterface &$workflow, array $form, FormStateInterface $formState) { + $type_plugin = $workflow->getTypePlugin(); + foreach ($formState->getValues()['attachments'] as $entity_type_id => $bundle_ids) { + foreach ($bundle_ids as $bundle_id => $checked) { + if ($checked) { + $type_plugin->addEntityTypeAndBundle($entity_type_id, $bundle_id); + } + else { + $type_plugin->removeEntityTypeAndBundle($entity_type_id, $bundle_id); + } + } + } + } + } diff --git a/core/modules/content_moderation/src/Routing/EntityTypeModerationRouteProvider.php b/core/modules/content_moderation/src/Routing/EntityTypeModerationRouteProvider.php deleted file mode 100644 index d1dcd2b..0000000 --- a/core/modules/content_moderation/src/Routing/EntityTypeModerationRouteProvider.php +++ /dev/null @@ -1,59 +0,0 @@ -getModerationFormRoute($entity_type)) { - $entity_type_id = $entity_type->id(); - $collection->add("entity.{$entity_type_id}.moderation", $moderation_route); - } - - return $collection; - } - - /** - * Gets the moderation-form route. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type. - * - * @return \Symfony\Component\Routing\Route|null - * The generated route, if available. - */ - protected function getModerationFormRoute(EntityTypeInterface $entity_type) { - if ($entity_type->hasLinkTemplate('moderation-form') && $entity_type->getFormClass('moderation')) { - $entity_type_id = $entity_type->id(); - - $route = new Route($entity_type->getLinkTemplate('moderation-form')); - - // @todo Come up with a new permission. - $route - ->setDefaults([ - '_entity_form' => "{$entity_type_id}.moderation", - '_title' => 'Moderation', - ]) - ->setRequirement('_permission', 'administer content moderation') - ->setOption('parameters', [ - $entity_type_id => ['type' => 'entity:' . $entity_type_id], - ]); - - return $route; - } - } - -} diff --git a/core/modules/content_moderation/src/Tests/ModerationStateBlockTest.php b/core/modules/content_moderation/src/Tests/ModerationStateBlockTest.php index e42f536..faf6934 100644 --- a/core/modules/content_moderation/src/Tests/ModerationStateBlockTest.php +++ b/core/modules/content_moderation/src/Tests/ModerationStateBlockTest.php @@ -51,17 +51,10 @@ protected function setUp() { public function testCustomBlockModeration() { $this->drupalLogin($this->rootUser); - $this->drupalGet('admin/structure/block/block-content/types'); - $this->assertLinkByHref('admin/structure/block/block-content/manage/basic/moderation'); - $this->drupalGet('admin/structure/block/block-content/manage/basic'); - $this->assertLinkByHref('admin/structure/block/block-content/manage/basic/moderation'); - $this->drupalGet('admin/structure/block/block-content/manage/basic/moderation'); - - // Enable moderation for custom blocks at - // admin/structure/block/block-content/manage/basic/moderation. - $edit = ['workflow' => 'editorial']; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertText(t('Your settings have been saved.')); + // Enable moderation for custom blocks. + $edit['attachments[block_content][basic]'] = TRUE; + $this->drupalPostForm('admin/config/workflow/workflows/manage/editorial', $edit, t('Save')); + $this->assertText(t('Saved the Editorial workflow Workflow.')); // Create a custom block at block/add and save it as draft. $body = 'Body of moderated block'; diff --git a/core/modules/content_moderation/src/Tests/ModerationStateNodeTest.php b/core/modules/content_moderation/src/Tests/ModerationStateNodeTest.php index a89ec9f..fe033bc 100644 --- a/core/modules/content_moderation/src/Tests/ModerationStateNodeTest.php +++ b/core/modules/content_moderation/src/Tests/ModerationStateNodeTest.php @@ -53,9 +53,8 @@ public function testCreatingContent() { $this->assertText(t('The Moderated content moderated content has been deleted.')); // Disable content moderation. - $this->drupalPostForm('admin/structure/types/manage/moderated_content/moderation', ['workflow' => ''], t('Save')); - $this->drupalGet('admin/structure/types/manage/moderated_content/moderation'); - $this->assertOptionSelected('edit-workflow', ''); + $edit['attachments[node][moderated_content]'] = FALSE; + $this->drupalPostForm('admin/config/workflow/workflows/manage/editorial', $edit, t('Save'));; // Ensure the parent environment is up-to-date. // @see content_moderation_workflow_insert() \Drupal::service('entity_type.bundle.info')->clearCachedBundles(); @@ -71,21 +70,6 @@ public function testCreatingContent() { $this->fail('Non-moderated test node was not saved correctly.'); } $this->assertEqual(NULL, $node->moderation_state->value); - - // \Drupal\content_moderation\Form\BundleModerationConfigurationForm() - // should not list workflows with no states. - $workflow = Workflow::create(['id' => 'stateless', 'label' => 'Stateless', 'type' => 'content_moderation']); - $workflow->save(); - - $this->drupalGet('admin/structure/types/manage/moderated_content/moderation'); - $this->assertNoText('Stateless'); - $workflow - ->addState('draft', 'Draft') - ->addState('published', 'Published') - ->addTransition('publish', 'Publish', ['draft', 'published'], 'published') - ->save(); - $this->drupalGet('admin/structure/types/manage/moderated_content/moderation'); - $this->assertText('Stateless'); } /** diff --git a/core/modules/content_moderation/src/Tests/ModerationStateNodeTypeTest.php b/core/modules/content_moderation/src/Tests/ModerationStateNodeTypeTest.php index 099b4dc..e752c65 100644 --- a/core/modules/content_moderation/src/Tests/ModerationStateNodeTypeTest.php +++ b/core/modules/content_moderation/src/Tests/ModerationStateNodeTypeTest.php @@ -42,17 +42,8 @@ public function testEnablingOnExistingContent() { ], t('Save and publish')); $this->assertText('Not moderated Test has been created.'); - // Now enable moderation state, ensuring all the expected links and tabs are - // present. - $this->drupalGet('admin/structure/types'); - $this->assertLinkByHref('admin/structure/types/manage/not_moderated/moderation'); - $this->drupalGet('admin/structure/types/manage/not_moderated'); - $this->assertLinkByHref('admin/structure/types/manage/not_moderated/moderation'); - $this->drupalGet('admin/structure/types/manage/not_moderated/moderation'); - $this->assertOptionSelected('edit-workflow', ''); - $this->assertNoLink('Delete'); - $edit['workflow'] = 'editorial'; - $this->drupalPostForm(NULL, $edit, t('Save')); + // Now enable moderation state. + $this->enableModerationThroughUi('not_moderated'); // And make sure it works. $nodes = \Drupal::entityTypeManager()->getStorage('node') diff --git a/core/modules/content_moderation/src/Tests/ModerationStateTestBase.php b/core/modules/content_moderation/src/Tests/ModerationStateTestBase.php index 22307df..0765fb6 100644 --- a/core/modules/content_moderation/src/Tests/ModerationStateTestBase.php +++ b/core/modules/content_moderation/src/Tests/ModerationStateTestBase.php @@ -38,6 +38,7 @@ 'access content overview', 'use editorial transition create_new_draft', 'use editorial transition publish', + 'administer workflows', ]; /** @@ -112,9 +113,11 @@ protected function createContentTypeFromUi($content_type_name, $content_type_id, * @param string $workflow_id * The workflow to attach to the bundle. */ - protected function enableModerationThroughUi($content_type_id, $workflow_id = 'editorial') { - $edit['workflow'] = $workflow_id; - $this->drupalPostForm('admin/structure/types/manage/' . $content_type_id . '/moderation', $edit, t('Save')); + public function enableModerationThroughUi($content_type_id, $workflow_id = 'editorial') { + $this->drupalGet('/admin/config/workflow/workflows'); + $this->assertLinkByHref('admin/config/workflow/workflows/manage/' . $workflow_id); + $edit['attachments[node][' . $content_type_id . ']'] = TRUE; + $this->drupalPostForm('admin/config/workflow/workflows/manage/' . $workflow_id, $edit, t('Save')); // Ensure the parent environment is up-to-date. // @see content_moderation_workflow_insert() \Drupal::service('entity_type.bundle.info')->clearCachedBundles(); diff --git a/core/modules/node/src/Tests/NodeEditFormTest.php b/core/modules/node/src/Tests/NodeEditFormTest.php index bef0252..0d6bf45 100644 --- a/core/modules/node/src/Tests/NodeEditFormTest.php +++ b/core/modules/node/src/Tests/NodeEditFormTest.php @@ -115,21 +115,6 @@ public function testNodeEdit() { // Check if the node revision checkbox is rendered on node edit form. $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertFieldById('edit-revision', NULL, 'The revision field is present.'); - - // Check that details form element opens when there are errors on child - // elements. - $this->drupalGet('node/' . $node->id() . '/edit'); - $edit = []; - // This invalid date will trigger an error. - $edit['created[0][value][date]'] = $this->randomMachineName(8); - // Get the current amount of open details elements. - $open_details_elements = count($this->cssSelect('details[open="open"]')); - $this->drupalPostForm(NULL, $edit, t('Save and keep published')); - // The node author details must be open. - $this->assertRaw('
'); - // Only one extra details element should now be open. - $open_details_elements++; - $this->assertEqual(count($this->cssSelect('details[open="open"]')), $open_details_elements, 'Exactly one extra open <details> element found.'); } /** diff --git a/core/modules/workflows/src/Form/WorkflowEditForm.php b/core/modules/workflows/src/Form/WorkflowEditForm.php index d8f99f9..8d2e398 100644 --- a/core/modules/workflows/src/Form/WorkflowEditForm.php +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php @@ -179,6 +179,8 @@ public function form(array $form, FormStateInterface $form_state) { '#markup' => $workflow->toLink($this->t('Add a new transition'), 'add-transition-form')->toString(), ]; + $form += $workflow->getTypePlugin()->editForm($workflow); + return $form; } @@ -188,6 +190,7 @@ public function form(array $form, FormStateInterface $form_state) { public function save(array $form, FormStateInterface $form_state) { /* @var \Drupal\workflows\WorkflowInterface $workflow */ $workflow = $this->entity; + $workflow->getTypePlugin()->editFormSave($workflow, $form, $form_state); $workflow->save(); drupal_set_message($this->t('Saved the %label Workflow.', ['%label' => $workflow->label()])); $form_state->setRedirectUrl($workflow->toUrl('collection')); diff --git a/core/modules/workflows/src/Plugin/WorkflowTypeBase.php b/core/modules/workflows/src/Plugin/WorkflowTypeBase.php index 1ed9fca..7f9462f 100644 --- a/core/modules/workflows/src/Plugin/WorkflowTypeBase.php +++ b/core/modules/workflows/src/Plugin/WorkflowTypeBase.php @@ -49,28 +49,28 @@ public function checkWorkflowAccess(WorkflowInterface $entity, $operation, Accou } /** - * {@inheritDoc} + * {@inheritdoc} */ public function decorateState(StateInterface $state) { return $state; } /** - * {@inheritDoc} + * {@inheritdoc} */ public function deleteState($state_id) { unset($this->configuration['states'][$state_id]); } /** - * {@inheritDoc} + * {@inheritdoc} */ public function decorateTransition(TransitionInterface $transition) { return $transition; } /** - * {@inheritDoc} + * {@inheritdoc} */ public function deleteTransition($transition_id) { unset($this->configuration['transitions'][$transition_id]); @@ -91,14 +91,14 @@ public function buildTransitionConfigurationForm(FormStateInterface $form_state, } /** - * {@inheritDoc} + * {@inheritdoc} */ public function getConfiguration() { return $this->configuration; } /** - * {@inheritDoc} + * {@inheritdoc} */ public function setConfiguration(array $configuration) { $this->configuration = NestedArray::mergeDeep( @@ -108,7 +108,7 @@ public function setConfiguration(array $configuration) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function defaultConfiguration() { return [ @@ -118,10 +118,24 @@ public function defaultConfiguration() { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function calculateDependencies() { return []; } + /** + * {@inheritdoc} + */ + public function editForm(WorkflowInterface $workflow) { + return []; + } + + /** + * {@inheritdoc} + */ + public function editFormSave(WorkflowInterface &$workflow, array $form, FormStateInterface $form_state) { + + } + } diff --git a/core/modules/workflows/src/WorkflowTypeInterface.php b/core/modules/workflows/src/WorkflowTypeInterface.php index 17fddec..287e672 100644 --- a/core/modules/workflows/src/WorkflowTypeInterface.php +++ b/core/modules/workflows/src/WorkflowTypeInterface.php @@ -117,4 +117,29 @@ public function buildStateConfigurationForm(FormStateInterface $form_state, Work */ public function buildTransitionConfigurationForm(FormStateInterface $form_state, WorkflowInterface $workflow, TransitionInterface $transition = NULL); + /** + * Returns a form array to append to the Workflow entity edit form. + * + * @param \Drupal\workflows\WorkflowInterface $workflow + * The workflow the form will be added to. + * + * @return array + * A form array to be used for type specific workflow settings. + * + * @see \Drupal\workflows\Form\WorkflowTransitionEditForm::form() + */ + public function editForm(WorkflowInterface $workflow); + + /** + * Save workflow type specific settings. + * + * @param \Drupal\workflows\WorkflowInterface $workflow + * The workflow the submitting form was added to. + * @param array $form + * The form array that was submitted. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The form state for the submitted form. + */ + public function editFormSave(WorkflowInterface &$workflow, array $form, FormStateInterface $form_state); + } diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml old mode 100644 new mode 100755