Chris@0: 'image', Chris@0: * '#attributes' => array('class' => array('foo')), Chris@0: * '#theme_wrappers' => array('container'), Chris@0: * ); Chris@0: * @endcode Chris@0: * and we need to pass the class 'bar' as an attribute for 'container', we Chris@0: * can rewrite our element thus: Chris@0: * @code Chris@0: * array( Chris@0: * '#theme' => 'image', Chris@0: * '#attributes' => array('class' => array('foo')), Chris@0: * '#theme_wrappers' => array( Chris@0: * 'container' => array( Chris@0: * '#attributes' => array('class' => array('bar')), Chris@0: * ), Chris@0: * ), Chris@0: * ); Chris@0: * @endcode Chris@0: * - If this element has an array of #post_render functions defined, they Chris@0: * are called sequentially to modify the rendered #children. Unlike Chris@0: * #pre_render functions, #post_render functions are passed both the Chris@0: * rendered #children attribute as a string and the element itself. Chris@0: * - If this element has #prefix and/or #suffix defined, they are Chris@0: * concatenated to #children. Chris@0: * - The rendering of this element is now complete. The next step will be Chris@0: * render caching. So this is the perfect time to update the stack. At Chris@0: * this point, children of this element (if any), have been rendered also, Chris@0: * and if there were any, their bubbleable rendering metadata will have Chris@0: * been bubbled up into the stack frame for the element that is currently Chris@0: * being rendered. The render cache item for this element must contain the Chris@0: * bubbleable rendering metadata for this element and all of its children. Chris@0: * However, right now, the topmost stack frame (the one for this element) Chris@0: * currently only contains the metadata for the children. Therefore, the Chris@0: * topmost stack frame is updated with this element's metadata, and then Chris@0: * the element's metadata is replaced with the metadata in the topmost Chris@0: * stack frame. This element now contains all bubbleable rendering Chris@0: * metadata for this element and all its children, so it's now ready for Chris@0: * render caching. Chris@0: * - If this element has #cache defined, the rendered output of this element Chris@0: * is saved to Renderer::render()'s internal cache. This includes the Chris@0: * changes made by #post_render. Chris@0: * At the same time, if $pre_bubbling_cid is set, it is compared to the Chris@0: * calculated cache ID. If they are different, then a redirecting cache Chris@0: * item is created, containing the #cache metadata of the current element, Chris@0: * and written to cache using the value of $pre_bubbling_cid as the cache Chris@0: * ID. This ensures the pre-bubbling ("wrong") cache ID redirects to the Chris@0: * post-bubbling ("right") cache ID. Chris@0: * - If this element also has #cache_properties defined, all the array items Chris@0: * matching the specified property names will be cached along with the Chris@0: * element markup. If properties include children names, the system Chris@0: * assumes only children's individual markup is relevant and ignores the Chris@0: * parent markup. This approach is normally not needed and should be Chris@0: * adopted only when dealing with very advanced use cases. Chris@0: * - If this element has attached placeholders ([#attached][placeholders]), Chris@0: * or any of its children has (which we would know thanks to the stack Chris@0: * having been updated just before the render caching step), its Chris@0: * placeholder element containing a #lazy_builder function is rendered in Chris@0: * isolation. The resulting markup is used to replace the placeholder, and Chris@0: * any bubbleable metadata is merged. Chris@0: * Placeholders must be unique, to guarantee that for instance, samples of Chris@0: * placeholders are not replaced as well. Chris@0: * - Just before finishing the rendering of this element, this element's Chris@0: * stack frame (the topmost one) is bubbled: the two topmost frames are Chris@0: * popped from the stack, they are merged and the result is pushed back Chris@0: * onto the stack. Chris@0: * So if for instance this element was a child element, then a new frame Chris@0: * was pushed onto the stack element at the beginning of rendering this Chris@0: * element, it was updated when the rendering was completed, and now we Chris@0: * merge it with the frame for the parent, so that the parent now has the Chris@0: * bubbleable rendering metadata for its child. Chris@0: * - #printed is set to TRUE for this element to ensure that it is only Chris@0: * rendered once. Chris@0: * - The final value of #children for this element is returned as the Chris@0: * rendered output. Chris@0: * Chris@0: * @param array $elements Chris@0: * The structured array describing the data to be rendered. Chris@0: * @param bool $is_root_call Chris@0: * (Internal use only.) Whether this is a recursive call or not. See Chris@0: * ::renderRoot(). Chris@0: * Chris@0: * @return \Drupal\Component\Render\MarkupInterface Chris@0: * The rendered HTML. Chris@0: * Chris@0: * @throws \LogicException Chris@0: * When called outside of a render context (i.e. outside of a renderRoot(), Chris@0: * renderPlain() or executeInRenderContext() call). Chris@0: * @throws \Exception Chris@0: * If a #pre_render callback throws an exception, it is caught to mark the Chris@0: * renderer as no longer being in a root render call, if any. Then the Chris@0: * exception is rethrown. Chris@0: * Chris@0: * @see \Drupal\Core\Render\ElementInfoManagerInterface::getInfo() Chris@0: * @see \Drupal\Core\Theme\ThemeManagerInterface::render() Chris@0: * @see drupal_process_states() Chris@0: * @see \Drupal\Core\Render\AttachmentsResponseProcessorInterface::processAttachments() Chris@0: * @see \Drupal\Core\Render\RendererInterface::renderRoot() Chris@0: */ Chris@0: public function render(&$elements, $is_root_call = FALSE); Chris@0: Chris@0: /** Chris@0: * Checks whether a render context is active. Chris@0: * Chris@0: * This is useful only in very specific situations to determine whether the Chris@0: * system is already capable of collecting bubbleable metadata. Normally it Chris@0: * should not be necessary to be concerned about this. Chris@0: * Chris@0: * @return bool Chris@0: * TRUE if the renderer has a render context active, FALSE otherwise. Chris@0: */ Chris@0: public function hasRenderContext(); Chris@0: Chris@0: /** Chris@0: * Executes a callable within a render context. Chris@0: * Chris@0: * Only for very advanced use cases. Prefer using ::renderRoot() and Chris@0: * ::renderPlain() instead. Chris@0: * Chris@0: * All rendering must happen within a render context. Within a render context, Chris@0: * all bubbleable metadata is bubbled and hence tracked. Outside of a render Chris@0: * context, it would be lost. This could lead to missing assets, incorrect Chris@0: * cache variations (and thus security issues), insufficient cache Chris@0: * invalidations, and so on. Chris@0: * Chris@0: * Any and all rendering must therefore happen within a render context, and it Chris@0: * is this method that provides that. Chris@0: * Chris@0: * @param \Drupal\Core\Render\RenderContext $context Chris@0: * The render context to execute the callable within. Chris@0: * @param callable $callable Chris@0: * The callable to execute. Chris@0: * Chris@0: * @return mixed Chris@0: * The callable's return value. Chris@0: * Chris@0: * @throws \LogicException Chris@0: * In case bubbling has failed, can only happen in case of broken code. Chris@0: * Chris@0: * @see \Drupal\Core\Render\RenderContext Chris@0: * @see \Drupal\Core\Render\BubbleableMetadata Chris@0: */ Chris@0: public function executeInRenderContext(RenderContext $context, callable $callable); Chris@0: Chris@0: /** Chris@0: * Merges the bubbleable rendering metadata o/t 2nd render array with the 1st. Chris@0: * Chris@0: * @param array $a Chris@0: * A render array. Chris@0: * @param array $b Chris@0: * A render array. Chris@0: * Chris@0: * @return array Chris@0: * The first render array, modified to also contain the bubbleable rendering Chris@0: * metadata of the second render array. Chris@0: * Chris@0: * @see \Drupal\Core\Render\BubbleableMetadata Chris@0: */ Chris@0: public function mergeBubbleableMetadata(array $a, array $b); Chris@0: Chris@0: /** Chris@0: * Adds a dependency on an object: merges its cacheability metadata. Chris@0: * Chris@0: * For instance, when a render array depends on some configuration, an entity, Chris@0: * or an access result, we must make sure their cacheability metadata is Chris@0: * present on the render array. This method makes doing that simple. Chris@0: * Chris@0: * @param array &$elements Chris@0: * The render array to update. Chris@0: * @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $dependency Chris@0: * The dependency. If the object implements CacheableDependencyInterface, Chris@0: * then its cacheability metadata will be used. Otherwise, the passed in Chris@0: * object must be assumed to be uncacheable, so max-age 0 is set. Chris@0: * Chris@0: * @see \Drupal\Core\Cache\CacheableMetadata::createFromObject() Chris@0: */ Chris@0: public function addCacheableDependency(array &$elements, $dependency); Chris@0: Chris@0: }