Issue #2207743 by dawehner, Xano: Convert element_info() to a service.

8.0.x
Alex Pott 2014-04-25 23:14:29 +01:00
parent 04dd275059
commit d196e8fb57
6 changed files with 263 additions and 47 deletions

View File

@ -772,3 +772,6 @@ services:
arguments: ['@cache.discovery', '@module_handler']
info_parser:
class: Drupal\Core\Extension\InfoParser
element_info:
class: Drupal\Core\Render\ElementInfo
arguments: ['@module_handler']

View File

@ -4178,25 +4178,12 @@ function drupal_render_cid_create($elements) {
*
* @param $type
* An element type as defined by hook_element_info().
*
* @deprecated As of Drupal 8.0, use \Drupal::service('element_info')->getInfo()
* instead.
*/
function element_info($type) {
// Use the advanced drupal_static() pattern, since this is called very often.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['cache'] = &drupal_static(__FUNCTION__);
}
$cache = &$drupal_static_fast['cache'];
if (!isset($cache)) {
$cache = \Drupal::moduleHandler()->invokeAll('element_info');
foreach ($cache as $element_type => $info) {
$cache[$element_type]['#type'] = $element_type;
}
// Allow modules to alter the element type defaults.
\Drupal::moduleHandler()->alter('element_info', $cache);
}
return isset($cache[$type]) ? $cache[$type] : array();
return \Drupal::service('element_info')->getInfo($type);
}
/**

View File

@ -0,0 +1,65 @@
<?php
/**
* @file
* Contains \Drupal\Core\Render\ElementInfo.
*/
namespace Drupal\Core\Render;
use Drupal\Core\Extension\ModuleHandlerInterface;
/**
* Provides the default element info implementation.
*/
class ElementInfo implements ElementInfoInterface {
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
*/
protected $moduleHandler;
/**
* Stores the available element information
*
* @var array
*/
protected $elementInfo;
/**
* Constructs a new ElementInfo instance.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(ModuleHandlerInterface $module_handler) {
$this->moduleHandler = $module_handler;
}
/**
* {@inheritdoc}
*/
public function getInfo($type) {
if (!isset($this->elementInfo)) {
$this->elementInfo = $this->buildInfo();
}
return isset($this->elementInfo[$type]) ? $this->elementInfo[$type] : array();
}
/**
* Builds up all element information.
*/
protected function buildInfo() {
$info = $this->moduleHandler->invokeAll('element_info');
foreach ($info as $element_type => $element) {
$info[$element_type]['#type'] = $element_type;
}
// Allow modules to alter the element type defaults.
$this->moduleHandler->alter('element_info', $info);
return $info;
}
}

View File

@ -0,0 +1,51 @@
<?php
/**
* @file
* Contains \Drupal\Core\Render\ElementInfoInterface.
*/
namespace Drupal\Core\Render;
/**
* Defines available render array element types.
*/
interface ElementInfoInterface {
/**
* Retrieves the default properties for the defined element type.
*
* Each of the form element types defined by this hook is assumed to have
* a matching theme function, e.g. theme_elementtype(), which should be
* registered with hook_theme() as normal.
*
* For more information about custom element types see the explanation at
* http://drupal.org/node/169815.
*
* @param string $type
* An element type as defined by hook_element_info().
*
* @return array
* An associative array describing the element types being defined. The array
* contains a sub-array for each element type, with the machine-readable type
* name as the key. Each sub-array has a number of possible attributes:
* - "#input": boolean indicating whether or not this element carries a value
* (even if it's hidden).
* - "#process": array of callback functions taking $element, $form_state,
* and $complete_form.
* - "#after_build": array of callables taking $element and $form_state.
* - "#validate": array of callback functions taking $form and $form_state.
* - "#element_validate": array of callback functions taking $element and
* $form_state.
* - "#pre_render": array of callables taking $element.
* - "#post_render": array of callables taking $children and $element.
* - "#submit": array of callback functions taking $form and $form_state.
* - "#title_display": optional string indicating if and how #title should be
* displayed, see the form-element template and theme_form_element_label().
*
* @see hook_element_info()
* @see hook_element_info_alter()
*/
public function getInfo($type);
}

View File

@ -185,32 +185,11 @@ function callback_queue_worker($queue_item_data) {
* specify their default values. The values returned by this hook will be
* merged with the elements returned by form constructor implementations and so
* can return defaults for any Form APIs keys in addition to those explicitly
* mentioned below.
* documented by \Drupal\Core\Render\ElementInfoInterface::getInfo().
*
* Each of the form element types defined by this hook is assumed to have
* a matching theme function, e.g. theme_elementtype(), which should be
* registered with hook_theme() as normal.
*
* For more information about custom element types see the explanation at
* http://drupal.org/node/169815.
*
* @return
* An associative array describing the element types being defined. The array
* contains a sub-array for each element type, with the machine-readable type
* name as the key. Each sub-array has a number of possible attributes:
* - "#input": boolean indicating whether or not this element carries a value
* (even if it's hidden).
* - "#process": array of callback functions taking $element, $form_state,
* and $complete_form.
* - "#after_build": array of callables taking $element and $form_state.
* - "#validate": array of callback functions taking $form and $form_state.
* - "#element_validate": array of callback functions taking $element and
* $form_state.
* - "#pre_render": array of callables taking $element.
* - "#post_render": array of callables taking $children and $element.
* - "#submit": array of callback functions taking $form and $form_state.
* - "#title_display": optional string indicating if and how #title should be
* displayed, see the form-element template and theme_form_element_label().
* @return array
* An associative array with structure identical to that of the return value
* of \Drupal\Core\Render\ElementInfoInterface::getInfo().
*
* @see hook_element_info_alter()
* @see system_element_info()
@ -228,15 +207,16 @@ function hook_element_info() {
* A module may implement this hook in order to alter the element type defaults
* defined by a module.
*
* @param $type
* All element type defaults as collected by hook_element_info().
* @param array $types
* An associative array with structure identical to that of the return value
* of \Drupal\Core\Render\ElementInfoInterface::getInfo().
*
* @see hook_element_info()
*/
function hook_element_info_alter(&$type) {
function hook_element_info_alter(array &$types) {
// Decrease the default size of textfields.
if (isset($type['textfield']['#size'])) {
$type['textfield']['#size'] = 40;
if (isset($types['textfield']['#size'])) {
$types['textfield']['#size'] = 40;
}
}

View File

@ -0,0 +1,130 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Render\ElementInfoTest.
*/
namespace Drupal\Tests\Core\Render;
use Drupal\Core\Render\ElementInfo;
use Drupal\Core\Render\ElementInfoInterface;
use Drupal\Tests\UnitTestCase;
/**
* Tests the element info.
*
* @coversDefaultClass \Drupal\Core\Render\ElementInfo
*/
class ElementInfoTest extends UnitTestCase {
/**
* The class under test.
*
* @var \Drupal\Core\Render\ElementInfoInterface
*/
protected $elementInfo;
/**
* The mocked module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $moduleHandler;
/**
* {@inheritdoc}
*/
public static function getInfo() {
return array(
'name' => 'Tests \Drupal\Core\Render\ElementInfo',
'description' => '',
'group' => 'Render',
);
}
/**
* {@inheritdoc}
*
* @covers ::__construct
*/
protected function setUp() {
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->elementInfo = new ElementInfo($this->moduleHandler);
}
/**
* Tests the getInfo method.
*
* @covers ::getInfo
* @covers ::buildInfo
*
* @dataProvider providerTestGetInfo
*/
public function testGetInfo($type, $expected_info, $element_info, callable $alter_callback = NULL) {
$this->moduleHandler->expects($this->once())
->method('invokeAll')
->with('element_info')
->will($this->returnValue($element_info));
$this->moduleHandler->expects($this->once())
->method('alter')
->with('element_info', $this->anything())
->will($this->returnCallback($alter_callback ?: function($info) {
return $info;
}));
$this->assertEquals($expected_info, $this->elementInfo->getInfo($type));
}
/**
* Provides tests data for getInfo.
*
* @return array
*/
public function providerTestGetInfo() {
$data = array();
// Provide an element and expect it is returned.
$data[] = array(
'page',
array(
'#type' => 'page',
'#show_messages' => TRUE,
'#theme' => 'page',
),
array('page' => array(
'#show_messages' => TRUE,
'#theme' => 'page',
)),
);
// Provide an element but request an non existent one.
$data[] = array(
'form',
array(
),
array('page' => array(
'#show_messages' => TRUE,
'#theme' => 'page',
)),
);
// Provide an element and alter it to ensure it is altered.
$data[] = array(
'page',
array(
'#type' => 'page',
'#show_messages' => TRUE,
'#theme' => 'page',
'#number' => 597219,
),
array('page' => array(
'#show_messages' => TRUE,
'#theme' => 'page',
)),
function ($alter_name, array &$info) {
$info['page']['#number'] = 597219;
}
);
return $data;
}
}