diff --git a/core/core.services.yml b/core/core.services.yml index ede41a1d091d165f4b0aedb3f0684c6b7f523308..f98c9f269ef638976c9e3db71fdb94fc946029f3 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -287,7 +287,7 @@ services: arguments: ['@stream_wrapper_manager', '@settings', '@logger.channel.file'] form_builder: class: Drupal\Core\Form\FormBuilder - arguments: ['@form_validator', '@form_submitter', '@form_cache', '@module_handler', '@event_dispatcher', '@request_stack', '@class_resolver', '@theme.manager', '@?csrf_token'] + arguments: ['@form_validator', '@form_submitter', '@form_cache', '@module_handler', '@event_dispatcher', '@request_stack', '@class_resolver', '@element_info', '@theme.manager', '@?csrf_token'] form_validator: class: Drupal\Core\Form\FormValidator arguments: ['@request_stack', '@string_translation', '@csrf_token', '@logger.channel.form'] @@ -856,7 +856,7 @@ services: - { name: event_subscriber } main_content_renderer.html: class: Drupal\Core\Render\MainContent\HtmlRenderer - arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher', '@module_handler', '@renderer', '@cache_contexts'] + arguments: ['@title_resolver', '@plugin.manager.display_variant', '@event_dispatcher', '@element_info', '@module_handler', '@renderer', '@cache_contexts'] tags: - { name: render.main_content_renderer, format: html } main_content_renderer.ajax: diff --git a/core/includes/common.inc b/core/includes/common.inc index 54714db2b43dfebc1288461fbce2bee9dec2f1e3..654a0f35dd3f36469c7adb690375f4f69475c1fa 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -1306,8 +1306,8 @@ function drupal_render_cache_generate_placeholder($callback, array &$context) { * @param $type * An element type as defined by hook_element_info(). * - * @deprecated As of Drupal 8.0, use \Drupal::service('element_info')->getInfo() - * instead. + * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal::service('element_info')->getInfo() instead. */ function element_info($type) { return \Drupal::service('element_info')->getInfo($type); @@ -1323,9 +1323,12 @@ function element_info($type) { * @param $default * (Optional) The value to return if the element type does not specify a * value for the property. Defaults to NULL. + * + * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + * Use \Drupal::service('element_info')->getInfoProperty() instead. */ function element_info_property($type, $property_name, $default = NULL) { - return (($info = element_info($type)) && array_key_exists($property_name, $info)) ? $info[$property_name] : $default; + return \Drupal::service('element_info')->getInfoProperty($type, $property_name, $default); } /** diff --git a/core/includes/theme.inc b/core/includes/theme.inc index a061ebc2ac1b83771b12161fb30ce50d9f9ad69a..dfee854c8a96cb8586b3737dadc7720ec7ee1ce5 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1556,7 +1556,7 @@ function template_preprocess_field(&$variables, $hook) { // We want other preprocess functions and the theme implementation to have // fast access to the field item render arrays. The item render array keys // (deltas) should always be numerically indexed starting from 0, and looping - // on those keys is faster than calling element_children() or looping on all + // on those keys is faster than calling Element::children() or looping on all // keys within $element, since that requires traversal of all element // properties. $variables['items'] = array(); diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php index 8d532ed8dda23e6f6ef03d3d3f922f95c4dec12e..4bc6272420d265cc0fbaf4fd57f848c21aef93a6 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -16,6 +16,7 @@ use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Render\Element; +use Drupal\Core\Render\ElementInfoManagerInterface; use Drupal\Core\Theme\ThemeManagerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\RequestStack; @@ -49,6 +50,13 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS */ protected $requestStack; + /** + * The element info manager. + * + * @var \Drupal\Core\Render\ElementInfoManagerInterface + */ + protected $elementInfo; + /** * The CSRF token generator to validate the form token. * @@ -111,12 +119,14 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS * The request stack. * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver * The class resolver. + * @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info + * The element info manager. * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager * The theme manager. * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token * The CSRF token generator. */ - public function __construct(FormValidatorInterface $form_validator, FormSubmitterInterface $form_submitter, FormCacheInterface $form_cache, ModuleHandlerInterface $module_handler, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, ClassResolverInterface $class_resolver, ThemeManagerInterface $theme_manager, CsrfTokenGenerator $csrf_token = NULL) { + public function __construct(FormValidatorInterface $form_validator, FormSubmitterInterface $form_submitter, FormCacheInterface $form_cache, ModuleHandlerInterface $module_handler, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, ClassResolverInterface $class_resolver, ElementInfoManagerInterface $element_info, ThemeManagerInterface $theme_manager, CsrfTokenGenerator $csrf_token = NULL) { $this->formValidator = $form_validator; $this->formSubmitter = $form_submitter; $this->formCache = $form_cache; @@ -124,6 +134,7 @@ public function __construct(FormValidatorInterface $form_validator, FormSubmitte $this->eventDispatcher = $event_dispatcher; $this->requestStack = $request_stack; $this->classResolver = $class_resolver; + $this->elementInfo = $element_info; $this->csrfToken = $csrf_token; $this->themeManager = $theme_manager; } @@ -606,7 +617,7 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) { $form['#id'] = Html::getUniqueId($form_id); } - $form += $this->getElementInfo('form'); + $form += $this->elementInfo->getInfo('form'); $form += array('#tree' => FALSE, '#parents' => array()); $form['#validate'][] = '::validateForm'; $form['#submit'][] = '::submitForm'; @@ -677,7 +688,7 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state $element['#processed'] = FALSE; // Use element defaults. - if (isset($element['#type']) && empty($element['#defaults_loaded']) && ($info = $this->getElementInfo($element['#type']))) { + if (isset($element['#type']) && empty($element['#defaults_loaded']) && ($info = $this->elementInfo->getInfo($element['#type']))) { // Overlay $info onto $element, retaining preexisting keys in $element. $element += $info; $element['#defaults_loaded'] = TRUE; @@ -751,7 +762,7 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state foreach (Element::children($element) as $key) { // Prior to checking properties of child elements, their default // properties need to be loaded. - if (isset($element[$key]['#type']) && empty($element[$key]['#defaults_loaded']) && ($info = $this->getElementInfo($element[$key]['#type']))) { + if (isset($element[$key]['#type']) && empty($element[$key]['#defaults_loaded']) && ($info = $this->elementInfo->getInfo($element[$key]['#type']))) { $element[$key] += $info; $element[$key]['#defaults_loaded'] = TRUE; } @@ -1078,15 +1089,6 @@ protected function buttonWasClicked($element, FormStateInterface &$form_state) { return FALSE; } - /** - * Wraps element_info(). - * - * @return array - */ - protected function getElementInfo($type) { - return element_info($type); - } - /** * Gets the current active user. * diff --git a/core/lib/Drupal/Core/Render/ElementInfoManager.php b/core/lib/Drupal/Core/Render/ElementInfoManager.php index 0c593da06c8f477b339b60b890673ec2b1fb725b..1bc1600d71fafdcf1a3b526ca4e0e77a30f98b50 100644 --- a/core/lib/Drupal/Core/Render/ElementInfoManager.php +++ b/core/lib/Drupal/Core/Render/ElementInfoManager.php @@ -85,6 +85,15 @@ public function getInfo($type) { return $info; } + /** + * {@inheritdoc} + */ + public function getInfoProperty($type, $property_name, $default = NULL) { + $info = $this->getInfo($type); + + return isset($info[$property_name]) ? $info[$property_name] : $default; + } + /** * Builds up all element information. * diff --git a/core/lib/Drupal/Core/Render/ElementInfoManagerInterface.php b/core/lib/Drupal/Core/Render/ElementInfoManagerInterface.php index d32acd690f93598349647c6905e55c0d5cec9d2f..7a460c1419dacb82a96dce31cb27496fe0fb8590 100644 --- a/core/lib/Drupal/Core/Render/ElementInfoManagerInterface.php +++ b/core/lib/Drupal/Core/Render/ElementInfoManagerInterface.php @@ -23,8 +23,7 @@ interface ElementInfoManagerInterface { * http://drupal.org/node/169815. * * @param string $type - * An element type as defined by hook_element_info() or the machine name - * of an element type plugin. + * The machine name of an element type plugin. * * @return array * An associative array describing the element types being defined. The @@ -52,4 +51,21 @@ interface ElementInfoManagerInterface { */ public function getInfo($type); + /** + * Retrieves a single property for the defined element type. + * + * @param string $type + * An element type as defined by hook_element_info(). + * @param string $property_name + * The property within the element type that should be returned. + * @param $default + * (Optional) The value to return if the element type does not specify a + * value for the property. Defaults to NULL. + * + * @return string + * The property value of the defined element type. Or the provided + * default value, which can be NULL. + */ + public function getInfoProperty($type, $property_name, $default = NULL); + } diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php index d12b18b750fea7fb99bf6e7f71d4a78e84147f13..882193000e60463591c93da0f2a3f2f44a9300e0 100644 --- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php +++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php @@ -14,6 +14,7 @@ use Drupal\Core\Controller\TitleResolverInterface; use Drupal\Core\Display\PageVariantInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Render\ElementInfoManagerInterface; use Drupal\Core\Render\PageDisplayVariantSelectionEvent; use Drupal\Core\Render\Renderer; use Drupal\Core\Render\RendererInterface; @@ -50,6 +51,13 @@ class HtmlRenderer implements MainContentRendererInterface { */ protected $eventDispatcher; + /** + * The element info manager. + * + * @var \Drupal\Core\Render\ElementInfoManagerInterface + */ + protected $elementInfoManager; + /** * The module handler. * @@ -80,6 +88,8 @@ class HtmlRenderer implements MainContentRendererInterface { * The display variant manager. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher * The event dispatcher. + * @param \Drupal\Core\Render\ElementInfoManagerInterface + * The element info manager. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. * @param \Drupal\Core\Render\RendererInterface $renderer @@ -87,10 +97,11 @@ class HtmlRenderer implements MainContentRendererInterface { * @param \Drupal\Core\Cache\CacheContexts $cache_contexts * The cache contexts service. */ - public function __construct(TitleResolverInterface $title_resolver, PluginManagerInterface $display_variant_manager, EventDispatcherInterface $event_dispatcher, ModuleHandlerInterface $module_handler, RendererInterface $renderer, CacheContexts $cache_contexts) { + public function __construct(TitleResolverInterface $title_resolver, PluginManagerInterface $display_variant_manager, EventDispatcherInterface $event_dispatcher, ElementInfoManagerInterface $element_info_manager, ModuleHandlerInterface $module_handler, RendererInterface $renderer, CacheContexts $cache_contexts) { $this->titleResolver = $title_resolver; $this->displayVariantManager = $display_variant_manager; $this->eventDispatcher = $event_dispatcher; + $this->elementInfoManager = $element_info_manager; $this->moduleHandler = $module_handler; $this->renderer = $renderer; $this->cacheContexts = $cache_contexts; @@ -117,7 +128,7 @@ public function renderResponse(array $main_content, Request $request, RouteMatch '#type' => 'html', 'page' => $page, ]; - $html += element_info('html'); + $html += $this->elementInfoManager->getInfo('html'); // The special page regions will appear directly in html.html.twig, not in // page.html.twig, hence add them here, just before rendering html.html.twig. diff --git a/core/lib/Drupal/Core/Render/RendererInterface.php b/core/lib/Drupal/Core/Render/RendererInterface.php index fe133b64348db0ee47101b5375ea8efa4f77fb0f..d2b799008f915d2194313044b07a31d7c623323c 100644 --- a/core/lib/Drupal/Core/Render/RendererInterface.php +++ b/core/lib/Drupal/Core/Render/RendererInterface.php @@ -147,8 +147,9 @@ public function renderPlain(&$elements); * element have not already been merged in (#defaults_loaded = TRUE) then * the defaults for this type of element, defined in hook_element_info(), * are merged into the array. #defaults_loaded is set by functions that - * process render arrays and call element_info() before passing the array - * to Renderer::render(), such as form_builder() in the Form API. + * process render arrays and call the element info service before passing + * the array to Renderer::render(), such as form_builder() in the Form + * API. * - If this element has an array of #pre_render functions defined, they are * called sequentially to modify the element before rendering. After all * the #pre_render functions have been called, #printed is checked a diff --git a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php index 6fe9d753cc88266c6a7c6685524d6ffa1b839e9a..da48f74122dc3b232871226bd765cf2ba7786111 100644 --- a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php +++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php @@ -9,13 +9,17 @@ use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\WidgetBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Render\Element; -use Drupal\file\Element\ManagedFile; +use Drupal\Core\Render\ElementInfoManagerInterface; use Drupal\Core\Url; +use Drupal\file\Element\ManagedFile; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Plugin implementation of the 'file_generic' widget. @@ -28,7 +32,22 @@ * } * ) */ -class FileWidget extends WidgetBase { +class FileWidget extends WidgetBase implements ContainerFactoryPluginInterface { + + /** + * {@inheritdoc} + */ + public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, ElementInfoManagerInterface $element_info) { + parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); + $this->elementInfo = $element_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static($plugin_id, $plugin_definition,$configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container->get('element_info')); + } /** * {@inheritdoc} @@ -212,7 +231,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen // Essentially we use the managed_file type, extended with some // enhancements. - $element_info = element_info('managed_file'); + $element_info = $this->elementInfo->getInfo('managed_file'); $element += array( '#type' => 'managed_file', '#upload_location' => $items[$delta]->getUploadLocation(), diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc index 19e9f4fab8c48a44f1fa336e16c1a7b661c872aa..8c35c6bf848ba766642b9cbbf57accea50b83083 100644 --- a/core/modules/language/language.admin.inc +++ b/core/modules/language/language.admin.inc @@ -51,7 +51,7 @@ function template_preprocess_language_negotiation_configure_form(&$variables) { foreach ($form[$type]['title'] as $id => $element) { // Do not take form control structures. - if (is_array($element) && element_child($id)) { + if (is_array($element) && Element::child($id)) { $table[$id]['#attributes']['class'][] = 'draggable'; $table[$id]['#weight'] = $element['#weight']; diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index c4f5cee951df72aa4c646fd459bd4387c0db1137..1ae8e58e76d58f819688e20ced1d527eeb840e68 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -327,7 +327,7 @@ protected function drupalBuildEntityView(EntityInterface $entity, $view_mode = ' // If the default values for this element have not been loaded yet, populate // them. if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) { - $elements += element_info($elements['#type']); + $elements += \Drupal::service('element_info')->getInfo($elements['#type']); } // Make any final changes to the element before it is rendered. This means diff --git a/core/modules/views_ui/admin.inc b/core/modules/views_ui/admin.inc index 97af75e8ced4ffffa764f3b56c6bd7bc15a96d98..64b90779478e4af6179f32ecba555c69734f7fd4 100644 --- a/core/modules/views_ui/admin.inc +++ b/core/modules/views_ui/admin.inc @@ -62,6 +62,7 @@ function views_ui_add_ajax_trigger(&$wrapping_element, $trigger_key, $refresh_pa // Add a submit button for users who do not have JavaScript enabled. It // should be displayed next to the triggering element on the form. $button_key = $trigger_key . '_trigger_update'; + $element_info = \Drupal::service('element_info'); $wrapping_element[$button_key] = array( '#type' => 'submit', // Hide this button when JavaScript is enabled. @@ -72,14 +73,14 @@ function views_ui_add_ajax_trigger(&$wrapping_element, $trigger_key, $refresh_pa // form API has added the #parents property to the triggering element for // us, we don't have any (easy) way to find out where its submitted values // will eventually appear in $form_state->getValues(). - '#process' => array_merge(array('views_ui_add_limited_validation'), element_info_property('submit', '#process', array())), + '#process' => array_merge(array('views_ui_add_limited_validation'), $element_info->getInfoProperty('submit', '#process', array())), // Add an after-build function that inserts a wrapper around the region of // the form that needs to be refreshed by AJAX (so that the AJAX system can // detect and dynamically update it). This is done in #after_build because // it's a convenient place where we have automatic access to the complete // form array, but also to minimize the chance that the HTML we add will // get clobbered by code that runs after we have added it. - '#after_build' => array_merge(element_info_property('submit', '#after_build', array()), array('views_ui_add_ajax_wrapper')), + '#after_build' => array_merge($element_info->getInfoProperty('submit', '#after_build', array()), array('views_ui_add_ajax_wrapper')), ); // Copy #weight and #access from the triggering element to the button, so // that the two elements will be displayed together. diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php index d47c2b0c10331126b1fbaa50733c7b9dc2314e74..2fc7fc4f821251eb551d47ec2361092076ab9926 100644 --- a/core/modules/views_ui/src/ViewEditForm.php +++ b/core/modules/views_ui/src/ViewEditForm.php @@ -18,6 +18,7 @@ use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; +use Drupal\Core\Render\ElementInfoManagerInterface; use Drupal\Core\Url; use Drupal\user\SharedTempStoreFactory; use Drupal\views\Views; @@ -51,6 +52,13 @@ class ViewEditForm extends ViewFormBase { */ protected $dateFormatter; + /** + * The element info manager. + * + * @var \Drupal\Core\Render\ElementInfoManagerInterface + */ + protected $elementInfo; + /** * Constructs a new ViewEditForm object. * @@ -60,11 +68,14 @@ class ViewEditForm extends ViewFormBase { * The request stack object. * @param \Drupal\Core\Datetime\DateFormatter $date_formatter * The date Formatter service. + * @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info + * The element info manager. */ - public function __construct(SharedTempStoreFactory $temp_store_factory, RequestStack $requestStack, DateFormatter $date_formatter) { + public function __construct(SharedTempStoreFactory $temp_store_factory, RequestStack $requestStack, DateFormatter $date_formatter, ElementInfoManagerInterface $element_info) { $this->tempStore = $temp_store_factory->get('views'); $this->requestStack = $requestStack; $this->dateFormatter = $date_formatter; + $this->elementInfo = $element_info; } /** @@ -74,7 +85,8 @@ public static function create(ContainerInterface $container) { return new static( $container->get('user.shared_tempstore'), $container->get('request_stack'), - $container->get('date.formatter') + $container->get('date.formatter'), + $container->get('element_info') ); } @@ -759,7 +771,7 @@ public function renderDisplayTop(ViewUI $view) { '#attributes' => array('class' => array('add-display')), // Allow JavaScript to remove the 'Add ' prefix from the button label when // placing the button in a "Add" dropdown menu. - '#process' => array_merge(array('views_ui_form_button_was_clicked'), element_info_property('submit', '#process', array())), + '#process' => array_merge(array('views_ui_form_button_was_clicked'), $this->elementInfo->getInfoProperty('submit', '#process', array())), '#values' => array($this->t('Add !display', array('!display' => $label)), $label), ); } diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index 028281b870810e2b776198742c5a0d89ccd00f22..4c82de70844a32e48c0f23afeb5ae05fa5aec16d 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -349,7 +349,7 @@ public function getStandardButtons(&$form, FormStateInterface $form_state, $form // button labels. if (isset($names)) { $form['actions']['submit']['#values'] = $names; - $form['actions']['submit']['#process'] = array_merge(array('views_ui_form_button_was_clicked'), element_info_property($form['actions']['submit']['#type'], '#process', array())); + $form['actions']['submit']['#process'] = array_merge(array('views_ui_form_button_was_clicked'), \Drupal::service('element_info')->getInfoProperty($form['actions']['submit']['#type'], '#process', array())); } // If a validation handler exists for the form, assign it to this button. $form['actions']['submit']['#validate'][] = [$form_state->getFormObject(), 'validateForm']; diff --git a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php index 3ad3d09cdd5d16e6a56bced6fb9e5c8002d07642..e11f60fe8e0e657d78b1c11a218f6bc0ccc8a466 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php +++ b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php @@ -62,6 +62,13 @@ abstract class FormTestBase extends UnitTestCase { */ protected $formCache; + /** + * The cache backend to use. + * + * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cache; + /** * The current user. * @@ -105,6 +112,14 @@ abstract class FormTestBase extends UnitTestCase { protected $classResolver; /** + * The element info manager. + * + * @var \Drupal\Core\Render\ElementInfoManagerInterface + */ + protected $elementInfo; + + /** + * * The event dispatcher. * * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject @@ -137,8 +152,18 @@ protected function setUp() { $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); $this->formCache = $this->getMock('Drupal\Core\Form\FormCacheInterface'); + $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); $this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'); + $this->classResolver = $this->getClassResolverStub(); + + $this->elementInfo = $this->getMockBuilder('\Drupal\Core\Render\ElementInfoManagerInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->elementInfo->expects($this->any()) + ->method('getInfo') + ->will($this->returnCallback(array($this, 'getInfo'))); + $this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator') ->disableOriginalConstructor() ->getMock(); @@ -162,7 +187,7 @@ protected function setUp() { ->getMock(); $this->root = dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__)))); - $this->formBuilder = new TestFormBuilder($this->formValidator, $this->formSubmitter, $this->formCache, $this->moduleHandler, $this->eventDispatcher, $this->requestStack, $this->classResolver, $this->themeManager, $this->csrfToken, $this->kernel); + $this->formBuilder = new TestFormBuilder($this->formValidator, $this->formSubmitter, $this->formCache, $this->moduleHandler, $this->eventDispatcher, $this->requestStack, $this->classResolver, $this->elementInfo, $this->themeManager, $this->csrfToken, $this->kernel); $this->formBuilder->setCurrentUser($this->account); } @@ -250,24 +275,17 @@ protected function assertFormElement(array $expected_form, array $actual_form, $ $this->assertSame(array_intersect_key($expected_element, $actual_element), $expected_element); } -} - -/** - * Provides a test form builder class. - */ -class TestFormBuilder extends FormBuilder { - - /** - * @param \Drupal\Core\Session\AccountInterface $account - */ - public function setCurrentUser(AccountInterface $account) { - $this->currentUser = $account; - } - /** - * {@inheritdoc} + * A stub method returning properties for the defined element type. + * + * @param string $type + * The machine name of an element type plugin. + * + * @return array + * An array with dummy values to be used in tests. Defaults to an empty + * array. */ - protected function getElementInfo($type) { + public function getInfo($type) { $types['token'] = array( '#input' => TRUE, ); @@ -290,8 +308,66 @@ protected function getElementInfo($type) { } return $types[$type]; } + } +/** + * Provides a test form builder class. + */ +class TestFormBuilder extends FormBuilder { + protected static $seenIds = array(); + + /** + * {@inheritdoc} + */ + protected function sendResponse(Response $response) { + parent::sendResponse($response); + // Throw an exception instead of exiting. + throw new \Exception('exit'); + } + + /** + * @param \Drupal\Core\Session\AccountInterface $account + */ + public function setCurrentUser(AccountInterface $account) { + $this->currentUser = $account; + } + + /** + * {@inheritdoc} + */ + protected function drupalHtmlClass($class) { + return $class; + } + + /** + * {@inheritdoc} + */ + protected function drupalHtmlId($id) { + if (isset(static::$seenIds[$id])) { + $id = $id . '--' . ++static::$seenIds[$id]; + } + else { + static::$seenIds[$id] = 1; + } + return $id; + } + + /** + * {@inheritdoc} + */ + public function drupalStaticReset($name = NULL) { + static::$seenIds = array(); + } + + /** + * {@inheritdoc} + */ + protected function requestUri() { + return ''; + } + +} } namespace { diff --git a/core/tests/Drupal/Tests/Core/Render/ElementInfoManagerTest.php b/core/tests/Drupal/Tests/Core/Render/ElementInfoManagerTest.php index 75b59ca7b8c538573c21341a95a10c48736127df..b0ca1f7ae7e7a7e30d0171a76da6aefc146ac0a7 100644 --- a/core/tests/Drupal/Tests/Core/Render/ElementInfoManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Render/ElementInfoManagerTest.php @@ -18,7 +18,7 @@ class ElementInfoManagerTest extends UnitTestCase { /** - * The class under test. + * The mocked element_info. * * @var \Drupal\Core\Render\ElementInfoManagerInterface */ @@ -237,4 +237,35 @@ public function providerTestGetInfoElementPlugin() { return $data; } + /** + * @covers ::getInfoProperty + */ + public function testGetInfoProperty() { + $this->themeManager + ->method('getActiveTheme') + ->willReturn(new ActiveTheme(['name' => 'test'])); + + $element_info = new TestElementInfoManager(new \ArrayObject(), $this->cache, $this->cacheTagsInvalidator, $this->moduleHandler, $this->themeManager); + $this->assertSame('baz', $element_info->getInfoProperty('foo', '#bar')); + $this->assertNull($element_info->getInfoProperty('foo', '#non_existing_property')); + $this->assertSame('qux', $element_info->getInfoProperty('foo', '#non_existing_property', 'qux')); + } +} + +/** + * Provides a test custom element plugin. + */ +class TestElementInfoManager extends ElementInfoManager { + + /** + * {@inheritdoc} + */ + protected $elementInfo = array( + 'test' => array( + 'foo' => array( + '#bar' => 'baz', + ), + ), + ); + }