Upgraded drupal core with security updates
[yaffs-website] / web / core / lib / Drupal / Core / Render / RendererInterface.php
1 <?php
2
3 namespace Drupal\Core\Render;
4
5 /**
6  * Defines an interface for turning a render array into a string.
7  */
8 interface RendererInterface {
9
10   /**
11    * Renders final HTML given a structured array tree.
12    *
13    * Calls ::render() in such a way that placeholders are replaced.
14    *
15    * Should therefore only be used in occasions where the final rendering is
16    * happening, just before sending a Response:
17    * - system internals that are responsible for rendering the final HTML
18    * - render arrays for non-HTML responses, such as feeds
19    *
20    * (Cannot be executed within another render context.)
21    *
22    * @param array $elements
23    *   The structured array describing the data to be rendered.
24    *
25    * @return \Drupal\Component\Render\MarkupInterface
26    *   The rendered HTML.
27    *
28    * @throws \LogicException
29    *   When called from inside another renderRoot() call.
30    *
31    * @see \Drupal\Core\Render\RendererInterface::render()
32    */
33   public function renderRoot(&$elements);
34
35   /**
36    * Renders final HTML in situations where no assets are needed.
37    *
38    * Calls ::render() in such a way that placeholders are replaced.
39    *
40    * Useful for instance when rendering the values of tokens or emails, which
41    * need a render array being turned into a string, but do not need any of the
42    * bubbleable metadata (the attached assets and cache tags).
43    *
44    * Some of these are a relatively common use case and happen *within* a
45    * ::renderRoot() call, but that is generally highly problematic (and hence an
46    * exception is thrown when a ::renderRoot() call happens within another
47    * ::renderRoot() call). However, in this case, we only care about the output,
48    * not about the bubbling. Hence this uses a separate render context, to not
49    * affect the parent ::renderRoot() call.
50    *
51    * (Can be executed within another render context: it runs in isolation.)
52    *
53    * @param array $elements
54    *   The structured array describing the data to be rendered.
55    *
56    * @return \Drupal\Component\Render\MarkupInterface
57    *   The rendered HTML.
58    *
59    * @see \Drupal\Core\Render\RendererInterface::renderRoot()
60    * @see \Drupal\Core\Render\RendererInterface::render()
61    */
62   public function renderPlain(&$elements);
63
64   /**
65    * Renders final HTML for a placeholder.
66    *
67    * Renders the placeholder in isolation.
68    *
69    * @param string $placeholder
70    *   An attached placeholder to render. (This must be a key of one of the
71    *   values of $elements['#attached']['placeholders'].)
72    * @param array $elements
73    *   The structured array describing the data to be rendered.
74    *
75    * @return array
76    *   The updated $elements.
77    *
78    * @see \Drupal\Core\Render\RendererInterface::render()
79    */
80   public function renderPlaceholder($placeholder, array $elements);
81
82   /**
83    * Renders HTML given a structured array tree.
84    *
85    * Renderable arrays have two kinds of key/value pairs: properties and
86    * children. Properties have keys starting with '#' and their values influence
87    * how the array will be rendered. Children are all elements whose keys do not
88    * start with a '#'. Their values should be renderable arrays themselves,
89    * which will be rendered during the rendering of the parent array. The markup
90    * provided by the children is typically inserted into the markup generated by
91    * the parent array.
92    *
93    * An important aspect of rendering is caching the result, when appropriate.
94    * Because the HTML of a rendered item includes all of the HTML of the
95    * rendered children, caching it requires certain information to bubble up
96    * from child elements to their parents:
97    * - Cache contexts, so that the render cache is varied by every context that
98    *   affects the rendered HTML. Because cache contexts affect the cache ID,
99    *   and therefore must be resolved for cache hits as well as misses, it is
100    *   up to the implementation of this interface to decide how to implement
101    *   the caching of items whose children specify cache contexts not directly
102    *   specified by the parent. \Drupal\Core\Render\Renderer implements this
103    *   with a lazy two-tier caching strategy. Alternate strategies could be to
104    *   not cache such parents at all or to cache them with the child elements
105    *   replaced by placeholder tokens that are dynamically rendered after cache
106    *   retrieval.
107    * - Cache tags, so that cached renderings are invalidated when site content
108    *   or configuration that can affect that rendering changes.
109    * - Placeholders, with associated self-contained placeholder render arrays,
110    *   for executing code to handle dynamic requirements that cannot be cached.
111    * A render context (\Drupal\Core\Render\RenderContext) can be used to perform
112    * bubbling; it is a stack of \Drupal\Core\Render\BubbleableMetadata objects.
113    *
114    * Additionally, whether retrieving from cache or not, it is important to
115    * know all of the assets (CSS and JavaScript) required by the rendered HTML,
116    * and this must also bubble from child to parent. Therefore,
117    * \Drupal\Core\Render\BubbleableMetadata includes that data as well.
118    *
119    * The process of rendering an element is recursive unless the element defines
120    * an implemented theme hook in #theme. During each call to
121    * Renderer::render(), the outermost renderable array (also known as an
122    * "element") is processed using the following steps:
123    *   - If this element has already been printed (#printed = TRUE) or the user
124    *     does not have access to it (#access = FALSE), then an empty string is
125    *     returned.
126    *   - If no render context is set yet, an exception is thrown. Otherwise,
127    *     an empty \Drupal\Core\Render\BubbleableMetadata is pushed onto the
128    *     render context.
129    *   - If this element has #cache defined then the cached markup for this
130    *     element will be returned if it exists in Renderer::render()'s cache. To
131    *     use Renderer::render() caching, set the element's #cache property to an
132    *     associative array with one or several of the following keys:
133    *     - 'keys': An array of one or more keys that identify the element. If
134    *       'keys' is set, the cache ID is created automatically from these keys.
135    *     - 'contexts': An array of one or more cache context IDs. These are
136    *       converted to a final value depending on the request. (For instance,
137    *       'user' is mapped to the current user's ID.)
138    *     - 'max-age': A time in seconds. Zero seconds means it is not cacheable.
139    *       \Drupal\Core\Cache\Cache::PERMANENT means it is cacheable forever.
140    *     - 'bin': Specify a cache bin to cache the element in. Default is
141    *       'default'.
142    *     When there is a render cache hit, there is no rendering work left to be
143    *     done, so the stack must be updated. The empty (and topmost) frame that
144    *     was just pushed onto the stack is updated with all bubbleable rendering
145    *     metadata from the element retrieved from render cache. Then, this stack
146    *     frame is bubbled: the two topmost frames are popped from the stack,
147    *     they are merged, and the result is pushed back onto the stack.
148    *     However, also in case of a cache miss we have to do something. Note
149    *     that a Renderer renders top-down, which means that we try to render a
150    *     parent first, and we try to avoid the work of rendering the children by
151    *     using the render cache. Though in this case, we are dealing with a
152    *     cache miss. So a Renderer traverses down the tree, rendering all
153    *     children. In doing so, the render stack is updated with the bubbleable
154    *     metadata of the children. That means that once the children are
155    *     rendered, we can render cache this element. But the cache ID may have
156    *     *changed* at that point, because the children's cache contexts have
157    *     been bubbled!
158    *     It is for that case that we must store the current (pre-bubbling) cache
159    *     ID, so that we can compare it with the new (post-bubbling) cache ID
160    *     when writing to the cache. We store the current cache ID in
161    *     $pre_bubbling_cid.
162    *   - If this element has #type defined and the default attributes for this
163    *     element have not already been merged in (#defaults_loaded = TRUE) then
164    *     the defaults for this type of element, defined by an element plugin,
165    *     are merged into the array. #defaults_loaded is set by functions that
166    *     process render arrays and call the element info service before passing
167    *     the array to Renderer::render(), such as form_builder() in the Form
168    *     API.
169    *   - If this element has #create_placeholder set to TRUE, and it has a
170    *     #lazy_builder callback, then the element is replaced with another
171    *     element that has only two properties: #markup and #attached. #markup
172    *     will contain placeholder markup, and #attached contains the placeholder
173    *     metadata, that will be used for replacing this placeholder. That
174    *     metadata contains a very compact render array (containing only
175    *     #lazy_builder and #cache) that will be rendered to replace the
176    *     placeholder with its final markup. This means that when the
177    *     #lazy_builder callback is called, it received a render array to add to
178    *     that only contains #cache.
179    *   - If this element has a #lazy_builder or an array of #pre_render
180    *     functions defined, they are called sequentially to modify the element
181    *     before rendering. #lazy_builder is preferred, since it allows for
182    *     placeholdering (see previous step), but #pre_render is still supported.
183    *     Both have their use case: #lazy_builder is for building a render array,
184    *     #pre_render is for decorating an existing render array.
185    *     After the #lazy_builder function is called, #lazy_builder is removed,
186    *     and #built is set to TRUE.
187    *     After the #lazy_builder and all #pre_render functions have been called,
188    *     #printed is checked a second time in case a #lazy_builder or
189    *     #pre_render function flags the element as printed. If #printed is set,
190    *     we return early and hence no rendering work is left to be done,
191    *     similarly to a render cache hit. Once again, the empty (and topmost)
192    *     frame that was just pushed onto the stack is updated with all
193    *     bubbleable rendering metadata from the element whose #printed = TRUE.
194    *     Then, this stack frame is bubbled: the two topmost frames are popped
195    *     from the stack, they are merged, and the result is pushed back onto the
196    *     stack.
197    *   - The child elements of this element are sorted by weight using uasort()
198    *     in \Drupal\Core\Render\Element::children(). Since this is expensive,
199    *     when passing already sorted elements to Renderer::render(), for example
200    *     from a database query, set $elements['#sorted'] = TRUE to avoid sorting
201    *     them a second time.
202    *   - The main render phase to produce #children for this element takes
203    *     place:
204    *     - If this element has #theme defined and #theme is an implemented theme
205    *       hook/suggestion then ThemeManagerInterface::render() is called and
206    *       must render both the element and its children. If #render_children is
207    *       set, ThemeManagerInterface::render() will not be called.
208    *       #render_children is usually only set internally by
209    *       ThemeManagerInterface::render() so that we can avoid the situation
210    *       where Renderer::render() called from within a theme preprocess
211    *       function creates an infinite loop.
212    *     - If this element does not have a defined #theme, or the defined #theme
213    *       hook is not implemented, or #render_children is set, then
214    *       Renderer::render() is called recursively on each of the child
215    *       elements of this element, and the result of each is concatenated onto
216    *       #children. This is skipped if #children is not empty at this point.
217    *     - Once #children has been rendered for this element, if #theme is not
218    *       implemented and #markup is set for this element, #markup will be
219    *       prepended to #children.
220    *   - If this element has #states defined then JavaScript state information
221    *     is added to this element's #attached attribute by
222    *     drupal_process_states().
223    *   - If this element has #attached defined then any required libraries,
224    *     JavaScript, CSS, or other custom data are added to the current page by
225    *     \Drupal\Core\Render\AttachmentsResponseProcessorInterface::processAttachments().
226    *   - If this element has an array of #theme_wrappers defined and
227    *     #render_children is not set, #children is then re-rendered by passing
228    *     the element in its current state to ThemeManagerInterface::render()
229    *     successively for each item in #theme_wrappers. Since #theme and
230    *     #theme_wrappers hooks often define variables with the same names it is
231    *     possible to explicitly override each attribute passed to each
232    *     #theme_wrappers hook by setting the hook name as the key and an array
233    *     of overrides as the value in #theme_wrappers array.
234    *     For example, if we have a render element as follows:
235    *     @code
236    *     array(
237    *       '#theme' => 'image',
238    *       '#attributes' => array('class' => array('foo')),
239    *       '#theme_wrappers' => array('container'),
240    *     );
241    *     @endcode
242    *     and we need to pass the class 'bar' as an attribute for 'container', we
243    *     can rewrite our element thus:
244    *     @code
245    *     array(
246    *       '#theme' => 'image',
247    *       '#attributes' => array('class' => array('foo')),
248    *       '#theme_wrappers' => array(
249    *         'container' => array(
250    *           '#attributes' => array('class' => array('bar')),
251    *         ),
252    *       ),
253    *     );
254    *      @endcode
255    *   - If this element has an array of #post_render functions defined, they
256    *     are called sequentially to modify the rendered #children. Unlike
257    *     #pre_render functions, #post_render functions are passed both the
258    *     rendered #children attribute as a string and the element itself.
259    *   - If this element has #prefix and/or #suffix defined, they are
260    *     concatenated to #children.
261    *   - The rendering of this element is now complete. The next step will be
262    *     render caching. So this is the perfect time to update the stack. At
263    *     this point, children of this element (if any), have been rendered also,
264    *     and if there were any, their bubbleable rendering metadata will have
265    *     been bubbled up into the stack frame for the element that is currently
266    *     being rendered. The render cache item for this element must contain the
267    *     bubbleable rendering metadata for this element and all of its children.
268    *     However, right now, the topmost stack frame (the one for this element)
269    *     currently only contains the metadata for the children. Therefore, the
270    *     topmost stack frame is updated with this element's metadata, and then
271    *     the element's metadata is replaced with the metadata in the topmost
272    *     stack frame. This element now contains all bubbleable rendering
273    *     metadata for this element and all its children, so it's now ready for
274    *     render caching.
275    *   - If this element has #cache defined, the rendered output of this element
276    *     is saved to Renderer::render()'s internal cache. This includes the
277    *     changes made by #post_render.
278    *     At the same time, if $pre_bubbling_cid is set, it is compared to the
279    *     calculated cache ID. If they are different, then a redirecting cache
280    *     item is created, containing the #cache metadata of the current element,
281    *     and written to cache using the value of $pre_bubbling_cid as the cache
282    *     ID. This ensures the pre-bubbling ("wrong") cache ID redirects to the
283    *     post-bubbling ("right") cache ID.
284    *   - If this element also has #cache_properties defined, all the array items
285    *     matching the specified property names will be cached along with the
286    *     element markup. If properties include children names, the system
287    *     assumes only children's individual markup is relevant and ignores the
288    *     parent markup. This approach is normally not needed and should be
289    *     adopted only when dealing with very advanced use cases.
290    *   - If this element has attached placeholders ([#attached][placeholders]),
291    *     or any of its children has (which we would know thanks to the stack
292    *     having been updated just before the render caching step), its
293    *     placeholder element containing a #lazy_builder function is rendered in
294    *     isolation. The resulting markup is used to replace the placeholder, and
295    *     any bubbleable metadata is merged.
296    *     Placeholders must be unique, to guarantee that for instance, samples of
297    *     placeholders are not replaced as well.
298    *   - Just before finishing the rendering of this element, this element's
299    *     stack frame (the topmost one) is bubbled: the two topmost frames are
300    *     popped from the stack, they are merged and the result is pushed back
301    *     onto the stack.
302    *     So if for instance this element was a child element, then a new frame
303    *     was pushed onto the stack element at the beginning of rendering this
304    *     element, it was updated when the rendering was completed, and now we
305    *     merge it with the frame for the parent, so that the parent now has the
306    *     bubbleable rendering metadata for its child.
307    *   - #printed is set to TRUE for this element to ensure that it is only
308    *     rendered once.
309    *   - The final value of #children for this element is returned as the
310    *     rendered output.
311    *
312    * @param array $elements
313    *   The structured array describing the data to be rendered.
314    * @param bool $is_root_call
315    *   (Internal use only.) Whether this is a recursive call or not. See
316    *   ::renderRoot().
317    *
318    * @return \Drupal\Component\Render\MarkupInterface
319    *   The rendered HTML.
320    *
321    * @throws \LogicException
322    *   When called outside of a render context (i.e. outside of a renderRoot(),
323    *   renderPlain() or executeInRenderContext() call).
324    * @throws \Exception
325    *   If a #pre_render callback throws an exception, it is caught to mark the
326    *   renderer as no longer being in a root render call, if any. Then the
327    *   exception is rethrown.
328    *
329    * @see \Drupal\Core\Render\ElementInfoManagerInterface::getInfo()
330    * @see \Drupal\Core\Theme\ThemeManagerInterface::render()
331    * @see drupal_process_states()
332    * @see \Drupal\Core\Render\AttachmentsResponseProcessorInterface::processAttachments()
333    * @see \Drupal\Core\Render\RendererInterface::renderRoot()
334    */
335   public function render(&$elements, $is_root_call = FALSE);
336
337   /**
338    * Checks whether a render context is active.
339    *
340    * This is useful only in very specific situations to determine whether the
341    * system is already capable of collecting bubbleable metadata. Normally it
342    * should not be necessary to be concerned about this.
343    *
344    * @return bool
345    *   TRUE if the renderer has a render context active, FALSE otherwise.
346    */
347   public function hasRenderContext();
348
349   /**
350    * Executes a callable within a render context.
351    *
352    * Only for very advanced use cases. Prefer using ::renderRoot() and
353    * ::renderPlain() instead.
354    *
355    * All rendering must happen within a render context. Within a render context,
356    * all bubbleable metadata is bubbled and hence tracked. Outside of a render
357    * context, it would be lost. This could lead to missing assets, incorrect
358    * cache variations (and thus security issues), insufficient cache
359    * invalidations, and so on.
360    *
361    * Any and all rendering must therefore happen within a render context, and it
362    * is this method that provides that.
363    *
364    * @param \Drupal\Core\Render\RenderContext $context
365    *   The render context to execute the callable within.
366    * @param callable $callable
367    *   The callable to execute.
368    *
369    * @return mixed
370    *   The callable's return value.
371    *
372    * @throws \LogicException
373    *   In case bubbling has failed, can only happen in case of broken code.
374    *
375    * @see \Drupal\Core\Render\RenderContext
376    * @see \Drupal\Core\Render\BubbleableMetadata
377    */
378   public function executeInRenderContext(RenderContext $context, callable $callable);
379
380   /**
381    * Merges the bubbleable rendering metadata o/t 2nd render array with the 1st.
382    *
383    * @param array $a
384    *   A render array.
385    * @param array $b
386    *   A render array.
387    *
388    * @return array
389    *   The first render array, modified to also contain the bubbleable rendering
390    *   metadata of the second render array.
391    *
392    * @see \Drupal\Core\Render\BubbleableMetadata
393    */
394   public function mergeBubbleableMetadata(array $a, array $b);
395
396   /**
397    * Adds a dependency on an object: merges its cacheability metadata.
398    *
399    * For instance, when a render array depends on some configuration, an entity,
400    * or an access result, we must make sure their cacheability metadata is
401    * present on the render array. This method makes doing that simple.
402    *
403    * @param array &$elements
404    *   The render array to update.
405    * @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $dependency
406    *   The dependency. If the object implements CacheableDependencyInterface,
407    *   then its cacheability metadata will be used. Otherwise, the passed in
408    *   object must be assumed to be uncacheable, so max-age 0 is set.
409    *
410    * @see \Drupal\Core\Cache\CacheableMetadata::createFromObject()
411    */
412   public function addCacheableDependency(array &$elements, $dependency);
413
414 }