Commit 6ffc4cd8 authored by alexpott's avatar alexpott

Issue #2226621 by JeroenT, ianthomas_uk, lokapujya, pjonckiere, marcingy,...

Issue #2226621 by JeroenT, ianthomas_uk, lokapujya, pjonckiere, marcingy, LinL, Xano, rpayanm, piyuesh23: Remove usage of element_info(), element_child() and element_children(). Deprecate element_info_property()
parent 2c889842
......@@ -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:
......
......@@ -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);
}
/**
......
......@@ -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();
......
......@@ -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.
*
......
......@@ -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.
*
......
......@@ -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);
}
......@@ -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.
......
......@@ -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
......
......@@ -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(),
......
......@@ -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'];
......
......@@ -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
......
......@@ -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.
......
......@@ -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),
);
}
......
......@@ -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'];
......
......@@ -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 {
......
......@@ -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',
),
),
);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment