diff --git a/core/core.services.yml b/core/core.services.yml index 12f3a3c..bd0464c 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -218,7 +218,7 @@ services: arguments: ['@event_dispatcher', '@service_container', '@controller_resolver'] language_manager: class: Drupal\Core\Language\LanguageManager - arguments: ['@state'] + arguments: ['@state', '@module_handler'] string_translator.custom_strings: class: Drupal\Core\StringTranslation\Translator\CustomStrings arguments: ['@settings'] diff --git a/core/includes/config.inc b/core/includes/config.inc index 6f55e61..8e9ce5e 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -192,26 +192,6 @@ function config_context_leave() { } /** - * Return a list of all config entity types provided by a module. - * - * @param string $module - * The name of the module possibly providing config entities. - * - * @return array - * An associative array containing the entity info for any config entities - * provided by the requested module, keyed by the entity type. - */ -function config_get_module_config_entities($module) { - // While this is a lot of work to generate, it's not worth static caching - // since this function is only called at install/uninstall, and only - // once per module. - $info = entity_get_info(); - return array_filter($info, function($entity_info) use ($module) { - return ($entity_info['module'] == $module) && is_subclass_of($entity_info['class'], 'Drupal\Core\Config\Entity\ConfigEntityInterface'); - }); -} - -/** * Returns the entity type of a configuration object. * * @param string $name diff --git a/core/includes/language.inc b/core/includes/language.inc index e057616..07cc383 100644 --- a/core/includes/language.inc +++ b/core/includes/language.inc @@ -546,29 +546,5 @@ function language_url_split_prefix($path, $languages) { } /** - * Returns the possible fallback languages ordered by language weight. - * - * @param - * (optional) The language type. Defaults to Language::TYPE_CONTENT. - * - * @return - * An array of language codes. - */ -function language_fallback_get_candidates($type = Language::TYPE_CONTENT) { - $fallback_candidates = &drupal_static(__FUNCTION__); - - if (!isset($fallback_candidates)) { - // Get languages ordered by weight, add Language::LANGCODE_NOT_SPECIFIED at the end. - $fallback_candidates = array_keys(language_list()); - $fallback_candidates[] = Language::LANGCODE_NOT_SPECIFIED; - - // Let other modules hook in and add/change candidates. - drupal_alter('language_fallback_candidates', $fallback_candidates); - } - - return $fallback_candidates; -} - -/** * @} End of "language_negotiation" */ diff --git a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php index 40c1447..b46d9f7 100644 --- a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php +++ b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php @@ -17,13 +17,6 @@ class EntityType extends Plugin { /** - * The name of the module providing the type. - * - * @var string - */ - public $module; - - /** * The name of the entity type class. * * This is not provided manually, it will be added by the discovery mechanism. diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php index 177a495..5447e90 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -423,6 +423,12 @@ protected function getTranslatedField($property_name, $langcode) { */ public function set($property_name, $value, $notify = TRUE) { $this->get($property_name)->setValue($value, FALSE); + + if ($property_name == 'langcode') { + // Avoid using unset as this unnecessarily triggers magic methods later + // on. + $this->language = NULL; + } } /** @@ -658,6 +664,7 @@ protected function initializeTranslation($langcode) { $translation->values = &$this->values; $translation->fields = &$this->fields; $translation->translations = &$this->translations; + $translation->enforceIsNew = &$this->enforceIsNew; $translation->translationInitialize = FALSE; return $translation; diff --git a/core/lib/Drupal/Core/Entity/ContentEntityFormController.php b/core/lib/Drupal/Core/Entity/ContentEntityFormController.php index 2103fc2..7f613bc 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityFormController.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityFormController.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Entity; use Drupal\Core\Language\Language; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Entity form controller variant for content entity types. @@ -17,6 +18,32 @@ class ContentEntityFormController extends EntityFormController { /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManagerInterface + */ + protected $entityManager; + + /** + * Constructs a ContentEntityFormController object. + * + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. + */ + public function __construct(EntityManagerInterface $entity_manager) { + $this->entityManager = $entity_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager') + ); + } + + /** * {@inheritdoc} */ public function form(array $form, array &$form_state) { @@ -38,6 +65,7 @@ public function form(array $form, array &$form_state) { * {@inheritdoc} */ public function validate(array $form, array &$form_state) { + $this->updateFormLangcode($form_state); $entity = $this->buildEntity($form, $form_state); $entity_type = $entity->entityType(); $entity_langcode = $entity->language()->id; @@ -73,53 +101,22 @@ public function validate(array $form, array &$form_state) { protected function init(array &$form_state) { // Ensure we act on the translation object corresponding to the current form // language. - $this->entity = $this->getTranslatedEntity($form_state); - parent::init($form_state); - } - - /** - * Returns the translation object corresponding to the form language. - * - * @param array $form_state - * A keyed array containing the current state of the form. - */ - protected function getTranslatedEntity(array $form_state) { $langcode = $this->getFormLangcode($form_state); - $translation = $this->entity->getTranslation($langcode); - // Ensure that the entity object is a BC entity if the original one is. - return $this->entity instanceof EntityBCDecorator ? $translation->getBCEntity() : $translation; + $this->entity = $this->entity->getTranslation($langcode); + parent::init($form_state); } /** * {@inheritdoc} */ - public function getFormLangcode(array $form_state) { - $entity = $this->entity; - if (!empty($form_state['langcode'])) { - $langcode = $form_state['langcode']; - } - else { - // If no form langcode was provided we default to the current content - // language and inspect existing translations to find a valid fallback, - // if any. - $translations = $entity->getTranslationLanguages(); - $languageManager = \Drupal::languageManager(); - $langcode = $languageManager->getLanguage(Language::TYPE_CONTENT)->id; - $fallback = $languageManager->isMultilingual() ? language_fallback_get_candidates() : array(); - while (!empty($langcode) && !isset($translations[$langcode])) { - $langcode = array_shift($fallback); - } - } - - // If the site is not multilingual or no translation for the given form - // language is available, fall back to the entity language. - if (!empty($langcode)) { - return $langcode; - } - else { - // If the entity is translatable, return the original language. - return $entity->getUntranslated()->language()->id; + public function getFormLangcode(array &$form_state) { + if (empty($form_state['langcode'])) { + // Imply a 'view' operation to ensure users edit entities in the same + // language they are displayed. This allows to keep contextual editing + // working also for multilingual entities. + $form_state['langcode'] = $this->entityManager->getTranslationFromContext($this->entity)->language()->id; } + return $form_state['langcode']; } /** @@ -136,8 +133,8 @@ public function buildEntity(array $form, array &$form_state) { $entity = clone $this->entity; $entity_type = $entity->entityType(); $info = entity_get_info($entity_type); - // @todo Exploit the Field API to process the submitted entity fields. + // @todo Exploit the Entity Field API to process the submitted field values. // Copy top-level form values that are entity fields but not handled by // field API without changing existing entity fields that are not being // edited by this form. Values of fields handled by field API are copied @@ -163,4 +160,5 @@ public function buildEntity(array $form, array &$form_state) { } return $entity; } + } diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php index 52ac7d5..54ee489 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormController.php +++ b/core/lib/Drupal/Core/Entity/EntityFormController.php @@ -269,6 +269,7 @@ protected function actions(array $form, array &$form_state) { * {@inheritdoc} */ public function validate(array $form, array &$form_state) { + $this->updateFormLangcode($form_state); // @todo Remove this. // Execute legacy global validation handlers. unset($form_state['validate_handlers']); @@ -292,8 +293,6 @@ public function validate(array $form, array &$form_state) { public function submit(array $form, array &$form_state) { // Remove button and internal Form API values from submitted values. form_state_values_clean($form_state); - - $this->updateFormLangcode($form_state); $this->entity = $this->buildEntity($form, $form_state); return $this->entity; } @@ -325,7 +324,7 @@ public function delete(array $form, array &$form_state) { /** * {@inheritdoc} */ - public function getFormLangcode(array $form_state) { + public function getFormLangcode(array &$form_state) { return $this->entity->language()->id; } diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php index 07d8af1..6ad106b 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php @@ -26,7 +26,7 @@ * @return string * The form language code. */ - public function getFormLangcode(array $form_state); + public function getFormLangcode(array &$form_state); /** * Checks whether the current form language matches the entity one. diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index 101c8b7..46a1ae0 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -456,4 +456,35 @@ public function getEntityTypeLabels() { return $options; } + /** + * {@inheritdoc} + */ + function getTranslationFromContext(ContentEntityInterface $entity, $langcode = NULL, $context = array()) { + $translation = $entity; + + if (empty($langcode)) { + $langcode = $this->languageManager->getLanguage(Language::TYPE_CONTENT)->id; + } + + // Retrieve language fallback candidates to perform the entity language + // negotiation. + $context['data'] = $entity; + $context += array('operation' => 'entity_view'); + $candidates = $this->languageManager->getFallbackCandidates($langcode, $context); + + // Ensure the default language has the proper language code. + $default_language = $entity->getUntranslated()->language(); + $candidates[$default_language->id] = Language::LANGCODE_DEFAULT; + + // Return the most fitting entity translation. + foreach ($candidates as $candidate) { + if ($entity->hasTranslation($candidate)) { + $translation = $entity->getTranslation($candidate); + break; + } + } + + return $translation; + } + } diff --git a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php index 0e898cb..0cfa9be 100644 --- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php @@ -244,4 +244,27 @@ public function getForm(EntityInterface $entity, $operation = 'default', array $ */ public function getBundleInfo($entity_type); + /** + * Returns the entity translation to be used in the given context. + * + * This will check whether a translation for the desired language is available + * and if not, it will fall back to the most appropriate translation based on + * the provided context. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The entity whose translation will be returned. + * @param string $langcode + * (optional) The language of the current context. Defaults to the current + * content language. + * @param array $context + * (optional) An associative array of arbitrary data that can be useful to + * determine the proper fallback sequence. + * + * @return \Drupal\Core\Entity\ContentEntityInterface + * A content entity object for the translated data. + * + * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates() + */ + function getTranslationFromContext(ContentEntityInterface $entity, $langcode = NULL, $context = array()); + } diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php index b79ca59..2680e6f 100644 --- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php +++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php @@ -7,13 +7,15 @@ namespace Drupal\Core\Entity; -use Drupal\entity\Entity\EntityDisplay; +use Drupal\Core\Entity\EntityManager; use Drupal\Core\Language\Language; +use Drupal\entity\Entity\EntityDisplay; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Base class for entity view controllers. */ -class EntityViewBuilder implements EntityViewBuilderInterface { +class EntityViewBuilder implements EntityControllerInterface, EntityViewBuilderInterface { /** * The type of entities for which this controller is instantiated. @@ -32,6 +34,13 @@ class EntityViewBuilder implements EntityViewBuilderInterface { protected $entityInfo; /** + * The entity manager service. + * + * @var \Drupal\Core\Entity\EntityManagerInterface + */ + protected $entityManager; + + /** * An array of view mode info for the type of entities for which this * controller is instantiated. * @@ -49,15 +58,33 @@ class EntityViewBuilder implements EntityViewBuilderInterface { */ protected $cacheBin = 'cache'; - public function __construct($entity_type) { + /** + * Constructs a new EntityViewBuilder. + * + * @param string $entity_type + * The entity type. + * @param array $entity_info + * The entity information array. + * @param \Drupal\Core\Entity\EntityManager $entity_manager + * The entity manager service. + */ + public function __construct($entity_type, array $entity_info, EntityManager $entity_manager) { $this->entityType = $entity_type; - $this->entityInfo = entity_get_info($entity_type); + $this->entityInfo = $entity_info; + $this->entityManager = $entity_manager; $this->viewModesInfo = entity_get_view_modes($entity_type); } /** * {@inheritdoc} */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static($entity_type, $entity_info, $container->get('entity.manager')); + } + + /** + * {@inheritdoc} + */ public function buildContent(array $entities, array $displays, $view_mode, $langcode = NULL) { field_attach_prepare_view($this->entityType, $entities, $displays, $langcode); @@ -167,9 +194,14 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la $view_modes = array(); $displays = array(); $context = array('langcode' => $langcode); - foreach ($entities as $entity) { + foreach ($entities as $key => $entity) { $bundle = $entity->bundle(); + // Ensure that from now on we are dealing with the proper translation + // object. + $entity = $this->entityManager->getTranslationFromContext($entity, $langcode); + $entities[$key] = $entity; + // Allow modules to change the view mode. $entity_view_mode = $view_mode; drupal_alter('entity_view_mode', $entity_view_mode, $entity, $context); diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php index 7181b32..b5ea710 100644 --- a/core/lib/Drupal/Core/Language/Language.php +++ b/core/lib/Drupal/Core/Language/Language.php @@ -153,7 +153,7 @@ public function extend($obj) { * @param array $languages * The array of language objects keyed by langcode. */ - public static function sort($languages) { + public static function sort(&$languages) { uasort($languages, function ($a, $b) { $a_weight = isset($a->weight) ? $a->weight : 0; $b_weight = isset($b->weight) ? $b->weight : 0; diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php index 7bc716d..532d404 100644 --- a/core/lib/Drupal/Core/Language/LanguageManager.php +++ b/core/lib/Drupal/Core/Language/LanguageManager.php @@ -7,8 +7,10 @@ namespace Drupal\Core\Language; -use Symfony\Component\HttpFoundation\Request; +use Drupal\Component\Utility\MapArray; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\KeyValueStore\KeyValueStoreInterface; +use Symfony\Component\HttpFoundation\Request; /** * Class responsible for initializing each language type. @@ -30,6 +32,13 @@ class LanguageManager { protected $state = NULL; /** + * The module handler service. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + + /** * An array of language objects keyed by language type. * * @var array @@ -57,10 +66,13 @@ class LanguageManager { * Constructs an LanguageManager object. * * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $state - * The state keyvalue store. + * (optional) The state keyvalue store. Defaults to NULL. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * (optional) The module handler service. Defaults to NULL. */ - public function __construct(KeyValueStoreInterface $state = NULL) { + public function __construct(KeyValueStoreInterface $state = NULL, ModuleHandlerInterface $module_handler = NULL) { $this->state = $state; + $this->moduleHandler = $module_handler; } /** @@ -162,6 +174,53 @@ public function isMultilingual() { } /** + * Returns the language fallback candidates for a given context. + * + * @param string $langcode + * (optional) The language of the current context. Defaults to NULL. + * @param array $context + * (optional) An associative array of data that can be useful to determine + * the fallback sequence. The following keys are used in core: + * - langcode: The desired language. + * - operation: The name of the operation indicating the context where + * language fallback is being applied, e.g. 'entity_view'. + * - data: An arbitrary data structure that makes sense in the provided + * context, e.g. an entity. + * + * @return array + * An array of language codes sorted by priority: first values should be + * tried first. + */ + public function getFallbackCandidates($langcode = NULL, array $context = array()) { + if ($this->isMultilingual()) { + // Get languages ordered by weight, add Language::LANGCODE_NOT_SPECIFIED at + // the end. + $candidates = array_keys(language_list()); + $candidates[] = Language::LANGCODE_NOT_SPECIFIED; + $candidates = MapArray::copyValuesToKeys($candidates); + + // The first candidate should always be the desired language if specified. + if (!empty($langcode)) { + $candidates = array($langcode => $langcode) + $candidates; + } + + // Let other modules hook in and add/change candidates. + $type = 'language_fallback_candidates'; + $types = array(); + if (!empty($context['operation'])) { + $types[] = $type . '_' . $context['operation']; + } + $types[] = $type; + $this->moduleHandler->alter($types, $candidates, $context); + } + else { + $candidates = array(Language::LANGCODE_DEFAULT); + } + + return $candidates; + } + + /** * Returns an array of the available language types. * * @return array() diff --git a/core/lib/Drupal/Core/TypedData/TranslatableInterface.php b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php index f94aa0b..af66bfe 100644 --- a/core/lib/Drupal/Core/TypedData/TranslatableInterface.php +++ b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php @@ -7,6 +7,8 @@ namespace Drupal\Core\TypedData; +use Drupal\Core\Language\LanguageManager; + /** * Interface for translatable data. */ @@ -35,10 +37,9 @@ public function getTranslationLanguages($include_default = TRUE); /** * Gets a translation of the data. * - * The returned translation has to be implement the same typed data interfaces - * as this typed data object, excluding the TranslatableInterface. E.g., if - * this typed data object implements the ComplexDataInterface and - * AccessibleInterface, the translation object has to implement both as well. + * The returned translation has to be of the same type than this typed data + * object. If the specified translation does not exist, a new one will be + * instantiated. * * @param $langcode * The language code of the translation to get or Language::LANGCODE_DEFAULT @@ -49,7 +50,6 @@ public function getTranslationLanguages($include_default = TRUE); */ public function getTranslation($langcode); - /** * Returns the translatable object referring to the original language. * diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php index ea12340..ca99fa6 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php @@ -20,7 +20,6 @@ * @EntityType( * id = "aggregator_feed", * label = @Translation("Aggregator feed"), - * module = "aggregator", * controllers = { * "storage" = "Drupal\aggregator\FeedStorageController", * "view_builder" = "Drupal\aggregator\FeedViewBuilder", diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php index 927b2cc..3007200 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php @@ -19,7 +19,6 @@ * @EntityType( * id = "aggregator_item", * label = @Translation("Aggregator feed item"), - * module = "aggregator", * controllers = { * "storage" = "Drupal\aggregator\ItemStorageController", * "view_builder" = "Drupal\aggregator\ItemViewBuilder" diff --git a/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php b/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php index 0ca5bef..d4761f5 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php @@ -9,7 +9,7 @@ use Drupal\Component\Utility\String; use Drupal\Core\Entity\ContentEntityFormController; -use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Language\Language; use Drupal\aggregator\CategoryStorageControllerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -20,13 +20,6 @@ class FeedFormController extends ContentEntityFormController { /** - * The feed storage. - * - * @var \Drupal\Core\Entity\EntityStorageControllerInterface - */ - protected $feedStorageController; - - /** * The category storage controller. * * @var \Drupal\aggregator\CategoryStorageControllerInterface @@ -36,13 +29,13 @@ class FeedFormController extends ContentEntityFormController { /** * Constructs a FeedForm object. * - * @param \Drupal\Core\Entity\EntityStorageControllerInterface $feed_storage - * The feed storage. + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. * @param \Drupal\aggregator\CategoryStorageControllerInterface $category_storage_controller * The category storage controller. */ - public function __construct(EntityStorageControllerInterface $feed_storage, CategoryStorageControllerInterface $category_storage_controller) { - $this->feedStorageController = $feed_storage; + public function __construct(EntityManagerInterface $entity_manager, CategoryStorageControllerInterface $category_storage_controller) { + parent::__construct($entity_manager); $this->categoryStorageController = $category_storage_controller; } @@ -51,7 +44,7 @@ public function __construct(EntityStorageControllerInterface $feed_storage, Cate */ public static function create(ContainerInterface $container) { return new static( - $container->get('plugin.manager.entity')->getStorageController('aggregator_feed'), + $container->get('entity.manager'), $container->get('aggregator.category.storage') ); } @@ -125,7 +118,8 @@ public function form(array $form, array &$form_state) { public function validate(array $form, array &$form_state) { $feed = $this->buildEntity($form, $form_state); // Check for duplicate titles. - $result = $this->feedStorageController->getFeedDuplicates($feed); + $feed_storage_controller = $this->entityManager->getStorageController('aggregator_feed'); + $result = $feed_storage_controller->getFeedDuplicates($feed); foreach ($result as $item) { if (strcasecmp($item->title, $feed->label()) == 0) { form_set_error('title', $this->t('A feed named %feed already exists. Enter a unique title.', array('%feed' => $feed->label()))); diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php index 9446451..2baf1fe 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php @@ -20,7 +20,6 @@ * id = "custom_block", * label = @Translation("Custom Block"), * bundle_label = @Translation("Custom Block type"), - * module = "custom_block", * controllers = { * "storage" = "Drupal\custom_block\CustomBlockStorageController", * "access" = "Drupal\custom_block\CustomBlockAccessController", diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php index c5444de..8321d70 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php @@ -19,7 +19,6 @@ * @EntityType( * id = "custom_block_type", * label = @Translation("Custom block type"), - * module = "custom_block", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "form" = { diff --git a/core/modules/block/lib/Drupal/block/Entity/Block.php b/core/modules/block/lib/Drupal/block/Entity/Block.php index f11031e..f433ea6 100644 --- a/core/modules/block/lib/Drupal/block/Entity/Block.php +++ b/core/modules/block/lib/Drupal/block/Entity/Block.php @@ -20,7 +20,6 @@ * @EntityType( * id = "block", * label = @Translation("Block"), - * module = "block", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\block\BlockAccessController", diff --git a/core/modules/book/lib/Drupal/book/Form/BookOutlineForm.php b/core/modules/book/lib/Drupal/book/Form/BookOutlineForm.php index 94d9b8a..61ff1fc 100644 --- a/core/modules/book/lib/Drupal/book/Form/BookOutlineForm.php +++ b/core/modules/book/lib/Drupal/book/Form/BookOutlineForm.php @@ -8,6 +8,7 @@ namespace Drupal\book\Form; use Drupal\Core\Entity\ContentEntityFormController; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\book\BookManager; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -32,19 +33,25 @@ class BookOutlineForm extends ContentEntityFormController { /** * Constructs a BookOutlineForm object. + * + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. + * @param \Drupal\book\BookManager $book_manager + * The BookManager service. */ - public function __construct(BookManager $bookManager) { - $this->bookManager = $bookManager; + public function __construct(EntityManagerInterface $entity_manager, BookManager $book_manager) { + parent::__construct($entity_manager); + $this->bookManager = $book_manager; } /** - * This method lets us inject the services this class needs. - * - * Only inject services that are actually needed. Which services - * are needed will vary by the controller. + * {@inheritdoc} */ public static function create(ContainerInterface $container) { - return new static($container->get('book.manager')); + return new static( + $container->get('entity.manager'), + $container->get('book.manager') + ); } /** diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/Breakpoint.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/Breakpoint.php index a149e68..0736131 100644 --- a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/Breakpoint.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/Breakpoint.php @@ -23,7 +23,6 @@ * @EntityType( * id = "breakpoint", * label = @Translation("Breakpoint"), - * module = "breakpoint", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" * }, diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php index 6a3150a..5f32b5e 100644 --- a/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Entity/BreakpointGroup.php @@ -20,7 +20,6 @@ * @EntityType( * id = "breakpoint_group", * label = @Translation("Breakpoint group"), - * module = "breakpoint", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" * }, diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 8b28e76..f6ab885 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -896,7 +896,7 @@ function comment_translation_configuration_element_submit($form, &$form_state) { $key = 'language_configuration'; $comment_form_state = array( 'content_translation' => array('key' => $key), - 'language' => array($key => array('entity_type' => 'comment', 'bundle' => $form['#field']['name'])), + 'language' => array($key => array('entity_type' => 'comment', 'bundle' => $form['#field']->name)), 'values' => array($key => array('content_translation' => $form_state['values']['content_translation'])), ); content_translation_language_configuration_element_submit($form, $comment_form_state); diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php index db10747..f0c38ad 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php @@ -24,13 +24,6 @@ class CommentFormController extends ContentEntityFormController { /** - * The entity manager service. - * - * @var \Drupal\Core\Entity\EntityManagerInterface - */ - protected $entityManager; - - /** * The field info service. * * @var \Drupal\field\FieldInfo @@ -58,14 +51,29 @@ public static function create(ContainerInterface $container) { * @param \Drupal\Core\Session\AccountInterface $current_user * The current user. */ - public function __construct(EntityManagerInterface $entity_manager, FieldInfo $field_info, AccountInterface $current_user) { - $this->entityManager = $entity_manager; + parent::__construct($entity_manager); $this->fieldInfo = $field_info; $this->currentUser = $current_user; } /** + * {@inheritdoc} + */ + protected function init(array &$form_state) { + $comment = $this->entity; + + // Make the comment inherit the current content language unless specifically + // set. + if ($comment->isNew()) { + $language_content = \Drupal::languageManager()->getLanguage(Language::TYPE_CONTENT); + $comment->langcode->value = $language_content->id; + } + + parent::init($form_state); + } + + /** * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state) { @@ -207,13 +215,6 @@ public function form(array $form, array &$form_state) { '#value' => ($comment->id() ? !$comment->uid->target_id : $this->currentUser->isAnonymous()), ); - // Make the comment inherit the current content language unless specifically - // set. - if ($comment->isNew()) { - $language_content = language(Language::TYPE_CONTENT); - $comment->langcode->value = $language_content->id; - } - // Add internal comment properties. $original = $comment->getUntranslated(); foreach (array('cid', 'pid', 'entity_id', 'entity_type', 'field_id', 'uid', 'langcode') as $key) { diff --git a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php index 22dfb09..d79363b 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php +++ b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php @@ -24,13 +24,6 @@ class CommentViewBuilder extends EntityViewBuilder implements EntityViewBuilderInterface, EntityControllerInterface { /** - * The entity manager service. - * - * @var \Drupal\Core\Entity\EntityManagerInterface - */ - protected $entityManager; - - /** * The field info service. * * @var \Drupal\field\FieldInfo @@ -57,6 +50,7 @@ class CommentViewBuilder extends EntityViewBuilder implements EntityViewBuilderI public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { return new static( $entity_type, + $entity_info, $container->get('entity.manager'), $container->get('field.info'), $container->get('module_handler'), @@ -69,6 +63,8 @@ public static function createInstance(ContainerInterface $container, $entity_typ * * @param string $entity_type * The entity type. + * @param array $entity_info + * The entity information array. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager service. * @param \Drupal\field\FieldInfo $field_info @@ -78,9 +74,8 @@ public static function createInstance(ContainerInterface $container, $entity_typ * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token * The CSRF token manager service. */ - public function __construct($entity_type, EntityManagerInterface $entity_manager, FieldInfo $field_info, ModuleHandlerInterface $module_handler, CsrfTokenGenerator $csrf_token) { - parent::__construct($entity_type); - $this->entityManager = $entity_manager; + public function __construct($entity_type, array $entity_info, EntityManagerInterface $entity_manager, FieldInfo $field_info, ModuleHandlerInterface $module_handler, CsrfTokenGenerator $csrf_token) { + parent::__construct($entity_type, $entity_info, $entity_manager); $this->fieldInfo = $field_info; $this->moduleHandler = $module_handler; $this->csrfToken = $csrf_token; diff --git a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php index 35db484..1db3983 100644 --- a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php +++ b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php @@ -21,7 +21,6 @@ * id = "comment", * label = @Translation("Comment"), * bundle_label = @Translation("Content type"), - * module = "comment", * controllers = { * "storage" = "Drupal\comment\CommentStorageController", * "access" = "Drupal\comment\CommentAccessController", diff --git a/core/modules/comment/lib/Drupal/comment/Form/DeleteForm.php b/core/modules/comment/lib/Drupal/comment/Form/DeleteForm.php index 07f3146..60b2036 100644 --- a/core/modules/comment/lib/Drupal/comment/Form/DeleteForm.php +++ b/core/modules/comment/lib/Drupal/comment/Form/DeleteForm.php @@ -10,6 +10,7 @@ use Drupal\comment\CommentManagerInterface; use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\ContentEntityConfirmFormBase; +use Drupal\Core\Entity\EntityManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -27,10 +28,13 @@ class DeleteForm extends ContentEntityConfirmFormBase { /** * Constructs a DeleteForm object. * + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. * @param \Drupal\comment\CommentManagerInterface $comment_manager * The comment manager service. */ - public function __construct(CommentManagerInterface $comment_manager) { + public function __construct(EntityManagerInterface $entity_manager, CommentManagerInterface $comment_manager) { + parent::__construct($entity_manager); $this->commentManager = $comment_manager; } @@ -39,6 +43,7 @@ public function __construct(CommentManagerInterface $comment_manager) { */ public static function create(ContainerInterface $container) { return new static( + $container->get('entity.manager'), $container->get('comment.manager') ); } diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigQueryTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigQueryTest.php index 6c55057..5aed97f 100644 --- a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigQueryTest.php +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigQueryTest.php @@ -16,7 +16,6 @@ * @EntityType( * id = "config_query_test", * label = @Translation("Test configuration for query"), - * module = "config_test", * controllers = { * "storage" = "Drupal\config_test\ConfigTestStorageController", * "list" = "Drupal\Core\Config\Entity\ConfigEntityListController", diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php index c4d330e..19ee07f 100644 --- a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php @@ -18,7 +18,6 @@ * @EntityType( * id = "config_test", * label = @Translation("Test configuration"), - * module = "config_test", * controllers = { * "storage" = "Drupal\config_test\ConfigTestStorageController", * "list" = "Drupal\config_test\ConfigTestListController", diff --git a/core/modules/contact/lib/Drupal/contact/Entity/Category.php b/core/modules/contact/lib/Drupal/contact/Entity/Category.php index 2e6dd3b..e636713 100644 --- a/core/modules/contact/lib/Drupal/contact/Entity/Category.php +++ b/core/modules/contact/lib/Drupal/contact/Entity/Category.php @@ -19,7 +19,6 @@ * @EntityType( * id = "contact_category", * label = @Translation("Contact category"), - * module = "contact", * controllers = { * "storage" = "Drupal\contact\CategoryStorageController", * "access" = "Drupal\contact\CategoryAccessController", diff --git a/core/modules/contact/lib/Drupal/contact/Entity/Message.php b/core/modules/contact/lib/Drupal/contact/Entity/Message.php index ec59424..9e424fa 100644 --- a/core/modules/contact/lib/Drupal/contact/Entity/Message.php +++ b/core/modules/contact/lib/Drupal/contact/Entity/Message.php @@ -16,7 +16,6 @@ * @EntityType( * id = "contact_message", * label = @Translation("Contact message"), - * module = "contact", * controllers = { * "storage" = "Drupal\Core\Entity\FieldableDatabaseStorageController", * "view_builder" = "Drupal\contact\MessageViewBuilder", diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index b31b8d8..2af6130 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -323,7 +323,12 @@ function content_translation_translate_access(EntityInterface $entity) { */ function content_translation_view_access(EntityInterface $entity, $langcode, AccountInterface $account = NULL) { $entity_type = $entity->entityType(); - return !empty($entity->translation[$langcode]['status']) || user_access('translate any entity', $account) || user_access("translate $entity_type entities", $account); + $info = $entity->entityInfo(); + $permission = "translate $entity_type"; + if (!empty($info['permission_granularity']) && $info['permission_granularity'] == 'bundle') { + $permission = "translate {$entity->bundle()} $entity_type"; + } + return !empty($entity->translation[$langcode]['status']) || user_access('translate any entity', $account) || user_access($permission, $account); } /** @@ -627,7 +632,10 @@ function content_translation_permission() { * Implements hook_form_alter(). */ function content_translation_form_alter(array &$form, array &$form_state) { - if (($form_controller = content_translation_form_controller($form_state)) && ($entity = $form_controller->getEntity()) && !$entity->isNew() && $entity instanceof ContentEntityInterface && $entity->isTranslatable()) { + $form_controller = content_translation_form_controller($form_state); + $entity = $form_controller ? $form_controller->getEntity() : NULL; + + if ($entity instanceof ContentEntityInterface && $entity->isTranslatable() && count($entity->getTranslationLanguages()) > 1) { $controller = content_translation_controller($entity->entityType()); $controller->entityFormAlter($form, $form_state, $entity); @@ -650,28 +658,16 @@ function content_translation_form_alter(array &$form, array &$form_state) { } /** - * Implements hook_field_language_alter(). + * Implements hook_language_fallback_candidates_OPERATION_alter(). * * Performs language fallback for unaccessible translations. */ -function content_translation_field_language_alter(&$display_language, $context) { - $entity = $context['entity']; - $entity_type = $entity->entityType(); - - if ($entity instanceof ContentEntityInterface && isset($entity->translation[$context['langcode']]) && $entity->isTranslatable() && !content_translation_view_access($entity, $context['langcode'])) { - $instances = field_info_instances($entity_type, $entity->bundle()); - // Avoid altering the real entity. - $entity = clone($entity); - $entity_langcode = $entity->getUntranslated()->language()->id; - - foreach ($entity->translation as $langcode => $translation) { - if ($langcode == $context['langcode'] || !content_translation_view_access($entity, $langcode)) { - $entity->removeTranslation($langcode); - } +function content_translation_language_fallback_candidates_entity_view_alter(&$candidates, $context) { + $entity = $context['data']; + foreach ($entity->getTranslationLanguages() as $langcode => $language) { + if (!content_translation_view_access($entity, $langcode)) { + unset($candidates[$langcode]); } - - // Find the new fallback values. - field_language_fallback($display_language, $entity, $context['langcode']); } } diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php index 21c8465..c24e064 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php @@ -34,18 +34,18 @@ * Tests the basic translation UI. */ function testTranslationUI() { - $this->assertBasicTranslation(); + $this->doTestBasicTranslation(); $this->doTestTranslationOverview(); - $this->assertOutdatedStatus(); - $this->assertPublishedStatus(); - $this->assertAuthoringInfo(); - $this->assertTranslationDeletion(); + $this->doTestOutdatedStatus(); + $this->doTestPublishedStatus(); + $this->doTestAuthoringInfo(); + $this->doTestTranslationDeletion(); } /** * Tests the basic translation workflow. */ - protected function assertBasicTranslation() { + protected function doTestBasicTranslation() { // Create a new test entity with original values in the default language. $default_langcode = $this->langcodes[0]; $values[$default_langcode] = $this->getNewEntityValues($default_langcode); @@ -117,7 +117,7 @@ protected function doTestTranslationOverview() { /** * Tests up-to-date status tracking. */ - protected function assertOutdatedStatus() { + protected function doTestOutdatedStatus() { $entity = entity_load($this->entityType, $this->entityId, TRUE); $langcode = 'fr'; $default_langcode = $this->langcodes[0]; @@ -150,7 +150,7 @@ protected function assertOutdatedStatus() { /** * Tests the translation publishing status. */ - protected function assertPublishedStatus() { + protected function doTestPublishedStatus() { $entity = entity_load($this->entityType, $this->entityId, TRUE); $path = $this->controller->getEditPath($entity); @@ -172,7 +172,7 @@ protected function assertPublishedStatus() { /** * Tests the translation authoring information. */ - protected function assertAuthoringInfo() { + protected function doTestAuthoringInfo() { $entity = entity_load($this->entityType, $this->entityId, TRUE); $path = $this->controller->getEditPath($entity); $values = array(); @@ -194,8 +194,8 @@ protected function assertAuthoringInfo() { $entity = entity_load($this->entityType, $this->entityId, TRUE); foreach ($this->langcodes as $langcode) { - $this->assertEqual($entity->translation[$langcode]['uid'] == $values[$langcode]['uid'], 'Translation author correctly stored.'); - $this->assertEqual($entity->translation[$langcode]['created'] == $values[$langcode]['created'], 'Translation date correctly stored.'); + $this->assertEqual($entity->translation[$langcode]['uid'], $values[$langcode]['uid'], 'Translation author correctly stored.'); + $this->assertEqual($entity->translation[$langcode]['created'], $values[$langcode]['created'], 'Translation date correctly stored.'); } // Try to post non valid values and check that they are rejected. @@ -207,14 +207,14 @@ protected function assertAuthoringInfo() { ); $this->drupalPostForm($path, $edit, $this->getFormSubmitAction($entity)); $this->assertTrue($this->xpath('//div[contains(@class, "error")]//ul'), 'Invalid values generate a list of form errors.'); - $this->assertEqual($entity->translation[$langcode]['uid'] == $values[$langcode]['uid'], 'Translation author correctly kept.'); - $this->assertEqual($entity->translation[$langcode]['created'] == $values[$langcode]['created'], 'Translation date correctly kept.'); + $this->assertEqual($entity->translation[$langcode]['uid'], $values[$langcode]['uid'], 'Translation author correctly kept.'); + $this->assertEqual($entity->translation[$langcode]['created'], $values[$langcode]['created'], 'Translation date correctly kept.'); } /** * Tests translation deletion. */ - protected function assertTranslationDeletion() { + protected function doTestTranslationDeletion() { // Confirm and delete a translation. $langcode = 'fr'; $entity = entity_load($this->entityType, $this->entityId, TRUE); diff --git a/core/modules/editor/lib/Drupal/editor/Entity/Editor.php b/core/modules/editor/lib/Drupal/editor/Entity/Editor.php index 8f25368..a7bc66c 100644 --- a/core/modules/editor/lib/Drupal/editor/Entity/Editor.php +++ b/core/modules/editor/lib/Drupal/editor/Entity/Editor.php @@ -18,7 +18,6 @@ * @EntityType( * id = "editor", * label = @Translation("Editor"), - * module = "editor", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" * }, diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module index 2749bcd..5e3602c 100644 --- a/core/modules/entity/entity.module +++ b/core/modules/entity/entity.module @@ -164,7 +164,7 @@ function entity_module_preuninstall($module) { // Clean up all entity bundles (including field instances) of every entity // type provided by the module that is being uninstalled. foreach (\Drupal::entityManager()->getDefinitions() as $entity_type => $entity_info) { - if ($entity_info['module'] == $module) { + if ($entity_info['provider'] == $module) { foreach (array_keys(entity_get_bundles($entity_type)) as $bundle) { entity_invoke_bundle_hook('delete', $entity_type, $bundle); } diff --git a/core/modules/entity/lib/Drupal/entity/Entity/EntityDisplay.php b/core/modules/entity/lib/Drupal/entity/Entity/EntityDisplay.php index 8b59366..e684a59 100644 --- a/core/modules/entity/lib/Drupal/entity/Entity/EntityDisplay.php +++ b/core/modules/entity/lib/Drupal/entity/Entity/EntityDisplay.php @@ -19,7 +19,6 @@ * @EntityType( * id = "entity_display", * label = @Translation("Entity display"), - * module = "entity", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" * }, diff --git a/core/modules/entity/lib/Drupal/entity/Entity/EntityFormDisplay.php b/core/modules/entity/lib/Drupal/entity/Entity/EntityFormDisplay.php index 1e04cfb..461f7ce 100644 --- a/core/modules/entity/lib/Drupal/entity/Entity/EntityFormDisplay.php +++ b/core/modules/entity/lib/Drupal/entity/Entity/EntityFormDisplay.php @@ -19,7 +19,6 @@ * @EntityType( * id = "entity_form_display", * label = @Translation("Entity form display"), - * module = "entity", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" * }, diff --git a/core/modules/entity/lib/Drupal/entity/Entity/EntityFormMode.php b/core/modules/entity/lib/Drupal/entity/Entity/EntityFormMode.php index 1ac34da..533321c 100644 --- a/core/modules/entity/lib/Drupal/entity/Entity/EntityFormMode.php +++ b/core/modules/entity/lib/Drupal/entity/Entity/EntityFormMode.php @@ -32,7 +32,6 @@ * @EntityType( * id = "form_mode", * label = @Translation("Form mode"), - * module = "entity", * controllers = { * "list" = "Drupal\entity\EntityFormModeListController", * "form" = { diff --git a/core/modules/entity/lib/Drupal/entity/Entity/EntityViewMode.php b/core/modules/entity/lib/Drupal/entity/Entity/EntityViewMode.php index 6a4abad..6107d4f 100644 --- a/core/modules/entity/lib/Drupal/entity/Entity/EntityViewMode.php +++ b/core/modules/entity/lib/Drupal/entity/Entity/EntityViewMode.php @@ -33,7 +33,6 @@ * @EntityType( * id = "view_mode", * label = @Translation("View mode"), - * module = "entity", * controllers = { * "list" = "Drupal\entity\EntityDisplayModeListController", * "form" = { diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayModeTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayModeTest.php index 803fbe3..29a46b5 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayModeTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayModeTest.php @@ -40,11 +40,11 @@ public function testEntityViewModeUI() { $this->drupalGet('admin/structure/display-modes/view'); $this->assertResponse(200); - $this->drupalGet('admin/structure/display-modes/view/add/entity_test_mul'); + $this->drupalGet('admin/structure/display-modes/view/add/entity_test_mulrev'); $this->assertResponse(404); $this->drupalGet('admin/structure/display-modes/view/add'); - $this->assertNoLink(t('Test entity - data table'), 'An entity type with no view builder cannot have view modes.'); + $this->assertNoLink(t('Test entity - revisions and data table'), 'An entity type with no view builder cannot have view modes.'); // Test adding a view mode. $this->clickLink(t('Test entity')); diff --git a/core/modules/field/config/field.settings.yml b/core/modules/field/config/field.settings.yml index 0a9ebdf..b6172c1 100644 --- a/core/modules/field/config/field.settings.yml +++ b/core/modules/field/config/field.settings.yml @@ -1,2 +1 @@ -language_fallback: true purge_batch_size: 10 diff --git a/core/modules/field/config/schema/field.schema.yml b/core/modules/field/config/schema/field.schema.yml index 9996784..424132b 100644 --- a/core/modules/field/config/schema/field.schema.yml +++ b/core/modules/field/config/schema/field.schema.yml @@ -4,9 +4,6 @@ field.settings: type: mapping label: 'Field settings' mapping: - language_fallback: - type: boolean - label: 'Whether the field display falls back to global language fallback configuration' purge_batch_size: type: integer label: 'Maximum number of field data records to purge' diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php index b4f0198..c252e2e 100644 --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -415,27 +415,6 @@ function hook_field_attach_view_alter(&$output, $context) { } /** - * Perform alterations on field_language() values. - * - * This hook is invoked to alter the array of display language codes for the - * given entity. - * - * @param $display_langcode - * A reference to an array of language codes keyed by field name. - * @param $context - * An associative array containing: - * - entity: The entity with fields to render. - * - langcode: The language code $entity has to be displayed in. - */ -function hook_field_language_alter(&$display_langcode, $context) { - // Do not apply core language fallback rules if they are disabled or if Locale - // is not registered as a translation handler. - if (field_language_fallback_enabled() && field_has_translation_handler($context['entity']->entityType())) { - field_language_fallback($display_langcode, $context['entity'], $context['langcode']); - } -} - -/** * Alter field_available_languages() values. * * This hook is invoked from field_available_languages() to allow modules to diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc index 548cc74..5567afd 100644 --- a/core/modules/field/field.attach.inc +++ b/core/modules/field/field.attach.inc @@ -120,19 +120,21 @@ function field_invoke_method($method, $target_function, EntityInterface $entity, $langcodes = _field_language_suggestion($available_langcodes, $options['langcode'], $field_name); foreach ($langcodes as $langcode) { - $items = $entity->getTranslation($langcode)->get($field_name); - $items->filterEmptyValues(); + if ($entity->hasTranslation($langcode)) { + $items = $entity->getTranslation($langcode)->get($field_name); + $items->filterEmptyValues(); - $result = $target->$method($items, $a, $b); + $result = $target->$method($items, $a, $b); - if (isset($result)) { - // For methods with array results, we merge results together. - // For methods with scalar results, we collect results in an array. - if (is_array($result)) { - $return = array_merge($return, $result); - } - else { - $return[] = $result; + if (isset($result)) { + // For methods with array results, we merge results together. + // For methods with scalar results, we collect results in an array. + if (is_array($result)) { + $return = array_merge($return, $result); + } + else { + $return[] = $result; + } } } } @@ -223,10 +225,12 @@ function field_invoke_method_multiple($method, $target_function, array $entities $langcode = !empty($options['langcode'][$id]) ? $options['langcode'][$id] : $options['langcode']; $langcodes = _field_language_suggestion($available_langcodes, $langcode, $field_name); foreach ($langcodes as $langcode) { - // Group the items corresponding to the current field. - $items = $entity->getTranslation($langcode)->get($field_name); - $items->filterEmptyValues(); - $grouped_items[$instance_uuid][$langcode][$id] = $items; + if ($entity->hasTranslation($langcode)) { + // Group the items corresponding to the current field. + $items = $entity->getTranslation($langcode)->get($field_name); + $items->filterEmptyValues(); + $grouped_items[$instance_uuid][$langcode][$id] = $items; + } } } } diff --git a/core/modules/field/field.deprecated.inc b/core/modules/field/field.deprecated.inc index b85380e..8ac2bc2 100644 --- a/core/modules/field/field.deprecated.inc +++ b/core/modules/field/field.deprecated.inc @@ -7,6 +7,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Language\Language; use Drupal\entity\Entity\EntityDisplay; use Drupal\field\Field; @@ -858,3 +859,80 @@ function field_access($op, FieldInterface $field, $entity_type, $entity = NULL, $items = $entity ? $entity->get($field->id()) : NULL; return $access_controller->fieldAccess($op, $field, $account, $items); } + +/** + * Ensures that a given language code is valid. + * + * Checks whether the given language code is one of the enabled language codes. + * Otherwise, it returns the current, global language code; or the site's + * default language code, if the additional parameter $default is TRUE. + * + * @param $langcode + * The language code to validate. + * @param $default + * Whether to return the default language code or the current language code in + * case $langcode is invalid. + * + * @return + * A valid language code. + * + * @deprecated This has been deprecated in favor of the Entity Field API. + */ +function field_valid_language($langcode, $default = TRUE) { + $languages = field_content_languages(); + if (in_array($langcode, $languages)) { + return $langcode; + } + return $default ? language_default()->id : language(Language::TYPE_CONTENT)->id; +} + +/** + * Returns the display language code for the fields attached to the given + * entity. + * + * The actual language code for each given field is determined based on the + * requested language code and the actual data available in the fields + * themselves. + * If there is no registered translation handler for the given entity type, the + * display language code to be used is just Language::LANGCODE_NOT_SPECIFIED, as + * no other language code is allowed by field_available_languages(). + * + * If translation handlers are found, we let modules provide alternative display + * language codes for fields not having the requested language code available. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity to be displayed. + * @param $field_name + * (optional) The name of the field to be displayed. Defaults to NULL. If + * no value is specified, the display language codes for every field attached + * to the given entity will be returned. + * @param $langcode + * (optional) The language code $entity has to be displayed in. Defaults to + * NULL. If no value is given the current language will be used. + * + * @return + * A language code if a field name is specified, an array of language codes + * keyed by field name otherwise. + * + * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates() + * @see \Drupal\Core\Entity\EntityInterface::getFieldLangcode() + * + * @deprecated This has been deprecated in favor of the Entity Field API. + */ +function field_language(EntityInterface $entity, $field_name = NULL, $langcode = NULL) { + $langcode = \Drupal::entityManager()->getTranslationFromContext($entity, $langcode)->language()->id; + $definitions = $entity->getPropertyDefinitions(); + $translatable = field_has_translation_handler($entity->entityType()); + if (!isset($field_name)) { + $display_langcodes = array(); + foreach ($definitions as $name => $definition) { + if (!empty($definition['configurable'])) { + $display_langcodes[$name] = $translatable ? $langcode : Language::LANGCODE_NOT_SPECIFIED; + } + } + return $display_langcodes; + } + elseif (!empty($definitions[$field_name]['configurable'])) { + return $translatable ? $langcode : Language::LANGCODE_NOT_SPECIFIED; + } +} diff --git a/core/modules/field/field.install b/core/modules/field/field.install index 2da4aec..55d6ff4 100644 --- a/core/modules/field/field.install +++ b/core/modules/field/field.install @@ -442,10 +442,7 @@ function field_update_8003() { * @ingroup config_upgrade */ function field_update_8004() { - update_variable_set('field_language_fallback', TRUE); - update_variables_to_config('field.settings', array( - 'field_language_fallback' => 'language_fallback', - )); + // Do nothing: the former update code has been moved to locale_update_8018(). } /** diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc index 96ecabb..68493c7 100644 --- a/core/modules/field/field.multilingual.inc +++ b/core/modules/field/field.multilingual.inc @@ -66,49 +66,6 @@ /** - * Applies language fallback rules to the fields attached to the given entity. - * - * Core language fallback rules simply check if fields have a field translation - * for the requested language code. If so, the requested language is returned, - * otherwise all the fallback candidates are inspected to see if there is a - * field translation available in another language. - * By default this is called by field_field_language_alter(), but this - * behavior can be disabled by setting the 'field.settings.language_fallback' - * variable to FALSE. - * - * @param $field_langcodes - * A reference to an array of language codes keyed by field name. - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity to be displayed. - * @param $langcode - * The language code $entity has to be displayed in. - */ -function field_language_fallback(&$field_langcodes, EntityInterface $entity, $langcode) { - // Lazily init fallback candidates to avoid unnecessary calls. - $fallback_candidates = NULL; - - foreach ($field_langcodes as $field_name => $field_langcode) { - // If the requested language is defined for the current field use it, - // otherwise search for a fallback value among the fallback candidates. - if (_field_translated_value_exists($entity, $langcode, $field_name)) { - $field_langcodes[$field_name] = $langcode; - } - else { - if (!isset($fallback_candidates)) { - require_once DRUPAL_ROOT . '/core/includes/language.inc'; - $fallback_candidates = language_fallback_get_candidates(); - } - foreach ($fallback_candidates as $fallback_langcode) { - if (_field_translated_value_exists($entity, $fallback_langcode, $field_name)) { - $field_langcodes[$field_name] = $fallback_langcode; - break; - } - } - } - } -} - -/** * Collects the available language codes for the given entity type and field. * * If the given field has language support enabled, an array of available @@ -196,13 +153,6 @@ function field_content_languages() { } /** - * Checks whether field language fallback is enabled. - */ -function field_language_fallback_enabled() { - return language_multilingual() && \Drupal::config('field.settings')->get('language_fallback'); -} - -/** * Checks whether a field has language support. * * A field has language support enabled if its 'translatable' property is set to @@ -242,126 +192,3 @@ function field_has_translation_handler($entity_type, $handler = NULL) { $info = entity_get_info($entity_type); return !empty($info['translatable']); } - -/** - * Ensures that a given language code is valid. - * - * Checks whether the given language code is one of the enabled language codes. - * Otherwise, it returns the current, global language code; or the site's - * default language code, if the additional parameter $default is TRUE. - * - * @param $langcode - * The language code to validate. - * @param $default - * Whether to return the default language code or the current language code in - * case $langcode is invalid. - * - * @return - * A valid language code. - */ -function field_valid_language($langcode, $default = TRUE) { - $languages = field_content_languages(); - if (in_array($langcode, $languages)) { - return $langcode; - } - return $default ? language_default()->id : language(Language::TYPE_CONTENT)->id; -} - -/** - * Returns the display language code for the fields attached to the given - * entity. - * - * The actual language code for each given field is determined based on the - * requested language code and the actual data available in the fields - * themselves. - * If there is no registered translation handler for the given entity type, the - * display language code to be used is just Language::LANGCODE_NOT_SPECIFIED, as no other - * language code is allowed by field_available_languages(). - * - * If translation handlers are found, we let modules provide alternative display - * language codes for fields not having the requested language code available. - * Core language fallback rules are provided by field_language_fallback() - * which is called by field_field_language_alter(). - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity to be displayed. - * @param $field_name - * (optional) The name of the field to be displayed. Defaults to NULL. If - * no value is specified, the display language codes for every field attached - * to the given entity will be returned. - * @param $langcode - * (optional) The language code $entity has to be displayed in. Defaults to - * NULL. If no value is given the current language will be used. - * - * @return - * A language code if a field name is specified, an array of language codes - * keyed by field name otherwise. - */ -function field_language(EntityInterface $entity, $displayed_field_name = NULL, $langcode = NULL) { - $display_langcodes = &drupal_static(__FUNCTION__, array()); - $id = $entity->id(); - $bundle = $entity->bundle(); - $entity_type = $entity->entityType(); - $langcode = field_valid_language($langcode, FALSE); - if (!isset($display_langcodes[$entity_type][$id][$langcode])) { - $display_langcode = array(); - - // By default, display language is set to one of the locked languages - // if the field translation is not available. It is up to translation - // handlers to implement language fallback rules. - foreach (field_info_instances($entity_type, $bundle) as $field_name => $instance) { - if (_field_translated_value_exists($entity, $langcode, $field_name)) { - $display_langcode[$field_name] = $langcode; - } - else { - // If the field has a value for one of the locked languages, then use - // that language for display. If not, the default one will be - // Language::LANGCODE_NOT_SPECIFIED. - $display_langcode[$field_name] = Language::LANGCODE_NOT_SPECIFIED; - foreach (language_list(Language::STATE_LOCKED) as $language_locked) { - if (isset($entity->{$field_name}[$language_locked->id])) { - $display_langcode[$field_name] = $language_locked->id; - break; - } - } - } - } - - if (field_has_translation_handler($entity_type)) { - $context = array( - 'entity' => $entity, - 'langcode' => $langcode, - ); - // Do not apply core language fallback rules if they are disabled or if - // the entity does not have a translation handler registered. - if (field_language_fallback_enabled() && field_has_translation_handler($entity_type)) { - field_language_fallback($display_langcode, $context['entity'], $context['langcode']); - } - drupal_alter('field_language', $display_langcode, $context); - } - - $display_langcodes[$entity_type][$id][$langcode] = $display_langcode; - } - - $display_langcode = $display_langcodes[$entity_type][$id][$langcode]; - - // Single-field mode. - if (isset($displayed_field_name)) { - return isset($display_langcode[$displayed_field_name]) ? $display_langcode[$displayed_field_name] : FALSE; - } - - return $display_langcode; -} - -/** - * Returns TRUE if a non-empty value exists for a given entity/language/field. - */ -function _field_translated_value_exists(EntityInterface $entity, $langcode, $field_name) { - if (!$entity->hasTranslation($langcode)) { - return FALSE; - } - $field = $entity->getTranslation($langcode)->$field_name; - $field->filterEmptyValues(); - $value = $field->getValue(); - return !empty($value); -} diff --git a/core/modules/field/lib/Drupal/field/Entity/Field.php b/core/modules/field/lib/Drupal/field/Entity/Field.php index 0a8d1a4..47003fb 100644 --- a/core/modules/field/lib/Drupal/field/Entity/Field.php +++ b/core/modules/field/lib/Drupal/field/Entity/Field.php @@ -22,7 +22,6 @@ * @EntityType( * id = "field_entity", * label = @Translation("Field"), - * module = "field", * controllers = { * "storage" = "Drupal\field\FieldStorageController" * }, diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php index 6d43b63..8fe1d1c 100644 --- a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php +++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php @@ -18,7 +18,6 @@ * @EntityType( * id = "field_instance", * label = @Translation("Field instance"), - * module = "field", * controllers = { * "storage" = "Drupal\field\FieldInstanceStorageController" * }, diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php index 4d5e3bb..c41c01f 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php +++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php @@ -261,14 +261,7 @@ public function query($use_groupby = FALSE) { $this->view->display_handler->options['field_langcode'] ); $placeholder = $this->placeholder(); - $langcode_fallback_candidates = array($langcode); - if (field_language_fallback_enabled()) { - require_once DRUPAL_ROOT . '/includes/language.inc'; - $langcode_fallback_candidates = array_merge($langcode_fallback_candidates, language_fallback_get_candidates()); - } - else { - $langcode_fallback_candidates[] = Language::LANGCODE_NOT_SPECIFIED; - } + $langcode_fallback_candidates = $this->languageManager->getFallbackCandidates($langcode, array('operation' => 'views_query', 'data' => $this)); $this->query->addWhereExpression(0, "$column IN($placeholder) OR $column IS NULL", array($placeholder => $langcode_fallback_candidates)); } } @@ -867,11 +860,12 @@ function field_langcode(EntityInterface $entity) { $this->view->display_handler->options['field_language'] ); - // Give the Field Language API a chance to fallback to a different language - // (or Language::LANGCODE_NOT_SPECIFIED), in case the field has no data for the selected language. - // field_view_field() does this as well, but since the returned language code - // is used before calling it, the fallback needs to happen explicitly. - $langcode = field_language($entity, $this->field_info['field_name'], $langcode); + // Give the Entity Field API a chance to fallback to a different language + // (or Language::LANGCODE_NOT_SPECIFIED), in case the field has no data + // for the selected language. field_view_field() does this as well, but + // since the returned language code is used before calling it, the + // fallback needs to happen explicitly. + $langcode = $this->entityManager->getTranslationFromContext($entity, $langcode)->language()->id; return $langcode; } diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php index b381cf5..de2dd94 100644 --- a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php @@ -80,6 +80,8 @@ public static function getInfo() { function setUp() { parent::setUp(); + $this->installConfig(array('language')); + $this->field_name = drupal_strtolower($this->randomName() . '_field_name'); $this->entity_type = 'entity_test'; @@ -159,6 +161,7 @@ function testTranslatableFieldSaveLoad() { $field_translations = array(); $available_langcodes = field_available_languages($entity_type, $this->field); $this->assertTrue(count($available_langcodes) > 1, 'Field is translatable.'); + $available_langcodes = array_keys(language_list()); $entity->langcode->value = reset($available_langcodes); foreach ($available_langcodes as $langcode) { $field_translations[$langcode] = $this->_generateTestFieldValues($this->field->getFieldCardinality()); @@ -228,100 +231,4 @@ function testTranslatableFieldSaveLoad() { } } - /** - * Tests display language logic for translatable fields. - */ - function testFieldDisplayLanguage() { - $field_name = drupal_strtolower($this->randomName() . '_field_name'); - $entity_type = 'entity_test'; - $bundle = 'entity_test'; - - // We need an additional field here to properly test display language - // suggestions. - $field = array( - 'name' => $field_name, - 'entity_type' => $entity_type, - 'type' => 'test_field', - 'cardinality' => 2, - 'translatable' => TRUE, - ); - entity_create('field_entity', $field)->save(); - - $instance = array( - 'field_name' => $field['name'], - 'entity_type' => $entity_type, - 'bundle' => $bundle, - ); - entity_create('field_instance', $instance)->save(); - - $enabled_langcodes = field_content_languages(); - $entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));; - $entity->langcode->value = reset($enabled_langcodes); - $instances = field_info_instances($entity_type, $bundle); - - $langcodes = array(); - // This array is used to store, for each field name, which one of the locked - // languages will be used for display. - $locked_languages = array(); - - // Generate field translations for languages different from the first - // enabled. - foreach ($instances as $instance) { - $field_name = $instance->getFieldName(); - $field = $instance->getField(); - do { - // Index 0 is reserved for the requested language, this way we ensure - // that no field is actually populated with it. - $langcode = $enabled_langcodes[mt_rand(1, count($enabled_langcodes) - 1)]; - } - while (isset($langcodes[$langcode])); - $langcodes[$langcode] = TRUE; - $entity->getTranslation($langcode)->{$field_name}->setValue($this->_generateTestFieldValues($field->getFieldCardinality())); - // If the langcode is one of the locked languages, then that one - // will also be used for display. Otherwise, the default one should be - // used, which is Language::LANGCODE_NOT_SPECIFIED. - if (language_is_locked($langcode)) { - $locked_languages[$field_name] = $langcode; - } - else { - $locked_languages[$field_name] = Language::LANGCODE_NOT_SPECIFIED; - } - } - - // Test multiple-fields display languages for untranslatable entities. - field_test_entity_info_translatable($entity_type, FALSE); - drupal_static_reset('field_language'); - $requested_langcode = $enabled_langcodes[0]; - $display_langcodes = field_language($entity, NULL, $requested_langcode); - foreach ($instances as $instance) { - $field_name = $instance->getFieldName(); - $this->assertTrue($display_langcodes[$field_name] == $locked_languages[$field_name], format_string('The display language for field %field_name is %language.', array('%field_name' => $field_name, '%language' => $locked_languages[$field_name]))); - } - - // Test multiple-fields display languages for translatable entities. - field_test_entity_info_translatable($entity_type, TRUE); - drupal_static_reset('field_language'); - $display_langcodes = field_language($entity, NULL, $requested_langcode); - foreach ($instances as $instance) { - $field_name = $instance->getFieldName(); - $langcode = $display_langcodes[$field_name]; - // As the requested language was not assinged to any field, if the - // returned language is defined for the current field, core fallback rules - // were successfully applied. - $this->assertTrue(!empty($entity->getTranslation($langcode)->{$field_name}) && $langcode != $requested_langcode, format_string('The display language for the field %field_name is %language.', array('%field_name' => $field_name, '%language' => $langcode))); - } - - // Test single-field display language. - drupal_static_reset('field_language'); - $langcode = field_language($entity, $this->field_name, $requested_langcode); - $this->assertTrue(!empty($entity->getTranslation($langcode)->{$this->field_name}) && $langcode != $requested_langcode, format_string('The display language for the (single) field %field_name is %language.', array('%field_name' => $field_name, '%language' => $langcode))); - - // Test field_language() basic behavior without language fallback. - \Drupal::state()->set('field_test.language_fallback', FALSE); - $entity->getTranslation($requested_langcode)->{$this->field_name}->value = mt_rand(1, 127); - drupal_static_reset('field_language'); - $display_langcode = field_language($entity, $this->field_name, $requested_langcode); - $this->assertEqual($display_langcode, $requested_langcode, 'Display language behave correctly when language fallback is disabled'); - } - } diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php index 8ddb73a..90d3ef7 100644 --- a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php @@ -109,6 +109,7 @@ function testFieldFormTranslationRevisions() { $field_name = $this->field->getFieldName(); // Store the field translations. + ksort($available_langcodes); $entity->langcode->value = key($available_langcodes); foreach ($available_langcodes as $langcode => $value) { $entity->getTranslation($langcode)->{$field_name}->value = $value + 1; diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module index 992e6ef..c02a40c 100644 --- a/core/modules/field/tests/modules/field_test/field_test.module +++ b/core/modules/field/tests/modules/field_test/field_test.module @@ -63,15 +63,6 @@ function field_test_field_available_languages_alter(&$langcodes, $context) { } /** - * Implements hook_field_language_alter(). - */ -function field_test_field_language_alter(&$display_langcode, $context) { - if (\Drupal::state()->get('field_test.language_fallback') ?: TRUE) { - field_language_fallback($display_langcode, $context['entity'], $context['langcode']); - } -} - -/** * Store and retrieve keyed data for later verification by unit tests. * * This function is a simple in-memory key-value store with the diff --git a/core/modules/field_ui/tests/modules/field_ui_test/lib/Drupal/field_ui_test/Entity/FieldUITestNoBundle.php b/core/modules/field_ui/tests/modules/field_ui_test/lib/Drupal/field_ui_test/Entity/FieldUITestNoBundle.php index 5389036..e6841c5 100644 --- a/core/modules/field_ui/tests/modules/field_ui_test/lib/Drupal/field_ui_test/Entity/FieldUITestNoBundle.php +++ b/core/modules/field_ui/tests/modules/field_ui_test/lib/Drupal/field_ui_test/Entity/FieldUITestNoBundle.php @@ -17,7 +17,6 @@ * @EntityType( * id = "field_ui_test_no_bundle", * label = @Translation("Test Field UI entity, no bundle"), - * module = "field_ui_test", * controllers = { * "storage" = "Drupal\Core\Entity\DatabaseStorageController" * }, diff --git a/core/modules/file/lib/Drupal/file/Entity/File.php b/core/modules/file/lib/Drupal/file/Entity/File.php index a620533..3239cdf 100644 --- a/core/modules/file/lib/Drupal/file/Entity/File.php +++ b/core/modules/file/lib/Drupal/file/Entity/File.php @@ -21,7 +21,6 @@ * @EntityType( * id = "file", * label = @Translation("File"), - * module = "file", * controllers = { * "storage" = "Drupal\file\FileStorageController", * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder" diff --git a/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php b/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php index 59866f2..6c4bf5b 100644 --- a/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php +++ b/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php @@ -20,7 +20,6 @@ * @EntityType( * id = "filter_format", * label = @Translation("Text format"), - * module = "filter", * controllers = { * "form" = { * "add" = "Drupal\filter\FilterFormatAddFormController", diff --git a/core/modules/forum/lib/Drupal/forum/Form/ForumFormController.php b/core/modules/forum/lib/Drupal/forum/Form/ForumFormController.php index 56bbb51..7b758ef 100644 --- a/core/modules/forum/lib/Drupal/forum/Form/ForumFormController.php +++ b/core/modules/forum/lib/Drupal/forum/Form/ForumFormController.php @@ -8,11 +8,7 @@ namespace Drupal\forum\Form; use Drupal\Core\Cache\Cache; -use Drupal\Core\Config\ConfigFactory; use Drupal\taxonomy\TermFormController; -use Drupal\taxonomy\TermStorageControllerInterface; -use Drupal\taxonomy\VocabularyStorageControllerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Base form controller for forum term edit forms. @@ -34,47 +30,6 @@ class ForumFormController extends TermFormController { protected $urlStub = 'forum'; /** - * The forum config. - * - * @var \Drupal\Core\Config\Config - */ - protected $config; - - /** - * Term Storage Controller. - * - * @var \Drupal\taxonomy\TermStorageControllerInterface - */ - protected $termStorage; - - /** - * Constructs a new ForumFormController object. - * - * @param \Drupal\taxonomy\VocabularyStorageControllerInterface $vocab_storage - * The vocabulary storage. - * @param \Drupal\Core\Config\ConfigFactory $config_factory - * The config factory service. - * @param \Drupal\taxonomy\TermStorageControllerInterface $term_storage - * The term storage. - */ - public function __construct(VocabularyStorageControllerInterface $vocab_storage, ConfigFactory $config_factory, TermStorageControllerInterface $term_storage) { - parent::__construct($vocab_storage, $config_factory); - $this->termStorage = $term_storage; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - $entity_manager = $container->get('entity.manager'); - return new static( - $entity_manager->getStorageController('taxonomy_vocabulary'), - $container->get('config.factory'), - $entity_manager->getStorageController('taxonomy_term') - ); - } - - /** * {@inheritdoc} */ public function form(array $form, array &$form_state) { @@ -121,8 +76,9 @@ public function buildEntity(array $form, array &$form_state) { */ public function save(array $form, array &$form_state) { $term = $this->entity; + $term_storage = $this->entityManager->getStorageController('taxonomy_term'); + $status = $term_storage->save($term); - $status = $this->termStorage->save($term); switch ($status) { case SAVED_NEW: drupal_set_message($this->t('Created new @type %term.', array('%term' => $term->label(), '@type' => $this->forumFormType))); diff --git a/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php index 4b8cf5a..a8d0e21 100644 --- a/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php +++ b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php @@ -24,7 +24,6 @@ * @EntityType( * id = "image_style", * label = @Translation("Image style"), - * module = "image", * controllers = { * "form" = { * "add" = "Drupal\image\Form\ImageStyleAddForm", diff --git a/core/modules/language/language.api.php b/core/modules/language/language.api.php index cba3f96..d0a31c4 100644 --- a/core/modules/language/language.api.php +++ b/core/modules/language/language.api.php @@ -58,5 +58,39 @@ function hook_language_delete($language) { } /** + * Allow modules to alter the language fallback candidates. + * + * @param array $candidates + * An array of language codes whose order will determine the language fallback + * order. + * @param array $context + * A language fallback context. + * + * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates() + */ +function hook_language_fallback_candidates_alter(array &$candidates, array $context) { + $candidates = array_reverse($candidates); +} + +/** + * Allow modules to alter the fallback candidates for specific operations. + * + * @param array $candidates + * An array of language codes whose order will determine the language fallback + * order. + * @param array $context + * A language fallback context. + * + * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates() + */ +function hook_language_fallback_candidates_OPERATION_alter(array &$candidates, array $context) { + // We know that the current OPERATION deals with entities so no need to check + // here. + if ($context['data']->entityType() == 'node') { + $candidates = array_reverse($candidates); + } +} + +/** * @} End of "addtogroup hooks". */ diff --git a/core/modules/language/lib/Drupal/language/Entity/Language.php b/core/modules/language/lib/Drupal/language/Entity/Language.php index c1c1006..d4c8e1b 100644 --- a/core/modules/language/lib/Drupal/language/Entity/Language.php +++ b/core/modules/language/lib/Drupal/language/Entity/Language.php @@ -20,7 +20,6 @@ * @EntityType( * id = "language_entity", * label = @Translation("Language"), - * module = "language", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "list" = "Drupal\language\LanguageListController", diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageFallbackTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageFallbackTest.php new file mode 100644 index 0000000..ba50def --- /dev/null +++ b/core/modules/language/lib/Drupal/language/Tests/LanguageFallbackTest.php @@ -0,0 +1,99 @@ + 'Language fallback', + 'description' => 'Tests the language fallback behavior.', + 'group' => 'Language', + ); + } + + /** + * The state storage service. + * + * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface + */ + protected $state; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->enableModules(array('language', 'language_test')); + $this->installConfig(array('language')); + + $this->state = $this->container->get('state'); + + for ($i = 0; $i < 3; $i++) { + $language = new Language(); + $language->id = $this->randomName(2); + $language->weight = -$i; + language_save($language); + } + } + + /** + * Tests language fallback candidates. + */ + public function testCandidates() { + $manager = $this->getLanguageManager(); + $expected = array_keys(language_list() + array(Language::LANGCODE_NOT_SPECIFIED => NULL)); + + // Check that language fallback candidates by default are all the available + // languages sorted by weight. + $candidates = $manager->getFallbackCandidates(); + $this->assertEqual(array_values($candidates), $expected, 'Language fallback candidates are properly returned.'); + + // Check that candidates are alterable. + $this->state->set('language_test.fallback_alter.candidates', TRUE); + $expected = array_slice($expected, 0, count($expected) - 1); + $candidates = $manager->getFallbackCandidates(); + $this->assertEqual(array_values($candidates), $expected, 'Language fallback candidates are alterable.'); + + // Check that candidates are alterable for specific operations. + $this->state->set('language_test.fallback_alter.candidates', FALSE); + $this->state->set('language_test.fallback_operation_alter.candidates', TRUE); + $expected[] = Language::LANGCODE_NOT_SPECIFIED; + $expected[] = Language::LANGCODE_NOT_APPLICABLE; + $candidates = $manager->getFallbackCandidates(NULL, array('operation' => 'test')); + $this->assertEqual(array_values($candidates), $expected, 'Language fallback candidates are alterable for specific operations.'); + + // Check that when the site is monolingual no language fallback is applied. + $default_langcode = language_default()->id; + foreach (language_list() as $langcode => $language) { + if ($langcode != $default_langcode) { + language_delete($langcode); + } + } + $candidates = $this->getLanguageManager()->getFallbackCandidates(); + $this->assertEqual(array_values($candidates), array(Language::LANGCODE_DEFAULT), 'Language fallback is not applied when the Language module is not enabled.'); + } + + /** + * Returns the language manager service. + * + * @return \Drupal\Core\Language\LanguageManager + * The language manager. + */ + protected function getLanguageManager() { + return $this->container->get('language_manager'); + } + +} diff --git a/core/modules/language/tests/language_test/language_test.module b/core/modules/language/tests/language_test/language_test.module index 33c2b36..8e8cbaf 100644 --- a/core/modules/language/tests/language_test/language_test.module +++ b/core/modules/language/tests/language_test/language_test.module @@ -109,3 +109,22 @@ function language_test_store_language_negotiation() { function language_test_language_negotiation_method($languages) { return 'it'; } + +/** + * Implements hook_language_fallback_candidates_alter(). + */ +function language_test_language_fallback_candidates_alter(array &$candidates, array $context) { + if (Drupal::state()->get('language_test.fallback_alter.candidates')) { + unset($candidates[Language::LANGCODE_NOT_SPECIFIED]); + } +} + +/** + * Implements hook_language_fallback_candidates_OPERATION_alter(). + */ +function language_test_language_fallback_candidates_test_alter(array &$candidates, array $context) { + if (Drupal::state()->get('language_test.fallback_operation_alter.candidates')) { + $langcode = Language::LANGCODE_NOT_APPLICABLE; + $candidates[$langcode] = $langcode; + } +} diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index 3ab0247..c55e203 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -965,6 +965,15 @@ function locale_update_8017() { } /** + * Removes the field language fallback settings as it is no longer supported. + * + * @ingroup config_upgrade + */ +function locale_update_8018() { + update_variable_del('locale_field_language_fallback'); +} + +/** * @} End of "addtogroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ diff --git a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php index 3c1a099..1a10efe 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/Entity/MenuLink.php @@ -24,7 +24,6 @@ * @EntityType( * id = "menu_link", * label = @Translation("Menu link"), - * module = "menu_link", * controllers = { * "storage" = "Drupal\menu_link\MenuLinkStorageController", * "access" = "Drupal\menu_link\MenuLinkAccessController", diff --git a/core/modules/node/lib/Drupal/node/Controller/NodeController.php b/core/modules/node/lib/Drupal/node/Controller/NodeController.php index 90e5899..4267101 100644 --- a/core/modules/node/lib/Drupal/node/Controller/NodeController.php +++ b/core/modules/node/lib/Drupal/node/Controller/NodeController.php @@ -127,7 +127,7 @@ public function page(NodeInterface $node) { * The page title. */ public function pageTitle(NodeInterface $node) { - return String::checkPlain($node->label()); + return String::checkPlain($this->entityManager()->getTranslationFromContext($node)->label()); } /** diff --git a/core/modules/node/lib/Drupal/node/Entity/Node.php b/core/modules/node/lib/Drupal/node/Entity/Node.php index 4633508..d7b1f6a 100644 --- a/core/modules/node/lib/Drupal/node/Entity/Node.php +++ b/core/modules/node/lib/Drupal/node/Entity/Node.php @@ -20,7 +20,6 @@ * id = "node", * label = @Translation("Content"), * bundle_label = @Translation("Content type"), - * module = "node", * controllers = { * "storage" = "Drupal\node\NodeStorageController", * "view_builder" = "Drupal\node\NodeViewBuilder", diff --git a/core/modules/node/lib/Drupal/node/Entity/NodeType.php b/core/modules/node/lib/Drupal/node/Entity/NodeType.php index 0fb1ecc..fb13664 100644 --- a/core/modules/node/lib/Drupal/node/Entity/NodeType.php +++ b/core/modules/node/lib/Drupal/node/Entity/NodeType.php @@ -19,7 +19,6 @@ * @EntityType( * id = "node_type", * label = @Translation("Content type"), - * module = "node", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\node\NodeTypeAccessController", diff --git a/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php b/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php index 11eb3f3..51da037 100644 --- a/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php +++ b/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php @@ -9,7 +9,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\ContentEntityConfirmFormBase; -use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Routing\UrlGeneratorInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -26,23 +26,16 @@ class NodeDeleteForm extends ContentEntityConfirmFormBase { protected $urlGenerator; /** - * The node type storage. - * - * @var \Drupal\Core\Entity\EntityStorageControllerInterface - */ - protected $nodeTypeStorage; - - /** * Constructs a NodeDeleteForm object. * + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator * The URL generator. - * @param \Drupal\Core\Entity\EntityStorageControllerInterface $node_type_storage - * The node type storage. */ - public function __construct(UrlGeneratorInterface $url_generator, EntityStorageControllerInterface $node_type_storage) { + public function __construct(EntityManagerInterface $entity_manager, UrlGeneratorInterface $url_generator) { + parent::__construct($entity_manager); $this->urlGenerator = $url_generator; - $this->nodeTypeStorage = $node_type_storage; } /** @@ -50,8 +43,8 @@ public function __construct(UrlGeneratorInterface $url_generator, EntityStorageC */ public static function create(ContainerInterface $container) { return new static( - $container->get('url_generator'), - $container->get('entity.manager')->getStorageController('node_type') + $container->get('entity.manager'), + $container->get('url_generator') ); } @@ -94,7 +87,8 @@ public function getConfirmText() { public function submit(array $form, array &$form_state) { $this->entity->delete(); watchdog('content', '@type: deleted %title.', array('@type' => $this->entity->bundle(), '%title' => $this->entity->label())); - $node_type = $this->nodeTypeStorage->load($this->entity->bundle())->label(); + $node_type_storage = $this->entityManager->getStorageController('node_type'); + $node_type = $node_type_storage->load($this->entity->bundle())->label(); drupal_set_message(t('@type %title has been deleted.', array('@type' => $node_type, '%title' => $this->entity->label()))); Cache::invalidateTags(array('content' => TRUE)); $form_state['redirect'] = ''; diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php index 6a2608c..baa8d23 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php @@ -72,7 +72,7 @@ protected function getFormSubmitAction(EntityInterface $entity) { /** * Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::assertPublishedStatus(). */ - protected function assertPublishedStatus() { + protected function doTestPublishedStatus() { $entity = entity_load($this->entityType, $this->entityId, TRUE); $path = $this->controller->getEditPath($entity); $languages = language_list(); @@ -104,7 +104,7 @@ protected function assertPublishedStatus() { /** * Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::assertAuthoringInfo(). */ - protected function assertAuthoringInfo() { + protected function doTestAuthoringInfo() { $entity = entity_load($this->entityType, $this->entityId, TRUE); $path = $this->controller->getEditPath($entity); $languages = language_list(); @@ -188,4 +188,47 @@ public function testDisabledBundle() { $this->assertEqual($enabledNode->id(), reset($rows)->entity_id); } + /** + * Tests that translations are rendered properly. + */ + function testTranslationRendering() { + $default_langcode = $this->langcodes[0]; + $values[$default_langcode] = $this->getNewEntityValues($default_langcode); + $this->entityId = $this->createEntity($values[$default_langcode], $default_langcode); + $node = \Drupal::entityManager()->getStorageController($this->entityType)->load($this->entityId); + $node->setPromoted(TRUE); + + // Create translations. + foreach (array_diff($this->langcodes, array($default_langcode)) as $langcode) { + $values[$langcode] = $this->getNewEntityValues($langcode); + $translation = $node->addTranslation($langcode, $values[$langcode]); + $translation->setPromoted(TRUE); + } + $node->save(); + + // Test that the frontpage view displays the correct translations. + \Drupal::moduleHandler()->install(array('views'), TRUE); + $this->rebuildContainer(); + $this->doTestTranslations('node', $values); + + // Test that the node page displays the correct translations. + $this->doTestTranslations('node/' . $node->id(), $values); + } + + /** + * Tests that the given path dsiplays the correct translation values. + * + * @param string $path + * The path to be tested. + * @param array $values + * The translation values to be found. + */ + protected function doTestTranslations($path, array $values) { + $languages = language_list(); + foreach ($this->langcodes as $langcode) { + $this->drupalGet($path, array('language' => $languages[$langcode])); + $this->assertText($values[$langcode]['title'], format_string('The %langcode node translation is correctly displayed.', array('%langcode' => $langcode))); + } + } + } diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc index 2f5d821..244a52b 100644 --- a/core/modules/node/node.tokens.inc +++ b/core/modules/node/node.tokens.inc @@ -129,11 +129,11 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr case 'body': case 'summary': - if (($items = $node->getTranslation($langcode)->get('body')) && !$items->isEmpty()) { + $translation = \Drupal::entityManager()->getTranslationFromContext($node, $langcode, array('operation' => 'node_tokens')); + if (($items = $translation->get('body')) && !$items->isEmpty()) { $item = $items[0]; $instance = field_info_instance('node', 'body', $node->getType()); - $field_langcode = field_language($node, 'body', $langcode); - + $field_langcode = $translation->language()->id; // If the summary was requested and is not empty, use it. if ($name == 'summary' && !empty($item->summary)) { $output = $sanitize ? $item->summary_processed : $item->summary; diff --git a/core/modules/picture/lib/Drupal/picture/Entity/PictureMapping.php b/core/modules/picture/lib/Drupal/picture/Entity/PictureMapping.php index c5a6e98..f059079 100644 --- a/core/modules/picture/lib/Drupal/picture/Entity/PictureMapping.php +++ b/core/modules/picture/lib/Drupal/picture/Entity/PictureMapping.php @@ -18,7 +18,6 @@ * @EntityType( * id = "picture_mapping", * label = @Translation("Picture mapping"), - * module = "picture", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "list" = "Drupal\picture\PictureMappingListController", diff --git a/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php b/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php index 094aa19..3b409dd 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php +++ b/core/modules/rdf/lib/Drupal/rdf/Entity/RdfMapping.php @@ -19,7 +19,6 @@ * @EntityType( * id = "rdf_mapping", * label = @Translation("RDF mapping"), - * module = "rdf", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" * }, diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php b/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php index b52fccb..d826f70 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Entity/ShortcutSet.php @@ -19,7 +19,6 @@ * @EntityType( * id = "shortcut_set", * label = @Translation("Shortcut set"), - * module = "shortcut", * controllers = { * "storage" = "Drupal\shortcut\ShortcutSetStorageController", * "access" = "Drupal\shortcut\ShortcutSetAccessController", diff --git a/core/modules/system/language.api.php b/core/modules/system/language.api.php index cfa42ec..de43f83 100644 --- a/core/modules/system/language.api.php +++ b/core/modules/system/language.api.php @@ -152,17 +152,6 @@ function hook_language_negotiation_info_alter(array &$negotiation_info) { } /** - * Perform alterations on the language fallback candidates. - * - * @param $fallback_candidates - * An array of language codes whose order will determine the language fallback - * order. - */ -function hook_language_fallback_candidates_alter(array &$fallback_candidates) { - $fallback_candidates = array_reverse($fallback_candidates); -} - -/** * @} End of "addtogroup hooks". */ diff --git a/core/modules/system/lib/Drupal/system/Entity/Action.php b/core/modules/system/lib/Drupal/system/Entity/Action.php index 27ba395..4962a92 100644 --- a/core/modules/system/lib/Drupal/system/Entity/Action.php +++ b/core/modules/system/lib/Drupal/system/Entity/Action.php @@ -21,7 +21,6 @@ * @EntityType( * id = "action", * label = @Translation("Action"), - * module = "system", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * }, diff --git a/core/modules/system/lib/Drupal/system/Entity/DateFormat.php b/core/modules/system/lib/Drupal/system/Entity/DateFormat.php index 54e58d8..fb4c7d3 100644 --- a/core/modules/system/lib/Drupal/system/Entity/DateFormat.php +++ b/core/modules/system/lib/Drupal/system/Entity/DateFormat.php @@ -20,7 +20,6 @@ * @EntityType( * id = "date_format", * label = @Translation("Date format"), - * module = "system", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\system\DateFormatAccessController", diff --git a/core/modules/system/lib/Drupal/system/Entity/Menu.php b/core/modules/system/lib/Drupal/system/Entity/Menu.php index 4727f8a..5f6d075 100644 --- a/core/modules/system/lib/Drupal/system/Entity/Menu.php +++ b/core/modules/system/lib/Drupal/system/Entity/Menu.php @@ -18,7 +18,6 @@ * @EntityType( * id = "menu", * label = @Translation("Menu"), - * module = "system", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "access" = "Drupal\system\MenuAccessController" diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php index bd6d098..7cbe7b5 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php @@ -34,7 +34,7 @@ public function testMethods() { $this->assertFalse($entity_manager->hasController('non_existent', 'non_existent'), 'A non existent entity type has no controller.'); $this->assertFalse($entity_manager->hasController('entity_test', 'non_existent'), 'An existent entity type does not have a non existent controller.'); - $this->assertFalse($entity_manager->hasController('entity_test_mul', 'view_builder'), 'The test entity does not have specified the view builder.'); + $this->assertFalse($entity_manager->hasController('entity_test_mulrev', 'view_builder'), 'The test entity does not have specified the view builder.'); $this->assertTrue($entity_manager->hasController('entity_test', 'storage'), 'The test entity has specified the controller class'); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php index e2b0d4f..bc0e195 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php @@ -10,6 +10,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\TypedData\TranslatableInterface; use Drupal\entity_test\Entity\EntityTestMulRev; +use Drupal\Component\Utility\MapArray; /** * Tests entity translation. @@ -83,6 +84,7 @@ function setUp() { $language = new Language(array( 'id' => 'l' . $i, 'name' => $this->randomString(), + 'weight' => $i, )); $this->langcodes[$i] = $language->id; language_save($language); @@ -494,6 +496,69 @@ function testEntityTranslationAPI() { } /** + * Tests language fallback applied to field and entity translations. + */ + function testLanguageFallback() { + $current_langcode = $this->container->get('language_manager')->getLanguage(Language::TYPE_CONTENT)->id; + $this->langcodes[] = $current_langcode; + + $values = array(); + foreach ($this->langcodes as $langcode) { + $values[$langcode]['name'] = $this->randomName(); + $values[$langcode]['user_id'] = mt_rand(0, 127); + } + + $default_langcode = $this->langcodes[0]; + $langcode = $this->langcodes[1]; + $langcode2 = $this->langcodes[2]; + + $entity_type = 'entity_test_mul'; + $controller = $this->entityManager->getStorageController($entity_type); + $entity = $controller->create(array('langcode' => $default_langcode) + $values[$default_langcode]); + $entity->save(); + + $entity->addTranslation($langcode, $values[$langcode]); + $entity->save(); + + // Check that retrieveing the current translation works as expected. + $entity = $this->reloadEntity($entity); + $translation = $this->entityManager->getTranslationFromContext($entity, $langcode2); + $this->assertEqual($translation->language()->id, $default_langcode, 'The current translation language matches the expected one.'); + + // Check that language fallback respects language weight by default. + $languages = language_list(); + $languages[$langcode]->weight = -1; + language_save($languages[$langcode]); + $translation = $this->entityManager->getTranslationFromContext($entity, $langcode2); + $this->assertEqual($translation->language()->id, $langcode, 'The current translation language matches the expected one.'); + + // Check that the current translation is properly returned. + $translation = $this->entityManager->getTranslationFromContext($entity); + $this->assertEqual($langcode, $translation->language()->id, 'The current translation language matches the topmost language fallback candidate.'); + $entity->addTranslation($current_langcode, $values[$current_langcode]); + $translation = $this->entityManager->getTranslationFromContext($entity); + $this->assertEqual($current_langcode, $translation->language()->id, 'The current translation language matches the current language.'); + + // Check that if the entity has no translation no fallback is applied. + $entity2 = $controller->create(array('langcode' => $default_langcode)); + $translation = $this->entityManager->getTranslationFromContext($entity2, $default_langcode); + $this->assertIdentical($entity2, $translation, 'When the entity has no translation no fallback is applied.'); + + // Checks that entity translations are rendered properly. + $controller = $this->entityManager->getViewBuilder($entity_type); + $build = $controller->view($entity); + $this->assertEqual($build['label']['#markup'], $values[$current_langcode]['name'], 'By default the entity is rendered in the current language.'); + $langcodes = MapArray::copyValuesToKeys($this->langcodes); + // We have no translation for the $langcode2 langauge, hence the expected + // result is the topmost existing translation, that is $langcode. + $langcodes[$langcode2] = $langcode; + foreach ($langcodes as $desired => $expected) { + $build = $controller->view($entity, 'full', $desired); + $this->assertEqual($build['label']['#markup'], $values[$expected]['name'], 'The entity is rendered in the expected language.'); + } + } + + /** * Check that field translatability is handled properly. */ function testFieldDefinitions() { diff --git a/core/modules/system/tests/modules/entity_cache_test_dependency/lib/Drupal/entity_cache_test_dependency/Entity/EntityCacheTest.php b/core/modules/system/tests/modules/entity_cache_test_dependency/lib/Drupal/entity_cache_test_dependency/Entity/EntityCacheTest.php index 1aad437..7a81687 100644 --- a/core/modules/system/tests/modules/entity_cache_test_dependency/lib/Drupal/entity_cache_test_dependency/Entity/EntityCacheTest.php +++ b/core/modules/system/tests/modules/entity_cache_test_dependency/lib/Drupal/entity_cache_test_dependency/Entity/EntityCacheTest.php @@ -19,8 +19,7 @@ * label = @Translation("Entity cache test"), * controllers = { * "storage" = "Drupal\Core\Entity\DatabaseStorageController", - * }, - * module = "entity_cache_test_dependency" + * } * ) */ class EntityCacheTest extends Entity { diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index 3ffcd22..c8f868e 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -147,7 +147,7 @@ function entity_test_entity_bundle_info() { $bundles = array(); $entity_info = entity_get_info(); foreach ($entity_info as $entity_type => $info) { - if ($info['module'] == 'entity_test') { + if ($info['provider'] == 'entity_test') { $bundles[$entity_type] = \Drupal::state()->get($entity_type . '.bundles') ?: array($entity_type => array('label' => 'Entity Test Bundle')); } } @@ -160,7 +160,7 @@ function entity_test_entity_bundle_info() { function entity_test_entity_view_mode_info_alter(&$view_modes) { $entity_info = entity_get_info(); foreach ($entity_info as $entity_type => $info) { - if ($entity_info[$entity_type]['module'] == 'entity_test' && !isset($view_modes[$entity_type])) { + if ($entity_info[$entity_type]['provider'] == 'entity_test' && !isset($view_modes[$entity_type])) { $view_modes[$entity_type] = array( 'full' => array( 'label' => t('Full object'), @@ -183,7 +183,7 @@ function entity_test_entity_view_mode_info_alter(&$view_modes) { function entity_test_entity_form_mode_info_alter(&$form_modes) { $entity_info = entity_get_info(); foreach ($entity_info as $entity_type => $info) { - if ($entity_info[$entity_type]['module'] == 'entity_test') { + if ($entity_info[$entity_type]['provider'] == 'entity_test') { $form_modes[$entity_type] = array( 'compact' => array( 'label' => t('Compact version'), diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php index 531d6d6..69f1aab 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php @@ -18,7 +18,6 @@ * @EntityType( * id = "entity_test", * label = @Translation("Test entity"), - * module = "entity_test", * controllers = { * "storage" = "Drupal\entity_test\EntityTestStorageController", * "list" = "Drupal\entity_test\EntityTestListController", @@ -99,8 +98,11 @@ protected function init() { /** * Overrides Drupal\entity\Entity::label(). */ - public function label($langcode = Language::LANGCODE_DEFAULT) { + public function label($langcode = NULL) { $info = $this->entityInfo(); + if (!isset($langcode)) { + $langcode = $this->activeLangcode; + } if (isset($info['entity_keys']['label']) && $info['entity_keys']['label'] == 'name') { return $this->getTranslation($langcode)->name->value; } diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php index a1c66cd..55a7b5e 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php @@ -17,7 +17,6 @@ * @EntityType( * id = "entity_test_cache", * label = @Translation("Test entity with field cache"), - * module = "entity_test", * controllers = { * "storage" = "Drupal\entity_test\EntityTestStorageController", * "access" = "Drupal\entity_test\EntityTestAccessController", diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestDefaultAccess.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestDefaultAccess.php index 4893c83..572dcbb 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestDefaultAccess.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestDefaultAccess.php @@ -16,7 +16,6 @@ * @EntityType( * id = "entity_test_default_access", * label = @Translation("Test entity with default access"), - * module = "entity_test", * controllers = { * "storage" = "Drupal\entity_test\EntityTestStorageController" * }, diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php index da3a31c..13041a4 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabel.php @@ -16,7 +16,6 @@ * @EntityType( * id = "entity_test_label", * label = @Translation("Entity Test label"), - * module = "entity_test", * controllers = { * "storage" = "Drupal\entity_test\EntityTestStorageController", * "view_builder" = "Drupal\entity_test\EntityTestViewBuilder" diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php index 1784aa2..92012a3 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestLabelCallback.php @@ -16,7 +16,6 @@ * @EntityType( * id = "entity_test_label_callback", * label = @Translation("Entity test label callback"), - * module = "entity_test", * controllers = { * "storage" = "Drupal\entity_test\EntityTestStorageController" * }, diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php index 76db7ab..7907322 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php @@ -17,9 +17,9 @@ * @EntityType( * id = "entity_test_mul", * label = @Translation("Test entity - data table"), - * module = "entity_test", * controllers = { * "storage" = "Drupal\entity_test\EntityTestStorageController", + * "view_builder" = "Drupal\entity_test\EntityTestViewBuilder", * "access" = "Drupal\entity_test\EntityTestAccessController", * "form" = { * "default" = "Drupal\entity_test\EntityTestFormController" diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php index 407640b..3d8df50 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php @@ -17,7 +17,6 @@ * @EntityType( * id = "entity_test_mulrev", * label = @Translation("Test entity - revisions and data table"), - * module = "entity_test", * controllers = { * "storage" = "Drupal\entity_test\EntityTestStorageController", * "access" = "Drupal\entity_test\EntityTestAccessController", diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestNoLabel.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestNoLabel.php index f56a5e0..a227a34 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestNoLabel.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestNoLabel.php @@ -16,7 +16,6 @@ * @EntityType( * id = "entity_test_no_label", * label = @Translation("Entity Test without label"), - * module = "entity_test", * controllers = { * "storage" = "Drupal\entity_test\EntityTestStorageController" * }, diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php index a6cd7bf..19760e8 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php @@ -17,7 +17,6 @@ * @EntityType( * id = "entity_test_rev", * label = @Translation("Test entity - revisions"), - * module = "entity_test", * controllers = { * "storage" = "Drupal\entity_test\EntityTestStorageController", * "access" = "Drupal\entity_test\EntityTestAccessController", diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php index 415aba0..033c5f1 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php @@ -21,7 +21,6 @@ * id = "taxonomy_term", * label = @Translation("Taxonomy term"), * bundle_label = @Translation("Vocabulary"), - * module = "taxonomy", * controllers = { * "storage" = "Drupal\taxonomy\TermStorageController", * "view_builder" = "Drupal\taxonomy\TermViewBuilder", diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php index 721d5ea..fe6669b 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php @@ -19,7 +19,6 @@ * @EntityType( * id = "taxonomy_vocabulary", * label = @Translation("Taxonomy vocabulary"), - * module = "taxonomy", * controllers = { * "storage" = "Drupal\taxonomy\VocabularyStorageController", * "list" = "Drupal\taxonomy\VocabularyListController", diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Form/TermDeleteForm.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Form/TermDeleteForm.php index 18d3a6a..cec3c3c 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Form/TermDeleteForm.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Form/TermDeleteForm.php @@ -8,7 +8,7 @@ namespace Drupal\taxonomy\Form; use Symfony\Component\DependencyInjection\ContainerInterface; -use Drupal\taxonomy\VocabularyStorageControllerInterface; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\ContentEntityConfirmFormBase; use Drupal\Core\Cache\Cache; @@ -18,32 +18,6 @@ class TermDeleteForm extends ContentEntityConfirmFormBase { /** - * The taxonomy vocabulary storage controller. - * - * @var \Drupal\taxonomy\VocabularyStorageControllerInterface - */ - protected $vocabularyStorageController; - - /** - * Constructs a new TermDelete object. - * - * @param \Drupal\taxonomy\VocabularyStorageControllerInterface $storage_controller - * The Entity manager. - */ - public function __construct(VocabularyStorageControllerInterface $storage_controller) { - $this->vocabularyStorageController = $storage_controller; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('entity.manager')->getStorageController('taxonomy_vocabulary') - ); - } - - /** * {@inheritdoc} */ public function getFormId() { @@ -85,7 +59,8 @@ public function getConfirmText() { */ public function submit(array $form, array &$form_state) { $this->entity->delete(); - $vocabulary = $this->vocabularyStorageController->load($this->entity->bundle()); + $storage_controller = $this->entityManager->getStorageController('taxonomy_vocabulary'); + $vocabulary = $storage_controller->load($this->entity->bundle()); // @todo Move to storage controller http://drupal.org/node/1988712 taxonomy_check_vocabulary_hierarchy($vocabulary, array('tid' => $this->entity->id())); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php index 8821b09..0dbaf63 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php @@ -10,6 +10,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Entity\ContentEntityFormController; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Language\Language; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -19,13 +20,6 @@ class TermFormController extends ContentEntityFormController { /** - * The vocabulary storage. - * - * @var \Drupal\taxonomy\VocabularyStorageControllerInterface - */ - protected $vocabStorage; - - /** * The config factory. * * @var \Drupal\Core\Config\ConfigFactory @@ -35,13 +29,13 @@ class TermFormController extends ContentEntityFormController { /** * Constructs a new TermFormController. * - * @param \Drupal\taxonomy\VocabularyStorageControllerInterface $vocab_storage - * The vocabulary storage. + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. * @param \Drupal\Core\Config\ConfigFactory $config_factory * The config factory. */ - public function __construct(VocabularyStorageControllerInterface $vocab_storage, ConfigFactory $config_factory) { - $this->vocabStorage = $vocab_storage; + public function __construct(EntityManagerInterface $entity_manager, ConfigFactory $config_factory) { + parent::__construct($entity_manager); $this->configFactory = $config_factory; } @@ -50,7 +44,7 @@ public function __construct(VocabularyStorageControllerInterface $vocab_storage, */ public static function create(ContainerInterface $container) { return new static( - $container->get('entity.manager')->getStorageController('taxonomy_vocabulary'), + $container->get('entity.manager'), $container->get('config.factory') ); } @@ -60,7 +54,8 @@ public static function create(ContainerInterface $container) { */ public function form(array $form, array &$form_state) { $term = $this->entity; - $vocabulary = $this->vocabStorage->load($term->bundle()); + $vocab_storage = $this->entityManager->getStorageController('taxonomy_vocabulary'); + $vocabulary = $vocab_storage->load($term->bundle()); $parent = array_keys(taxonomy_term_load_parents($term->id())); $form_state['taxonomy']['parent'] = $parent; diff --git a/core/modules/tour/lib/Drupal/tour/Entity/Tour.php b/core/modules/tour/lib/Drupal/tour/Entity/Tour.php index f686d6d..35a33b2 100644 --- a/core/modules/tour/lib/Drupal/tour/Entity/Tour.php +++ b/core/modules/tour/lib/Drupal/tour/Entity/Tour.php @@ -19,7 +19,6 @@ * @EntityType( * id = "tour", * label = @Translation("Tour"), - * module = "tour", * controllers = { * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController", * "view_builder" = "Drupal\tour\TourViewBuilder" diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php index 7140112..fdb39ae 100644 --- a/core/modules/user/lib/Drupal/user/AccountFormController.php +++ b/core/modules/user/lib/Drupal/user/AccountFormController.php @@ -8,6 +8,7 @@ namespace Drupal\user; use Drupal\Core\Entity\ContentEntityFormController; +use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageManager; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -27,10 +28,13 @@ /** * Constructs a new EntityFormController object. * + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. * @param \Drupal\Core\Language\LanguageManager $language_manager * The language manager. */ - public function __construct(LanguageManager $language_manager) { + public function __construct(EntityManagerInterface $entity_manager, LanguageManager $language_manager) { + parent::__construct($entity_manager); $this->languageManager = $language_manager; } @@ -39,6 +43,7 @@ public function __construct(LanguageManager $language_manager) { */ public static function create(ContainerInterface $container) { return new static( + $container->get('entity.manager'), $container->get('language_manager') ); } diff --git a/core/modules/user/lib/Drupal/user/Entity/Role.php b/core/modules/user/lib/Drupal/user/Entity/Role.php index 5bb6631..d58a358 100644 --- a/core/modules/user/lib/Drupal/user/Entity/Role.php +++ b/core/modules/user/lib/Drupal/user/Entity/Role.php @@ -17,7 +17,6 @@ * @EntityType( * id = "user_role", * label = @Translation("Role"), - * module = "user", * controllers = { * "storage" = "Drupal\user\RoleStorageController", * "access" = "Drupal\user\RoleAccessController", diff --git a/core/modules/user/lib/Drupal/user/Entity/User.php b/core/modules/user/lib/Drupal/user/Entity/User.php index 4180551..359031a 100644 --- a/core/modules/user/lib/Drupal/user/Entity/User.php +++ b/core/modules/user/lib/Drupal/user/Entity/User.php @@ -18,7 +18,6 @@ * @EntityType( * id = "user", * label = @Translation("User"), - * module = "user", * controllers = { * "storage" = "Drupal\user\UserStorageController", * "access" = "Drupal\user\UserAccessController", diff --git a/core/modules/user/lib/Drupal/user/Form/UserCancelForm.php b/core/modules/user/lib/Drupal/user/Form/UserCancelForm.php index 973c84e..59d6145 100644 --- a/core/modules/user/lib/Drupal/user/Form/UserCancelForm.php +++ b/core/modules/user/lib/Drupal/user/Form/UserCancelForm.php @@ -9,6 +9,7 @@ use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Entity\ContentEntityConfirmFormBase; +use Drupal\Core\Entity\EntityManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -42,8 +43,11 @@ class UserCancelForm extends ContentEntityConfirmFormBase { * * @param \Drupal\Core\Config\ConfigFactory $config_factory * The config factory. + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. */ - public function __construct(ConfigFactory $config_factory) { + public function __construct(EntityManagerInterface $entity_manager, ConfigFactory $config_factory) { + parent::__construct($entity_manager); $this->configFactory = $config_factory; } @@ -52,6 +56,7 @@ public function __construct(ConfigFactory $config_factory) { */ public static function create(ContainerInterface $container) { return new static( + $container->get('entity.manager'), $container->get('config.factory') ); } diff --git a/core/modules/views/lib/Drupal/views/Entity/View.php b/core/modules/views/lib/Drupal/views/Entity/View.php index ceb423e..1420ed8 100644 --- a/core/modules/views/lib/Drupal/views/Entity/View.php +++ b/core/modules/views/lib/Drupal/views/Entity/View.php @@ -20,7 +20,6 @@ * @EntityType( * id = "view", * label = @Translation("View"), - * module = "views", * controllers = { * "storage" = "Drupal\views\ViewStorageController", * "access" = "Drupal\views\ViewAccessController"