diff --git a/composer.json b/composer.json
index 26d4063..f0b4f77 100644
--- a/composer.json
+++ b/composer.json
@@ -8,5 +8,8 @@
"documentation": "https://api.drupal.org/api/examples",
"source": "http://cgit.drupalcode.org/examples"
},
+ "suggest": {
+ "drupal/devel": "Some modules will be able to pretty-print PHP with this module."
+ },
"license": "GPL-2.0+"
}
diff --git a/render_example/config/install/render_example.settings.yml b/render_example/config/install/render_example.settings.yml
new file mode 100644
index 0000000..f1df332
--- /dev/null
+++ b/render_example/config/install/render_example.settings.yml
@@ -0,0 +1,6 @@
+show_block: false
+show_page: false
+note_about_render_arrays: false
+move_breadcrumbs: false
+reverse_sidebar: false
+wrap_blocks: false
diff --git a/render_example/config/schema/render_example.schema.yml b/render_example/config/schema/render_example.schema.yml
new file mode 100644
index 0000000..ca8b19c
--- /dev/null
+++ b/render_example/config/schema/render_example.schema.yml
@@ -0,0 +1,16 @@
+render_example.settings:
+ type: config_object
+ label: 'Render Example Settings'
+ mapping:
+ show_block:
+ type: boolean
+ show_page:
+ type: boolean
+ note_about_render_arrays:
+ type: boolean
+ move_breadcrumbs:
+ type: boolean
+ reverse_sidebar:
+ type: boolean
+ wrap_blocks:
+ type: boolean
diff --git a/render_example/render_example.info.yml b/render_example/render_example.info.yml
index 79238fa..ddf0447 100644
--- a/render_example/render_example.info.yml
+++ b/render_example/render_example.info.yml
@@ -4,4 +4,7 @@ description: Provides examples demonstrating Drupal's Render API.
package: Example modules
core: 8.x
dependencies:
+ - core:block
+ - core:node
+ - core:user
- examples:examples
diff --git a/render_example/render_example.links.menu.yml b/render_example/render_example.links.menu.yml
new file mode 100644
index 0000000..76afbc3
--- /dev/null
+++ b/render_example/render_example.links.menu.yml
@@ -0,0 +1,19 @@
+render_example.description:
+ title: Render Example
+ description: Examples of building and altering render arrays.
+ route_name: render_example.description
+ expanded: TRUE
+
+render_example.altering:
+ title: Altering Render Arrays
+ description: Using hooks and callbacks to alter render arrays.
+ route_name: render_example.altering
+ parent: render_example.description
+ weight: -9
+
+render_example.arrays:
+ title: Building Render Arrays
+ description: Building render arrays in controllers.
+ route_name: render_example.arrays
+ parent: render_example.description
+ weight: -8
diff --git a/render_example/render_example.module b/render_example/render_example.module
index 3cfd633..79524b4 100644
--- a/render_example/render_example.module
+++ b/render_example/render_example.module
@@ -140,6 +140,11 @@ function render_example_add_suffix(array $element) {
* represents the page currently being viewed.
*/
function render_example_preprocess_page(&$variables) {
+ // Only modify the 'altering' page.
+ if (\Drupal::routeMatch()->getRouteName() != 'render_example.altering') {
+ return;
+ }
+
$config = \Drupal::config('render_example.settings');
// Preprocess hooks are invoked by the theme layer, and are used to give
@@ -159,12 +164,8 @@ function render_example_preprocess_page(&$variables) {
// printing it to the screen.
$page = &$variables['page'];
- if (\Drupal::routeMatch()->getRouteName() == 'render_example.altering') {
-
- }
-
// Move the breadcrumbs into the content area.
- if ($config->get('render_example.move_breadcrumbs') && !empty($page['breadcrumb']) && !empty($page['content'])) {
+ if ($config->get('move_breadcrumbs') && !empty($page['breadcrumb']) && !empty($page['content'])) {
$page['content']['breadcrumb'] = $page['breadcrumb'];
unset($page['breadcrumb']);
$page['content']['breadcrumb']['#weight'] = -99999;
@@ -174,7 +175,7 @@ function render_example_preprocess_page(&$variables) {
}
// Re-sort the contents of the sidebar in reverse order.
- if ($config->get('render_example.reverse_sidebar') && !empty($page['sidebar_first'])) {
+ if ($config->get('reverse_sidebar') && !empty($page['sidebar_first'])) {
$page['sidebar_first'] = array_reverse($page['sidebar_first']);
foreach (Element::children($page['sidebar_first']) as $element) {
// Reverse the weights if they exist.
@@ -189,7 +190,7 @@ function render_example_preprocess_page(&$variables) {
// Show the render array used to build the current page.
// This relies on the Devel module's variable dumper service.
// https://wwww.drupal.org/project/devel
- if (Drupal::moduleHandler()->moduleExists('devel') && $config->get('render_example.show_page')) {
+ if (Drupal::moduleHandler()->moduleExists('devel') && $config->get('show_page')) {
$page['content']['page_render_array'] = [
'#type' => 'markup',
'#prefix' => '
around it.
- if ($config->get('render_example.prefix')) {
+ if ($config->get('wrap_blocks')) {
$variables['content']['#prefix'] = '
' . t('Prefixed') . '
';
$variables['content']['#suffix'] = '
' . t('Block suffix') . '';
}
// Show the render array used to build each block if the Devel module is
// installed and the feature is enabled.
- if (Drupal::moduleHandler()->moduleExists('devel') && $config->get('render_example.show_block')) {
+ if (Drupal::moduleHandler()->moduleExists('devel') && $config->get('show_block')) {
$variables['content']['block_render_array'] = [
'#type' => 'markup',
'#prefix' => '
' . t('The block render array for @block_id.', ['@block_id' => $variables['plugin_id']]) . '
',
diff --git a/render_example/render_example.routing.yml b/render_example/render_example.routing.yml
index fff4a60..5f93efa 100644
--- a/render_example/render_example.routing.yml
+++ b/render_example/render_example.routing.yml
@@ -1,21 +1,21 @@
render_example.description:
- path: 'examples/render_example'
+ path: 'examples/render-example'
defaults:
_controller: '\Drupal\render_example\Controller\RenderExampleController::description'
requirements:
- _access: 'access content'
+ _permission: 'access content'
render_example.altering:
- path: 'examples/render_example/altering'
+ path: 'examples/render-example/altering'
defaults:
_form: '\Drupal\render_example\Form\RenderExampleDemoForm'
_title: 'Alter pages and blocks'
requirements:
- _access: 'access content'
+ _permission: 'access content'
render_example.arrays:
- path: 'examples/render_example/arrays'
+ path: 'examples/render-example/arrays'
defaults:
_controller: '\Drupal\render_example\Controller\RenderExampleController::arrays'
requirements:
- _access: 'access content'
+ _permission: 'access content'
diff --git a/render_example/src/Controller/RenderExampleController.php b/render_example/src/Controller/RenderExampleController.php
index 694f2f8..61ea14e 100644
--- a/render_example/src/Controller/RenderExampleController.php
+++ b/render_example/src/Controller/RenderExampleController.php
@@ -20,15 +20,8 @@ use Drupal\Core\Session\AccountInterface;
* @ingroup render_example
*/
class RenderExampleController extends ControllerBase {
- use DescriptionTemplateTrait;
-
- /**
- * Current user.
- *
- * @var \Drupal\user\UserInterface
- */
- protected $currentUser;
+ use DescriptionTemplateTrait;
/**
* Constructs a new BlockController instance.
@@ -422,23 +415,25 @@ class RenderExampleController extends ControllerBase {
foreach (Element::children($element) as $key) {
$child = $element[$key];
unset($element[$key]);
- $element[$key] = [
- // The value from the #description property will be used as a title
- // for this element in the final output.
- 'description' => [
- '#markup' => $child['#description'],
- ],
- // Move the original element to 'rendered'. The rendering process is
- // recursive so this will still be located, and rendered to HTML.
- 'rendered' => $child,
- // Export the element definition as a string of text so we can display
- // the array that was used to create the rendered output just below the
- // output.
- 'unrendered' => [
- '#markup' => htmlentities(Variable::export($child)),
- ],
- '#theme' => 'render_array',
- ];
+ if (isset($child['#description'])) {
+ $element[$key] = [
+ // The value from the #description property will be used as a title
+ // for this element in the final output.
+ 'description' => [
+ '#markup' => $child['#description'],
+ ],
+ // Move the original element to 'rendered'. The rendering process is
+ // recursive so this will still be located, and rendered to HTML.
+ 'rendered' => $child,
+ // Export the element definition as a string of text so we can display
+ // the array that was used to create the rendered output just below the
+ // output.
+ 'unrendered' => [
+ '#markup' => htmlentities(Variable::export($child)),
+ ],
+ '#theme' => 'render_array',
+ ];
+ }
}
// Return our modified version of the original $element.
diff --git a/render_example/src/Element/Marquee.php b/render_example/src/Element/Marquee.php
index 3ec03e7..1a5c301 100644
--- a/render_example/src/Element/Marquee.php
+++ b/render_example/src/Element/Marquee.php
@@ -40,7 +40,6 @@ class Marquee extends RenderElement {
* {@inheritdoc}
*/
public function getInfo() {
- $class = get_class($this);
// Returns an array of default properties that will be merged with any
// properties defined in a render array when using this element type.
@@ -52,7 +51,7 @@ class Marquee extends RenderElement {
// Define a default #pre_render method. We will use this to handle
// additional processing for the custom attributes we add below.
'#pre_render' => [
- [$class, 'preRenderMarquee'],
+ [self::class, 'preRenderMarquee'],
],
// This is a custom property for our element type. We set it to blank by
// default. The expectation is that a user will add the content that they
diff --git a/render_example/src/Form/RenderExampleDemoForm.php b/render_example/src/Form/RenderExampleDemoForm.php
index 1460a4c..539c0be 100644
--- a/render_example/src/Form/RenderExampleDemoForm.php
+++ b/render_example/src/Form/RenderExampleDemoForm.php
@@ -8,6 +8,7 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
+
/**
* Provides the form for toggling module features on and off.
*
@@ -63,14 +64,14 @@ class RenderExampleDemoForm extends ConfigFormBase {
'render_example_show_block' => [
'#type' => 'checkbox',
'#title' => $this->t('Show block render arrays'),
- '#default_value' => $config->get('render_example.show_block'),
+ '#default_value' => $config->get('show_block'),
// Only enable this option if the Devel module is enabled.
'#access' => $this->moduleHandler->moduleExists('devel'),
],
'render_example_show_page' => [
'#type' => 'checkbox',
'#title' => $this->t('Show page render arrays'),
- '#default_value' => $config->get('render_example.show_page'),
+ '#default_value' => $config->get('show_page'),
// Only enable this option if the Devel module is enabled.
'#access' => $this->moduleHandler->moduleExists('devel'),
],
@@ -89,19 +90,19 @@ class RenderExampleDemoForm extends ConfigFormBase {
'#title' => t('Move the breadcrumbs to the top of the content area'),
'#description' => t('Uses hook_preprocess_page() to move the breadcrumbs into another region.'),
'#type' => 'checkbox',
- '#default_value' => $config->get('render_example.move_breadcrumbs'),
+ '#default_value' => $config->get('move_breadcrumbs'),
],
'render_example_reverse_sidebar' => [
'#title' => t('Reverse ordering of sidebar_first elements (if it exists)'),
'#description' => t('Uses hook_preprocess_page() to reverse the ordering of items in sidebar_first'),
'#type' => 'checkbox',
- '#default_value' => $config->get('render_example.reverse_sidebar'),
+ '#default_value' => $config->get('reverse_sidebar'),
],
- 'render_example_prefix' => [
+ 'render_example_wrap_blocks' => [
'#title' => t('Use #prefix and #suffix to wrap a div around every block'),
'#description' => t('Uses hook_block_view_alter() to wrap all blocks with a div using #prefix and #suffix'),
'#type' => 'checkbox',
- '#default_value' => $config->get('render_example.prefix'),
+ '#default_value' => $config->get('wrap_blocks'),
],
];
@@ -273,12 +274,11 @@ class RenderExampleDemoForm extends ConfigFormBase {
$values = $form_state->getValues();
$config = $this->config('render_example.settings');
- $config->set('render_example.show_block', $values['render_example_show_block'])->save();
- $config->set('render_example.show_page', $values['render_example_show_page'])->save();
- $config->set('render_example.note_about_render_arrays', $values['render_example_note_about_render_arrays'])->save();
- $config->set('render_example.move_breadcrumbs', $values['render_example_move_breadcrumbs'])->save();
- $config->set('render_example.reverse_sidebar', $values['render_example_reverse_sidebar'])->save();
- $config->set('render_example.prefix', $values['render_example_prefix'])->save();
+ $config->set('show_block', $values['render_example_show_block'])->save();
+ $config->set('show_page', $values['render_example_show_page'])->save();
+ $config->set('move_breadcrumbs', $values['render_example_move_breadcrumbs'])->save();
+ $config->set('reverse_sidebar', $values['render_example_reverse_sidebar'])->save();
+ $config->set('wrap_blocks', $values['render_example_wrap_blocks'])->save();
parent::submitForm($form, $form_state);
}
diff --git a/render_example/src/Tests/RenderExampleTest.php b/render_example/src/Tests/RenderExampleTest.php
deleted file mode 100644
index c292887..0000000
--- a/render_example/src/Tests/RenderExampleTest.php
+++ /dev/null
@@ -1,142 +0,0 @@
-xpath($xpath);
- $this->assertTrue(!empty($result), format_string('Found xpath %xpath', ['%xpath' => $xpath]));
- }
- }
-
- /**
- * Asserts that the string value of the result is the same as the passed text.
- *
- * @param string[] $xpath_array
- * Array of keyed arrays of tests to be made. Each child array consists of
- * $xpath => $expected_text.
- */
- protected function assertRenderedText(array $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', [
- '%ary' => $xpath,
- '%text' => $text,
- ]));
- }
- }
-
- /**
- * Basic functional test of render_example module.
- *
- * - Login user.
- * - Create an example node.
- * - 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([
- 'access devel information',
- 'access content',
- ]);
- $this->drupalLogin($web_user);
-
- // Turn on the block render array display and make sure it shows up.
- $edit = [
- 'render_example_show_block' => TRUE,
- ];
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
-
- $xpath_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 = [
- 'render_example_show_page' => TRUE,
- 'render_example_show_block' => FALSE,
- ];
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
-
- $xpath_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 = [
- 'render_example_note_about_render_arrays' => TRUE,
- ];
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
- $xpath_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 = [
- 'render_example_move_navigation_menu' => TRUE,
- ];
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
- $xpath_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 = [
- 'render_example_prefix' => TRUE,
- ];
- $this->drupalPost('examples/render_example/altering', $edit, t('Save configuration'));
- $xpath_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 = [
- '//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/tests/src/Functional/RenderExampleMenuTest.php b/render_example/tests/src/Functional/RenderExampleMenuTest.php
new file mode 100644
index 0000000..f2dc164
--- /dev/null
+++ b/render_example/tests/src/Functional/RenderExampleMenuTest.php
@@ -0,0 +1,64 @@
+drupalLogin(
+ $this->createUser(['access content'])
+ );
+
+ $assertion = $this->assertSession();
+
+ // Get the front page, which should only have the links in the sidebar.
+ $this->drupalGet('');
+ foreach ($links as $path) {
+ $assertion->linkByHrefExists($path);
+ }
+
+ // Get each path and verify a 200 response.
+ foreach ($links as $path) {
+ $this->drupalGet($path);
+ $assertion->statusCodeEquals(200);
+ }
+ }
+
+}
diff --git a/render_example/tests/src/Functional/RenderExampleTest.php b/render_example/tests/src/Functional/RenderExampleTest.php
new file mode 100644
index 0000000..874d074
--- /dev/null
+++ b/render_example/tests/src/Functional/RenderExampleTest.php
@@ -0,0 +1,126 @@
+createUser([
+ 'access content',
+ ]);
+ $this->drupalLogin($web_user);
+
+ $session = $this->assertSession();
+
+ $this->drupalGet('examples/render-example/altering');
+ // Make sure we're telling the user about devel.
+ $session->pageTextContains('Install the Devel module (https://www.drupal.org/project/devel) to enable additional demonstration features.');
+
+ // Test moving the breadcrumb to the top of the content region. Since we
+ // just installed render_example and the config defaults to FALSE for all
+ // the alter options, we shouldn't have to manage state before making
+ // assertions.
+ $breadcrumb_xpath = "//main[@id='content']//div[contains(@class, 'block-system-breadcrumb-block')]";
+ $this->assertEmpty($this->xpath($breadcrumb_xpath));
+ // Move the breadcrumbs to content region.
+ $this->drupalPostForm(
+ 'examples/render-example/altering',
+ [
+ 'render_example_move_breadcrumbs' => TRUE,
+ 'render_example_reverse_sidebar' => FALSE,
+ 'render_example_wrap_blocks' => FALSE,
+ ],
+ t('Save configuration')
+ );
+ $this->assertNotEmpty($this->xpath($breadcrumb_xpath));
+
+ // Test reversing order of items in region sidebar-first. Get the node
+ // elements under the sidebar region div.
+ $breadcrumb_xpath = "//div[contains(@class,'region-sidebar-first')]/*";
+ $elements = $this->xpath($breadcrumb_xpath);
+ // There should be two elements, a div and then a nav.
+ $this->assertEquals('div', $elements[0]->getTagName());
+ $this->assertTrue($elements[0]->hasClass('block-search'));
+ $this->assertEquals('nav', $elements[1]->getTagName());
+ $this->drupalPostForm(
+ 'examples/render-example/altering',
+ [
+ 'render_example_move_breadcrumbs' => FALSE,
+ 'render_example_reverse_sidebar' => TRUE,
+ 'render_example_wrap_blocks' => FALSE,
+ ],
+ t('Save configuration')
+ );
+ // Get the elements again.
+ $elements = $this->xpath($breadcrumb_xpath);
+ // There should be two elements, a nav and then a div.
+ $this->assertEquals('nav', $elements[0]->getTagName());
+ $this->assertEquals('div', $elements[1]->getTagName());
+ $this->assertTrue($elements[1]->hasClass('block-search'));
+
+ // Test wrapping blocks in divs.
+ $xpath = "//div[contains(@class,'block')]//div[@class='content']/div[@class='block-prefix']";
+ $this->assertEmpty($this->xpath($xpath));
+ $this->drupalPostForm(
+ 'examples/render-example/altering',
+ [
+ 'render_example_move_breadcrumbs' => FALSE,
+ 'render_example_reverse_sidebar' => FALSE,
+ 'render_example_wrap_blocks' => TRUE,
+ ],
+ t('Save configuration')
+ );
+ $this->assertNotEmpty($this->xpath($xpath));
+
+ /*
+ // Test some rendering facets of the various render examples.
+ $this->drupalGet('examples/render-example/arrays');
+
+ $xpath_array = [
+ 'foof' => 'Hello ' . $web_user->getAccountName() . ', welcome to the #cache example.',
+ '//div[@class="render_example--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="render_example--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="render_example--rendered"][starts-with(.,"The current time was")]' => 'The current time was when this was cached. Updated every seconds',
+ '//div[@class="render_example--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="render_example--rendered"]/div[text()][starts-with(.,"markup for pre_")]' => 'markup for pre_render and post_render example',
+ '//div[@class="render_example--rendered"]/div[text()][starts-with(.,"This markup was added")]' => 'This markup was added after rendering by a #post_render',
+ '//div[@class="render_example--rendered"]/div[text()][starts-with(.,"This #suffix")]' => 'This #suffix was added by a #pre_render',
+ ];
+ foreach($xpath_array as $key => $value) {
+ $session->pageTextContains($value);
+ }
+ *
+ */
+ }
+
+}