Drupal 8  8.0.2
Renderer Class Reference
Inheritance diagram for Renderer:

Public Member Functions

 __construct (ControllerResolverInterface $controller_resolver, ThemeManagerInterface $theme, ElementInfoManagerInterface $element_info, PlaceholderGeneratorInterface $placeholder_generator, RenderCacheInterface $render_cache, RequestStack $request_stack, array $renderer_config)
 
 renderRoot (&$elements)
 
 renderPlain (&$elements)
 
 renderPlaceholder ($placeholder, array $elements)
 
 render (&$elements, $is_root_call=FALSE)
 
 hasRenderContext ()
 
 executeInRenderContext (RenderContext $context, callable $callable)
 
 mergeBubbleableMetadata (array $a, array $b)
 
 addCacheableDependency (array &$elements, $dependency)
 

Protected Member Functions

 doRender (&$elements, $is_root_call=FALSE)
 
 getCurrentRenderContext ()
 
 setCurrentRenderContext (RenderContext $context=NULL)
 
 replacePlaceholders (array &$elements)
 
 xssFilterAdminIfUnsafe ($string)
 
 ensureMarkupIsSafe (array $elements)
 

Protected Attributes

 $theme
 
 $controllerResolver
 
 $elementInfo
 
 $placeholderGenerator
 
 $renderCache
 
 $rendererConfig
 
 $isRenderingRoot = FALSE
 
 $requestStack
 

Static Protected Attributes

static $contextCollection
 

Detailed Description

Turns a render array into a HTML string.

Constructor & Destructor Documentation

__construct ( ControllerResolverInterface  $controller_resolver,
ThemeManagerInterface  $theme,
ElementInfoManagerInterface  $element_info,
PlaceholderGeneratorInterface  $placeholder_generator,
RenderCacheInterface  $render_cache,
RequestStack  $request_stack,
array  $renderer_config 
)

Constructs a new Renderer.

Parameters
\Drupal\Core\Controller\ControllerResolverInterface$controller_resolverThe controller resolver.
\Drupal\Core\Theme\ThemeManagerInterface$themeThe theme manager.
\Drupal\Core\Render\ElementInfoManagerInterface$element_infoThe element info.
\Drupal\Core\Render\PlaceholderGeneratorInterface$placeholder_generatorThe placeholder generator.
\Drupal\Core\Render\RenderCacheInterface$render_cacheThe render cache service.
\Symfony\Component\HttpFoundation\RequestStack$request_stackThe request stack.
array$renderer_configThe renderer configuration array.

References Drupal\requestStack(), and Drupal\theme().

Here is the call graph for this function:

Member Function Documentation

addCacheableDependency ( array &  $elements,
  $dependency 
)

{Adds a dependency on an object: merges its cacheability metadata.For instance, when a render array depends on some configuration, an entity, or an access result, we must make sure their cacheability metadata is present on the render array. This method makes doing that simple.

Parameters
array&$elementsThe render array to update.
\Drupal\Core\Cache\CacheableDependencyInterface | mixed$dependencyThe dependency. If the object implements CacheableDependencyInterface, then its cacheability metadata will be used. Otherwise, the passed in object must be assumed to be uncacheable, so max-age 0 is set.
See Also
::createFromObject()
}

Implements RendererInterface.

References CacheableMetadata\createFromObject(), and CacheableMetadata\createFromRenderArray().

Referenced by Renderer\doRender().

Here is the call graph for this function:

Here is the caller graph for this function:

doRender ( $elements,
  $is_root_call = FALSE 
)
protected

See the docs for ::render().

References Renderer\addCacheableDependency(), Element\children(), CacheableMetadata\createFromRenderArray(), Renderer\ensureMarkupIsSafe(), Renderer\getCurrentRenderContext(), Cache\mergeContexts(), Cache\PERMANENT, Renderer\replacePlaceholders(), Drupal\theme(), and Renderer\xssFilterAdminIfUnsafe().

Referenced by Renderer\render().

Here is the call graph for this function:

Here is the caller graph for this function:

ensureMarkupIsSafe ( array  $elements)
protected

Escapes #plain_text or filters #markup as required.

Drupal uses Twig's auto-escape feature to improve security. This feature automatically escapes any HTML that is not known to be safe. Due to this the render system needs to ensure that all markup it generates is marked safe so that Twig does not do any additional escaping.

By default all #markup is filtered to protect against XSS using the admin tag list. Render arrays can alter the list of tags allowed by the filter using the #allowed_tags property. This value should be an array of tags that Xss::filter() would accept. Render arrays can escape text instead of XSS filtering by setting the #plain_text property instead of #markup. If #plain_text is used #allowed_tags is ignored.

Parameters
array$elementsA render array with #markup set.
Returns
|string The escaped markup wrapped in a Markup object. If SafeMarkup::isSafe($elements['#markup']) returns TRUE, it won't be escaped or filtered again.
See Also
::escape()
::filter()
::adminFilter()

References Html\escape(), Xss\filter(), Xss\getAdminTagList(), and SafeMarkup\isSafe().

Referenced by Renderer\doRender().

Here is the call graph for this function:

Here is the caller graph for this function:

executeInRenderContext ( RenderContext  $context,
callable  $callable 
)

{Executes a callable within a render context.Only for very advanced use cases. Prefer using ::renderRoot() and ::renderPlain() instead.All rendering must happen within a render context. Within a render context, all bubbleable metadata is bubbled and hence tracked. Outside of a render context, it would be lost. This could lead to missing assets, incorrect cache variations (and thus security issues), insufficient cache invalidations, and so on.Any and all rendering must therefore happen within a render context, and it is this method that provides that.

Parameters
\Drupal\Core\Render\RenderContext$contextThe render context to execute the callable within.
callable$callableThe callable to execute.
Returns
mixed The callable's return value.
Exceptions
\LogicExceptionIn case bubbling has failed, can only happen in case of broken code.
See Also
}

Implements RendererInterface.

References Renderer\getCurrentRenderContext(), and Renderer\setCurrentRenderContext().

Referenced by Renderer\renderPlain(), and Renderer\renderRoot().

Here is the call graph for this function:

Here is the caller graph for this function:

getCurrentRenderContext ( )
protected

Returns the current render context.

Returns
The current render context.

References Drupal\requestStack().

Referenced by Renderer\doRender(), Renderer\executeInRenderContext(), and Renderer\hasRenderContext().

Here is the call graph for this function:

Here is the caller graph for this function:

hasRenderContext ( )

{Checks whether a render context is active.This is useful only in very specific situations to determine whether the system is already capable of collecting bubbleable metadata. Normally it should not be necessary to be concerned about this.

Returns
bool TRUE if the renderer has a render context active, FALSE otherwise.
}

Implements RendererInterface.

References Renderer\getCurrentRenderContext().

Here is the call graph for this function:

mergeBubbleableMetadata ( array  $a,
array  $b 
)

{Merges the bubbleable rendering metadata o/t 2nd render array with the 1st.

Parameters
array$aA render array.
array$bA render array.
Returns
array The first render array, modified to also contain the bubbleable rendering metadata of the second render array.
See Also
}

Implements RendererInterface.

References BubbleableMetadata\createFromRenderArray().

Referenced by Renderer\renderPlaceholder().

Here is the call graph for this function:

Here is the caller graph for this function:

render ( $elements,
  $is_root_call = FALSE 
)

{Renders HTML given a structured array tree.Renderable arrays have two kinds of key/value pairs: properties and children. Properties have keys starting with '#' and their values influence how the array will be rendered. Children are all elements whose keys do not start with a '#'. Their values should be renderable arrays themselves, which will be rendered during the rendering of the parent array. The markup provided by the children is typically inserted into the markup generated by the parent array.An important aspect of rendering is caching the result, when appropriate. Because the HTML of a rendered item includes all of the HTML of the rendered children, caching it requires certain information to bubble up from child elements to their parents:

  • Cache contexts, so that the render cache is varied by every context that affects the rendered HTML. Because cache contexts affect the cache ID, and therefore must be resolved for cache hits as well as misses, it is up to the implementation of this interface to decide how to implement the caching of items whose children specify cache contexts not directly specified by the parent. implements this with a lazy two-tier caching strategy. Alternate strategies could be to not cache such parents at all or to cache them with the child elements replaced by placeholder tokens that are dynamically rendered after cache retrieval.
  • Cache tags, so that cached renderings are invalidated when site content or configuration that can affect that rendering changes.
  • Placeholders, with associated self-contained placeholder render arrays, for executing code to handle dynamic requirements that cannot be cached. A render context () can be used to perform bubbling; it is a stack of objects.
Additionally, whether retrieving from cache or not, it is important to know all of the assets (CSS and JavaScript) required by the rendered HTML, and this must also bubble from child to parent. Therefore, includes that data as well.The process of rendering an element is recursive unless the element defines an implemented theme hook in theme. During each call to Renderer::render(), the outermost renderable array (also known as an "element") is processed using the following steps:

  • If this element has already been printed (#printed = TRUE) or the user does not have access to it (#access = FALSE), then an empty string is returned.
  • If no render context is set yet, an exception is thrown. Otherwise, an empty is pushed onto the render context.
  • If this element has cache defined then the cached markup for this element will be returned if it exists in Renderer::render()'s cache. To use Renderer::render() caching, set the element's cache property to an associative array with one or several of the following keys:
    • 'keys': An array of one or more keys that identify the element. If 'keys' is set, the cache ID is created automatically from these keys.
    • 'contexts': An array of one or more cache context IDs. These are converted to a final value depending on the request. (For instance, 'user' is mapped to the current user's ID.)
    • 'max-age': A time in seconds. Zero seconds means it is not cacheable. ::PERMANENT means it is cacheable forever.
    • 'bin': Specify a cache bin to cache the element in. Default is 'default'. When there is a render cache hit, there is no rendering work left to be done, so the stack must be updated. The empty (and topmost) frame that was just pushed onto the stack is updated with all bubbleable rendering metadata from the element retrieved from render cache. Then, this stack frame is bubbled: the two topmost frames are popped from the stack, they are merged, and the result is pushed back onto the stack. However, also in case of a cache miss we have to do something. Note that a Renderer renders top-down, which means that we try to render a parent first, and we try to avoid the work of rendering the children by using the render cache. Though in this case, we are dealing with a cache miss. So a Renderer traverses down the tree, rendering all children. In doing so, the render stack is updated with the bubbleable metadata of the children. That means that once the children are rendered, we can render cache this element. But the cache ID may have changed at that point, because the children's cache contexts have been bubbled! It is for that case that we must store the current (pre-bubbling) cache ID, so that we can compare it with the new (post-bubbling) cache ID when writing to the cache. We store the current cache ID in $pre_bubbling_cid.
  • If this element has #type defined and the default attributes for this element have not already been merged in (#defaults_loaded = TRUE) then the defaults for this type of element, defined by an element plugin, are merged into the array. #defaults_loaded is set by functions that 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 #create_placeholder set to TRUE, and it has a #lazy_builder callback, then the element is replaced with another element that has only two properties: #markup and #attached. #markup will contain placeholder markup, and #attached contains the placeholder metadata, that will be used for replacing this placeholder. That metadata contains a very compact render array (containing only #lazy_builder and cache) that will be rendered to replace the placeholder with its final markup. This means that when the #lazy_builder callback is called, it received a render array to add to that only contains cache.
  • If this element has a #lazy_builder or an array of #pre_render functions defined, they are called sequentially to modify the element before rendering. #lazy_builder is preferred, since it allows for placeholdering (see previous step), but #pre_render is still supported. Both have their use case: #lazy_builder is for building a render array, #pre_render is for decorating an existing render array. After the #lazy_builder function is called, #lazy_builder is removed, and #built is set to TRUE. After the #lazy_builder and all #pre_render functions have been called, #printed is checked a second time in case a #lazy_builder or #pre_render function flags the element as printed. If #printed is set, we return early and hence no rendering work is left to be done, similarly to a render cache hit. Once again, the empty (and topmost) frame that was just pushed onto the stack is updated with all bubbleable rendering metadata from the element whose #printed = TRUE. Then, this stack frame is bubbled: the two topmost frames are popped from the stack, they are merged, and the result is pushed back onto the stack.
  • The child elements of this element are sorted by weight using uasort() in ::children(). Since this is expensive, when passing already sorted elements to Renderer::render(), for example from a database query, set $elements['#sorted'] = TRUE to avoid sorting them a second time.
  • The main render phase to produce #children for this element takes place:
    • If this element has theme defined and theme is an implemented theme hook/suggestion then ThemeManagerInterface::render() is called and must render both the element and its children. If #render_children is set, ThemeManagerInterface::render() will not be called. #render_children is usually only set internally by ThemeManagerInterface::render() so that we can avoid the situation where Renderer::render() called from within a theme preprocess function creates an infinite loop.
    • If this element does not have a defined theme, or the defined theme hook is not implemented, or #render_children is set, then Renderer::render() is called recursively on each of the child elements of this element, and the result of each is concatenated onto #children. This is skipped if #children is not empty at this point.
    • Once #children has been rendered for this element, if theme is not implemented and #markup is set for this element, #markup will be prepended to #children.
  • If this element has #states defined then JavaScript state information is added to this element's #attached attribute by drupal_process_states().
  • If this element has #attached defined then any required libraries, JavaScript, CSS, or other custom data are added to the current page by ::processAttachments().
  • If this element has an array of #theme_wrappers defined and #render_children is not set, #children is then re-rendered by passing the element in its current state to ThemeManagerInterface::render() successively for each item in #theme_wrappers. Since theme and #theme_wrappers hooks often define variables with the same names it is possible to explicitly override each attribute passed to each #theme_wrappers hook by setting the hook name as the key and an array of overrides as the value in #theme_wrappers array. For example, if we have a render element as follows:
    array(
    '#theme' => 'image',
    '#attributes' => array('class' => array('foo')),
    '#theme_wrappers' => array('container'),
    );
    and we need to pass the class 'bar' as an attribute for 'container', we can rewrite our element thus:
    array(
    '#theme' => 'image',
    '#attributes' => array('class' => array('foo')),
    '#theme_wrappers' => array(
    'container' => array(
    '#attributes' => array('class' => array('bar')),
    ),
    ),
    );
  • If this element has an array of #post_render functions defined, they are called sequentially to modify the rendered #children. Unlike #pre_render functions, #post_render functions are passed both the rendered #children attribute as a string and the element itself.
  • If this element has #prefix and/or #suffix defined, they are concatenated to #children.
  • The rendering of this element is now complete. The next step will be render caching. So this is the perfect time to update the stack. At this point, children of this element (if any), have been rendered also, and if there were any, their bubbleable rendering metadata will have been bubbled up into the stack frame for the element that is currently being rendered. The render cache item for this element must contain the bubbleable rendering metadata for this element and all of its children. However, right now, the topmost stack frame (the one for this element) currently only contains the metadata for the children. Therefore, the topmost stack frame is updated with this element's metadata, and then the element's metadata is replaced with the metadata in the topmost stack frame. This element now contains all bubbleable rendering metadata for this element and all its children, so it's now ready for render caching.
  • If this element has cache defined, the rendered output of this element is saved to Renderer::render()'s internal cache. This includes the changes made by #post_render. At the same time, if $pre_bubbling_cid is set, it is compared to the calculated cache ID. If they are different, then a redirecting cache item is created, containing the cache metadata of the current element, and written to cache using the value of $pre_bubbling_cid as the cache ID. This ensures the pre-bubbling ("wrong") cache ID redirects to the post-bubbling ("right") cache ID.
  • If this element also has #cache_properties defined, all the array items matching the specified property names will be cached along with the element markup. If properties include children names, the system assumes only children's individual markup is relevant and ignores the parent markup. This approach is normally not needed and should be adopted only when dealing with very advanced use cases.
  • If this element has attached placeholders ([#attached][placeholders]), or any of its children has (which we would know thanks to the stack having been updated just before the render caching step), its placeholder element containing a #lazy_builder function is rendered in isolation. The resulting markup is used to replace the placeholder, and any bubbleable metadata is merged. Placeholders must be unique, to guarantee that for instance, samples of placeholders are not replaced as well.
  • Just before finishing the rendering of this element, this element's stack frame (the topmost one) is bubbled: the two topmost frames are popped from the stack, they are merged and the result is pushed back onto the stack. So if for instance this element was a child element, then a new frame was pushed onto the stack element at the beginning of rendering this element, it was updated when the rendering was completed, and now we merge it with the frame for the parent, so that the parent now has the bubbleable rendering metadata for its child.
  • #printed is set to TRUE for this element to ensure that it is only rendered once.
  • The final value of #children for this element is returned as the rendered output.
Parameters
array$elementsThe structured array describing the data to be rendered.
bool$is_root_call(Internal use only.) Whether this is a recursive call or not. See ::renderRoot().
Returns
The rendered HTML.
Exceptions
\LogicExceptionWhen called outside of a render context. (i.e. outside of a renderRoot(), renderPlain() or executeInRenderContext() call.)
\ExceptionIf a #pre_render callback throws an exception, it is caught to mark the renderer as no longer being in a root render call, if any. Then the exception is rethrown.
See Also
::getInfo()
::render()
drupal_process_states()
::processAttachments()
::renderRoot()
}

Implements RendererInterface.

References Renderer\doRender().

Referenced by Renderer\renderPlain(), and Renderer\renderRoot().

Here is the call graph for this function:

Here is the caller graph for this function:

renderPlaceholder (   $placeholder,
array  $elements 
)

{Renders final HTML for a placeholder.Renders the placeholder in isolation.

Parameters
string$placeholderAn attached placeholder to render. (This must be a key of one of the values of $elements['#attached']['placeholders'].)
array$elementsThe structured array describing the data to be rendered.
Returns
array The updated $elements.
See Also
::render()
}

Implements RendererInterface.

References Renderer\mergeBubbleableMetadata(), and Renderer\renderPlain().

Referenced by Renderer\replacePlaceholders().

Here is the call graph for this function:

Here is the caller graph for this function:

renderPlain ( $elements)

{Renders final HTML in situations where no assets are needed.Calls ::render() in such a way that placeholders are replaced.Useful for instance when rendering the values of tokens or emails, which need a render array being turned into a string, but do not need any of the bubbleable metadata (the attached assets and cache tags).Some of these are a relatively common use case and happen within a ::renderRoot() call, but that is generally highly problematic (and hence an exception is thrown when a ::renderRoot() call happens within another ::renderRoot() call). However, in this case, we only care about the output, not about the bubbling. Hence this uses a separate render context, to not affect the parent ::renderRoot() call.(Can be executed within another render context: it runs in isolation.)

Parameters
array$elementsThe structured array describing the data to be rendered.
Returns
The rendered HTML.
See Also
::renderRoot()
::render()
}

Implements RendererInterface.

References Renderer\executeInRenderContext(), and Renderer\render().

Referenced by Renderer\renderPlaceholder().

Here is the call graph for this function:

Here is the caller graph for this function:

renderRoot ( $elements)

{Renders final HTML given a structured array tree.Calls ::render() in such a way that placeholders are replaced.Should therefore only be used in occasions where the final rendering is happening, just before sending a Response:

  • system internals that are responsible for rendering the final HTML
  • render arrays for non-HTML responses, such as feeds
(Cannot be executed within another render context.)
Parameters
array$elementsThe structured array describing the data to be rendered.
Returns
The rendered HTML.
Exceptions
\LogicExceptionWhen called from inside another renderRoot() call.
See Also
::render()
}

Implements RendererInterface.

References Renderer\executeInRenderContext(), and Renderer\render().

Here is the call graph for this function:

replacePlaceholders ( array &  $elements)
protected

Replaces placeholders.

Placeholders may have:

  • #lazy_builder callback, to build a render array to be rendered into markup that can replace the placeholder
  • cache: to cache the result of the placeholder

Also merges the bubbleable metadata resulting from the rendering of the contents of the placeholders. Hence $elements will be contain the entirety of bubbleable metadata.

Parameters
array&$elementsThe structured array describing the data being rendered. Including the bubbleable metadata associated with the markup that replaced the placeholders.
Returns
bool Whether placeholders were replaced.
See Also
::renderPlaceholder()

References Renderer\renderPlaceholder().

Referenced by Renderer\doRender().

Here is the call graph for this function:

Here is the caller graph for this function:

setCurrentRenderContext ( RenderContext  $context = NULL)
protected

Sets the current render context.

Parameters
\Drupal\Core\Render\RenderContext | null$contextThe render context. This can be NULL for instance when restoring the original render context, which is in fact NULL.
Returns
$this

References Drupal\requestStack().

Referenced by Renderer\executeInRenderContext().

Here is the call graph for this function:

Here is the caller graph for this function:

xssFilterAdminIfUnsafe (   $string)
protected

Applies a very permissive XSS/HTML filter for admin-only use.

Note: This method only filters if $string is not marked safe already. This ensures that HTML intended for display is not filtered.

Parameters
string | \Drupal\Core\Render\Markup$stringA string.
Returns
The escaped string wrapped in a Markup object. If SafeMarkup::isSafe($string) returns TRUE, it won't be escaped again.

References Xss\filterAdmin(), and SafeMarkup\isSafe().

Referenced by Renderer\doRender().

Here is the call graph for this function:

Here is the caller graph for this function:


The documentation for this class was generated from the following file: