You are here

protected function StylePluginBase::renderFields in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/views/src/Plugin/views/style/StylePluginBase.php \Drupal\views\Plugin\views\style\StylePluginBase::renderFields()
  2. 10 core/modules/views/src/Plugin/views/style/StylePluginBase.php \Drupal\views\Plugin\views\style\StylePluginBase::renderFields()

Renders all of the fields for a given style and store them on the object.

Parameters

array $result: The result array from $view->result

2 calls to StylePluginBase::renderFields()
StylePluginBase::getField in core/modules/views/src/Plugin/views/style/StylePluginBase.php
Gets a rendered field.
StylePluginBase::renderGrouping in core/modules/views/src/Plugin/views/style/StylePluginBase.php
Group records as needed for rendering.

File

core/modules/views/src/Plugin/views/style/StylePluginBase.php, line 664

Class

StylePluginBase
Base class for views style plugins.

Namespace

Drupal\views\Plugin\views\style

Code

protected function renderFields(array $result) {
  if (!$this
    ->usesFields()) {
    return;
  }
  if (!isset($this->rendered_fields)) {
    $this->rendered_fields = [];
    $this->view->row_index = 0;
    $field_ids = array_keys($this->view->field);

    // Only tokens relating to field handlers preceding the one we invoke
    // ::getRenderTokens() on are returned, so here we need to pick the last
    // available field handler.
    $render_tokens_field_id = end($field_ids);

    // If all fields have a field::access FALSE there might be no fields, so
    // there is no reason to execute this code.
    if (!empty($field_ids)) {
      $renderer = $this
        ->getRenderer();

      /** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache_plugin */
      $cache_plugin = $this->view->display_handler
        ->getPlugin('cache');
      $max_age = $cache_plugin
        ->getCacheMaxAge();

      /** @var \Drupal\views\ResultRow $row */
      foreach ($result as $index => $row) {
        $this->view->row_index = $index;

        // Here we implement render caching for result rows. Since we never
        // build a render array for single rows, given that style templates
        // need individual field markup to support proper theming, we build
        // a raw render array containing all field render arrays and cache it.
        // This allows us to cache the markup of the various children, that is
        // individual fields, which is then available for style template
        // preprocess functions, later in the rendering workflow.
        // @todo Fetch all the available cached row items in one single cache
        //   get operation, once https://www.drupal.org/node/2453945 is fixed.
        $data = [
          '#pre_render' => [
            [
              $this,
              'elementPreRenderRow',
            ],
          ],
          '#row' => $row,
          '#cache' => [
            'keys' => $cache_plugin
              ->getRowCacheKeys($row),
            'tags' => $cache_plugin
              ->getRowCacheTags($row),
            'max-age' => $max_age,
          ],
          '#cache_properties' => $field_ids,
        ];
        $renderer
          ->addCacheableDependency($data, $this->view->storage);

        // Views may be rendered both inside and outside a render context:
        // - HTML views are rendered inside a render context: then we want to
        //   use ::render(), so that attachments and cacheability are bubbled.
        // - non-HTML views are rendered outside a render context: then we
        //   want to use ::renderPlain(), so that no bubbling happens
        if ($renderer
          ->hasRenderContext()) {
          $renderer
            ->render($data);
        }
        else {
          $renderer
            ->renderPlain($data);
        }

        // Extract field output from the render array and post process it.
        $fields = $this->view->field;
        $rendered_fields =& $this->rendered_fields[$index];
        $post_render_tokens = [];
        foreach ($field_ids as $id) {
          $rendered_fields[$id] = $data[$id]['#markup'];
          $tokens = $fields[$id]
            ->postRender($row, $rendered_fields[$id]);
          if ($tokens) {
            $post_render_tokens += $tokens;
          }
        }

        // Populate row tokens.
        $this->rowTokens[$index] = $this->view->field[$render_tokens_field_id]
          ->getRenderTokens([]);

        // Replace post-render tokens.
        if ($post_render_tokens) {
          $placeholders = array_keys($post_render_tokens);
          $values = array_values($post_render_tokens);
          foreach ($this->rendered_fields[$index] as &$rendered_field) {

            // Placeholders and rendered fields have been processed by the
            // render system and are therefore safe.
            $rendered_field = ViewsRenderPipelineMarkup::create(str_replace($placeholders, $values, $rendered_field));
          }
        }
      }
    }
    unset($this->view->row_index);
  }
}