diff --git a/render_example/css/render_example.css b/render_example/css/render_example.css
new file mode 100644
index 0000000..0da7f30
--- /dev/null
+++ b/render_example/css/render_example.css
@@ -0,0 +1,20 @@
+.render-array {
+ border: 2px solid #000;
+ margin-top: 10px;
+ padding-left: 5px;
+ padding-top: 5px;
+}
+
+.render-header {
+ font-size: large;
+ font-style: italic;
+}
+
+.unrendered-label {
+ font-style: italic;
+ margin-top: 10px;
+}
+
+.rendered {
+ background-color: #add8e6;
+}
diff --git a/render_example/lib/Drupal/render_example/Tests/RenderExampleTest.php b/render_example/lib/Drupal/render_example/Tests/RenderExampleTest.php
deleted file mode 100644
index a5d7c74..0000000
--- a/render_example/lib/Drupal/render_example/Tests/RenderExampleTest.php
+++ /dev/null
@@ -1,135 +0,0 @@
- 'Render example functionality',
- 'description' => 'Test Render Example',
- 'group' => 'Examples',
- // @todo Figure out if this is used, inherited from D7.
- 'dependencies' => array('devel'),
- );
- }
-
- /**
- * Assert that all of the xpaths in the array have results.
- *
- * @param $xpath_array
- * An array of xpaths, each of which must return something.
- */
- function assertRenderResults($xpath_array) {
- foreach ($xpath_array as $xpath) {
- $result = $this->xpath($xpath);
- $this->assertTrue(!empty($result), format_string('Found xpath %xpath', array('%xpath' => $xpath)));
- }
- }
-
- /**
- * Asserts that the string value of the result is the same as the passed text.
- *
- * @param $xpath_array
- * Array of keyed arrays of tests to be made. Each child array consists of
- * $xpath => $expected_text
- */
- function assertRenderedText($xpath_array) {
- foreach ($xpath_array as $xpath => $text) {
- $result = $this->xpath($xpath);
- $this->assertTrue((string)$result[0][0] == $text, format_string('%ary selects text %text', array('%ary' => $xpath, '%text' => $text)));
- }
- }
-
- /**
- * Login user, create an example node, and test blog functionality through the admin and user interfaces.
- */
- function testRenderExampleBasic() {
- // Create a user that can access devel information and log in.
- $web_user = $this->drupalCreateUser(array('access devel information', 'access content'));
- $this->drupalLogin($web_user);
-
- // Turn on the block render array display and make sure it shows up.
- $edit = array(
- 'render_example_show_block' => TRUE,
- );
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
-
- $xpath_array = array(
- "//div[@id='sidebar-first']//fieldset[starts-with(@id, 'edit-render-example-block-fieldset')]",
- '//*[@id="content"]//fieldset[contains(@id,"edit-render-example-block-fieldset")]',
- );
- $this->assertRenderResults($xpath_array);
-
-
- // Turn off block render array display and turn on the page render array
- // display.
- $edit = array(
- 'render_example_show_page' => TRUE,
- 'render_example_show_block' => FALSE,
- );
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
-
- $xpath_array = array(
- '//*[@id="content"]//fieldset[starts-with(@id,"edit-render-example-page-fieldset")]',
- );
- $this->assertRenderResults($xpath_array);
-
- // Add note about render arrays to the top of sidebar_first.
- $edit = array(
- 'render_example_note_about_render_arrays' => TRUE,
- );
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
- $xpath_array = array(
- '//*[@id="sidebar-first"]//ol//li[starts-with(.,"Render arrays are everywhere")]',
- );
- $this->assertRenderResults($xpath_array);
-
- // Move the navigation menu to the top of the content area.
- $edit = array(
- 'render_example_move_navigation_menu' => TRUE,
- );
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
- $xpath_array = array(
- '//*[@id="content"]//h2[starts-with(.,"Navigation")]',
- );
- $this->assertRenderResults($xpath_array);
-
- // Skip a test for reversing order of sidebar_first as I think it would
- // be too fragile.
-
- // Test the addition of #prefix and #suffix
- $edit = array(
- 'render_example_prefix' => TRUE,
- );
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
- $xpath_array = array(
- '//*[@id="sidebar-first"]//*[contains(@class, "block-prefix")]/span[contains(@class, "block-suffix")]',
- );
- $this->assertRenderResults($xpath_array);
-
- // Test some rendering facets of the various render examples
- $this->drupalGet('examples/render_example/arrays');
- $content = $this->xpath('//*[@class="render-array"][1]');
-
- $xpath_array = array(
- '//div[@class="rendered"][starts-with(.,"Some basic text in a #markup")]' => 'Some basic text in a #markup (shows basic markup and how it is rendered)',
- '//div[@class="rendered"][starts-with(.,"This is some text that should be put to")]' => 'This is some text that should be put together | This is some more text that we need | ',
- '//div[@class="rendered"][starts-with(.,"The current time was")]' => 'The current time was when this was cached. Updated every seconds',
- '//div[@class="rendered"]/div[text()][starts-with(.,"(prefix)This one")]' => '(prefix)This one adds a prefix and suffix, which put a div around the item(suffix)',
- '//div[@class="rendered"]/div[text()][starts-with(.,"markup for pre_")]' => 'markup for pre_render and post_render example',
- '//div[@class="rendered"]/div[text()][starts-with(.,"This markup was added")]' => 'This markup was added after rendering by a #post_render',
- '//div[@class="rendered"]/div[text()][starts-with(.,"This #suffix")]' => 'This #suffix was added by a #pre_render',
- );
- $this->assertRenderedText($xpath_array);
- }
-}
diff --git a/render_example/render_example.css b/render_example/render_example.css
deleted file mode 100644
index 0da7f30..0000000
--- a/render_example/render_example.css
+++ /dev/null
@@ -1,20 +0,0 @@
-.render-array {
- border: 2px solid #000;
- margin-top: 10px;
- padding-left: 5px;
- padding-top: 5px;
-}
-
-.render-header {
- font-size: large;
- font-style: italic;
-}
-
-.unrendered-label {
- font-style: italic;
- margin-top: 10px;
-}
-
-.rendered {
- background-color: #add8e6;
-}
diff --git a/render_example/render_example.info b/render_example/render_example.info
deleted file mode 100644
index e1b4605..0000000
--- a/render_example/render_example.info
+++ /dev/null
@@ -1,7 +0,0 @@
-name = Render example
-description = Demonstrates drupal_render's capabilities and altering render arrays
-package = Example modules
-core = 8.x
-; @todo Remove dependency?
-dependencies[] = devel
-stylesheets[all][] = render_example.css
diff --git a/render_example/render_example.info.yml b/render_example/render_example.info.yml
new file mode 100644
index 0000000..0788ec1
--- /dev/null
+++ b/render_example/render_example.info.yml
@@ -0,0 +1,12 @@
+name: Render example
+description: "Demonstrates drupal_render's capabilities and altering render arrays."
+type: module
+package: Example modules
+core: 8.x
+# @todo Remove dependency?
+dependencies:
+ - devel
+ - examples
+stylesheets:
+ all:
+ - css/render_example.css
\ No newline at end of file
diff --git a/render_example/render_example.install b/render_example/render_example.install
deleted file mode 100644
index a6bd4cc..0000000
--- a/render_example/render_example.install
+++ /dev/null
@@ -1,16 +0,0 @@
- 'Render Example',
- 'page callback' => 'render_example_info',
- 'access callback' => TRUE,
- );
- $items['examples/render_example/altering'] = array(
- 'title' => 'Alter pages and blocks',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('render_example_demo_form'),
- 'access arguments' => array('access devel information'),
- );
- $items['examples/render_example/arrays'] = array(
- 'title' => 'Render array examples',
- 'page callback' => 'render_example_arrays',
- 'access callback' => TRUE,
- );
-
- return $items;
-}
-
-
-/**
- * Simple basic information about the module; an entry point.
- */
-function render_example_info() {
- return t('The render example provides a
', array('!arrays' => url('examples/render_example/arrays'), '!alter' => url('examples/render_example/altering')));
-}
-
-
-/**
- * Provides a number of render arrays and show what they do.
- *
- * Each array is keyed by a description; it's returned for rendering at page
- * render time. It's easy to add new examples to this.
- *
- * The array items in $demos are intended to be raw, normal render arrays
- * that can be experimented with to end up with different outcomes.
- */
-function render_example_arrays() {
-
- $interval = 60; // Interval in seconds for cache update with #cache.
-
- $demos = array(
- // Demonstrate the simplest markup, a #markup element.
- t('Super simple #markup') => array(
- '#markup' => t('Some basic text in a #markup (shows basic markup and how it is rendered)'),
- ),
-
- // Shows how #prefix and #suffix can add markup into an array.
- t('Using #prefix and #suffix') => array(
- '#markup' => t('This one adds a prefix and suffix, which put a div around the item'),
- '#prefix' => '
(prefix)
',
- '#suffix' => '
(suffix)
',
- ),
-
- // When #theme is provided, it is the #theme function's job to figure out
- // the meaning of the render array. The #theme function receives the entire
- // element in $variables and must return it, where it will be the content
- // of '#children'. When a #theme or other function is provided, custom
- // properties can be invented and used as needed, as the #separator
- // property provided here.
- //
- // If #theme is not provided, either explicitly or by the underlying
- // element, then the children are rendered using their own properties and
- // the results go into #children.
- t('theme for an element') => array(
- 'child' => array(
- t('This is some text that should be put together'),
- t('This is some more text that we need'),
- ),
- '#separator' => ' | ', // Made up for this theme function.
- '#theme' => 'render_example_aggregate',
- ),
-
- // #theme_wrappers provides an array of theme functions which theme the
- // envelope or "wrapper" of a set of child elements. The theme function
- // finds its element children (the sub-arrays) already rendered in
- // '#children'.
- t('theme_wrappers demonstration') => array(
- 'child1' => array('#markup' => t('Markup for child1')),
- 'child2' => array('#markup' => t('Markup for child2')),
- '#theme_wrappers' => array('render_example_add_div', 'render_example_add_notes'),
- ),
-
- // Add '#pre_render' and '#post_render' handlers.
- // - '#pre_render' functions get access to the array before it is rendered
- // and can change it. This is similar to a theme function, but it is a
- // specific fixed function and changes the array in place rather than
- // rendering it..
- // - '#post_render' functions get access to the rendered content, but also
- // have the original array available.
- t('pre_render and post_render') => array(
- '#markup' => '' . t('markup for pre_render and post_render example') . '
',
- '#pre_render' => array('render_example_add_suffix'),
- '#post_render' => array('render_example_add_prefix'),
- ),
-
- // Cache an element for $interval seconds using #cache.
- // The assumption here is that this is an expensive item to render, perhaps
- // large or otherwise expensive. Of course here it's just a piece of markup,
- // so we don't get the value.
- //
- // #cache allows us to set
- // - 'keys', an array of strings that will create the string cache key.
- // - 'bin', the cache bin
- // - 'expire', the expire timestamp. Note that this is actually limited
- // to the granularity of a cron run.
- // - 'granularity', a bitmask determining at what level the caching is done
- // (user, role, page).
- t('cache demonstration') => array(
- // If your expensive function were to be executed here it would happen
- // on every page load regardless of the cache. The actual markup is
- // added via the #pre_render function, so that drupal_render() will only
- // execute the expensive function if this array has not been cached.
- '#markup' => '',
- '#pre_render' => array('render_example_cache_pre_render'),
- '#cache' => array(
- 'keys' => array('render_example', 'cache', 'demonstration'),
- 'bin' => 'cache',
- 'expire' => time() + $interval,
- 'granularity' => DRUPAL_CACHE_PER_PAGE | DRUPAL_CACHE_PER_ROLE,
- ),
- ),
- );
-
-
- // The rest of this function just places the above arrays in a context where
- // they can be rendered (hopefully attractively and usefully) on the page.
- $page_array = array();
- foreach ($demos as $key => $item) {
- $page_array[$key]['#theme_wrappers'] = array('render_array');
- $page_array[$key]['#description'] = $key;
-
- $page_array[$key]['unrendered'] = array(
- '#prefix' => '' . t('Unrendered array (as plain text and with a krumo version)') . ':
',
- '#type' => 'markup',
- '#markup' => htmlentities(drupal_var_export($item)),
- );
- $page_array[$key]['kpr'] = array(
- // The kpr() function is from devel module and is here only allow us
- // to output the array in a way that's easy to explore.
- '#markup' => kpr($item, TRUE),
- );
- $page_array[$key]['hr'] = array('#markup' => '
');
- $page_array[$key]['rendered'] = array($item);
- $page_array[$key]['rendered']['#prefix'] = 'Rendered version (light blue):
' . '';
- $page_array[$key]['rendered']['#suffix'] = '
';
- }
-
- return $page_array;
-}
+use Drupal\Core\Element;
+use Drupal\Core\Config;
/**
* A '#pre_render' function.
@@ -202,7 +46,10 @@ function render_example_cache_pre_render($element) {
*/
function render_example_cache_expensive() {
$interval = 60;
- $time_message = t('The current time was %time when this was cached. Updated every %interval seconds', array('%time' => date('r'), '%interval' => $interval));
+ $time_message = t('The current time was %time when this was cached. Updated every %interval seconds', array(
+ '%time' => date('r'),
+ '%interval' => $interval
+ ));
// Uncomment the following line to demonstrate that this function is not
// being run when the rendered array is cached.
// drupal_set_message($time_message);
@@ -245,81 +92,12 @@ function render_example_add_prefix($markup, $element) {
return $markup;
}
-/**
- * A #theme function.
- *
- * This #theme function has the responsibility of consolidating/rendering the
- * children's markup and returning it, where it will be placed in the
- * element's #children property.
- */
-function theme_render_example_aggregate($variables) {
- $output = '';
- foreach (element_children($variables['element']['child']) as $item) {
- $output .= $variables['element']['child'][$item] . $variables['element']['#separator'];
- }
- return $output;
-}
-
/*************** Altering Section **************************
* The following section of the example builds and arranges the altering
* example.
*/
/**
- * Builds the form that offers options of what items to show.
- */
-function render_example_demo_form($form, &$form_state) {
- $form['description'] = array(
- '#type' => 'markup',
- '#markup' => t('This example shows what render arrays look like in the building of a page. It will not work unless the user running it has the "access devel information" privilege. It shows both the actual arrays used to build a page or block and also the capabilities of altering the page late in its lifecycle.'),
- );
-
- $form['show_arrays'] = array(
- '#type' => 'fieldset',
- '#title' => t('Show render arrays'),
- );
-
- foreach (array('block', 'page') as $type) {
- $form['show_arrays']['render_example_show_' . $type] = array(
- '#type' => 'checkbox',
- '#title' => t('Show @type render arrays', array('@type' => $type)),
- '#default_value' => variable_get('render_example_show_' . $type, FALSE),
- );
- }
-
- $form['page_fiddling'] = array(
- '#type' => 'fieldset',
- '#title' => t('Make changes on page via hook_page_alter()'),
- );
- $form['page_fiddling']['render_example_note_about_render_arrays'] = array(
- '#title' => t('Add a note about render arrays to top of sidebar_first (if it exists)'),
- '#description' => t('Creates a simple render array that displays the use of #pre_render, #post_render, #theme, and #theme_wrappers.'),
- '#type' => 'checkbox',
- '#default_value' => variable_get('render_example_note_about_render_arrays', FALSE),
- );
- $form['page_fiddling']['render_example_move_navigation_menu'] = array(
- '#title' => t('Move the navigation menu to the top of the content area'),
- '#description' => t('Uses hook_page_alter() to move the navigation menu into another region.'),
- '#type' => 'checkbox',
- '#default_value' => variable_get('render_example_move_navigation_menu', FALSE),
- );
- $form['page_fiddling']['render_example_reverse_sidebar'] = array(
- '#title' => t('Reverse ordering of sidebar_first elements (if it exists) - will affect the above'),
- '#description' => t('Uses hook_page_alter() to reverse the ordering of items in sidebar_first'),
- '#type' => 'checkbox',
- '#default_value' => variable_get('render_example_reverse_sidebar', FALSE),
- );
- $form['page_fiddling']['render_example_prefix'] = array(
- '#title' => t('Use #prefix and #suffix to wrap a div around every block'),
- '#description' => t('Uses hook_page_alter to wrap all blocks with a div using #prefix and #suffix'),
- '#type' => 'checkbox',
- '#default_value' => variable_get('render_example_prefix'),
- );
-
- return system_settings_form($form);
-}
-
-/**
* Implements hook_page_alter().
*
* Alters the page in several different ways based on how the form has been
@@ -328,11 +106,12 @@ function render_example_demo_form($form, &$form_state) {
function render_example_page_alter(&$page) {
$original_page = $page;
+ $config = \Drupal::config('render_example.settings');
// Re-sort the sidebar in reverse order.
- if (variable_get('render_example_reverse_sidebar', FALSE) && !empty($page['sidebar_first'])) {
+ if ($config->get('render_example_reverse_sidebar') && !empty($page['sidebar_first'])) {
$page['sidebar_first'] = array_reverse($page['sidebar_first']);
- foreach (element_children($page['sidebar_first']) as $element) {
+ foreach (Element::children($page['sidebar_first']) as $element) {
// Reverse the weights if they exist.
if (!empty($page['sidebar_first'][$element]['#weight'])) {
$page['sidebar_first'][$element]['#weight'] *= -1;
@@ -343,7 +122,7 @@ function render_example_page_alter(&$page) {
// Add a list of items to the top of sidebar_first.
// This shows how #theme and #theme_wrappers work.
- if (variable_get('render_example_note_about_render_arrays', FALSE) && !empty($page['sidebar_first'])) {
+ if ($config->get('render_example_note_about_render_arrays') && !empty($page['sidebar_first'])) {
$items = array(
t('Render arrays are everywhere in D7'),
t('Leave content unrendered as much as possible'),
@@ -353,7 +132,6 @@ function render_example_page_alter(&$page) {
$note = array(
'#title' => t('Render Array Example'),
'#items' => $items,
-
// The functions in #pre_render get to alter the actual data before it
// gets rendered by the various theme functions.
'#pre_render' => array('render_example_change_to_ol'),
@@ -365,16 +143,18 @@ function render_example_page_alter(&$page) {
'#theme' => 'item_list',
// Then the theme operations in #theme_wrappers can wrap more around
// what #theme left in #chilren.
- '#theme_wrappers' => array('render_example_add_div', 'render_example_add_notes'),
+ '#theme_wrappers' => array(
+ 'render_example_add_div',
+ 'render_example_add_notes'
+ ),
'#weight' => -9999,
);
$page['sidebar_first']['render_array_note'] = $note;
$page['sidebar_first']['#sorted'] = FALSE;
}
-
// Move the navigation menu into the content area.
- if (variable_get('render_example_move_navigation_menu', FALSE) && !empty($page['sidebar_first']['system_navigation']) && !empty($page['content'])) {
+ if ($config->get('render_example_move_navigation_menu') && !empty($page['sidebar_first']['system_navigation']) && !empty($page['content'])) {
$page['content']['system_navigation'] = $page['sidebar_first']['system_navigation'];
$page['content']['system_navigation']['#weight'] = -99999;
unset($page['content']['#sorted']);
@@ -382,7 +162,7 @@ function render_example_page_alter(&$page) {
}
// Show the render array used to build the page render array display.
- if (variable_get('render_example_show_page', FALSE)) {
+ if ($config->get('render_example_show_page')) {
$form['render_example_page_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Page render array'),
@@ -400,9 +180,9 @@ function render_example_page_alter(&$page) {
}
// Add render array to the bottom of each block
- if (variable_get('render_example_show_block', FALSE)) {
- foreach (element_children($page) as $region_name) {
- foreach (element_children($page[$region_name]) as $block_name) {
+ if ($config->get('render_example.show_block')) {
+ foreach (Element::children($page) as $region_name) {
+ foreach (Element::children($page[$region_name]) as $block_name) {
// Push the block down a level so we can add another block after it.
$old_block = $page[$region_name][$block_name];
@@ -425,16 +205,16 @@ function render_example_page_alter(&$page) {
);
// Add the new block that contains the render array.
- $page[$region_name][$block_name]['render_example_block_render_array'] = drupal_get_form('render_example_embedded_form', $form);
+ $page[$region_name][$block_name]['render_example_block_render_array'] = drupal_get_form('render_example_embedded_form', $form);
$page[$region_name][$block_name]['render_example_block_render_array']['#weight'] = 999;
}
}
}
// Add #prefix and #suffix to a block to wrap a div around it.
- if (variable_get('render_example_prefix', FALSE)) {
- foreach (element_children($page) as $region_name) {
- foreach (element_children($page[$region_name]) as $block_name) {
+ if ($config->get('render_example_prefix')) {
+ foreach (Element::children($page) as $region_name) {
+ foreach (Element::children($page[$region_name]) as $block_name) {
$block = &$page[$region_name][$block_name];
$block['#prefix'] = 'Prefixed
';
$block['#suffix'] = '
Block suffix ';
@@ -480,41 +260,8 @@ function render_example_theme() {
'render element' => 'element',
),
);
- return $items;
-}
-
-/**
- * Wraps a div around the already-rendered #children.
- */
-function theme_render_example_add_div($variables) {
- $element = $variables['element'];
- $output = '';
- $output .= $element['#children'];
- $output .= '
';
- return $output;
-}
-
-/**
- * Wraps a div and add a little text after the rendered #children.
- */
-function theme_render_example_add_notes($variables) {
- $element = $variables['element'];
- $output = '';
- $output .= $element['#children'];
- $output .= '' . t('This is a note added by a #theme_wrapper') . '';
- $output .= '
';
- return $output;
-}
-
-/**
- * Themes the render array (from the demonstration page).
- */
-function theme_render_array($variables) {
- $heading = '';
-
- $rendered = '' . $heading . $variables['element']['#children'] . '
';
- return $rendered;
+ return $items;
}
/**
diff --git a/render_example/render_example.routing.yml b/render_example/render_example.routing.yml
new file mode 100644
index 0000000..16e9436
--- /dev/null
+++ b/render_example/render_example.routing.yml
@@ -0,0 +1,21 @@
+render_example.description:
+ path: 'examples/render_example'
+ defaults:
+ _controller: '\Drupal\render_example\Controller\RenderExampleController::description'
+ requirements:
+ _access: 'TRUE'
+
+render_example.altering:
+ path: 'examples/render_example/altering'
+ defaults:
+ _form: '\Drupal\render_example\Form\RenderExampleDemoForm'
+ _title: 'Alter pages and blocks'
+ requirements:
+ _access: 'TRUE'
+
+render_example.arrays:
+ path: 'examples/render_example/arrays'
+ defaults:
+ _controller: '\Drupal\render_example\Controller\RenderExampleController::arrays'
+ requirements:
+ _access: 'TRUE'
\ No newline at end of file
diff --git a/render_example/src/Controller/RenderExampleController.php b/render_example/src/Controller/RenderExampleController.php
new file mode 100644
index 0000000..013b866
--- /dev/null
+++ b/render_example/src/Controller/RenderExampleController.php
@@ -0,0 +1,137 @@
+ t('The render example provides a ', array(
+ '!arrays' => \Drupal::url('render_example.arrays'),
+ '!alter' => \Drupal::url('render_example.altering')
+ )),
+ );
+
+ return $output;
+ }
+
+ public function arrays() {
+ $interval = 60; // Interval in seconds for cache update with #cache.
+
+ $demos = array(
+ // Demonstrate the simplest markup, a #markup element.
+ t('Super simple #markup') => array(
+ '#markup' => t('Some basic text in a #markup (shows basic markup and how it is rendered)'),
+ ),
+ // Shows how #prefix and #suffix can add markup into an array.
+ t('Using #prefix and #suffix') => array(
+ '#markup' => t('This one adds a prefix and suffix, which put a div around the item'),
+ '#prefix' => '
(prefix)
',
+ '#suffix' => '
(suffix)
',
+ ),
+ // When #theme is provided, it is the #theme function's job to figure out
+ // the meaning of the render array. The #theme function receives the entire
+ // element in $variables and must return it, where it will be the content
+ // of '#children'. When a #theme or other function is provided, custom
+ // properties can be invented and used as needed, as the #separator
+ // property provided here.
+ //
+ // If #theme is not provided, either explicitly or by the underlying
+ // element, then the children are rendered using their own properties and
+ // the results go into #children.
+ t('theme for an element') => array(
+ 'child' => array(
+ t('This is some text that should be put together'),
+ t('This is some more text that we need'),
+ ),
+ '#separator' => ' | ', // Made up for this theme function.
+ '#theme' => 'render_example_aggregate',
+ ),
+ // #theme_wrappers provides an array of theme functions which theme the
+ // envelope or "wrapper" of a set of child elements. The theme function
+ // finds its element children (the sub-arrays) already rendered in
+ // '#children'.
+ t('theme_wrappers demonstration') => array(
+ 'child1' => array('#markup' => t('Markup for child1')),
+ 'child2' => array('#markup' => t('Markup for child2')),
+ '#theme_wrappers' => array(
+ 'render_example_add_div',
+ 'render_example_add_notes'
+ ),
+ ),
+ // Add '#pre_render' and '#post_render' handlers.
+ // - '#pre_render' functions get access to the array before it is rendered
+ // and can change it. This is similar to a theme function, but it is a
+ // specific fixed function and changes the array in place rather than
+ // rendering it..
+ // - '#post_render' functions get access to the rendered content, but also
+ // have the original array available.
+ t('pre_render and post_render') => array(
+ '#markup' => '' . t('markup for pre_render and post_render example') . '
',
+ '#pre_render' => array('render_example_add_suffix'),
+ '#post_render' => array('render_example_add_prefix'),
+ ),
+ // Cache an element for $interval seconds using #cache.
+ // The assumption here is that this is an expensive item to render, perhaps
+ // large or otherwise expensive. Of course here it's just a piece of markup,
+ // so we don't get the value.
+ //
+ // #cache allows us to set
+ // - 'keys', an array of strings that will create the string cache key.
+ // - 'bin', the cache bin
+ // - 'expire', the expire timestamp. Note that this is actually limited
+ // to the granularity of a cron run.
+ // - 'granularity', a bitmask determining at what level the caching is done
+ // (user, role, page).
+ t('cache demonstration') => array(
+ // If your expensive function were to be executed here it would happen
+ // on every page load regardless of the cache. The actual markup is
+ // added via the #pre_render function, so that drupal_render() will only
+ // execute the expensive function if this array has not been cached.
+ '#markup' => '',
+ '#pre_render' => array('render_example_cache_pre_render'),
+ '#cache' => array(
+ 'keys' => array('render_example', 'cache', 'demonstration'),
+ 'bin' => 'cache',
+ 'expire' => time() + $interval,
+ 'granularity' => DRUPAL_CACHE_PER_PAGE | DRUPAL_CACHE_PER_ROLE,
+ ),
+ ),
+ );
+
+
+ // The rest of this function just places the above arrays in a context where
+ // they can be rendered (hopefully attractively and usefully) on the page.
+ $page_array = array();
+ foreach ($demos as $key => $item) {
+ $page_array[$key]['#theme_wrappers'] = array('render_array');
+ $page_array[$key]['#description'] = $key;
+
+ $page_array[$key]['unrendered'] = array(
+ '#prefix' => '' . t('Unrendered array (as plain text and with a krumo version)') . ':
',
+ '#type' => 'markup',
+ '#markup' => htmlentities(Variable::export($item)),
+ );
+ $page_array[$key]['kpr'] = array(
+ // The kpr() function is from devel module and is here only allow us
+ // to output the array in a way that's easy to explore.
+ '#markup' => kpr($item, TRUE),
+ );
+ $page_array[$key]['hr'] = array('#markup' => '
');
+ $page_array[$key]['rendered'] = array($item);
+ $page_array[$key]['rendered']['#prefix'] = 'Rendered version (light blue):
' . '';
+ $page_array[$key]['rendered']['#suffix'] = '
';
+ }
+
+ return $page_array;
+ }
+
+}
\ No newline at end of file
diff --git a/render_example/src/Form/RenderExampleDemoForm.php b/render_example/src/Form/RenderExampleDemoForm.php
new file mode 100644
index 0000000..6f500d9
--- /dev/null
+++ b/render_example/src/Form/RenderExampleDemoForm.php
@@ -0,0 +1,120 @@
+config('render_example.settings');
+
+ $form['description'] = array(
+ '#type' => 'markup',
+ '#markup' => t('This example shows what render arrays look like in the building of a page. It will not work unless the user running it has the "access devel information" privilege. It shows both the actual arrays used to build a page or block and also the capabilities of altering the page late in its lifecycle.'),
+ );
+
+ $form['show_arrays'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Show render arrays'),
+ );
+
+ foreach ($this->show_arrays as $type) {
+ $form['show_arrays']['render_example_show_' . $type] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Show @type render arrays', array('@type' => $type)),
+ '#default_value' => $config->get("render_example.show_{$type}"),
+ );
+ }
+
+ $form['page_fiddling'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Make changes on page via hook_page_alter()'),
+ );
+ $form['page_fiddling']['render_example_note_about_render_arrays'] = array(
+ '#title' => t('Add a note about render arrays to top of sidebar_first (if it exists)'),
+ '#description' => t('Creates a simple render array that displays the use of #pre_render, #post_render, #theme, and #theme_wrappers.'),
+ '#type' => 'checkbox',
+ '#default_value' => $config->get('render_example.note_about_render_arrays'),
+ );
+ $form['page_fiddling']['render_example_move_navigation_menu'] = array(
+ '#title' => t('Move the navigation menu to the top of the content area'),
+ '#description' => t('Uses hook_page_alter() to move the navigation menu into another region.'),
+ '#type' => 'checkbox',
+ '#default_value' => $config->get('render_example.move_navigation_menu'),
+ );
+ $form['page_fiddling']['render_example_reverse_sidebar'] = array(
+ '#title' => t('Reverse ordering of sidebar_first elements (if it exists) - will affect the above'),
+ '#description' => t('Uses hook_page_alter() to reverse the ordering of items in sidebar_first'),
+ '#type' => 'checkbox',
+ '#default_value' => $config->get('render_example.reverse_sidebar'),
+ );
+ $form['page_fiddling']['render_example_prefix'] = array(
+ '#title' => t('Use #prefix and #suffix to wrap a div around every block'),
+ '#description' => t('Uses hook_page_alter to wrap all blocks with a div using #prefix and #suffix'),
+ '#type' => 'checkbox',
+ '#default_value' => $config->get('render_example.prefix'),
+ );
+
+ return parent::buildForm($form, $form_state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getEditableConfigNames() {
+ return ['render_example.settings'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $values = $form_state->getValues();
+
+ $config = $this->config('render_example.settings');
+ foreach ($this->show_arrays as $type) {
+ $config->set("render_example.show_{$type}", $values["render_example_show_{$type}"])
+ ->save();
+ }
+ $config->set('render_example.note_about_render_arrays', $values['render_example_note_about_render_arrays'])
+ ->save();
+ $config->set('render_example.move_navigation_menu', $values['render_example_move_navigation_menu'])
+ ->save();
+ $config->set('render_example.reverse_sidebar', $values['render_example_reverse_sidebar'])
+ ->save();
+ $config->set('render_example.prefix', $values['render_example_prefix'])
+ ->save();
+
+ parent::submitForm($form, $form_state);
+ }
+
+}
\ No newline at end of file
diff --git a/render_example/src/Tests/RenderExampleTest.php b/render_example/src/Tests/RenderExampleTest.php
new file mode 100644
index 0000000..35d3bd2
--- /dev/null
+++ b/render_example/src/Tests/RenderExampleTest.php
@@ -0,0 +1,140 @@
+xpath($xpath);
+ $this->assertTrue(!empty($result), format_string('Found xpath %xpath', array('%xpath' => $xpath)));
+ }
+ }
+
+ /**
+ * Asserts that the string value of the result is the same as the passed text.
+ *
+ * @param $xpath_array
+ * Array of keyed arrays of tests to be made. Each child array consists of
+ * $xpath => $expected_text
+ */
+ protected function assertRenderedText($xpath_array) {
+ foreach ($xpath_array as $xpath => $text) {
+ $result = $this->xpath($xpath);
+ $this->assertTrue((string) $result[0][0] == $text, format_string('%ary selects text %text', array(
+ '%ary' => $xpath,
+ '%text' => $text
+ )));
+ }
+ }
+
+ /**
+ * Login user, create an example node, and test blog functionality through the admin and user interfaces.
+ */
+ public function testRenderExampleBasic() {
+ // Create a user that can access devel information and log in.
+ $web_user = $this->drupalCreateUser(array(
+ 'access devel information',
+ 'access content'
+ ));
+ $this->drupalLogin($web_user);
+
+ // Turn on the block render array display and make sure it shows up.
+ $edit = array(
+ 'render_example_show_block' => TRUE,
+ );
+ $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+
+ $xpath_array = array(
+ "//div[@id='sidebar-first']//fieldset[starts-with(@id, 'edit-render-example-block-fieldset')]",
+ '//*[@id="content"]//fieldset[contains(@id,"edit-render-example-block-fieldset")]',
+ );
+ $this->assertRenderResults($xpath_array);
+
+
+ // Turn off block render array display and turn on the page render array
+ // display.
+ $edit = array(
+ 'render_example_show_page' => TRUE,
+ 'render_example_show_block' => FALSE,
+ );
+ $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+
+ $xpath_array = array(
+ '//*[@id="content"]//fieldset[starts-with(@id,"edit-render-example-page-fieldset")]',
+ );
+ $this->assertRenderResults($xpath_array);
+
+ // Add note about render arrays to the top of sidebar_first.
+ $edit = array(
+ 'render_example_note_about_render_arrays' => TRUE,
+ );
+ $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+ $xpath_array = array(
+ '//*[@id="sidebar-first"]//ol//li[starts-with(.,"Render arrays are everywhere")]',
+ );
+ $this->assertRenderResults($xpath_array);
+
+ // Move the navigation menu to the top of the content area.
+ $edit = array(
+ 'render_example_move_navigation_menu' => TRUE,
+ );
+ $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+ $xpath_array = array(
+ '//*[@id="content"]//h2[starts-with(.,"Navigation")]',
+ );
+ $this->assertRenderResults($xpath_array);
+
+ // Skip a test for reversing order of sidebar_first as I think it would
+ // be too fragile.
+
+ // Test the addition of #prefix and #suffix
+ $edit = array(
+ 'render_example_prefix' => TRUE,
+ );
+ $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
+ $xpath_array = array(
+ '//*[@id="sidebar-first"]//*[contains(@class, "block-prefix")]/span[contains(@class, "block-suffix")]',
+ );
+ $this->assertRenderResults($xpath_array);
+
+ // Test some rendering facets of the various render examples
+ $this->drupalGet('examples/render_example/arrays');
+ $content = $this->xpath('//*[@class="render-array"][1]');
+
+ $xpath_array = array(
+ '//div[@class="rendered"][starts-with(.,"Some basic text in a #markup")]' => 'Some basic text in a #markup (shows basic markup and how it is rendered)',
+ '//div[@class="rendered"][starts-with(.,"This is some text that should be put to")]' => 'This is some text that should be put together | This is some more text that we need | ',
+ '//div[@class="rendered"][starts-with(.,"The current time was")]' => 'The current time was when this was cached. Updated every seconds',
+ '//div[@class="rendered"]/div[text()][starts-with(.,"(prefix)This one")]' => '(prefix)This one adds a prefix and suffix, which put a div around the item(suffix)',
+ '//div[@class="rendered"]/div[text()][starts-with(.,"markup for pre_")]' => 'markup for pre_render and post_render example',
+ '//div[@class="rendered"]/div[text()][starts-with(.,"This markup was added")]' => 'This markup was added after rendering by a #post_render',
+ '//div[@class="rendered"]/div[text()][starts-with(.,"This #suffix")]' => 'This #suffix was added by a #pre_render',
+ );
+ $this->assertRenderedText($xpath_array);
+ }
+
+}
\ No newline at end of file
diff --git a/render_example/templates/render-array.html.twig b/render_example/templates/render-array.html.twig
new file mode 100644
index 0000000..d2a8bed
--- /dev/null
+++ b/render_example/templates/render-array.html.twig
@@ -0,0 +1,19 @@
+{#
+/**
+ * @file
+ * Default theme implementation to render_array.
+ *
+ * Themes the render array (from the demonstration page).
+ *
+ * Available variables:
+ * - element: Element that will be rendered.
+ *
+ * @ingroup themeable
+ */
+#}
+
+
+ {{ element['#children'] }}
+
\ No newline at end of file
diff --git a/render_example/templates/render-example-add-div.html.twig b/render_example/templates/render-example-add-div.html.twig
new file mode 100644
index 0000000..6a0e210
--- /dev/null
+++ b/render_example/templates/render-example-add-div.html.twig
@@ -0,0 +1,16 @@
+{#
+/**
+ * @file
+ * Default theme implementation to render_example_add_div.
+ *
+ * Wraps a div around the already-rendered #children.
+ *
+ * Available variables:
+ * - element: Element that will be rendered.
+ *
+ * @ingroup themeable
+ */
+#}
+
+ {{ element['#children'] }}
+
\ No newline at end of file
diff --git a/render_example/templates/render-example-add-notes.html.twig b/render_example/templates/render-example-add-notes.html.twig
new file mode 100644
index 0000000..ab3676e
--- /dev/null
+++ b/render_example/templates/render-example-add-notes.html.twig
@@ -0,0 +1,17 @@
+{#
+/**
+ * @file
+ * Default theme implementation to render_example_add_notes.
+ *
+ * Wraps a div and add a little text after the rendered #children.
+ *
+ * Available variables:
+ * - element: Element that will be rendered.
+ *
+ * @ingroup themeable
+ */
+#}
+
+ {{ element['#children'] }}
+ {% trans %}This is a note added by a #theme_wrapper{% endtrans %}
+
\ No newline at end of file
diff --git a/render_example/templates/render-example-aggregate.html.twig b/render_example/templates/render-example-aggregate.html.twig
new file mode 100644
index 0000000..3b920fc
--- /dev/null
+++ b/render_example/templates/render-example-aggregate.html.twig
@@ -0,0 +1,17 @@
+{#
+/**
+ * @file
+ * Default theme implementation to render_example_aggregate.
+ *
+ * The contents are rendered above feed listings when browsing source feeds.
+ * For example, "example.com/aggregator/sources/1".
+ *
+ * Available variables:
+ * - element: Element that will be rendered.
+ *
+ * @ingroup themeable
+ */
+#}
+{%- for item in element.child -%}
+ {{ item }} {{ element['#separator'] }}
+{%- endfor -%}
\ No newline at end of file