diff --git a/.htaccess b/.htaccess index 5248bd8..0ad7be3 100644 --- a/.htaccess +++ b/.htaccess @@ -3,7 +3,7 @@ # # Protect files and directories from prying eyes. - + Require all denied diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml index 0e589e1..069ff09 100644 --- a/core/config/schema/core.data_types.schema.yml +++ b/core/config/schema/core.data_types.schema.yml @@ -211,14 +211,9 @@ route: config_dependencies_base: type: mapping mapping: - config: + entity: type: sequence - label: 'Configuration entity dependencies' - sequence: - - type: string - content: - type: sequence - label: 'Content entity dependencies' + label: 'Entity dependencies' sequence: - type: string module: diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 0ea383f..b6cce93 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -414,6 +414,94 @@ function _drupal_set_preferred_header_name($name = NULL) { } /** + * Sends the HTTP response headers that were previously set, adding defaults. + * + * Headers are set in _drupal_add_http_header(). Default headers are not set + * if they have been replaced or unset using _drupal_add_http_header(). + * + * @param array $default_headers + * (optional) An array of headers as name/value pairs. + * @param bool $only_default + * (optional) If TRUE and headers have already been sent, send only the + * specified headers. + * + * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. + * See https://drupal.org/node/2181523. + */ +function drupal_send_headers($default_headers = array(), $only_default = FALSE) { + $headers_sent = &drupal_static(__FUNCTION__, FALSE); + $headers = drupal_get_http_header(); + if ($only_default && $headers_sent) { + $headers = array(); + } + $headers_sent = TRUE; + + $header_names = _drupal_set_preferred_header_name(); + foreach ($default_headers as $name => $value) { + $name_lower = strtolower($name); + if (!isset($headers[$name_lower])) { + $headers[$name_lower] = $value; + $header_names[$name_lower] = $name; + } + } + foreach ($headers as $name_lower => $value) { + if ($name_lower == 'status') { + header($_SERVER['SERVER_PROTOCOL'] . ' ' . $value); + } + // Skip headers that have been unset. + elseif ($value !== FALSE) { + header($header_names[$name_lower] . ': ' . $value); + } + } +} + +/** + * Sets HTTP headers in preparation for a page response. + * + * Authenticated users are always given a 'no-cache' header, and will fetch a + * fresh page on every request. This prevents authenticated users from seeing + * locally cached pages. + * + * Also give each page a unique ETag. This should force clients to include both + * an If-Modified-Since header and an If-None-Match header when doing + * conditional requests for the page (required by RFC 2616, section 13.3.4), + * making the validation more robust. This is a workaround for a bug in Mozilla + * Firefox that is triggered when Drupal's caching is enabled and the user + * accesses Drupal via an HTTP proxy (see + * https://bugzilla.mozilla.org/show_bug.cgi?id=269303): When an authenticated + * user requests a page, and then logs out and requests the same page again, + * Firefox may send a conditional request based on the page that was cached + * locally when the user was logged in. If this page did not have an ETag + * header, the request only contains an If-Modified-Since header. The date will + * be recent, because with authenticated users the Last-Modified header always + * refers to the time of the request. If the user accesses Drupal via a proxy + * server, and the proxy already has a cached copy of the anonymous page with an + * older Last-Modified date, the proxy may respond with 304 Not Modified, making + * the client think that the anonymous and authenticated pageviews are + * identical. + * + * @see drupal_page_set_cache() + * + * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. + * See https://drupal.org/node/2181523. + */ +function drupal_page_header() { + $headers_sent = &drupal_static(__FUNCTION__, FALSE); + if ($headers_sent) { + return TRUE; + } + $headers_sent = TRUE; + + $default_headers = array( + 'Expires' => 'Sun, 19 Nov 1978 05:00:00 GMT', + 'Last-Modified' => gmdate(DateTimePlus::RFC7231, REQUEST_TIME), + 'Cache-Control' => 'no-cache, must-revalidate, post-check=0, pre-check=0', + 'ETag' => '"' . REQUEST_TIME . '"', + ); + drupal_send_headers($default_headers); +} + +/** * Sets HTTP headers in preparation for a cached page response. * * The headers allow as much as possible in proxies and browsers without any diff --git a/core/includes/common.inc b/core/includes/common.inc index eedd47a..f656206 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -2261,6 +2261,8 @@ function drupal_clear_js_cache() { * The fully populated response. * @param \Symfony\Component\HttpFoundation\Request $request * The request for this page. + * + * @see drupal_page_header() */ function drupal_page_set_cache(Response $response, Request $request) { // Check if the current page may be compressed. diff --git a/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php b/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php index b77d3a2..2b095c1 100644 --- a/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php +++ b/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php @@ -47,19 +47,18 @@ public function defaultConfiguration(); * dependencies listing the specified roles. * * @return array - * An array of dependencies grouped by type (config, content, module, - * theme). For example: + * An array of dependencies grouped by type (module, theme, entity). For + * example: * @code * array( - * 'config' => array('user.role.anonymous', 'user.role.authenticated'), - * 'content' => array('node:article:f0a189e6-55fb-47fb-8005-5bef81c44d6d'), + * 'entity' => array('user.role.anonymous', 'user.role.authenticated'), * 'module' => array('node', 'user'), * 'theme' => array('seven'), * ); * @endcode * * @see \Drupal\Core\Config\Entity\ConfigDependencyManager - * @see \Drupal\Core\Entity\EntityInterface::getConfigDependencyName() + * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName() */ public function calculateDependencies(); diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php index a97cf72..8b9707f 100644 --- a/core/lib/Drupal/Core/Config/ConfigManager.php +++ b/core/lib/Drupal/Core/Config/ConfigManager.php @@ -192,14 +192,14 @@ public function uninstall($type, $name) { // Work out if any of the entity's dependencies are going to be affected // by the uninstall. $affected_dependencies = array( - 'config' => array(), + 'entity' => array(), 'module' => array(), 'theme' => array(), ); - if (isset($entity_dependencies['config'])) { + if (isset($entity_dependencies['entity'])) { foreach ($extension_dependent_entities as $extension_dependent_entity) { - if (in_array($extension_dependent_entity->getConfigDependencyName(), $entity_dependencies['config'])) { - $affected_dependencies['config'][] = $extension_dependent_entity; + if (in_array($extension_dependent_entity->getConfigDependencyName(), $entity_dependencies['entity'])) { + $affected_dependencies['entity'][] = $extension_dependent_entity; } } } diff --git a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php index c5fdec1..c0ea6cf 100644 --- a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php +++ b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php @@ -86,8 +86,7 @@ public function uninstall($type, $name); * Finds config entities that are dependent on extensions or entities. * * @param string $type - * The type of dependency being checked. Either 'module', 'theme', 'config' - * or 'content'. + * The type of dependency being checked. Either 'module', 'theme', 'entity'. * @param array $names * The specific names to check. If $type equals 'module' or 'theme' then it * should be a list of module names or theme names. In the case of entity it @@ -102,8 +101,7 @@ public function findConfigEntityDependents($type, array $names); * Finds config entities that are dependent on extensions or entities. * * @param string $type - * The type of dependency being checked. Either 'module', 'theme', 'config' - * or 'content'. + * The type of dependency being checked. Either 'module', 'theme', 'entity'. * @param array $names * The specific names to check. If $type equals 'module' or 'theme' then it * should be a list of module names or theme names. In the case of entity it diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php index ef7f645..e7806bc 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php @@ -22,13 +22,9 @@ * The configuration dependency value is structured like this: * * array( - * 'config => array( + * 'entity => array( * // An array of configuration entity object names. Recalculated on save. * ), - * 'content => array( - * // An array of content entity configuration dependency names. The default - * // format is "ENTITY_TYPE_ID:BUNDLE:UUID". Recalculated on save. - * ), * 'module' => array( * // An array of module names. Recalculated on save. * ), @@ -39,8 +35,7 @@ * // An array of configuration dependencies that the config entity is * // ensured to have regardless of the details of the configuration. These * // dependencies are not recalculated on save. - * 'config' => array(), - * 'content' => array(), + * 'entity' => array(), * 'module' => array(), * 'theme' => array(), * ), @@ -115,12 +110,12 @@ * module dependency in the sub-module only. * * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies() + * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName() * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::onDependencyRemoval() * @see \Drupal\Core\Config\Entity\ConfigEntityBase::addDependency() * @see \Drupal\Core\Config\ConfigInstallerInterface::installDefaultConfig() * @see \Drupal\Core\Config\ConfigManagerInterface::uninstall() * @see \Drupal\Core\Config\Entity\ConfigEntityDependency - * @see \Drupal\Core\Entity\EntityInterface::getConfigDependencyName() * @see \Drupal\Core\Plugin\PluginDependencyTrait */ class ConfigDependencyManager { @@ -143,8 +138,7 @@ class ConfigDependencyManager { * Gets dependencies. * * @param string $type - * The type of dependency being checked. Either 'module', 'theme', 'config' - * or 'content'. + * The type of dependency being checked. Either 'module', 'theme', 'entity'. * @param string $name * The specific name to check. If $type equals 'module' or 'theme' then it * should be a module name or theme name. In the case of entity it should be @@ -157,17 +151,17 @@ public function getDependentEntities($type, $name) { $dependent_entities = array(); $entities_to_check = array(); - if ($type == 'config') { + if ($type == 'entity') { $entities_to_check[] = $name; } else { - if ($type == 'module' || $type == 'theme' || $type == 'content') { + if ($type == 'module' || $type == 'theme') { $dependent_entities = array_filter($this->data, function (ConfigEntityDependency $entity) use ($type, $name) { return $entity->hasDependency($type, $name); }); } - // If checking content, module, or theme dependencies, discover which - // entities are dependent on the entities that have a direct dependency. + // If checking module or theme dependencies then discover which entities + // are dependent on the entities that have a direct dependency. foreach ($dependent_entities as $entity) { $entities_to_check[] = $entity->getConfigDependencyName(); } @@ -249,7 +243,7 @@ protected function getGraph() { foreach ($this->data as $entity) { $graph_key = $entity->getConfigDependencyName(); $graph[$graph_key]['edges'] = array(); - $dependencies = $entity->getDependencies('config'); + $dependencies = $entity->getDependencies('entity'); if (!empty($dependencies)) { foreach ($dependencies as $dependency) { $graph[$graph_key]['edges'][$dependency] = TRUE; diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php index 9ca55b6..7da6ecb 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityDependency.php @@ -50,8 +50,7 @@ public function __construct($name, $values = array()) { * Gets the configuration entity's dependencies of the supplied type. * * @param string $type - * The type of dependency to return. Either 'module', 'theme', 'config' or - * 'content'. + * The type of dependency to return. Either 'module', 'theme', 'entity'. * * @return array * The list of dependencies of the supplied type. @@ -71,8 +70,7 @@ public function getDependencies($type) { * Determines if the entity is dependent on extensions or entities. * * @param string $type - * The type of dependency being checked. Either 'module', 'theme', 'config' - * or 'content'. + * The type of dependency being checked. Either 'module', 'theme', 'entity'. * @param string $name * The specific name to check. If $type equals 'module' or 'theme' then it * should be a module name or theme name. In the case of entity it should be @@ -91,7 +89,7 @@ public function hasDependency($type, $name) { /** * Gets the configuration entity's configuration dependency name. * - * @see \Drupal\Core\Entity\EntityInterface::getConfigDependencyName() + * @see Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName() * * @return string * The configuration dependency name for the entity. diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php index 15347e3..b83df5d 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -152,6 +152,16 @@ public function set($property_name, $value); public function calculateDependencies(); /** + * Gets the configuration dependency name. + * + * @return string + * The configuration dependency name. + * + * @see \Drupal\Core\Config\Entity\ConfigDependencyManager + */ + public function getConfigDependencyName(); + + /** * Informs the entity that entities it depends on will be deleted. * * This method allows configuration entities to remove dependencies instead diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php index 48262e5..b28c4c2 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php @@ -250,7 +250,10 @@ protected function doSave($id, EntityInterface $entity) { } // Retrieve the desired properties and set them in config. - $config->setData($this->mapToStorageRecord($entity)); + $record = $this->mapToStorageRecord($entity); + foreach ($record as $key => $value) { + $config->set($key, $value); + } $config->save(); return $is_new ? SAVED_NEW : SAVED_UPDATED; diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php index bca72c4..6cacf4e 100644 --- a/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php +++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Connection.php @@ -336,7 +336,7 @@ public function rollback($savepoint_name = 'drupal_transaction') { } // A previous rollback to an earlier savepoint may mean that the savepoint // in question has already been rolled back. - if (!isset($this->transactionLayers[$savepoint_name])) { + if (!in_array($savepoint_name, $this->transactionLayers)) { return; } diff --git a/core/lib/Drupal/Core/Entity/DependencyTrait.php b/core/lib/Drupal/Core/Entity/DependencyTrait.php index 8dac895..5815ab1 100644 --- a/core/lib/Drupal/Core/Entity/DependencyTrait.php +++ b/core/lib/Drupal/Core/Entity/DependencyTrait.php @@ -28,7 +28,7 @@ * If $type is 'module' or 'theme', the name of the module or theme. If * $type is 'entity', the full configuration object name. * - * @see \Drupal\Core\Entity\EntityInterface::getConfigDependencyName() + * @see \Drupal\Core\Config\Entity\ConfigEntityInterface::getConfigDependencyName() * * @return $this */ diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index fa9626a..bd00ece 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -561,11 +561,4 @@ public function __sleep() { return $this->traitSleep(); } - /** - * {@inheritdoc} - */ - public function getConfigDependencyName() { - return $this->getEntityTypeId() . ':' . $this->bundle() . ':' . $this->uuid(); - } - } diff --git a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php index e46dff0..251bb00 100644 --- a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php +++ b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php @@ -162,7 +162,7 @@ public function calculateDependencies() { // If the target entity type uses entities to manage its bundles then // depend on the bundle entity. $bundle_entity = \Drupal::entityManager()->getStorage($bundle_entity_type_id)->load($this->bundle); - $this->addDependency('config', $bundle_entity->getConfigDependencyName()); + $this->addDependency('entity', $bundle_entity->getConfigDependencyName()); } else { // Depend on the provider of the entity type. @@ -173,7 +173,7 @@ public function calculateDependencies() { foreach ($fields as $field_name => $component) { $field = FieldConfig::loadByName($this->targetEntityType, $this->bundle, $field_name); if ($field) { - $this->addDependency('config', $field->getConfigDependencyName()); + $this->addDependency('entity', $field->getConfigDependencyName()); } // Create a dependency on the module that provides the formatter or // widget. @@ -190,7 +190,7 @@ public function calculateDependencies() { // Depend on configured modes. if ($this->mode != 'default') { $mode_entity = \Drupal::entityManager()->getStorage('entity_' . $this->displayContext . '_mode')->load($target_entity_type->id() . '.' . $this->mode); - $this->addDependency('config', $mode_entity->getConfigDependencyName()); + $this->addDependency('entity', $mode_entity->getConfigDependencyName()); } return $this->dependencies; } @@ -387,7 +387,7 @@ private function fieldHasDisplayOptions(FieldDefinitionInterface $definition) { */ public function onDependencyRemoval(array $dependencies) { $changed = FALSE; - foreach ($dependencies['config'] as $entity) { + foreach ($dependencies['entity'] as $entity) { if ($entity instanceof FieldConfigInterface) { // Remove components for fields that are being deleted. $this->removeComponent($entity->getName()); diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php index 674078d..ae0e85e 100644 --- a/core/lib/Drupal/Core/Entity/EntityInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityInterface.php @@ -404,18 +404,4 @@ public function getTypedData(); */ public function getCacheTags(); - /** - * Gets the configuration dependency name. - * - * Configuration entities can depend on content and configuration entities. - * They store an array of content and config dependency names in their - * "dependencies" key. - * - * @return string - * The configuration dependency name. - * - * @see \Drupal\Core\Config\Entity\ConfigDependencyManager - */ - public function getConfigDependencyName(); - } diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php index 8368694..be561a6 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -1715,12 +1715,7 @@ public function countFieldData($storage_definition, $as_bool = FALSE) { if ($table_mapping->requiresDedicatedTableStorage($storage_definition)) { $is_deleted = $this->storageDefinitionIsDeleted($storage_definition); - if ($this->entityType->isRevisionable()) { - $table_name = $table_mapping->getDedicatedRevisionTableName($storage_definition, $is_deleted); - } - else { - $table_name = $table_mapping->getDedicatedDataTableName($storage_definition, $is_deleted); - } + $table_name = $table_mapping->getDedicatedDataTableName($storage_definition, $is_deleted); $query = $this->database->select($table_name, 't'); $or = $query->orConditionGroup(); foreach ($storage_definition->getColumns() as $column_name => $data) { diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php index fb68b07..42600fd 100644 --- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php @@ -98,18 +98,10 @@ public function onRespond(FilterResponseEvent $event) { // Attach globally-declared headers to the response object so that Symfony // can send them for us correctly. - // @todo Remove this once drupal_process_attached() no longer calls - // _drupal_add_http_header(), which has its own static. Instead, - // _drupal_process_attached() should use - // \Symfony\Component\HttpFoundation\Response->headers->set(), which is - // already documented on the (deprecated) _drupal_process_attached() to - // become the final, intended mechanism. + // @todo remove this once we have removed all _drupal_add_http_header() + // calls. $headers = drupal_get_http_header(); foreach ($headers as $name => $value) { - // Symfony special-cases the 'Status' header. - if ($name === 'status') { - $response->setStatusCode($value); - } $response->headers->set($name, $value, FALSE); } diff --git a/core/lib/Drupal/Core/Field/FieldConfigBase.php b/core/lib/Drupal/Core/Field/FieldConfigBase.php index 79eb14b..05fc94b 100644 --- a/core/lib/Drupal/Core/Field/FieldConfigBase.php +++ b/core/lib/Drupal/Core/Field/FieldConfigBase.php @@ -233,7 +233,7 @@ public function calculateDependencies() { // If the target entity type uses entities to manage its bundles then // depend on the bundle entity. $bundle_entity = $this->entityManager()->getStorage($bundle_entity_type_id)->load($this->bundle); - $this->addDependency('config', $bundle_entity->getConfigDependencyName()); + $this->addDependency('entity', $bundle_entity->getConfigDependencyName()); } return $this->dependencies; } diff --git a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php index e7b91fc..0a5b38a 100644 --- a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php +++ b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php @@ -100,4 +100,13 @@ public function toArray(); */ public function isEmpty(); + /** + * React to changes to a child property. + * + * Note that this is invoked after any changes have been applied. + * + * @param $property_name + * The name of the property which is changed. + */ + public function onChange($property_name); } diff --git a/core/lib/Drupal/Core/TypedData/ListInterface.php b/core/lib/Drupal/Core/TypedData/ListInterface.php index 4e78b48..2c5dbc7 100644 --- a/core/lib/Drupal/Core/TypedData/ListInterface.php +++ b/core/lib/Drupal/Core/TypedData/ListInterface.php @@ -39,6 +39,16 @@ public function isEmpty(); public function getItemDefinition(); /** + * React to changes to a child item. + * + * Note that this is invoked after any changes have been applied. + * + * @param $delta + * The delta of the item which is changed. + */ + public function onChange($delta); + + /** * Returns the item at the specified position in this list. * * @param int $index diff --git a/core/lib/Drupal/Core/TypedData/TraversableTypedDataInterface.php b/core/lib/Drupal/Core/TypedData/TraversableTypedDataInterface.php index 34b1df5..d42557e 100644 --- a/core/lib/Drupal/Core/TypedData/TraversableTypedDataInterface.php +++ b/core/lib/Drupal/Core/TypedData/TraversableTypedDataInterface.php @@ -10,16 +10,4 @@ /** * An interface for typed data objects that can be traversed. */ -interface TraversableTypedDataInterface extends TypedDataInterface, \Traversable { - - /** - * React to changes to a child property or item. - * - * Note that this is invoked after any changes have been applied. - * - * @param $name - * The name of the property or the delta of the list item which is changed. - */ - public function onChange($name); - -} +interface TraversableTypedDataInterface extends TypedDataInterface, \Traversable {} diff --git a/core/misc/dialog/dialog.ajax.js b/core/misc/dialog/dialog.ajax.js index 4d9d6c4..4845cbd 100644 --- a/core/misc/dialog/dialog.ajax.js +++ b/core/misc/dialog/dialog.ajax.js @@ -15,10 +15,7 @@ // dialogs. Non-modal dialogs are responsible for creating their own // elements, since there can be multiple non-modal dialogs at a time. if (!$('#drupal-modal').length) { - // Add 'ui-front' jQuery UI class so jQuery UI widgets like autocomplete - // sit on top of dialogs. For more information see - // http://api.jqueryui.com/theming/stacking-elements/. - $('
').hide().appendTo('body'); + $('
').hide().appendTo('body'); } // Special behaviors specific when attaching content within a dialog. diff --git a/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.summary.yml b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.summary.yml index 4c840d5..d775c94 100644 --- a/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.summary.yml +++ b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_feed.aggregator_feed.summary.yml @@ -16,7 +16,7 @@ hidden: feed_icon: true status: true dependencies: - config: + entity: - core.entity_view_mode.aggregator_feed.summary module: - aggregator diff --git a/core/modules/aggregator/config/install/core.entity_view_display.aggregator_item.aggregator_item.summary.yml b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_item.aggregator_item.summary.yml index 6cb424d..bc46892 100644 --- a/core/modules/aggregator/config/install/core.entity_view_display.aggregator_item.aggregator_item.summary.yml +++ b/core/modules/aggregator/config/install/core.entity_view_display.aggregator_item.aggregator_item.summary.yml @@ -13,7 +13,7 @@ hidden: description: true status: true dependencies: - config: + entity: - core.entity_view_mode.aggregator_item.summary module: - aggregator diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 95e1bd6..39e15ea 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -8,7 +8,7 @@ use Drupal\block\BlockInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; -use Drupal\language\ConfigurableLanguageInterface; +use Drupal\language\Entity\ConfigurableLanguage; use Drupal\system\Entity\Menu; use Drupal\block\Entity\Block; @@ -315,7 +315,7 @@ function block_menu_delete(Menu $menu) { * * Delete the potential block visibility settings of the deleted language. */ -function block_configurable_language_delete(ConfigurableLanguageInterface $language) { +function block_configurable_language_delete(ConfigurableLanguage $language) { // Remove the block visibility settings for the deleted language. foreach (Block::loadMultiple() as $block) { /** @var $block \Drupal\block\BlockInterface */ diff --git a/core/modules/block_content/src/Plugin/Derivative/BlockContent.php b/core/modules/block_content/src/Plugin/Derivative/BlockContent.php index 54ec325..f77a297 100644 --- a/core/modules/block_content/src/Plugin/Derivative/BlockContent.php +++ b/core/modules/block_content/src/Plugin/Derivative/BlockContent.php @@ -18,13 +18,9 @@ class BlockContent extends DeriverBase { */ public function getDerivativeDefinitions($base_plugin_definition) { $block_contents = entity_load_multiple('block_content'); - /** @var $block_content \Drupal\block_content\Entity\BlockContent */ foreach ($block_contents as $block_content) { $this->derivatives[$block_content->uuid()] = $base_plugin_definition; $this->derivatives[$block_content->uuid()]['admin_label'] = $block_content->label(); - $this->derivatives[$block_content->uuid()]['config_dependencies']['content'] = array( - $block_content->getConfigDependencyName() - ); } return parent::getDerivativeDefinitions($base_plugin_definition); } diff --git a/core/modules/block_content/src/Tests/BlockContentCreationTest.php b/core/modules/block_content/src/Tests/BlockContentCreationTest.php index b8314d4..7956d1d 100644 --- a/core/modules/block_content/src/Tests/BlockContentCreationTest.php +++ b/core/modules/block_content/src/Tests/BlockContentCreationTest.php @@ -7,7 +7,6 @@ namespace Drupal\block_content\Tests; -use Drupal\Component\Utility\Unicode; use Drupal\Core\Database\Database; use Drupal\block_content\Entity\BlockContent; @@ -211,25 +210,4 @@ public function testBlockDelete() { $this->assertNoText('This will also remove'); } - /** - * Test that placed content blocks create a dependency in the block placement. - */ - public function testConfigDependencies() { - $block = $this->createBlockContent(); - // Place the block. - $block_placement_id = Unicode::strtolower($block->label()); - $instance = array( - 'id' => $block_placement_id, - 'settings[label]' => $block->label(), - 'region' => 'sidebar_first', - ); - $block = entity_load('block_content', 1); - $url = 'admin/structure/block/add/block_content:' . $block->uuid() . '/' . \Drupal::config('system.theme')->get('default'); - $this->drupalPostForm($url, $instance, t('Save block')); - - $dependencies = \Drupal::service('config.manager')->findConfigEntityDependentsAsEntities('content', array($block->getConfigDependencyName())); - $block_placement = reset($dependencies); - $this->assertEqual($block_placement_id, $block_placement->id(), "The block placement config entity has a dependency on the block content entity."); - } - } diff --git a/core/modules/book/config/install/core.base_field_override.node.book.promote.yml b/core/modules/book/config/install/core.base_field_override.node.book.promote.yml index f747d77..609d391 100644 --- a/core/modules/book/config/install/core.base_field_override.node.book.promote.yml +++ b/core/modules/book/config/install/core.base_field_override.node.book.promote.yml @@ -2,7 +2,7 @@ langcode: en status: true dependencies: - config: + entity: - node.type.book id: node.book.promote field_name: promote diff --git a/core/modules/config/src/Tests/ConfigDependencyTest.php b/core/modules/config/src/Tests/ConfigDependencyTest.php index fa903b9..27f5a13 100644 --- a/core/modules/config/src/Tests/ConfigDependencyTest.php +++ b/core/modules/config/src/Tests/ConfigDependencyTest.php @@ -68,22 +68,22 @@ public function testDependencyMangement() { $this->assertTrue(array_search('node', $raw_config->get('dependencies.module')) !== FALSE, 'Node module is written to the dependencies array as this has to be explicit.'); // Create additional entities to test dependencies on config entities. - $entity2 = $storage->create(array('id' => 'entity2', 'dependencies' => array('enforced' => array('config' => array($entity1->getConfigDependencyName()))))); + $entity2 = $storage->create(array('id' => 'entity2', 'dependencies' => array('enforced' => array('entity' => array($entity1->getConfigDependencyName()))))); $entity2->save(); - $entity3 = $storage->create(array('id' => 'entity3', 'dependencies' => array('enforced' => array('config' => array($entity2->getConfigDependencyName()))))); + $entity3 = $storage->create(array('id' => 'entity3', 'dependencies' => array('enforced' => array('entity' => array($entity2->getConfigDependencyName()))))); $entity3->save(); - $entity4 = $storage->create(array('id' => 'entity4', 'dependencies' => array('enforced' => array('config' => array($entity3->getConfigDependencyName()))))); + $entity4 = $storage->create(array('id' => 'entity4', 'dependencies' => array('enforced' => array('entity' => array($entity3->getConfigDependencyName()))))); $entity4->save(); // Test getting $entity1's dependencies as configuration dependency objects. - $dependents = $config_manager->findConfigEntityDependents('config', array($entity1->getConfigDependencyName())); + $dependents = $config_manager->findConfigEntityDependents('entity', array($entity1->getConfigDependencyName())); $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on itself.'); $this->assertTrue(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity1.'); $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on config_test.dynamic.entity1.'); $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on config_test.dynamic.entity1.'); // Test getting $entity2's dependencies as entities. - $dependents = $config_manager->findConfigEntityDependentsAsEntities('config', array($entity2->getConfigDependencyName())); + $dependents = $config_manager->findConfigEntityDependentsAsEntities('entity', array($entity2->getConfigDependencyName())); $dependent_ids = $this->getDependentIds($dependents); $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on config_test.dynamic.entity1.'); $this->assertFalse(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 does not have a dependency on itself.'); @@ -102,28 +102,20 @@ public function testDependencyMangement() { // objects after making $entity3 also dependent on node module but $entity1 // no longer depend on node module. $entity1->setEnforcedDependencies([])->save(); - $entity3->setEnforcedDependencies(['module' => ['node'], 'config' => [$entity2->getConfigDependencyName()]])->save(); + $entity3->setEnforcedDependencies(['module' => ['node'], 'entity' => [$entity2->getConfigDependencyName()]])->save(); $dependents = $config_manager->findConfigEntityDependents('module', array('node')); $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on the Node module.'); $this->assertFalse(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 does not have a dependency on the Node module.'); $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on the Node module.'); $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on the Node module.'); - // Test dependency on a fake content entity. - $entity2->setEnforcedDependencies(['config' => [$entity1->getConfigDependencyName()], 'content' => ['node:page:uuid']])->save();; - $dependents = $config_manager->findConfigEntityDependents('content', array('node:page:uuid')); - $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on the content entity.'); - $this->assertTrue(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 has a dependency on the content entity.'); - $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on the content entity (via entity2).'); - $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on the content entity (via entity3).'); - // Create a configuration entity of a different type with the same ID as one // of the entities already created. $alt_storage = $this->container->get('entity.manager')->getStorage('config_query_test'); - $alt_storage->create(array('id' => 'entity1', 'dependencies' => array('enforced' => array('config' => array($entity1->getConfigDependencyName())))))->save(); + $alt_storage->create(array('id' => 'entity1', 'dependencies' => array('enforced' => array('entity' => array($entity1->getConfigDependencyName())))))->save(); $alt_storage->create(array('id' => 'entity2', 'dependencies' => array('enforced' => array('module' => array('views')))))->save(); - $dependents = $config_manager->findConfigEntityDependentsAsEntities('config', array($entity1->getConfigDependencyName())); + $dependents = $config_manager->findConfigEntityDependentsAsEntities('entity', array($entity1->getConfigDependencyName())); $dependent_ids = $this->getDependentIds($dependents); $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on itself.'); $this->assertTrue(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity1.'); @@ -177,7 +169,7 @@ public function testConfigEntityUninstall() { 'id' => 'entity2', 'dependencies' => array( 'enforced' => array( - 'config' => array($entity1->getConfigDependencyName()), + 'entity' => array($entity1->getConfigDependencyName()), ), ), ) @@ -205,7 +197,7 @@ public function testConfigEntityUninstall() { 'id' => 'entity2', 'dependencies' => array( 'enforced' => array( - 'config' => array($entity1->getConfigDependencyName()), + 'entity' => array($entity1->getConfigDependencyName()), ), ), ) @@ -220,7 +212,7 @@ public function testConfigEntityUninstall() { $this->assertFalse($storage->load('entity1'), 'Entity 1 deleted'); $entity2 = $storage->load('entity2'); $this->assertTrue($entity2, 'Entity 2 not deleted'); - $this->assertEqual($entity2->calculateDependencies()['config'], array(), 'Entity 2 dependencies updated to remove dependency on Entity1.'); + $this->assertEqual($entity2->calculateDependencies()['entity'], array(), 'Entity 2 dependencies updated to remove dependency on Entity1.'); } /** diff --git a/core/modules/config/src/Tests/ConfigEntityNormalizeTest.php b/core/modules/config/src/Tests/ConfigEntityNormalizeTest.php deleted file mode 100644 index 5e52cfe..0000000 --- a/core/modules/config/src/Tests/ConfigEntityNormalizeTest.php +++ /dev/null @@ -1,41 +0,0 @@ -installConfig(static::$modules); - } - - public function testNormalize() { - $config_entity = entity_create('config_test', array('id' => 'system', 'label' => 'foobar', 'weight' => 1)); - $config_entity->save(); - - // Modify stored config entity, this is comparable with a schema change. - $config = \Drupal::config('config_test.dynamic.system'); - $data = array( - 'label' => 'foobar', - 'additional_key' => TRUE - ) + $config->getRawData(); - $config->setData($data)->save(); - $this->assertNotIdentical($config_entity->toArray(), $config->getRawData(), 'Stored config entity is not is equivalent to config schema.'); - - $config_entity = entity_load('config_test', 'system', TRUE); - $config_entity->save(); - - $config = \Drupal::config('config_test.dynamic.system'); - $this->assertIdentical($config_entity->toArray(), $config->getRawData(), 'Stored config entity is equivalent to config schema.'); - } - -} diff --git a/core/modules/config/src/Tests/ConfigImportUITest.php b/core/modules/config/src/Tests/ConfigImportUITest.php index e2e2118..8285979 100644 --- a/core/modules/config/src/Tests/ConfigImportUITest.php +++ b/core/modules/config/src/Tests/ConfigImportUITest.php @@ -375,7 +375,7 @@ function testImportErrorLog() { 'status' => TRUE, // Add a dependency on primary, to ensure that is synced first. 'dependencies' => array( - 'config' => array($name_primary), + 'entity' => array($name_primary), ), 'id' => 'secondary', 'label' => 'Secondary Sync', diff --git a/core/modules/config/src/Tests/ConfigImporterTest.php b/core/modules/config/src/Tests/ConfigImporterTest.php index fd69055..d8179d5 100644 --- a/core/modules/config/src/Tests/ConfigImporterTest.php +++ b/core/modules/config/src/Tests/ConfigImporterTest.php @@ -226,7 +226,7 @@ function testSecondaryWritePrimaryFirst() { 'uuid' => $uuid->generate(), // Add a dependency on primary, to ensure that is synced first. 'dependencies' => array( - 'config' => array($name_primary), + 'entity' => array($name_primary), ) ); $staging->write($name_secondary, $values_secondary); @@ -265,7 +265,7 @@ function testSecondaryWriteSecondaryFirst() { 'uuid' => $uuid->generate(), // Add a dependency on secondary, so that is synced first. 'dependencies' => array( - 'config' => array($name_secondary), + 'entity' => array($name_secondary), ) ); $staging->write($name_primary, $values_primary); @@ -323,7 +323,7 @@ function testSecondaryUpdateDeletedDeleterFirst() { 'uuid' => $uuid->generate(), // Add a dependency on deleter, to make sure that is synced first. 'dependencies' => array( - 'config' => array($name_deleter), + 'entity' => array($name_deleter), ) ); $storage->write($name_deletee, $values_deletee); @@ -339,7 +339,7 @@ function testSecondaryUpdateDeletedDeleterFirst() { // Add a dependency on deleter, to make sure that is synced first. This // will also be synced after the deletee due to alphabetical ordering. 'dependencies' => array( - 'config' => array($name_deleter), + 'entity' => array($name_deleter), ) ); $storage->write($name_other, $values_other); @@ -395,7 +395,7 @@ function testSecondaryUpdateDeletedDeleteeFirst() { 'uuid' => $uuid->generate(), // Add a dependency on deletee, to make sure that is synced first. 'dependencies' => array( - 'config' => array($name_deletee), + 'entity' => array($name_deletee), ), ); $storage->write($name_deleter, $values_deleter); @@ -444,7 +444,7 @@ function testSecondaryDeletedDeleteeSecond() { 'uuid' => $uuid->generate(), // Add a dependency on deletee, to make sure this delete is synced first. 'dependencies' => array( - 'config' => array($name_deletee), + 'entity' => array($name_deletee), ), ); $storage->write($name_deleter, $values_deleter); diff --git a/core/modules/config/tests/config_test/src/Entity/ConfigTest.php b/core/modules/config/tests/config_test/src/Entity/ConfigTest.php index ae56360..67e88fc 100644 --- a/core/modules/config/tests/config_test/src/Entity/ConfigTest.php +++ b/core/modules/config/tests/config_test/src/Entity/ConfigTest.php @@ -123,12 +123,12 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti public function onDependencyRemoval(array $dependencies) { $changed = FALSE; $fix_deps = \Drupal::state()->get('config_test.fix_dependencies', array()); - foreach ($dependencies['config'] as $entity) { + foreach ($dependencies['entity'] as $entity) { if (in_array($entity->getConfigDependencyName(), $fix_deps)) { - $key = array_search($entity->getConfigDependencyName(), $this->dependencies['enforced']['config']); + $key = array_search($entity->getConfigDependencyName(), $this->dependencies['enforced']['entity']); if ($key !== FALSE) { $changed = TRUE; - unset($this->dependencies['enforced']['config'][$key]); + unset($this->dependencies['enforced']['entity'][$key]); } } } diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php index bb8d359..c7dc0c0 100644 --- a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php +++ b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php @@ -27,7 +27,7 @@ class ConfigTranslationUiTest extends WebTestBase { * * @var array */ - public static $modules = array('node', 'contact', 'contact_test', 'config_translation', 'config_translation_test', 'views', 'views_ui', 'contextual'); + public static $modules = array('node', 'contact', 'config_translation', 'config_translation_test', 'views', 'views_ui', 'contextual'); /** * Languages to enable. diff --git a/core/modules/contact/tests/modules/contact_test/config/install/contact.form.feedback.yml b/core/modules/contact/config/install/contact.form.feedback.yml similarity index 100% rename from core/modules/contact/tests/modules/contact_test/config/install/contact.form.feedback.yml rename to core/modules/contact/config/install/contact.form.feedback.yml diff --git a/core/modules/contact/contact.install b/core/modules/contact/contact.install new file mode 100644 index 0000000..dbe3397 --- /dev/null +++ b/core/modules/contact/contact.install @@ -0,0 +1,25 @@ +get('mail'); + if (empty($site_mail)) { + $site_mail = ini_get('sendmail_from'); + } + $config = \Drupal::config('contact.form.feedback'); + // Update the recipients if the default configuration entity has been created. + // We should never rely on default config entities as during enabling a module + // during config sync they will not exist. + if (!$config->isNew()) { + \Drupal::config('contact.form.feedback')->set('recipients', array($site_mail))->save(); + } +} diff --git a/core/modules/contact/src/Tests/ContactSitewideTest.php b/core/modules/contact/src/Tests/ContactSitewideTest.php index beee430..7e6207f 100644 --- a/core/modules/contact/src/Tests/ContactSitewideTest.php +++ b/core/modules/contact/src/Tests/ContactSitewideTest.php @@ -23,7 +23,7 @@ class ContactSitewideTest extends WebTestBase { * * @var array */ - public static $modules = array('text', 'contact', 'field_ui', 'contact_test'); + public static $modules = array('text', 'contact', 'field_ui'); /** * Tests configuration options and the site-wide contact form. diff --git a/core/modules/contact/src/Tests/ContactStorageTest.php b/core/modules/contact/src/Tests/ContactStorageTest.php index 741e6b5..4d1b73b 100644 --- a/core/modules/contact/src/Tests/ContactStorageTest.php +++ b/core/modules/contact/src/Tests/ContactStorageTest.php @@ -27,7 +27,6 @@ class ContactStorageTest extends ContactSitewideTest { 'contact', 'field_ui', 'contact_storage_test', - 'contact_test', ); public static function getInfo() { diff --git a/core/modules/contact/src/Tests/MessageEntityTest.php b/core/modules/contact/src/Tests/MessageEntityTest.php index f888345..9d1ed65 100644 --- a/core/modules/contact/src/Tests/MessageEntityTest.php +++ b/core/modules/contact/src/Tests/MessageEntityTest.php @@ -22,13 +22,7 @@ class MessageEntityTest extends KernelTestBase { * * @var array */ - public static $modules = array( - 'system', - 'contact', - 'field', - 'user', - 'contact_test', - ); + public static $modules = array('system', 'contact', 'field', 'user'); protected function setUp() { parent::setUp(); diff --git a/core/modules/contact/tests/modules/contact_test/contact_test.info.yml b/core/modules/contact/tests/modules/contact_test/contact_test.info.yml deleted file mode 100644 index 6750f45..0000000 --- a/core/modules/contact/tests/modules/contact_test/contact_test.info.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: 'Contact test module' -type: module -description: 'Contains test contact form.' -package: Testing -version: VERSION -core: 8.x -dependencies: - - contact diff --git a/core/modules/editor/src/Entity/Editor.php b/core/modules/editor/src/Entity/Editor.php index 1c93a52..83928cc 100644 --- a/core/modules/editor/src/Entity/Editor.php +++ b/core/modules/editor/src/Entity/Editor.php @@ -101,7 +101,7 @@ public function label() { public function calculateDependencies() { parent::calculateDependencies(); // Create a dependency on the associated FilterFormat. - $this->addDependency('config', $this->getFilterFormat()->getConfigDependencyName()); + $this->addDependency('entity', $this->getFilterFormat()->getConfigDependencyName()); // @todo use EntityWithPluginCollectionInterface so configuration between // config entity and dependency on provider is managed automatically. $definition = $this->editorPluginManager()->createInstance($this->editor)->getPluginDefinition(); diff --git a/core/modules/editor/tests/src/Unit/EditorConfigEntityUnitTest.php b/core/modules/editor/tests/src/Unit/EditorConfigEntityUnitTest.php index 26a230a..5036532 100644 --- a/core/modules/editor/tests/src/Unit/EditorConfigEntityUnitTest.php +++ b/core/modules/editor/tests/src/Unit/EditorConfigEntityUnitTest.php @@ -152,7 +152,7 @@ public function testCalculateDependencies() { $dependencies = $entity->calculateDependencies(); $this->assertContains('test_module', $dependencies['module']); - $this->assertContains('filter.format.test', $dependencies['config']); + $this->assertContains('filter.format.test', $dependencies['entity']); } } diff --git a/core/modules/field/src/Entity/FieldConfig.php b/core/modules/field/src/Entity/FieldConfig.php index ec75234..2e5f329 100644 --- a/core/modules/field/src/Entity/FieldConfig.php +++ b/core/modules/field/src/Entity/FieldConfig.php @@ -170,7 +170,7 @@ public function preSave(EntityStorageInterface $storage) { public function calculateDependencies() { parent::calculateDependencies(); // Mark the field_storage_config as a a dependency. - $this->addDependency('config', $this->getFieldStorageDefinition()->getConfigDependencyName()); + $this->addDependency('entity', $this->getFieldStorageDefinition()->getConfigDependencyName()); return $this->dependencies; } diff --git a/core/modules/field/src/Plugin/views/field/Field.php b/core/modules/field/src/Plugin/views/field/Field.php index c05f6ed..7c14b56 100644 --- a/core/modules/field/src/Plugin/views/field/Field.php +++ b/core/modules/field/src/Plugin/views/field/Field.php @@ -944,7 +944,7 @@ function field_langcode(EntityInterface $entity) { */ public function getDependencies() { // Add the module providing the configured field storage as a dependency. - return array('config' => array($this->getFieldStorageConfig()->getConfigDependencyName())); + return array('entity' => array($this->getFieldStorageConfig()->getConfigDependencyName())); } /** diff --git a/core/modules/field/src/Tests/FieldDataCountTest.php b/core/modules/field/src/Tests/FieldDataCountTest.php index 1930c27..cc1d792 100644 --- a/core/modules/field/src/Tests/FieldDataCountTest.php +++ b/core/modules/field/src/Tests/FieldDataCountTest.php @@ -25,18 +25,11 @@ class FieldDataCountTest extends FieldUnitTestBase { protected $storage; /** - * @var \Drupal\Core\Entity\DynamicallyFieldableEntityStorageInterface - */ - protected $storage_rev; - - /** * {@inheritdoc} */ protected function setUp() { parent::setUp(); - $this->installEntitySchema('entity_test_rev'); $this->storage = \Drupal::entityManager()->getStorage('entity_test'); - $this->storage_rev = \Drupal::entityManager()->getStorage('entity_test_rev'); } /** @@ -104,38 +97,6 @@ public function testEntityCountAndHasData() { field_purge_batch(6); $this->assertIdentical($field_storage->hasdata(), TRUE, 'There are entities with deleted field data.'); $this->assertEqual($this->storage->countFieldData($field_storage), 6, 'There are 6 entities with deleted field data.'); - - $entity_type = 'entity_test_rev'; - $this->createFieldWithStorage('_2', $entity_type); - - $entity_init = entity_create($entity_type, array( - 'type' => $entity_type, - )); - $cardinality = $this->fieldTestData->field_storage_2->getCardinality(); - - $this->assertIdentical($this->fieldTestData->field_storage_2->hasData(), FALSE, 'There are no entities with field data.'); - $this->assertIdentical($this->storage_rev->countFieldData($this->fieldTestData->field_storage_2), 0, 'There are 0 entities with field data.'); - - // Create 1 entity with the field. - $entity = clone($entity_init); - $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality()); - $entity->{$this->fieldTestData->field_name_2} = $values; - $entity->setNewRevision(); - $entity->save(); - $first_revision = $entity->getRevisionId(); - - $this->assertIdentical($this->fieldTestData->field_storage_2->hasData(), TRUE, 'There are entities with field data.'); - $this->assertIdentical($this->storage_rev->countFieldData($this->fieldTestData->field_storage_2), 1, 'There is 1 entity with field data.'); - - $entity->{$this->fieldTestData->field_name_2} = array(); - $entity->setNewRevision(); - $entity->save(); - - $this->assertIdentical($this->fieldTestData->field_storage_2->hasData(), TRUE, 'There are entities with field data.'); - - $storage = $this->container->get('entity.manager')->getStorage($entity_type); - $entity = $storage->loadRevision($first_revision); - $this->assertEqual(count($entity->{$this->fieldTestData->field_name_2}), $cardinality, format_string('Revision %revision_id: expected number of values.', array('%revision_id' => $first_revision))); } } diff --git a/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.entity_test.field_test_import.yml b/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.entity_test.field_test_import.yml index bce6cf7..b205693 100644 --- a/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.entity_test.field_test_import.yml +++ b/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.entity_test.field_test_import.yml @@ -11,5 +11,5 @@ default_value_callback: '' settings: { } field_type: text dependencies: - config: + entity: - field.storage.entity_test.field_test_import diff --git a/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.entity_test.field_test_import_2.yml b/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.entity_test.field_test_import_2.yml index f52930f..ce26663 100644 --- a/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.entity_test.field_test_import_2.yml +++ b/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.entity_test.field_test_import_2.yml @@ -11,5 +11,5 @@ default_value_callback: '' settings: { } field_type: text dependencies: - config: + entity: - field.storage.entity_test.field_test_import_2 diff --git a/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.test_bundle.field_test_import_2.yml b/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.test_bundle.field_test_import_2.yml index e95266a..37adede 100644 --- a/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.test_bundle.field_test_import_2.yml +++ b/core/modules/field/tests/modules/field_test_config/config/install/field.field.entity_test.test_bundle.field_test_import_2.yml @@ -11,5 +11,5 @@ default_value_callback: '' settings: { } field_type: text dependencies: - config: + entity: - field.storage.entity_test.field_test_import_2 diff --git a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.entity_test.field_test_import_staging.yml b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.entity_test.field_test_import_staging.yml index 30768c0..fe28921 100644 --- a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.entity_test.field_test_import_staging.yml +++ b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.entity_test.field_test_import_staging.yml @@ -12,5 +12,5 @@ default_value_callback: '' settings: { } field_type: text dependencies: - config: + entity: - field.storage.entity_test.field_test_import_staging diff --git a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.test_bundle.field_test_import_staging_2.yml b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.test_bundle.field_test_import_staging_2.yml index 447205d..d1db2b2 100644 --- a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.test_bundle.field_test_import_staging_2.yml +++ b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.test_bundle.field_test_import_staging_2.yml @@ -12,5 +12,5 @@ default_value_callback: '' settings: { } field_type: text dependencies: - config: + entity: - field.storage.entity_test.field_test_import_staging_2 diff --git a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.test_bundle_2.field_test_import_staging_2.yml b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.test_bundle_2.field_test_import_staging_2.yml index 282fc83..07953c9 100644 --- a/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.test_bundle_2.field_test_import_staging_2.yml +++ b/core/modules/field/tests/modules/field_test_config/staging/field.field.entity_test.test_bundle_2.field_test_import_staging_2.yml @@ -12,5 +12,5 @@ default_value_callback: '' settings: { } field_type: text dependencies: - config: + entity: - field.storage.entity_test.field_test_import_staging_2 diff --git a/core/modules/field/tests/src/Unit/FieldConfigEntityUnitTest.php b/core/modules/field/tests/src/Unit/FieldConfigEntityUnitTest.php index 63f2d4b..eb516d7 100644 --- a/core/modules/field/tests/src/Unit/FieldConfigEntityUnitTest.php +++ b/core/modules/field/tests/src/Unit/FieldConfigEntityUnitTest.php @@ -132,8 +132,8 @@ public function testCalculateDependencies() { 'field_type' => 'test_field', ), $this->entityTypeId); $dependencies = $field->calculateDependencies(); - $this->assertContains('field.storage.test_entity_type.test_field', $dependencies['config']); - $this->assertContains('test.test_entity_type.id', $dependencies['config']); + $this->assertContains('field.storage.test_entity_type.test_field', $dependencies['entity']); + $this->assertContains('test.test_entity_type.id', $dependencies['entity']); } /** diff --git a/core/modules/field_ui/src/Tests/EntityDisplayTest.php b/core/modules/field_ui/src/Tests/EntityDisplayTest.php index 3a76027..c2ef81c 100644 --- a/core/modules/field_ui/src/Tests/EntityDisplayTest.php +++ b/core/modules/field_ui/src/Tests/EntityDisplayTest.php @@ -89,7 +89,7 @@ public function testEntityDisplayCRUD() { $new_display->save(); $new_display = entity_load('entity_view_display', $new_display->id()); $dependencies = $new_display->calculateDependencies(); - $this->assertEqual(array('config' => array('core.entity_view_mode.entity_test.other_view_mode'), 'module' => array('entity_test')), $dependencies); + $this->assertEqual(array('entity' => array('core.entity_view_mode.entity_test.other_view_mode'), 'module' => array('entity_test')), $dependencies); $this->assertEqual($new_display->targetEntityType, $display->targetEntityType); $this->assertEqual($new_display->bundle, $display->bundle); $this->assertEqual($new_display->mode, 'other_view_mode'); @@ -200,7 +200,7 @@ public function testFieldComponent() { // Check that the display has dependencies on the field and the module that // provides the formatter. $dependencies = $display->calculateDependencies(); - $this->assertEqual(array('config' => array('field.field.entity_test.entity_test.test_field'), 'module' => array('entity_test', 'field_test')), $dependencies); + $this->assertEqual(array('entity' => array('field.field.entity_test.entity_test.test_field'), 'module' => array('entity_test', 'field_test')), $dependencies); } /** @@ -292,7 +292,7 @@ public function testRenameDeleteBundle() { $this->assertEqual('node.article_rename.default', $new_form_display->id); $expected_view_dependencies = array( - 'config' => array('field.field.node.article_rename.body', 'node.type.article_rename'), + 'entity' => array('field.field.node.article_rename.body', 'node.type.article_rename'), 'module' => array('entity_test', 'text', 'user') ); // Check that the display has dependencies on the bundle, fields and the @@ -304,7 +304,7 @@ public function testRenameDeleteBundle() { // the modules that provide the formatters. $dependencies = $new_form_display->calculateDependencies(); $expected_form_dependencies = array( - 'config' => array('field.field.node.article_rename.body', 'node.type.article_rename'), + 'entity' => array('field.field.node.article_rename.body', 'node.type.article_rename'), 'module' => array('text') ); $this->assertEqual($expected_form_dependencies, $dependencies); diff --git a/core/modules/forum/config/install/core.base_field_override.node.forum.promote.yml b/core/modules/forum/config/install/core.base_field_override.node.forum.promote.yml index c265238..3f20b64 100644 --- a/core/modules/forum/config/install/core.base_field_override.node.forum.promote.yml +++ b/core/modules/forum/config/install/core.base_field_override.node.forum.promote.yml @@ -2,7 +2,7 @@ langcode: en status: true dependencies: - config: + entity: - node.type.forum id: node.forum.promote field_name: promote diff --git a/core/modules/forum/config/install/core.base_field_override.node.forum.title.yml b/core/modules/forum/config/install/core.base_field_override.node.forum.title.yml index 3b7b222..c956f34 100644 --- a/core/modules/forum/config/install/core.base_field_override.node.forum.title.yml +++ b/core/modules/forum/config/install/core.base_field_override.node.forum.title.yml @@ -2,7 +2,7 @@ langcode: en status: true dependencies: - config: + entity: - node.type.forum id: node.forum.title field_name: title diff --git a/core/modules/forum/config/install/core.entity_form_display.taxonomy_term.forums.default.yml b/core/modules/forum/config/install/core.entity_form_display.taxonomy_term.forums.default.yml index 1d8fb47..4e13510 100644 --- a/core/modules/forum/config/install/core.entity_form_display.taxonomy_term.forums.default.yml +++ b/core/modules/forum/config/install/core.entity_form_display.taxonomy_term.forums.default.yml @@ -17,5 +17,5 @@ content: settings: { } third_party_settings: { } dependencies: - config: + entity: - taxonomy.vocabulary.forums diff --git a/core/modules/forum/config/install/core.entity_view_display.taxonomy_term.forums.default.yml b/core/modules/forum/config/install/core.entity_view_display.taxonomy_term.forums.default.yml index 8984c3c..f2f5b61 100644 --- a/core/modules/forum/config/install/core.entity_view_display.taxonomy_term.forums.default.yml +++ b/core/modules/forum/config/install/core.entity_view_display.taxonomy_term.forums.default.yml @@ -13,5 +13,5 @@ content: hidden: { } status: true dependencies: - config: + entity: - taxonomy.vocabulary.forums diff --git a/core/modules/forum/config/install/field.field.taxonomy_term.forums.forum_container.yml b/core/modules/forum/config/install/field.field.taxonomy_term.forums.forum_container.yml index 3f4cd1e..8056915 100644 --- a/core/modules/forum/config/install/field.field.taxonomy_term.forums.forum_container.yml +++ b/core/modules/forum/config/install/field.field.taxonomy_term.forums.forum_container.yml @@ -14,6 +14,6 @@ default_value_callback: '' settings: { } field_type: boolean dependencies: - config: + entity: - field.storage.taxonomy_term.forum_container - taxonomy.vocabulary.forums diff --git a/core/modules/forum/config/install/rdf.mapping.node.forum.yml b/core/modules/forum/config/install/rdf.mapping.node.forum.yml index 4d159da..be874cd 100644 --- a/core/modules/forum/config/install/rdf.mapping.node.forum.yml +++ b/core/modules/forum/config/install/rdf.mapping.node.forum.yml @@ -32,7 +32,7 @@ fieldMappings: arguments: interaction_type: 'UserComments' dependencies: - config: + entity: - node.type.forum module: - node diff --git a/core/modules/forum/config/install/rdf.mapping.taxonomy_term.forums.yml b/core/modules/forum/config/install/rdf.mapping.taxonomy_term.forums.yml index 78408d8..be766eb 100644 --- a/core/modules/forum/config/install/rdf.mapping.taxonomy_term.forums.yml +++ b/core/modules/forum/config/install/rdf.mapping.taxonomy_term.forums.yml @@ -12,7 +12,7 @@ fieldMappings: properties: - 'schema:description' dependencies: - config: + entity: - taxonomy.vocabulary.forums module: - taxonomy diff --git a/core/modules/hal/hal.services.yml b/core/modules/hal/hal.services.yml index 4e89841..cebec8f 100644 --- a/core/modules/hal/hal.services.yml +++ b/core/modules/hal/hal.services.yml @@ -22,6 +22,11 @@ services: arguments: ['@rest.link_manager', '@entity.manager', '@module_handler'] tags: - { name: normalizer, priority: 10 } + serializer.normalizer.collection.hal: + class: Drupal\hal\Normalizer\CollectionNormalizer + arguments: ['@rest.link_manager'] + tags: + - { name: normalizer, priority: 10 } serializer.encoder.hal: class: Drupal\hal\Encoder\JsonEncoder tags: diff --git a/core/modules/hal/src/Normalizer/CollectionNormalizer.php b/core/modules/hal/src/Normalizer/CollectionNormalizer.php new file mode 100644 index 0000000..66ede8d --- /dev/null +++ b/core/modules/hal/src/Normalizer/CollectionNormalizer.php @@ -0,0 +1,92 @@ +linkManager = $link_manager; + } + + /** + * {@inheritdoc} + */ + public function normalize($object, $format = NULL, array $context = array()) { + // Create the array of normalized properties, starting with the URI. + $normalized = array( + '_links' => array( + 'self' => array( + 'href' => $object->getUri(), + ), + ), + ); + + // $object is not type-hinted, so we cannot be sure this method will not be + // called on a non-Collection object, and there is no interface to check on. + if (!$object instanceof Collection) { + return $normalized; + } + + // If we have additional hypermedia links add them here. + $links = $object->getLinks(); + if (is_array($links) && count($links)) { + foreach ($links as $key => $link) { + $normalized['_links'][$key] = array('href' => $link); + } + } + + // Add the list of items. + $link_relation = $this->linkManager->getCollectionItemRelation($object->getCollectionId()); + $normalized['_embedded'][$link_relation] = $this->serializer->normalize($object->getItems(), $format, $context); + + return $normalized; + } + + /** + * {@inheritdoc} + * + * @todo Implement denormalization once normalization has settled. + */ + public function denormalize($data, $class, $format = NULL, array $context = array()) { + } + + /** + * {@inheritdoc} + * + * @todo Implement denormalization once normalization has settled. + */ + public function supportsDenormalization($data, $type, $format = NULL) { + return FALSE; + } +} diff --git a/core/modules/hal/src/Tests/FileNormalizeTest.php b/core/modules/hal/src/Tests/FileNormalizeTest.php index d841ddf..46c2a4a 100644 --- a/core/modules/hal/src/Tests/FileNormalizeTest.php +++ b/core/modules/hal/src/Tests/FileNormalizeTest.php @@ -11,6 +11,7 @@ use Drupal\hal\Encoder\JsonEncoder; use Drupal\hal\Normalizer\FieldItemNormalizer; use Drupal\hal\Normalizer\FileEntityNormalizer; +use Drupal\rest\LinkManager\CollectionLinkManager; use Drupal\rest\LinkManager\LinkManager; use Drupal\rest\LinkManager\RelationLinkManager; use Drupal\rest\LinkManager\TypeLinkManager; @@ -39,7 +40,7 @@ protected function setUp() { $this->installEntitySchema('file'); $entity_manager = \Drupal::entityManager(); - $link_manager = new LinkManager(new TypeLinkManager(new MemoryBackend('default')), new RelationLinkManager(new MemoryBackend('default'), $entity_manager)); + $link_manager = new LinkManager(new TypeLinkManager(new MemoryBackend('default')), new RelationLinkManager(new MemoryBackend('default'), $entity_manager), new CollectionLinkManager()); // Set up the mock serializer. $normalizers = array( diff --git a/core/modules/hal/src/Tests/NormalizeTest.php b/core/modules/hal/src/Tests/NormalizeTest.php index ee40c25..9a82f63 100644 --- a/core/modules/hal/src/Tests/NormalizeTest.php +++ b/core/modules/hal/src/Tests/NormalizeTest.php @@ -7,10 +7,13 @@ namespace Drupal\hal\Tests; +use Drupal\Core\Entity\ContentEntityBase; + /** * Tests that entities can be normalized in HAL. * - * @group hal + * @coversDefaultClass \Drupal\hal\Normalizer\ContentEntityNormalizer + * @group HAL */ class NormalizeTest extends NormalizerTestBase { diff --git a/core/modules/hal/src/Tests/NormalizerTestBase.php b/core/modules/hal/src/Tests/NormalizerTestBase.php index e7b59d6..6c56de3 100644 --- a/core/modules/hal/src/Tests/NormalizerTestBase.php +++ b/core/modules/hal/src/Tests/NormalizerTestBase.php @@ -14,6 +14,7 @@ use Drupal\hal\Normalizer\FieldItemNormalizer; use Drupal\hal\Normalizer\FieldNormalizer; use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\rest\LinkManager\CollectionLinkManager; use Drupal\rest\LinkManager\LinkManager; use Drupal\rest\LinkManager\RelationLinkManager; use Drupal\rest\LinkManager\TypeLinkManager; @@ -116,7 +117,11 @@ protected function setUp() { ))->save(); $entity_manager = \Drupal::entityManager(); - $link_manager = new LinkManager(new TypeLinkManager(new MemoryBackend('default')), new RelationLinkManager(new MemoryBackend('default'), $entity_manager)); + $link_manager = new LinkManager( + new TypeLinkManager(new MemoryBackend('default')), + new RelationLinkManager(new MemoryBackend('default'), $entity_manager), + new CollectionLinkManager() + ); $chain_resolver = new ChainEntityResolver(array(new UuidResolver($entity_manager), new TargetIdResolver())); diff --git a/core/modules/hal/tests/src/Unit/CollectionNormalizerTest.php b/core/modules/hal/tests/src/Unit/CollectionNormalizerTest.php new file mode 100644 index 0000000..7953815 --- /dev/null +++ b/core/modules/hal/tests/src/Unit/CollectionNormalizerTest.php @@ -0,0 +1,199 @@ +getCollection(); + $normalizer = new CollectionNormalizer($this->getLinkManagerStub()); + $this->assertTrue($normalizer->supportsNormalization($collection, 'hal_json')); + $this->assertFalse($normalizer->supportsNormalization($collection, 'json')); + $this->assertFalse($normalizer->supportsNormalization(new \stdClass(), 'hal_json')); + } + + /** + * Tests the normalize method. + */ + public function testNormalize() { + $test_values = $this->getTestValues(); + $collection = $this->getCollection(); + + // Create the normalizer and inject the LinkManagerStub. + $normalizer = new CollectionNormalizer($this->getLinkManagerStub()); + // Inject the Serializer. Handle the call to Serializer::normalize, + // ensuring that the items array is passed in. + $serializer = $this->getSerializerStub(); + $serializer->expects($this->any()) + ->method('normalize') + ->with($collection->getItems()) + ->will($this->returnValue($test_values['items'])); + $normalizer->setSerializer($serializer); + // Get the normalized array. + $normalized = $normalizer->normalize($collection, 'hal_json'); + + // Test that self link points to collection URI. + $this->assertEquals($normalized['_links']['self']['href'], $test_values['uri']); + // There should only be a self-key. + $this->assertEquals(array_keys($normalized['_links']), array('self')); + + // Test that the correct link relation was retrieved from the LinkManager + // and added to _embedded. + $this->assertArrayHasKey($test_values['item_link_relation'], $normalized['_embedded']); + // Test that the item link relation points to the serialized item array. + $this->assertEquals($normalized['_embedded'][$test_values['item_link_relation']], $test_values['items']); + } + + /** + * Tests the normalize method on pageable collection. + */ + public function testNormalizePageableCollection() { + $test_values = $this->getTestValues(); + $collection = $this->getPageableCollection(); + + // Create the normalizer and inject the LinkManagerStub. + $normalizer = new CollectionNormalizer($this->getLinkManagerStub()); + // Inject the Serializer. Handle the call to Serializer::normalize, + // ensuring that the items array is passed in. + $serializer = $this->getSerializerStub(); + $serializer->expects($this->any()) + ->method('normalize') + ->with($collection->getItems()) + ->will($this->returnValue($test_values['items'])); + $normalizer->setSerializer($serializer); + // Get the normalized array. + $normalized = $normalizer->normalize($collection, 'hal_json'); + + // Test that self link points to collection URI. + $this->assertEquals($normalized['_links']['self']['href'], $test_values['uri']); + // There should be the self-key, _first, _prev, _next and _last-keys. + $this->assertArrayHasKey('self', $normalized['_links']); + $this->assertArrayHasKey('first', $normalized['_links']); + $this->assertArrayHasKey('prev', $normalized['_links']); + $this->assertArrayHasKey('next', $normalized['_links']); + $this->assertArrayHasKey('last', $normalized['_links']); + $this->assertEquals(array_keys($normalized['_links']), + array('self', 'first', 'prev', 'next', 'last') + ); + + // Test that the correct link relation was retrieved from the LinkManager + // and added to _embedded. + $this->assertArrayHasKey($test_values['item_link_relation'], $normalized['_embedded']); + // Test that the item link relation points to the serialized item array. + $this->assertEquals($normalized['_embedded'][$test_values['item_link_relation']], $test_values['items']); + } + + /** + * Get an \Drupal\serialization\Collection for testing. + * + * @return \Drupal\serialization\Collection + * The Collection object, configured with test values. + */ + protected function getCollection() { + $test_values = $this->getTestValues(); + + // Get a mock node. + $node = $this->getMockBuilder('Drupal\node\Entity\Node') + ->disableOriginalConstructor() + ->getMock(); + + $collection = new Collection('test_id'); + $collection->setUri($test_values['uri']); + $collection->setItems(array($node)); + + return $collection; + } + + /** + * Get an pageable \Drupal\serialization\Collection for testing. + * + * @return \Drupal\serialization\Collection + * The Collection object, configured with test values. + */ + protected function getPageableCollection() { + $test_values = $this->getTestValues(); + + // Get a dummy node. + $node = $this->getMockBuilder('Drupal\node\Entity\Node') + ->disableOriginalConstructor() + ->getMock(); + + $collection = new Collection('test_id'); + $collection->setUri($test_values['uri']); + $collection->setItems(array($node)); + + $collection->setLinks(array( + 'first' => $test_values['uri'] . '?page=0', + 'prev' => $test_values['uri'] . '?page=0', + 'next' => $test_values['uri'] . '?page=2', + 'last' => $test_values['uri'] . '?page=2', + )); + + return $collection; + } + + /** + * Get a stub LinkManager for testing. + * + * @return \Drupal\rest\LinkManager\LinkManagerInterface + * The LinkManager stub. + */ + protected function getLinkManagerStub() { + $test_values = $this->getTestValues(); + + $link_manager = $this->getMockBuilder('Drupal\rest\LinkManager\LinkManager') + ->disableOriginalConstructor() + ->getMock(); + + $link_manager->expects($this->any()) + ->method('getCollectionItemRelation') + ->will($this->returnValue($test_values['item_link_relation'])); + + return $link_manager; + } + + /** + * Get a stub Serializer for testing. + * + * @return \Symfony\Component\Serializer\SerializerInterface|\Symfony\Component\Serializer\Normalizer\NormalizerInterface|\Symfony\Component\Serializer\Normalizer\DenormalizerInterface|\Symfony\Component\Serializer\Encoder\EncoderInterface|\Symfony\Component\Serializer\Encoder\DecoderInterface|\PHPUnit_Framework_MockObject_MockObject + * The Serializer mock. + */ + protected function getSerializerStub() { + $serializer = $this->getMockBuilder('Symfony\Component\Serializer\Serializer') + ->disableOriginalConstructor() + ->getMock(); + + return $serializer; + } + + /** + * Get the array of test values. + * + * @return array + * An array of test values, used for configuring stub methods and testing. + */ + protected function getTestValues() { + return array( + 'item_link_relation' => 'item', + 'items' => 'Array of serialized entities goes here', + 'uri' => 'http://example.com/test-path', + ); + } +} diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 68126f6..a605360 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -8,7 +8,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Routing\RouteMatchInterface; -use Drupal\language\ConfigurableLanguageInterface; +use Drupal\language\Entity\ConfigurableLanguage; use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUI; use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl; use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrlFallback; @@ -418,7 +418,7 @@ function language_modules_uninstalled($modules) { /** * Implements hook_ENTITY_TYPE_insert() for 'configurable_language'. */ -function language_configurable_language_insert(ConfigurableLanguageInterface $language) { +function language_configurable_language_insert(ConfigurableLanguage $language) { if ($language->isLocked()) { return; } @@ -432,7 +432,7 @@ function language_configurable_language_insert(ConfigurableLanguageInterface $la /** * Implements hook_ENTITY_TYPE_delete() for 'configurable_language'. */ -function language_configurable_language_delete(ConfigurableLanguageInterface $language) { +function language_configurable_language_delete(ConfigurableLanguage $language) { // Remove language from language prefix list. $prefixes = language_negotiation_url_prefixes(); unset($prefixes[$language->id()]); diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 846ee88..04dfb80 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -20,7 +20,7 @@ use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\StringTranslation\TranslationWrapper; use Drupal\Core\Language\LanguageInterface; -use Drupal\language\ConfigurableLanguageInterface; +use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Component\Utility\Crypt; /** @@ -198,7 +198,7 @@ function locale_theme() { /** * Implements hook_ENTITY_TYPE_insert() for 'configurable_language'. */ -function locale_configurable_language_insert(ConfigurableLanguageInterface $language) { +function locale_configurable_language_insert(ConfigurableLanguage $language) { // @todo move these two cache clears out. See http://drupal.org/node/1293252 // Changing the language settings impacts the interface: clear render cache. \Drupal::cache('render')->deleteAll(); @@ -209,7 +209,7 @@ function locale_configurable_language_insert(ConfigurableLanguageInterface $lang /** * Implements hook_ENTITY_TYPE_update() for 'configurable_language'. */ -function locale_configurable_language_update(ConfigurableLanguageInterface $language) { +function locale_configurable_language_update(ConfigurableLanguage $language) { // @todo move these two cache clears out. See http://drupal.org/node/1293252 // Changing the language settings impacts the interface: clear render cache. \Drupal::cache('render')->deleteAll(); @@ -220,7 +220,7 @@ function locale_configurable_language_update(ConfigurableLanguageInterface $lang /** * Implements hook_ENTITY_TYPE_delete() for 'configurable_language'. */ -function locale_configurable_language_delete(ConfigurableLanguageInterface $language) { +function locale_configurable_language_delete(ConfigurableLanguage $language) { // Remove translations. \Drupal::service('locale.storage')->deleteTranslations(array('language' => $language->id())); diff --git a/core/modules/locale/locale.translation.inc b/core/modules/locale/locale.translation.inc index 5453f7c..61083cd 100644 --- a/core/modules/locale/locale.translation.inc +++ b/core/modules/locale/locale.translation.inc @@ -83,7 +83,7 @@ function locale_translation_get_projects(array $project_names = array()) { * Clears the projects cache. */ function locale_translation_clear_cache_projects() { - drupal_static_reset('locale_translation_get_projects'); + drupal_static('locale_translation_get_projects', array()); } /** diff --git a/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php index e0c20fc..30ab0a0 100644 --- a/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php +++ b/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php @@ -22,7 +22,7 @@ class LocaleConfigTranslationTest extends WebTestBase { * * @var array */ - public static $modules = array('locale', 'contact', 'contact_test'); + public static $modules = array('locale', 'contact'); /** * {@inheritdoc} diff --git a/core/modules/locale/src/Tests/LocaleTranslationProjectsTest.php b/core/modules/locale/src/Tests/LocaleTranslationProjectsTest.php deleted file mode 100644 index aa8c955..0000000 --- a/core/modules/locale/src/Tests/LocaleTranslationProjectsTest.php +++ /dev/null @@ -1,68 +0,0 @@ -moduleHandler = $this->container->get('module_handler'); - $this->projectStorage = $this->container->get('locale.project'); - } - - - /** - * Tests locale_translation_clear_cache_projects(). - */ - public function testLocaleTranslationClearCacheProjects() { - $this->moduleHandler->loadInclude('locale', 'inc', 'locale.translation'); - - $expected = []; - $this->assertIdentical($expected, locale_translation_get_projects()); - - $this->projectStorage->set('foo', []); - $expected['foo'] = new \stdClass(); - $this->assertEqual($expected, locale_translation_get_projects()); - - $this->projectStorage->set('bar', []); - locale_translation_clear_cache_projects(); - $expected['bar'] = new \stdClass(); - $this->assertEqual($expected, locale_translation_get_projects()); - } - -} diff --git a/core/modules/node/node.module b/core/modules/node/node.module index bb4e2b2..11f2092 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -30,7 +30,7 @@ use Drupal\Core\Entity\Display\EntityFormDisplayInterface; use Drupal\Core\Template\Attribute; use Drupal\file\Entity\File; -use Drupal\language\ConfigurableLanguageInterface; +use Drupal\language\Entity\ConfigurableLanguage; use Drupal\block\Entity\Block; use Drupal\Core\Session\AccountInterface; @@ -1400,7 +1400,7 @@ function node_modules_uninstalled($modules) { /** * Implements hook_ENTITY_TYPE_delete() for 'configurable_language'. */ -function node_configurable_language_delete(ConfigurableLanguageInterface $language) { +function node_configurable_language_delete(ConfigurableLanguage $language) { // On nodes with this language, unset the language. \Drupal::entityManager()->getStorage('node')->clearRevisionsLanguage($language); } diff --git a/core/modules/options/tests/options_config_install_test/config/install/core.entity_form_display.node.options_install_test.default.yml b/core/modules/options/tests/options_config_install_test/config/install/core.entity_form_display.node.options_install_test.default.yml index b24ca9e..3b96a57 100644 --- a/core/modules/options/tests/options_config_install_test/config/install/core.entity_form_display.node.options_install_test.default.yml +++ b/core/modules/options/tests/options_config_install_test/config/install/core.entity_form_display.node.options_install_test.default.yml @@ -1,7 +1,7 @@ langcode: en status: true dependencies: - config: + entity: - field.field.node.options_install_test.body - node.type.options_install_test module: diff --git a/core/modules/options/tests/options_config_install_test/config/install/core.entity_view_display.node.options_install_test.default.yml b/core/modules/options/tests/options_config_install_test/config/install/core.entity_view_display.node.options_install_test.default.yml index d2a3b18..506ee9d 100644 --- a/core/modules/options/tests/options_config_install_test/config/install/core.entity_view_display.node.options_install_test.default.yml +++ b/core/modules/options/tests/options_config_install_test/config/install/core.entity_view_display.node.options_install_test.default.yml @@ -1,7 +1,7 @@ langcode: en status: true dependencies: - config: + entity: - field.field.node.options_install_test.body - node.type.options_install_test module: diff --git a/core/modules/options/tests/options_config_install_test/config/install/core.entity_view_display.node.options_install_test.teaser.yml b/core/modules/options/tests/options_config_install_test/config/install/core.entity_view_display.node.options_install_test.teaser.yml index a6a9b60..356a6a2 100644 --- a/core/modules/options/tests/options_config_install_test/config/install/core.entity_view_display.node.options_install_test.teaser.yml +++ b/core/modules/options/tests/options_config_install_test/config/install/core.entity_view_display.node.options_install_test.teaser.yml @@ -1,7 +1,7 @@ langcode: en status: true dependencies: - config: + entity: - core.entity_view_mode.node.teaser - field.field.node.options_install_test.body - node.type.options_install_test diff --git a/core/modules/options/tests/options_config_install_test/config/install/field.field.node.options_install_test.body.yml b/core/modules/options/tests/options_config_install_test/config/install/field.field.node.options_install_test.body.yml index 2078a84..20fd4d3 100644 --- a/core/modules/options/tests/options_config_install_test/config/install/field.field.node.options_install_test.body.yml +++ b/core/modules/options/tests/options_config_install_test/config/install/field.field.node.options_install_test.body.yml @@ -1,7 +1,7 @@ langcode: en status: true dependencies: - config: + entity: - field.storage.node.body - node.type.options_install_test id: node.options_install_test.body diff --git a/core/modules/options/tests/options_config_install_test/config/install/field.field.node.options_install_test.field_options_float.yml b/core/modules/options/tests/options_config_install_test/config/install/field.field.node.options_install_test.field_options_float.yml index 39fd25e..581f2b7 100644 --- a/core/modules/options/tests/options_config_install_test/config/install/field.field.node.options_install_test.field_options_float.yml +++ b/core/modules/options/tests/options_config_install_test/config/install/field.field.node.options_install_test.field_options_float.yml @@ -1,7 +1,7 @@ langcode: en status: true dependencies: - config: + entity: - field.storage.node.field_options_float - node.type.options_install_test id: node.options_install_test.field_options_float diff --git a/core/modules/rdf/src/Entity/RdfMapping.php b/core/modules/rdf/src/Entity/RdfMapping.php index 9f7915b..b842547 100644 --- a/core/modules/rdf/src/Entity/RdfMapping.php +++ b/core/modules/rdf/src/Entity/RdfMapping.php @@ -145,7 +145,7 @@ public function calculateDependencies() { // If the target entity type uses entities to manage its bundles then // depend on the bundle entity. $bundle_entity = \Drupal::entityManager()->getStorage($bundle_entity_type_id)->load($this->bundle); - $this->addDependency('config', $bundle_entity->getConfigDependencyName()); + $this->addDependency('entity', $bundle_entity->getConfigDependencyName()); } return $this->dependencies; } diff --git a/core/modules/rdf/tests/src/Unit/RdfMappingConfigEntityUnitTest.php b/core/modules/rdf/tests/src/Unit/RdfMappingConfigEntityUnitTest.php index 52f1616..9420d65 100644 --- a/core/modules/rdf/tests/src/Unit/RdfMappingConfigEntityUnitTest.php +++ b/core/modules/rdf/tests/src/Unit/RdfMappingConfigEntityUnitTest.php @@ -93,7 +93,7 @@ public function testCalculateDependencies() { $entity = new RdfMapping($values, $this->entityTypeId); $dependencies = $entity->calculateDependencies(); - $this->assertArrayNotHasKey('config', $dependencies); + $this->assertArrayNotHasKey('entity', $dependencies); $this->assertContains('test_module', $dependencies['module']); } @@ -142,7 +142,7 @@ public function testCalculateDependenciesWithEntityBundle() { $entity = new RdfMapping($values, $this->entityTypeId); $dependencies = $entity->calculateDependencies(); - $this->assertContains('test_module.type.' . $bundle_id, $dependencies['config']); + $this->assertContains('test_module.type.' . $bundle_id, $dependencies['entity']); $this->assertContains('test_module', $dependencies['module']); } diff --git a/core/modules/rest/rest.services.yml b/core/modules/rest/rest.services.yml index c25d692..58dde91 100644 --- a/core/modules/rest/rest.services.yml +++ b/core/modules/rest/rest.services.yml @@ -15,13 +15,15 @@ services: - { name: access_check } rest.link_manager: class: Drupal\rest\LinkManager\LinkManager - arguments: ['@rest.link_manager.type', '@rest.link_manager.relation'] + arguments: ['@rest.link_manager.type', '@rest.link_manager.relation', '@rest.link_manager.collection'] rest.link_manager.type: class: Drupal\rest\LinkManager\TypeLinkManager arguments: ['@cache.default'] rest.link_manager.relation: class: Drupal\rest\LinkManager\RelationLinkManager arguments: ['@cache.default', '@entity.manager'] + rest.link_manager.collection: + class: Drupal\rest\LinkManager\CollectionLinkManager rest.resource_routes: class: Drupal\rest\Routing\ResourceRoutes arguments: ['@plugin.manager.rest', '@config.factory', '@logger.channel.rest'] diff --git a/core/modules/rest/src/LinkManager/CollectionLinkManager.php b/core/modules/rest/src/LinkManager/CollectionLinkManager.php new file mode 100644 index 0000000..79c8747 --- /dev/null +++ b/core/modules/rest/src/LinkManager/CollectionLinkManager.php @@ -0,0 +1,23 @@ +typeLinkManager = $type_link_manager; $this->relationLinkManager = $relation_link_manager; + $this->collectionLinkManager = $collection_link_manager; } /** @@ -62,4 +72,12 @@ public function getRelationUri($entity_type, $bundle, $field_name) { public function getRelationInternalIds($relation_uri) { return $this->relationLinkManager->getRelationInternalIds($relation_uri); } + + /** + * {@inheritdoc} + */ + public function getCollectionItemRelation($collection_id) { + return $this->collectionLinkManager->getCollectionItemRelation($collection_id); + } + } diff --git a/core/modules/rest/src/LinkManager/LinkManagerInterface.php b/core/modules/rest/src/LinkManager/LinkManagerInterface.php index 60e5629..69be4be 100644 --- a/core/modules/rest/src/LinkManager/LinkManagerInterface.php +++ b/core/modules/rest/src/LinkManager/LinkManagerInterface.php @@ -19,5 +19,5 @@ * custom logic, it is expected to be more common for plugin managers to proxy * the method invocations to the respective components. */ -interface LinkManagerInterface extends TypeLinkManagerInterface, RelationLinkManagerInterface { +interface LinkManagerInterface extends TypeLinkManagerInterface, RelationLinkManagerInterface, CollectionLinkManagerInterface { } diff --git a/core/modules/rest/src/Plugin/views/display/RestExport.php b/core/modules/rest/src/Plugin/views/display/RestExport.php index a78b175..3764531 100644 --- a/core/modules/rest/src/Plugin/views/display/RestExport.php +++ b/core/modules/rest/src/Plugin/views/display/RestExport.php @@ -247,7 +247,7 @@ public function optionsSummary(&$categories, &$options) { * {@inheritdoc} */ public function collectRoutes(RouteCollection $collection) { - parent::collectRoutes($collection); + $result = parent::collectRoutes($collection); $view_id = $this->view->storage->id(); $display_id = $this->display['id']; @@ -262,6 +262,8 @@ public function collectRoutes(RouteCollection $collection) { // Add the new requirements to the route. $route->addRequirements($requirements); } + + return $result; } /** diff --git a/core/modules/rest/src/Plugin/views/style/Serializer.php b/core/modules/rest/src/Plugin/views/style/Serializer.php index 09e94e6..c3f823f 100644 --- a/core/modules/rest/src/Plugin/views/style/Serializer.php +++ b/core/modules/rest/src/Plugin/views/style/Serializer.php @@ -8,6 +8,9 @@ namespace Drupal\rest\Plugin\views\style; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\UrlGeneratorInterface; +use Drupal\Core\State\StateInterface; +use Drupal\serialization\Collection; use Drupal\views\ViewExecutable; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\Plugin\views\style\StylePluginBase; @@ -53,6 +56,20 @@ class Serializer extends StylePluginBase { protected $formats = array(); /** + * The URL generator service. + * + * @var \Drupal\Core\Routing\UrlGeneratorInterface + */ + protected $urlGenerator; + + /** + * The state service. + * + * @var \Drupal\Core\State\StateInterface + */ + protected $state; + + /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { @@ -61,19 +78,23 @@ public static function create(ContainerInterface $container, array $configuratio $plugin_id, $plugin_definition, $container->get('serializer'), - $container->getParameter('serializer.formats') + $container->getParameter('serializer.formats'), + $container->get('url_generator'), + $container->get('state') ); } /** * Constructs a Plugin object. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, SerializerInterface $serializer, array $serializer_formats) { + public function __construct(array $configuration, $plugin_id, array $plugin_definition, SerializerInterface $serializer, array $serializer_formats, UrlGeneratorInterface $url_generator, StateInterface $state) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->definition = $plugin_definition + $configuration; $this->serializer = $serializer; $this->formats = $serializer_formats; + $this->urlGenerator = $url_generator; + $this->state = $state; } /** @@ -115,22 +136,7 @@ public function submitOptionsForm(&$form, FormStateInterface $form_state) { * {@inheritdoc} */ public function render() { - $rows = array(); - // If the Data Entity row plugin is used, this will be an array of entities - // which will pass through Serializer to one of the registered Normalizers, - // which will transform it to arrays/scalars. If the Data field row plugin - // is used, $rows will not contain objects and will pass directly to the - // Encoder. - foreach ($this->view->result as $row) { - $rows[] = $this->view->rowPlugin->render($row); - } - - $content_type = $this->displayHandler->getContentType(); - if (!empty($this->view->live_preview)) { - $content_type = $this->options['formats'] ? reset($this->options['formats']) : 'json'; - } - - return $this->serializer->serialize($rows, $content_type); + return $this->serializer->serialize($this->getCollection(), $this->displayHandler->getContentType()); } /** @@ -150,4 +156,86 @@ public function getFormats() { return $this->formats; } + /** + * Instantiate Collection object needed to encapsulate serialization. + * + * @return \Drupal\serialization\Collection + * Collection object wrapping items/rows of the view. + */ + public function getCollection() { + $this->view = $this->view; + + $display = $this->view->getDisplay(); + // Build full view-display id. + $view_id = $this->view->storage->id(); + $display_id = $display->display['id']; + + // Instantiate collection object. + $collection = new Collection($view_id . '_' . $display_id); + + $collection->setTitle($this->view->getTitle()); + $collection->setDescription($display->getOption('display_description')); + + // Route as defined in e.g. \Drupal\rest\Plugin\views\display\RestExport. + $route_names = $this->state->get('views.view_route_names'); + $route_name = $route_names["$view_id.$display_id"]; + + // Get base url path for the view; getUrl returns a path not an absolute + // URL (and no page information). + $view_base_url = $this->view->getUrl(); + + // Inject the page into the canonical URI of the view. + if ($this->view->getCurrentPage() > 0) { + $uri = $this->urlGenerator->generateFromRoute($route_name, array(), array('query' => array('page' => $this->view->getCurrentPage()), 'absolute' => TRUE)); + } + else { + $uri = $this->urlGenerator->generateFromRoute($route_name, array(), array('absolute' => TRUE)); + } + $collection->setUri($uri); + + $rows = array(); + foreach ($this->view->result as $row) { + $rows[] = $this->view->rowPlugin->render($row); + } + $collection->setItems($rows); + + $pager = $this->view->getPager(); + + // Determine whether we have more items than we are showing, in that case + // we are a pageable collection. + if ($pager->getTotalItems() > $pager->getItemsPerPage()) { + // Calculate pager links. + $current_page = $pager->getCurrentPage(); + // Starting at page=0 we need to decrement. + $total = ceil($pager->getTotalItems() / $pager->getItemsPerPage()) - 1; + + $collection->setLink('first', $this->urlGenerator->generateFromRoute($route_name, array(), array( + 'query' => array('page' => 0), + 'absolute' => TRUE, + ))); + + // If we are not on the first page add a previous link. + if ($current_page > 0) { + $collection->setLink('prev', $this->urlGenerator->generateFromRoute($route_name, array(), array( + 'query' => array('page' => $current_page - 1), + 'absolute' => TRUE, + ))); + } + + // If we are not on the last page add a next link. + if ($current_page < $total) { + $collection->setLink('next', $this->urlGenerator->generateFromRoute($route_name, array(), array( + 'query' => array('page' => $current_page + 1), + 'absolute' => TRUE, + ))); + } + + $collection->setLink('last', $this->urlGenerator->generateFromRoute($route_name, array(), array( + 'query' => array('page' => $total), + 'absolute' => TRUE, + ))); + } + + return $collection; + } } diff --git a/core/modules/rest/src/Tests/Views/StyleSerializerTest.php b/core/modules/rest/src/Tests/Views/StyleSerializerTest.php index 0822eab..7c0c066 100644 --- a/core/modules/rest/src/Tests/Views/StyleSerializerTest.php +++ b/core/modules/rest/src/Tests/Views/StyleSerializerTest.php @@ -7,7 +7,11 @@ namespace Drupal\rest\Tests\Views; +use Drupal\Component\Serialization\Json; use Drupal\Component\Utility\String; +use Drupal\Core\Url; +use Drupal\serialization\Collection; +use Drupal\views\ViewExecutable; use Drupal\views\Views; use Drupal\views\Tests\Plugin\PluginTestBase; use Drupal\views\Tests\ViewTestData; @@ -59,6 +63,37 @@ protected function setUp() { } /** + * Retrieves a Drupal path or an absolute path with hal+json. + * + * Sets Accept-Header to application/hal+json and decodes the result. + * + * @param string $path + * Path to request HAL+JSON from. + * @param array $options + * Array of options to pass to the URL generator. + * @param array $headers + * Array of headers. + * + * @return array + * Decoded json. + * Requests a Drupal path in HAL+JSON format, and JSON decodes the response. + */ + protected function drupalGetHalJson($path, array $options = array(), array $headers = array()) { + $headers[] = 'Accept: application/hal+json'; + return Json::decode($this->drupalGet($path, $options, $headers)); + } + + /** + * Retrieve the Collection object for given view. + * + * @return \Drupal\serialization\Collection + * The collection object to pass into the serializer. + */ + protected function getCollectionFromView(ViewExecutable $view) { + return $view->getStyle()->getCollection($view); + } + + /** * Checks the behavior of the Serializer callback paths and row plugins. */ public function testSerializerResponses() { @@ -67,7 +102,8 @@ public function testSerializerResponses() { $view->initDisplay(); $this->executeView($view); - $actual_json = $this->drupalGet('test/serialize/field', array(), array('Accept: application/json')); + // application/json-type serialization. + $actual_json = $this->drupalGetJSON('test/serialize/field'); $this->assertResponse(200); // Test the http Content-type. @@ -83,8 +119,7 @@ public function testSerializerResponses() { $expected[] = $expected_row; } - $this->assertIdentical($actual_json, json_encode($expected), 'The expected JSON output was found.'); - + $this->assertIdentical($actual_json, $expected, 'The expected JSON output was found.'); // Test that the rendered output and the preview output are the same. $view->destroy(); @@ -92,35 +127,156 @@ public function testSerializerResponses() { // Mock the request content type by setting it on the display handler. $view->display_handler->setContentType('json'); $output = $view->preview(); - $this->assertIdentical($actual_json, drupal_render($output), 'The expected JSON preview output was found.'); + $this->assertIdentical(Json::encode($actual_json), drupal_render($output), 'The expected JSON preview output was found.'); // Test a 403 callback. $this->drupalGet('test/serialize/denied'); $this->assertResponse(403); // Test the entity rows. + $view = Views::getView('test_serializer_display_entity'); + $view->setDisplay('rest_export_1'); + $this->executeView($view); + + $serializer = $this->container->get('serializer'); + // Create the entity collection. + $collection = $this->getCollectionFromView($view); + $expected = $serializer->serialize($collection, 'json'); + + $this->assertFalse($collection->hasLinks(), 'Collection created from a non-paging view does not have (hypermedia) link relations'); + + $actual_json = $this->drupalGetJSON('test/serialize/entity'); + $this->assertResponse(200); + $this->assertIdentical(Json::encode($actual_json), $expected, 'The expected JSON output was found.'); + + // application/hal+json-type serialization. + $expected = $serializer->serialize($collection, 'hal_json'); + $actual_json = $this->drupalGetHalJson('test/serialize/entity'); + $this->assertIdentical(Json::encode($actual_json), $expected, 'The expected HAL output was found.'); + + // Make assertions on the structure of the response. + $this->assertTrue(isset($actual_json['_embedded']), 'Has _embedded key.'); + $this->assertTrue(isset($actual_json['_links']), 'Has _links key.'); + + $this->assertEqual(count($actual_json['_embedded']['item']), 10); + $this->assertEqual($actual_json['_links']['self']['href'], $this->viewUrl($view)); + $this->assertEqual(array_keys($actual_json['_links']), array('self')); + } + /** + * Build an absolute URL from a view path, accounting for paging. + * + * @param ViewExecutable $view + * @param null $page + * + * @return string + */ + protected function viewUrl(ViewExecutable $view, $page = NULL) { + $base_url = 'base://' . $view->getUrl(); + $options = array( + 'absolute' => TRUE, + ); + if (isset($page)) { + $options += array('query' => array('page' => $page)); + } + + return Url::fromUri($base_url, $options)->toString(); + } + + /** + * Checks the paging behavior of callback paths and row plugins. + */ + protected function testSerializerPageableCollectionHalJsonResponses() { + // Test the entity rows - with paging. $view = Views::getView('test_serializer_display_entity'); - $view->initDisplay(); + $view->setDisplay('rest_export_paging'); $this->executeView($view); // Get the serializer service. $serializer = $this->container->get('serializer'); + // Create the entity collection from the current view. + $collection = $this->getCollectionFromView($view); + $this->assertTrue($collection->hasLinks(), 'Collection created from a paging view has (hypermedia) link relations'); + + $expected = $serializer->serialize($collection, 'hal_json'); + $actual_json = $this->drupalGetHalJson('test/serialize/entity_paging'); + $this->assertIdentical(Json::encode($actual_json), $expected, 'The expected HAL output was found.'); + + // Make assertions on the structure of the response. + $this->assertTrue(isset($actual_json['_embedded']) && isset($actual_json['_links']), 'Has _links and _embedded keys'); + + $this->assertEqual(count($actual_json['_embedded']['item']), 1); + $this->assertEqual($actual_json['_links']['self']['href'], $this->viewUrl($view)); + $this->assertEqual($actual_json['_links']['first']['href'], $this->viewUrl($view, 0)); + $this->assertEqual($actual_json['_links']['next']['href'], $this->viewUrl($view, 1)); + $this->assertEqual($actual_json['_links']['last']['href'], $this->viewUrl($view, 9)); + $this->assertEqual(array_keys($actual_json['_links']), array( + 'self', + 'first', + 'next', + 'last', + )); + + // Load the second page. + $actual_json_page_1 = $this->drupalGetHalJson($actual_json['_links']['next']['href']); + $this->assertTrue(isset($actual_json_page_1['_embedded']) && isset($actual_json_page_1['_links']), 'Has _links and _embedded keys'); + + $this->assertEqual(count($actual_json_page_1['_embedded']['item']), 1); + $this->assertEqual($actual_json_page_1['_links']['self']['href'], $this->viewUrl($view, 1)); + $this->assertEqual($actual_json_page_1['_links']['first']['href'], $this->viewUrl($view, 0)); + $this->assertEqual($actual_json_page_1['_links']['prev']['href'], $this->viewUrl($view, 0)); + $this->assertEqual($actual_json_page_1['_links']['next']['href'], $this->viewUrl($view, 2)); + $this->assertEqual($actual_json_page_1['_links']['last']['href'], $this->viewUrl($view, 9)); + $this->assertEqual(array_keys($actual_json_page_1['_links']), array( + 'self', + 'first', + 'prev', + 'next', + 'last', + )); + + // Test the entity rows - with paging. + $view = Views::getView('test_serializer_display_entity'); + $view->setDisplay('rest_export_paging'); + $view->setCurrentPage(1); + $this->executeView($view); - $entities = array(); - foreach ($view->result as $row) { - $entities[] = $row->_entity; - } + // Create the entity collection. + $collection = $this->getCollectionFromView($view); + $this->assertTrue($collection->hasLinks(), 'Collection created from a paging view has (hypermedia) link relations'); + $expected = $serializer->serialize($collection, 'hal_json'); - $expected = $serializer->serialize($entities, 'json'); + $this->assertEqual(Json::encode($actual_json_page_1), $expected, 'The expected HAL output for page=1 was found.'); - $actual_json = $this->drupalGet('test/serialize/entity', array(), array('Accept: application/json')); - $this->assertResponse(200); - $this->assertIdentical($actual_json, $expected, 'The expected JSON output was found.'); + // Load the last page. + $actual_json_page_last = $this->drupalGetHalJSON($actual_json['_links']['last']['href']); + + $this->assertTrue(isset($actual_json_page_last['_embedded']) && isset($actual_json_page_last['_links']), 'Has _links and _embedded keys'); + + $this->assertEqual(count($actual_json_page_last['_embedded']['item']), 1); + $this->assertEqual($actual_json_page_last['_links']['self']['href'], $this->viewUrl($view, 9)); + $this->assertEqual($actual_json_page_last['_links']['first']['href'], $this->viewUrl($view, 0)); + $this->assertEqual($actual_json_page_last['_links']['prev']['href'], $this->viewUrl($view, 8)); + $this->assertEqual($actual_json_page_last['_links']['last']['href'], $this->viewUrl($view, 9)); + $this->assertEqual(array_keys($actual_json_page_last['_links']), array( + 'self', + 'first', + 'prev', + 'last', + )); - $expected = $serializer->serialize($entities, 'hal_json'); - $actual_json = $this->drupalGet('test/serialize/entity', array(), array('Accept: application/hal+json')); - $this->assertIdentical($actual_json, $expected, 'The expected HAL output was found.'); + // Test the entity rows - with paging. + $view = Views::getView('test_serializer_display_entity'); + $view->setDisplay('rest_export_paging'); + $view->setCurrentPage(9); + $this->executeView($view); + + // Create the entity collection. + $collection = $this->getCollectionFromView($view); + $this->assertTrue($collection->hasLinks(), 'Collection created from a paging view has (hypermedia) link relations'); + $expected = $serializer->serialize($collection, 'hal_json'); + + $this->assertEqual(Json::encode($actual_json_page_last), $expected, 'The expected HAL output for last page was found.'); } /** @@ -233,6 +389,146 @@ public function testUIFieldAlias() { $this->assertIdentical($this->drupalGetJSON('test/serialize/field'), $expected); } + + /** + * Tests the Serializer paths and responses for field-based views. + */ + public function testSerializerFieldDisplayResponse() { + $view = Views::getView('test_serializer_display_field'); + $view->setDisplay('rest_export_1'); + // Mock the request content type by setting it on the display handler. + $view->display_handler->setContentType('hal_json'); + $this->executeView($view); + + $view_output = $view->preview(); + $view_result = array(); + foreach ($view->result as $row) { + $expected_row = array(); + foreach ($view->field as $id => $field) { + $expected_row[$id] = $field->render($row); + } + $view_result[] = $expected_row; + } + + $serializer = $this->container->get('serializer'); + $collection = $this->getCollectionFromView($view); + $expected = $serializer->serialize($collection, 'hal_json'); + + $actual_json = $this->drupalGetHalJson('test/serialize/field'); + + $this->assertIdentical(Json::encode($actual_json), drupal_render($view_output), 'Preview output matches the (reserialized) JSON returned from the view via HTTP GET.'); + $this->assertIdentical(Json::encode($actual_json), $expected, 'HAL serializer output matches the (reserialized) JSON returned from the view via HTTP GET.'); + $this->assertIdentical($actual_json['_embedded']['item'], $view_result, 'View result matches JSON returned from the view via HTTP GET'); + } + + /** + * Tests the Serializer paths and responses for field-based views with paging. + */ + public function testSerializerFieldDisplayPagingResponse() { + $view = Views::getView('test_serializer_display_field'); + $view->setDisplay('rest_export_paging'); + // Mock the request content type by setting it on the display handler. + $view->display_handler->setContentType('hal_json'); + $this->executeView($view); + + $view_output = $view->preview(); + $view_result = array(); + foreach ($view->result as $row) { + $expected_row = array(); + foreach ($view->field as $id => $field) { + $expected_row[$id] = $field->render($row); + } + $view_result[] = $expected_row; + } + + $serializer = $this->container->get('serializer'); + $collection = $this->getCollectionFromView($view); + $expected = $serializer->serialize($collection, 'hal_json'); + + $actual_json = $this->drupalGetHalJson('test/serialize/field-paging'); + + $this->assertIdentical(Json::encode($actual_json), drupal_render($view_output), 'Preview output matches the (reserialized) JSON returned from the view via HTTP GET.'); + $this->assertIdentical(Json::encode($actual_json), $expected, 'HAL serializer output matches the (reserialized) JSON returned from the view via HTTP GET.'); + $this->assertIdentical($actual_json['_embedded']['item'], $view_result, 'View result matches JSON returned from the view via HTTP GET'); + + // Make assertions on the structure of the response. + $this->assertTrue(isset($actual_json['_embedded']) && isset($actual_json['_links']), 'Has _links and _embedded keys'); + + $this->assertEqual(count($actual_json['_embedded']['item']), 1); + $this->assertEqual($actual_json['_links']['self']['href'], $this->viewUrl($view)); + $this->assertEqual($actual_json['_links']['first']['href'], $this->viewUrl($view, 0)); + $this->assertEqual($actual_json['_links']['next']['href'], $this->viewUrl($view, 1)); + $this->assertEqual($actual_json['_links']['last']['href'], $this->viewUrl($view, 4)); + $this->assertEqual(array_keys($actual_json['_links']), array( + 'self', + 'first', + 'next', + 'last', + )); + + // Load the second page. + $actual_json_page_1 = $this->drupalGetHalJson($actual_json['_links']['next']['href']); + + $this->assertTrue(isset($actual_json_page_1['_embedded']) && isset($actual_json_page_1['_links']), 'Has _links and _embedded keys'); + + $this->assertEqual(count($actual_json_page_1['_embedded']['item']), 1); + $this->assertEqual($actual_json_page_1['_links']['self']['href'], $this->viewUrl($view, 1)); + $this->assertEqual($actual_json_page_1['_links']['first']['href'], $this->viewUrl($view, 0)); + $this->assertEqual($actual_json_page_1['_links']['prev']['href'], $this->viewUrl($view, 0)); + $this->assertEqual($actual_json_page_1['_links']['next']['href'], $this->viewUrl($view, 2)); + $this->assertEqual($actual_json_page_1['_links']['last']['href'], $this->viewUrl($view, 4)); + $this->assertEqual(array_keys($actual_json_page_1['_links']), array( + 'self', + 'first', + 'prev', + 'next', + 'last', + )); + + // Test the entity rows - with paging. + $view = Views::getView('test_serializer_display_field'); + $view->setDisplay('rest_export_paging'); + $view->setCurrentPage(1); + $this->executeView($view); + + // Create the entity collection. + $collection = $this->getCollectionFromView($view); + $this->assertTrue($collection->hasLinks(), 'Collection created from a paging view has (hypermedia) link relations'); + $expected = $serializer->serialize($collection, 'hal_json'); + + $this->assertEqual(Json::encode($actual_json_page_1), $expected, 'The expected HAL output for page=1 was found.'); + + // Load the last page. + $actual_json_page_last = $this->drupalGetHalJson($actual_json['_links']['last']['href']); + + $this->assertTrue(isset($actual_json_page_last['_embedded']) && isset($actual_json_page_last['_links']), 'Has _links and _embedded keys'); + + $this->assertEqual(count($actual_json_page_last['_embedded']['item']), 1); + $this->assertEqual($actual_json_page_last['_links']['self']['href'], $this->viewUrl($view, 4)); + $this->assertEqual($actual_json_page_last['_links']['first']['href'], $this->viewUrl($view, 0)); + $this->assertEqual($actual_json_page_last['_links']['prev']['href'], $this->viewUrl($view, 3)); + $this->assertEqual($actual_json_page_last['_links']['last']['href'], $this->viewUrl($view, 4)); + $this->assertEqual(array_keys($actual_json_page_last['_links']), array( + 'self', + 'first', + 'prev', + 'last', + )); + + // Test the entity rows - with paging. + $view = Views::getView('test_serializer_display_field'); + $view->setDisplay('rest_export_paging'); + $view->setCurrentPage(4); + $this->executeView($view); + + // Create the entity collection. + $collection = $this->getCollectionFromView($view); + $this->assertTrue($collection->hasLinks(), 'Collection created from a paging view has (hypermedia) link relations'); + $expected = $serializer->serialize($collection, 'hal_json'); + + $this->assertEqual(Json::encode($actual_json_page_last), $expected, 'The expected HAL output for last page was found.'); + } + /** * Tests the raw output options for row field rendering. */ @@ -273,17 +569,15 @@ public function testLivePreview() { $view = Views::getView('test_serializer_display_entity'); $view->setDisplay('rest_export_1'); + $view->display_handler->setContentType('json'); $this->executeView($view); // Get the serializer service. $serializer = $this->container->get('serializer'); - $entities = array(); - foreach ($view->result as $row) { - $entities[] = $row->_entity; - } - - $expected = String::checkPlain($serializer->serialize($entities, 'json')); + // Create the collection. + $collection = $this->getCollectionFromView($view); + $expected = String::checkPlain($serializer->serialize($collection, 'json')); $view->live_preview = TRUE; @@ -302,6 +596,8 @@ public function testFieldapiField() { $result = $this->drupalGetJSON('test/serialize/node-field'); $this->assertEqual($result[0]['nid'], $node->id()); $this->assertEqual($result[0]['body'], $node->body->processed); + + // @todo: add HAL+JSON and paging. } } diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml index 687f3f2..8a8e3c0 100644 --- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml +++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml @@ -45,6 +45,21 @@ display: defaults: access: false path: test/serialize/entity + rest_export_paging: + display_plugin: rest_export + id: rest_export_paging + display_title: serializer + position: null + display_options: + defaults: + access: false + path: test/serialize/entity_paging + pager: + type: full + options: + items_per_page: 1 + offset: 0 + id: 0 base_field: id status: true module: rest diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml index 9a85fb8..d18aff3 100644 --- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml +++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml @@ -101,6 +101,29 @@ display: type: serializer row: type: data_field + rest_export_paging: + display_plugin: rest_export + id: rest_export_paging + display_title: 'serializer - paging' + position: null + display_options: + defaults: + access: false + style: false + row: false + path: test/serialize/field-paging + access: + type: none + style: + type: serializer + row: + type: data_field + pager: + type: full + options: + items_per_page: 1 + offset: 0 + id: 0 base_field: id status: true module: rest diff --git a/core/modules/serialization/src/Collection.php b/core/modules/serialization/src/Collection.php new file mode 100644 index 0000000..451af3d --- /dev/null +++ b/core/modules/serialization/src/Collection.php @@ -0,0 +1,215 @@ +id = $collection_id; + } + + /** + * Get the internal ID of the collection. + */ + public function getCollectionId() { + return $this->id; + } + + /** + * Get the items in the collection. + * + * @return array + * The items of the collection. + */ + public function getItems() { + return $this->items; + } + + /** + * Set the items list. + * + * @param array $items + * The items of the collection. + */ + public function setItems($items) { + $this->items = $items; + } + + /** + * Get the collection title. + * + * @return string + * The title of the collection. + */ + public function getTitle() { + return $this->title; + } + + /** + * Set the collection title. + * + * @param string $title + * The items of the collection. + */ + public function setTitle($title) { + $this->title = $title; + } + + /** + * Get the collection URI. + * + * @return string + * The URI ("self") of the collection. + */ + public function getUri() { + return $this->uri; + } + + /** + * Set the collection URI. + * + * @param string $uri + * The URI ("self") of the collection. + */ + public function setUri($uri) { + $this->uri = $uri; + } + + /** + * Get the collection description. + * + * @return string + * The description of the collection. + */ + public function getDescription() { + return $this->description; + } + + /** + * Set the collection URI. + * + * @param string $description + * The description of the collection. + */ + public function setDescription($description) { + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public function getIterator() { + return new \ArrayIterator($this->getItems()); + } + + /** + * Sets a link URI for a given type. + * + * @param string $type + * The link relation type. + * @param string $uri + * The link relation URI. + */ + public function setLink($type, $uri) { + $this->links[$type] = $uri; + } + + /** + * Gets a link URI for a given type. + * + * @param string $type + * The link relation type. + * + * @return NULL|String + * The URI of the link relation type or NULL. + */ + public function getLink($type) { + return isset($this->links[$type]) ? $this->links[$type] : NULL; + } + + /** + * Sets all link URIs. + * + * @param array $links + * Associative array of link relation types and URIs. + */ + public function setLinks(array $links) { + $this->links = $links; + } + + /** + * Gets all link URIs. + * + * @return array + * Associative array of link relation types and URIs. + */ + public function getLinks() { + return $this->links; + } + + /** + * Returns true if (hypermedia) link relations have been added. + * + * @return bool + * True if link relations have been added. + */ + public function hasLinks() { + // $this->links should be an array, so no type checking is needed. + return (bool) count($this->links); + } +} diff --git a/core/modules/serialization/tests/src/Unit/CollectionTest.php b/core/modules/serialization/tests/src/Unit/CollectionTest.php new file mode 100644 index 0000000..52ccd5b --- /dev/null +++ b/core/modules/serialization/tests/src/Unit/CollectionTest.php @@ -0,0 +1,110 @@ + 'CollectionTest', + 'description' => 'Tests the Collection class used for serializing collections.', + 'group' => 'Serialization', + ); + } + + /** + * Tests the constructor, as well as getters and setters. + * + * @covers ::__construct + * @covers ::getTitle + * @covers ::setTitle + * @covers ::getURI + * @covers ::setURI + * @covers ::getDescription + * @covers ::setDescription + */ + public function testConstructor() { + $collection_id = $this->randomMachineName(); + $collection = new Collection($collection_id); + $this->assertSame($collection_id, $collection->getCollectionId(), 'Id has been set accordingly'); + + $this->assertEquals($collection->getTitle(), NULL, 'Collection title is not set'); + $collection->setTitle($collection_id); + $this->assertEquals($collection->getTitle(), $collection_id, 'Collection title has been set'); + + $this->assertEquals($collection->getUri(), NULL, 'Collection URI is not set'); + $collection->setURI('http://example.com/' . $collection_id); + $this->assertEquals($collection->getUri(), 'http://example.com/' . $collection_id, 'Collection URI has been set'); + + $this->assertEquals($collection->getDescription(), NULL, 'Collection description is not set'); + $collection->setDescription($collection_id); + $this->assertEquals($collection->getDescription(), $collection_id, 'Collection description has been set'); + } + + /** + * Tests items setter and getter as well as iteration. + * + * @covers ::setItems + * @covers ::getItems + * @covers ::getIterator + */ + public function testSettingItemsAndIterating() { + $collection = new Collection('example'); + + $this->assertEquals($collection->getItems(), NULL, 'By default the items are NULL'); + + $example = array(1, 2, 3); + $collection->setItems($example); + $this->assertEquals($collection->getItems(), $example, 'Setters and getters work on the Collection'); + + // Iterating over collection returns the same array. + $array = array(); + foreach ($collection as $k => $v) { + $array[$k] = $v; + } + $this->assertEquals($array, $collection->getItems(), 'Array filled via iteration matches the array of the getter'); + } + + /** + * Tests setters and getters for link relations. + * + * @covers ::setLinks + * @covers ::getLinks + * @covers ::hasLinks + * @covers ::getLink + * @covers ::setLink + */ + public function testSetGetHasLinks() { + $collection = new Collection('example'); + $this->assertFalse($collection->hasLinks(), 'By default a Collection does not have any link relations'); + + $collection->setURI('http://example.com/collection'); + $this->assertFalse($collection->hasLinks(), 'Setting the main URI (self) of the collection does not count as a link relation'); + + $this->assertEquals($collection->getLink('next'), NULL, 'Before setting a link for a type the getter returns NULL'); + $collection->setLink('next', 'http://example.com/collection/?page=1'); + $this->assertEquals($collection->getLink('next'), 'http://example.com/collection/?page=1', 'After setting a link for a type the getter returns correctly'); + $this->assertTrue($collection->hasLinks(), 'Setting another URI (self) of the collection does not count as a link relation'); + $this->assertEquals($collection->getLinks(), array('next' => 'http://example.com/collection/?page=1')); + + $collection->setLinks(array()); + $this->assertFalse($collection->hasLinks(), 'After resetting links to an empty array, hasLinks should return false'); + } +} diff --git a/core/modules/simpletest/src/Tests/FolderTest.php b/core/modules/simpletest/src/Tests/FolderTest.php index 99e2ee7..9df2b33 100644 --- a/core/modules/simpletest/src/Tests/FolderTest.php +++ b/core/modules/simpletest/src/Tests/FolderTest.php @@ -10,7 +10,7 @@ use Drupal\simpletest\WebTestBase; /** - * This test will check SimpleTest's treatment of hook_install during setUp. + * This test will check SimpleTest's treatment of hook_install during setUp. * Image module is used for test. * * @group simpletest diff --git a/core/modules/system/src/Plugin/Derivative/SystemMenuBlock.php b/core/modules/system/src/Plugin/Derivative/SystemMenuBlock.php index 7936128..611ef2a 100644 --- a/core/modules/system/src/Plugin/Derivative/SystemMenuBlock.php +++ b/core/modules/system/src/Plugin/Derivative/SystemMenuBlock.php @@ -52,7 +52,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { foreach ($this->menuStorage->loadMultiple() as $menu => $entity) { $this->derivatives[$menu] = $base_plugin_definition; $this->derivatives[$menu]['admin_label'] = $entity->label(); - $this->derivatives[$menu]['config_dependencies']['config'] = array($entity->getConfigDependencyName()); + $this->derivatives[$menu]['config_dependencies']['entity'] = array($entity->getConfigDependencyName()); } return $this->derivatives; } diff --git a/core/modules/system/src/Tests/Action/ActionUnitTest.php b/core/modules/system/src/Tests/Action/ActionUnitTest.php index 3a0dce2..937c6e0 100644 --- a/core/modules/system/src/Tests/Action/ActionUnitTest.php +++ b/core/modules/system/src/Tests/Action/ActionUnitTest.php @@ -91,7 +91,7 @@ public function testDependencies() { $action->save(); $expected = array( - 'config' => array( + 'entity' => array( 'user.role.' . DRUPAL_ANONYMOUS_RID, ), 'module' => array( diff --git a/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php b/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php index ce5b81b..8695f0e 100644 --- a/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php +++ b/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php @@ -162,7 +162,7 @@ public function testSystemMenuBlockConfigDependencies() { $dependencies = $block->calculateDependencies(); $expected = array( - 'config' => array( + 'entity' => array( 'system.menu.' . $this->menu->id() ), 'module' => array( diff --git a/core/modules/system/src/Tests/System/HtaccessTest.php b/core/modules/system/src/Tests/System/HtaccessTest.php deleted file mode 100644 index 29f133d..0000000 --- a/core/modules/system/src/Tests/System/HtaccessTest.php +++ /dev/null @@ -1,41 +0,0 @@ -assertNoFileAccess('core/core.services.yml'); - // Try accessing a core module YAML file. - $this->assertNoFileAccess('core/modules/system/system.services.yml'); - } - - /** - * Asserts that a file exists but not accessible via HTTP. - * - * @param $path - * Path to file. Without leading slash. - */ - protected function assertNoFileAccess($path) { - $this->assertTrue(file_exists(DRUPAL_ROOT . '/' . $path)); - $this->drupalGet($path); - $this->assertResponse(403); - } - -} diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php index fba946f..7a2181d 100644 --- a/core/modules/system/theme.api.php +++ b/core/modules/system/theme.api.php @@ -158,7 +158,7 @@ * suggestions as input, and can change this array (adding suggestions and * removing them). * - * @section assets Assets + * @section Assets * * We can distinguish between three types of assets: * 1. unconditional page-level assets (loaded on all pages where the theme is in @@ -187,7 +187,7 @@ * @see callbacks * @see theme_render * - * @} + * @} End of "defgroup themeable". */ /** diff --git a/core/modules/user/src/Plugin/Action/ChangeUserRoleBase.php b/core/modules/user/src/Plugin/Action/ChangeUserRoleBase.php index 5e5c176..62c4214 100644 --- a/core/modules/user/src/Plugin/Action/ChangeUserRoleBase.php +++ b/core/modules/user/src/Plugin/Action/ChangeUserRoleBase.php @@ -86,7 +86,7 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s public function calculateDependencies() { if (!empty($this->configuration['rid'])) { $prefix = $this->entityType->getConfigPrefix() . '.'; - $this->addDependency('config', $prefix . $this->configuration['rid']); + $this->addDependency('entity', $prefix . $this->configuration['rid']); } return $this->dependencies; } diff --git a/core/modules/views/src/EventSubscriber/RouteSubscriber.php b/core/modules/views/src/EventSubscriber/RouteSubscriber.php index abc5bb6..f1f02b3 100644 --- a/core/modules/views/src/EventSubscriber/RouteSubscriber.php +++ b/core/modules/views/src/EventSubscriber/RouteSubscriber.php @@ -7,6 +7,7 @@ namespace Drupal\views\EventSubscriber; +use Drupal\Core\Page\HtmlPage; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\State\StateInterface; use Drupal\Core\Routing\RouteSubscriberBase; @@ -25,6 +26,7 @@ * routes are overridden by views. This information is used to determine which * views have to be added by views in the dynamic event. * + * Additional to adding routes it also changes the htmlpage response code. * * @see \Drupal\views\Plugin\views\display\PathPluginBase */ @@ -83,6 +85,7 @@ public function reset() { */ public static function getSubscribedEvents() { $events = parent::getSubscribedEvents(); + $events[KernelEvents::VIEW][] = array('onHtmlPage', 75); $events[RoutingEvents::FINISHED] = array('routeRebuildFinished'); // Ensure to run after the entity resolver subscriber // @see \Drupal\Core\EventSubscriber\EntityRouteAlterSubscriber @@ -111,6 +114,23 @@ protected function getViewsDisplayIDsWithRoute() { } /** + * Sets the proper response code coming from the http status area handler. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event + * The Event to process. + * + * @see \Drupal\views\Plugin\views\area\HTTPStatusCode + */ + public function onHtmlPage(GetResponseForControllerResultEvent $event) { + $page = $event->getControllerResult(); + if ($page instanceof HtmlPage) { + if (($request = $event->getRequest()) && $request->attributes->has('view_id')) { + $page->setStatusCode($request->attributes->get('_http_statuscode', 200)); + }; + } + } + + /** * Returns a set of route objects. * * @return \Symfony\Component\Routing\RouteCollection diff --git a/core/modules/views/src/Plugin/Derivative/ViewsBlock.php b/core/modules/views/src/Plugin/Derivative/ViewsBlock.php index 3ebfc5f..cec9895 100644 --- a/core/modules/views/src/Plugin/Derivative/ViewsBlock.php +++ b/core/modules/views/src/Plugin/Derivative/ViewsBlock.php @@ -103,7 +103,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { 'category' => $display->getOption('block_category'), 'admin_label' => $desc, 'config_dependencies' => array( - 'config' => array( + 'entity' => array( $view->getConfigDependencyName(), ) ) diff --git a/core/modules/views/src/Plugin/Derivative/ViewsExposedFilterBlock.php b/core/modules/views/src/Plugin/Derivative/ViewsExposedFilterBlock.php index f405aed..0ef5fcd 100644 --- a/core/modules/views/src/Plugin/Derivative/ViewsExposedFilterBlock.php +++ b/core/modules/views/src/Plugin/Derivative/ViewsExposedFilterBlock.php @@ -94,7 +94,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { $this->derivatives[$delta] = array( 'admin_label' => $desc, 'config_dependencies' => array( - 'config' => array( + 'entity' => array( $view->getConfigDependencyName(), ) ) diff --git a/core/modules/views/src/Plugin/views/area/HTTPStatusCode.php b/core/modules/views/src/Plugin/views/area/HTTPStatusCode.php index 036e369..0f7756d 100644 --- a/core/modules/views/src/Plugin/views/area/HTTPStatusCode.php +++ b/core/modules/views/src/Plugin/views/area/HTTPStatusCode.php @@ -64,8 +64,8 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { */ function render($empty = FALSE) { if (!$empty || !empty($this->options['empty'])) { - $build['#attached']['http_header'][] = ['Status', $this->options['status_code']]; - return $build; + $this->view->getResponse()->setStatusCode($this->options['status_code']); + $this->view->getRequest()->attributes->set('_http_statuscode', $this->options['status_code']); } } diff --git a/core/modules/views/src/Tests/Handler/AreaTitleTest.php b/core/modules/views/src/Tests/Handler/AreaTitleTest.php index 8df15ef..86d9e83 100644 --- a/core/modules/views/src/Tests/Handler/AreaTitleTest.php +++ b/core/modules/views/src/Tests/Handler/AreaTitleTest.php @@ -54,7 +54,7 @@ public function testTitleText() { $this->executeView($view); $view->result = array(); $view->render(); - $this->assertEqual($view->getTitle(), 'test_title_empty', 'The title area should override the title if the result is empty.'); + $this->assertEqual($view->getTitle(), 'test_title_header', 'The title area on the header should override the title if the result is empty.'); $view->destroy(); } diff --git a/core/modules/views/src/Tests/Handler/AreaTitleWebTest.php b/core/modules/views/src/Tests/Handler/AreaTitleWebTest.php deleted file mode 100644 index 7d0fde5..0000000 --- a/core/modules/views/src/Tests/Handler/AreaTitleWebTest.php +++ /dev/null @@ -1,64 +0,0 @@ -enableViewsTestModule(); - } - - /** - * Tests the title area handler. - */ - public function testTitleText() { - $this->drupalGet('test-area-title'); - $this->assertTitle('test_title_header | Drupal'); - - // Check the view to return no result. - /** @var \Drupal\views\Entity\View $view */ - $view = View::load('test_area_title'); - $display =& $view->getDisplay('default'); - $display['display_options']['filters']['id'] = [ - 'field' => 'id', - 'id' => 'id', - 'table' => 'views_test_data', - 'relationship' => 'none', - 'plugin_id' => 'numeric', - 'provider' => 'views_test_data', - // Add a value which does not exist. - 'value' => ['value' => '042118160112'], - ]; - $view->save(); - - $this->drupalGet('test-area-title'); - $this->assertTitle('test_title_empty | Drupal'); - } - -} diff --git a/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php b/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php index d8a0b56..d7d25c3 100644 --- a/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php +++ b/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php @@ -39,7 +39,7 @@ public function testExposedBlock() { $block = $this->createBlock('views_exposed_filter_block:test_exposed_block-page_1'); $dependencies = $block->calculateDependencies(); $expected = array( - 'config' => array('views.view.test_exposed_block'), + 'entity' => array('views.view.test_exposed_block'), 'module' => array('views'), 'theme' => array('stark') ); @@ -55,7 +55,7 @@ public function testViewsBlock() { $block = $this->createBlock('views_block:content_recent-block_1'); $dependencies = $block->calculateDependencies(); $expected = array( - 'config' => array('views.view.content_recent'), + 'entity' => array('views.view.content_recent'), 'module' => array('views'), 'theme' => array('stark') ); diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_area_title.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_area_title.yml index d5eb231..219bc95 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_area_title.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_area_title.yml @@ -46,8 +46,8 @@ display: position: 0 page_1: display_options: - path: test-area-title defaults: + empty: '0' header: '0' header: title: diff --git a/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php b/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php index e125d3b..c31306a 100644 --- a/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php +++ b/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php @@ -39,7 +39,7 @@ public function testEntityDecoration() { // calls id(), which breaks the ->expect($this->once()) call. Call it later. // EntityInterface::isSyncing() is only called during syncing process. // EntityInterface::isUninstalling() is only called during uninstallation - // process. EntityInterface::getConfigDependencyName() and + // process. ConfigEntityInterface::getConfigDependencyName() and // ConfigEntityInterface::calculateDependencies() are only used for // dependency management. if (!in_array($reflection_method->getName(), ['isNew', 'isSyncing', 'isUninstalling', 'getConfigDependencyName', 'calculateDependencies'])) { diff --git a/core/profiles/minimal/config/install/block.block.stark_admin.yml b/core/profiles/minimal/config/install/block.block.stark_admin.yml index 0f3fdd5..0934049 100644 --- a/core/profiles/minimal/config/install/block.block.stark_admin.yml +++ b/core/profiles/minimal/config/install/block.block.stark_admin.yml @@ -16,7 +16,7 @@ settings: level: 1 depth: 0 dependencies: - config: + entity: - system.menu.admin module: - system diff --git a/core/profiles/minimal/config/install/block.block.stark_tools.yml b/core/profiles/minimal/config/install/block.block.stark_tools.yml index ef8442b..c8268bb 100644 --- a/core/profiles/minimal/config/install/block.block.stark_tools.yml +++ b/core/profiles/minimal/config/install/block.block.stark_tools.yml @@ -16,7 +16,7 @@ settings: level: 1 depth: 0 dependencies: - config: + entity: - system.menu.tools module: - system diff --git a/core/profiles/standard/config/install/block.block.bartik_account_menu.yml b/core/profiles/standard/config/install/block.block.bartik_account_menu.yml index 1463759..37ef707 100644 --- a/core/profiles/standard/config/install/block.block.bartik_account_menu.yml +++ b/core/profiles/standard/config/install/block.block.bartik_account_menu.yml @@ -17,7 +17,7 @@ settings: level: 1 depth: 1 dependencies: - config: + entity: - system.menu.account module: - system diff --git a/core/profiles/standard/config/install/block.block.bartik_footer.yml b/core/profiles/standard/config/install/block.block.bartik_footer.yml index 4132736..3074b3a 100644 --- a/core/profiles/standard/config/install/block.block.bartik_footer.yml +++ b/core/profiles/standard/config/install/block.block.bartik_footer.yml @@ -17,7 +17,7 @@ settings: level: 1 depth: 0 dependencies: - config: + entity: - system.menu.footer module: - system diff --git a/core/profiles/standard/config/install/block.block.bartik_main_menu.yml b/core/profiles/standard/config/install/block.block.bartik_main_menu.yml index 7f847c2..90a596f 100644 --- a/core/profiles/standard/config/install/block.block.bartik_main_menu.yml +++ b/core/profiles/standard/config/install/block.block.bartik_main_menu.yml @@ -17,7 +17,7 @@ settings: level: 1 depth: 1 dependencies: - config: + entity: - system.menu.main module: - system diff --git a/core/profiles/standard/config/install/block.block.bartik_tools.yml b/core/profiles/standard/config/install/block.block.bartik_tools.yml index 4b102eb..9a4b8b3 100644 --- a/core/profiles/standard/config/install/block.block.bartik_tools.yml +++ b/core/profiles/standard/config/install/block.block.bartik_tools.yml @@ -17,7 +17,7 @@ settings: level: 1 depth: 0 dependencies: - config: + entity: - system.menu.tools module: - system diff --git a/core/profiles/standard/config/install/contact.form.feedback.yml b/core/profiles/standard/config/install/contact.form.feedback.yml deleted file mode 100644 index 8fb7765..0000000 --- a/core/profiles/standard/config/install/contact.form.feedback.yml +++ /dev/null @@ -1,7 +0,0 @@ -id: feedback -label: 'Website feedback' -recipients: { } -reply: '' -weight: 0 -status: true -langcode: en diff --git a/core/profiles/standard/config/install/core.base_field_override.node.page.promote.yml b/core/profiles/standard/config/install/core.base_field_override.node.page.promote.yml index d3a0923..1555eed 100644 --- a/core/profiles/standard/config/install/core.base_field_override.node.page.promote.yml +++ b/core/profiles/standard/config/install/core.base_field_override.node.page.promote.yml @@ -2,7 +2,7 @@ langcode: en status: true dependencies: - config: + entity: - node.type.page id: node.page.promote field_name: promote diff --git a/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml b/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml index 4a74b69..e8d8733 100644 --- a/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml +++ b/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml @@ -38,7 +38,7 @@ content: hidden: { } status: true dependencies: - config: + entity: - field.field.node.article.body - field.field.node.article.comment - field.field.node.article.field_image diff --git a/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml b/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml index fb6f75d..a0da43b 100644 --- a/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml +++ b/core/profiles/standard/config/install/core.entity_view_display.node.article.default.yml @@ -25,7 +25,7 @@ content: settings: { } third_party_settings: { } dependencies: - config: + entity: - field.field.node.article.body - field.field.node.article.field_image - field.field.node.article.field_tags diff --git a/core/profiles/standard/config/install/core.entity_view_display.node.article.teaser.yml b/core/profiles/standard/config/install/core.entity_view_display.node.article.teaser.yml index 7f8ed57..5caa85c 100644 --- a/core/profiles/standard/config/install/core.entity_view_display.node.article.teaser.yml +++ b/core/profiles/standard/config/install/core.entity_view_display.node.article.teaser.yml @@ -26,7 +26,7 @@ content: third_party_settings: { } label: above dependencies: - config: + entity: - core.entity_view_mode.node.teaser - field.field.node.article.body - field.field.node.article.field_image diff --git a/core/profiles/standard/config/install/core.entity_view_display.user.user.compact.yml b/core/profiles/standard/config/install/core.entity_view_display.user.user.compact.yml index a46bd1b..410f3f3 100644 --- a/core/profiles/standard/config/install/core.entity_view_display.user.user.compact.yml +++ b/core/profiles/standard/config/install/core.entity_view_display.user.user.compact.yml @@ -15,7 +15,7 @@ hidden: member_for: true status: true dependencies: - config: + entity: - core.entity_view_mode.user.compact module: - image diff --git a/core/profiles/standard/config/install/editor.editor.basic_html.yml b/core/profiles/standard/config/install/editor.editor.basic_html.yml index 54ad5b1..fdf6e96 100644 --- a/core/profiles/standard/config/install/editor.editor.basic_html.yml +++ b/core/profiles/standard/config/install/editor.editor.basic_html.yml @@ -42,7 +42,7 @@ image_upload: status: true langcode: en dependencies: - config: + entity: - filter.format.basic_html module: - ckeditor diff --git a/core/profiles/standard/config/install/editor.editor.full_html.yml b/core/profiles/standard/config/install/editor.editor.full_html.yml index 80da28c..66df850 100644 --- a/core/profiles/standard/config/install/editor.editor.full_html.yml +++ b/core/profiles/standard/config/install/editor.editor.full_html.yml @@ -54,7 +54,7 @@ image_upload: status: true langcode: en dependencies: - config: + entity: - filter.format.full_html module: - ckeditor diff --git a/core/profiles/standard/config/install/field.field.node.article.field_image.yml b/core/profiles/standard/config/install/field.field.node.article.field_image.yml index fc6a482..efc110c 100644 --- a/core/profiles/standard/config/install/field.field.node.article.field_image.yml +++ b/core/profiles/standard/config/install/field.field.node.article.field_image.yml @@ -27,6 +27,6 @@ status: true langcode: en field_type: image dependencies: - config: + entity: - field.storage.node.field_image - node.type.article diff --git a/core/profiles/standard/config/install/field.field.node.article.field_tags.yml b/core/profiles/standard/config/install/field.field.node.article.field_tags.yml index cfce273..001f510 100644 --- a/core/profiles/standard/config/install/field.field.node.article.field_tags.yml +++ b/core/profiles/standard/config/install/field.field.node.article.field_tags.yml @@ -12,6 +12,6 @@ settings: { } status: true langcode: en dependencies: - config: + entity: - field.storage.node.field_tags - node.type.article diff --git a/core/profiles/standard/config/install/field.field.user.user.user_picture.yml b/core/profiles/standard/config/install/field.field.user.user.user_picture.yml index a2c4faf..d6b31c2 100644 --- a/core/profiles/standard/config/install/field.field.user.user.user_picture.yml +++ b/core/profiles/standard/config/install/field.field.user.user.user_picture.yml @@ -27,5 +27,5 @@ settings: title_field_required: false field_type: image dependencies: - config: + entity: - field.storage.user.user_picture diff --git a/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml b/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml index 268eb80..d8aa944 100644 --- a/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml +++ b/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml @@ -27,5 +27,5 @@ fieldMappings: dependencies: module: - comment - config: + entity: - comment.type.comment diff --git a/core/profiles/standard/config/install/rdf.mapping.node.article.yml b/core/profiles/standard/config/install/rdf.mapping.node.article.yml index f1b167e..d1b7f80 100644 --- a/core/profiles/standard/config/install/rdf.mapping.node.article.yml +++ b/core/profiles/standard/config/install/rdf.mapping.node.article.yml @@ -41,7 +41,7 @@ fieldMappings: properties: - 'schema:about' dependencies: - config: + entity: - node.type.article module: - node diff --git a/core/profiles/standard/config/install/rdf.mapping.node.page.yml b/core/profiles/standard/config/install/rdf.mapping.node.page.yml index 166bd2a..38120ff 100644 --- a/core/profiles/standard/config/install/rdf.mapping.node.page.yml +++ b/core/profiles/standard/config/install/rdf.mapping.node.page.yml @@ -32,7 +32,7 @@ fieldMappings: arguments: interaction_type: 'UserComments' dependencies: - config: + entity: - node.type.page module: - node diff --git a/core/profiles/standard/config/install/rdf.mapping.taxonomy_term.tags.yml b/core/profiles/standard/config/install/rdf.mapping.taxonomy_term.tags.yml index 9c7b4dc..60bf174 100644 --- a/core/profiles/standard/config/install/rdf.mapping.taxonomy_term.tags.yml +++ b/core/profiles/standard/config/install/rdf.mapping.taxonomy_term.tags.yml @@ -11,7 +11,7 @@ fieldMappings: properties: - 'schema:description' dependencies: - config: + entity: - taxonomy.vocabulary.tags module: - taxonomy diff --git a/core/profiles/standard/src/Tests/StandardTest.php b/core/profiles/standard/src/Tests/StandardTest.php index 3ba2347..b05285e 100644 --- a/core/profiles/standard/src/Tests/StandardTest.php +++ b/core/profiles/standard/src/Tests/StandardTest.php @@ -8,7 +8,6 @@ namespace Drupal\standard\Tests; use Drupal\config\Tests\SchemaCheckTestTrait; -use Drupal\contact\Entity\ContactForm; use Drupal\simpletest\WebTestBase; /** @@ -113,10 +112,6 @@ function testStandard() { \Drupal::moduleHandler()->uninstall(array('editor', 'ckeditor')); $this->rebuildContainer(); \Drupal::moduleHandler()->install(array('editor')); - /** @var \Drupal\contact\ContactFormInterface $contact_form */ - $contact_form = ContactForm::load('feedback'); - $recipients = $contact_form->getRecipients(); - $this->assertEqual(['simpletest@example.com'], $recipients); } } diff --git a/core/profiles/standard/standard.profile b/core/profiles/standard/standard.profile index ad69906..4af6456 100644 --- a/core/profiles/standard/standard.profile +++ b/core/profiles/standard/standard.profile @@ -4,7 +4,6 @@ * Enables modules and site configuration for a standard site installation. */ -use Drupal\contact\Entity\ContactForm; use Drupal\Core\Form\FormStateInterface; /** @@ -15,13 +14,4 @@ use Drupal\Core\Form\FormStateInterface; function standard_form_install_configure_form_alter(&$form, FormStateInterface $form_state) { // Pre-populate the site name with the server name. $form['site_information']['site_name']['#default_value'] = \Drupal::request()->server->get('SERVER_NAME'); - $form['#submit'][] = 'standard_form_install_configure_submit'; -} - -/** - * Submission handler to sync the contact.form.feedback recipient. - */ -function standard_form_install_configure_submit($form, FormStateInterface $form_state) { - $site_mail = $form_state->getValue('site_mail'); - ContactForm::load('feedback')->setRecipients([$site_mail])->save(); } diff --git a/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php b/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php index df90beb..e08f1b3 100644 --- a/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php @@ -200,7 +200,7 @@ function testOptimizeRemoveCharset() { $cases = array( array( 'asset' => array( - 'type' => 'inline', + 'type' => 'inline', 'data' => '@charset "UTF-8";html{font-family:"sans-serif";}', 'preprocess' => FALSE, ), diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php index eeb7538..ff50e9c 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigDependencyManagerTest.php @@ -19,7 +19,7 @@ class ConfigDependencyManagerTest extends UnitTestCase { public function testNoConfiguration() { $dep_manger = new ConfigDependencyManager(); - $this->assertEmpty($dep_manger->getDependentEntities('config', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84')); + $this->assertEmpty($dep_manger->getDependentEntities('entity', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84')); } public function testNoConfigEntities() { @@ -29,7 +29,7 @@ public function testNoConfigEntities() { 'key' => 'value', ), )); - $this->assertEmpty($dep_manger->getDependentEntities('config', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84')); + $this->assertEmpty($dep_manger->getDependentEntities('entity', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84')); // Configuration is always dependent on its provider. $dependencies = $dep_manger->getDependentEntities('module', 'simple'); diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php index 2da84fe..6676d5a 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php @@ -275,12 +275,12 @@ public function providerCalculateDependenciesWithPluginCollections() { array( 'provider' => 'test', 'config_dependencies' => array( - 'config' => array($instance_dependency_1), + 'entity' => array($instance_dependency_1), 'module' => array($instance_dependency_2), ) ), array( - 'config' => array($instance_dependency_1), + 'entity' => array($instance_dependency_1), 'module' => array($instance_dependency_2, 'test') ) ) diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php index 4b2870f..98a9d31 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityDependencyTest.php @@ -22,7 +22,7 @@ public function testEmptyDependencies() { $this->assertEquals('config_test.dynamic.entity_id', $dep->getConfigDependencyName()); $this->assertEquals(array(), $dep->getDependencies('theme')); - $this->assertEquals(array(), $dep->getDependencies('config')); + $this->assertEquals(array(), $dep->getDependencies('entity')); $this->assertEquals(array('config_test'), $dep->getDependencies('module')); $this->assertTrue($dep->hasDependency('module', 'config_test')); $this->assertFalse($dep->hasDependency('module', 'views')); @@ -36,7 +36,7 @@ public function testWithDependencies() { 'node', 'views' ), - 'config' => array( + 'entity' => array( 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84', ), ), @@ -44,14 +44,14 @@ public function testWithDependencies() { $dep = new ConfigEntityDependency('config_test.dynamic.entity_id', $values); $this->assertEquals(array(), $dep->getDependencies('theme')); - $this->assertEquals(array('config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'), $dep->getDependencies('config')); + $this->assertEquals(array('config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84'), $dep->getDependencies('entity')); $this->assertEquals(array('node', 'views', 'config_test'), $dep->getDependencies('module')); $this->assertTrue($dep->hasDependency('module', 'config_test')); $this->assertTrue($dep->hasDependency('module', 'views')); $this->assertTrue($dep->hasDependency('module', 'node')); $this->assertFalse($dep->hasDependency('module', 'block')); - $this->assertTrue($dep->hasDependency('config', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84')); - $this->assertFalse($dep->hasDependency('config', 'config_test.dynamic.another_id:7dfa5cb7-2248-4d52-8c00-cd8e02d1e78e')); + $this->assertTrue($dep->hasDependency('entity', 'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84')); + $this->assertFalse($dep->hasDependency('entity', 'config_test.dynamic.another_id:7dfa5cb7-2248-4d52-8c00-cd8e02d1e78e')); } } diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php index c0cd87b..eeecf30 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php @@ -235,8 +235,8 @@ public function testSaveInsert(EntityInterface $entity) { $config_object->expects($this->atLeastOnce()) ->method('isNew') ->will($this->returnValue(TRUE)); - $config_object->expects($this->exactly(1)) - ->method('setData'); + $config_object->expects($this->exactly(3)) + ->method('set'); $config_object->expects($this->once()) ->method('save'); @@ -294,8 +294,8 @@ public function testSaveUpdate(EntityInterface $entity) { $config_object->expects($this->atLeastOnce()) ->method('isNew') ->will($this->returnValue(FALSE)); - $config_object->expects($this->exactly(1)) - ->method('setData'); + $config_object->expects($this->exactly(3)) + ->method('set'); $config_object->expects($this->once()) ->method('save'); @@ -354,8 +354,8 @@ public function testSaveRename(ConfigEntityInterface $entity) { $config_object->expects($this->atLeastOnce()) ->method('isNew') ->will($this->returnValue(FALSE)); - $config_object->expects($this->exactly(1)) - ->method('setData'); + $config_object->expects($this->exactly(3)) + ->method('set'); $config_object->expects($this->once()) ->method('save'); diff --git a/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php b/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php index 34a2016..2263126 100644 --- a/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php +++ b/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php @@ -67,7 +67,7 @@ protected function getConfigData() { 'id' => 'node.article.body', 'uuid' => $uuid->generate(), 'dependencies' => array( - 'config' => array( + 'entity' => array( 'field.storage.node.body' ), ), diff --git a/core/themes/bartik/css/style.css b/core/themes/bartik/css/style.css index fcdebc1..c55134d 100644 --- a/core/themes/bartik/css/style.css +++ b/core/themes/bartik/css/style.css @@ -1371,12 +1371,9 @@ div.tabs { background: #f0f0f0; background: rgba(30, 50, 10, 0.08); } -div.messages { - margin: 8px 15px 8px 23px; /* LTR */ -} +div.messages, [dir="rtl"] div.messages { - margin-right: 23px; - margin-left: 15px; + margin: 8px 15px; } /* -------------- Breadcrumbs -------------- */ diff --git a/web.config b/web.config index b072d9b..b71c37c 100644 --- a/web.config +++ b/web.config @@ -22,7 +22,7 @@ - +