/**
  * Renders all of the fields for a given style and store them on the object.
  *
  * @param array $result
  *   The result array from $view->result
  */
 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');
             /** @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)], '#cache_properties' => $field_ids];
                 $renderer->addCacheableDependency($data, $this->view->storage);
                 $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 = ViewsRenderPipelineSafeString::create(str_replace($placeholders, $values, $rendered_field));
                     }
                 }
             }
         }
         unset($this->view->row_index);
     }
 }
 /**
  * {@inheritdoc}
  */
 public function render()
 {
     $build = array();
     $build['#markup'] = $this->renderer->executeInRenderContext(new RenderContext(), function () {
         return $this->view->style_plugin->render();
     });
     $this->view->element['#content_type'] = $this->getMimeType();
     $this->view->element['#cache_properties'][] = '#content_type';
     // Encode and wrap the output in a pre tag if this is for a live preview.
     if (!empty($this->view->live_preview)) {
         $build['#prefix'] = '<pre>';
         $build['#plain_text'] = $build['#markup'];
         $build['#suffix'] = '</pre>';
         unset($build['#markup']);
     } elseif ($this->view->getRequest()->getFormat($this->view->element['#content_type']) !== 'html') {
         // This display plugin is primarily for returning non-HTML formats.
         // However, we still invoke the renderer to collect cacheability metadata.
         // Because the renderer is designed for HTML rendering, it filters
         // #markup for XSS unless it is already known to be safe, but that filter
         // only works for HTML. Therefore, we mark the contents as safe to bypass
         // the filter. So long as we are returning this in a non-HTML response
         // (checked above), this is safe, because an XSS attack only works when
         // executed by an HTML agent.
         // @todo Decide how to support non-HTML in the render API in
         //   https://www.drupal.org/node/2501313.
         $build['#markup'] = ViewsRenderPipelineSafeString::create($build['#markup']);
     }
     parent::applyDisplayCachablityMetadata($build);
     return $build;
 }
 /**
  * {@inheritdoc}
  */
 public function renderText($alter)
 {
     // We need to preserve the safeness of the value regardless of the
     // alterations made by this method. Any alterations or replacements made
     // within this method need to ensure that at the minimum the result is
     // XSS admin filtered. See self::renderAltered() as an example that does.
     $value_is_safe = SafeMarkup::isSafe($this->last_render);
     // Cast to a string so that empty checks and string functions work as
     // expected.
     $value = (string) $this->last_render;
     if (!empty($alter['alter_text']) && $alter['text'] !== '') {
         $tokens = $this->getRenderTokens($alter);
         $value = $this->renderAltered($alter, $tokens);
     }
     if (!empty($this->options['alter']['trim_whitespace'])) {
         $value = trim($value);
     }
     // Check if there should be no further rewrite for empty values.
     $no_rewrite_for_empty = $this->options['hide_alter_empty'] && $this->isValueEmpty($this->original_value, $this->options['empty_zero']);
     // Check whether the value is empty and return nothing, so the field isn't rendered.
     // First check whether the field should be hidden if the value(hide_alter_empty = TRUE) /the rewrite is empty (hide_alter_empty = FALSE).
     // For numeric values you can specify whether "0"/0 should be empty.
     if (($this->options['hide_empty'] && empty($value) || $alter['phase'] != static::RENDER_TEXT_PHASE_EMPTY && $no_rewrite_for_empty) && $this->isValueEmpty($value, $this->options['empty_zero'], FALSE)) {
         return '';
     }
     // Only in empty phase.
     if ($alter['phase'] == static::RENDER_TEXT_PHASE_EMPTY && $no_rewrite_for_empty) {
         // If we got here then $alter contains the value of "No results text"
         // and so there is nothing left to do.
         if ($value_is_safe) {
             $value = ViewsRenderPipelineSafeString::create($value);
         }
         return $value;
     }
     if (!empty($alter['strip_tags'])) {
         $value = strip_tags($value, $alter['preserve_tags']);
     }
     $suffix = '';
     if (!empty($alter['trim']) && !empty($alter['max_length'])) {
         $length = strlen($value);
         $value = $this->renderTrimText($alter, $value);
         if ($this->options['alter']['more_link'] && strlen($value) < $length) {
             $tokens = $this->getRenderTokens($alter);
             $more_link_text = $this->options['alter']['more_link_text'] ? $this->options['alter']['more_link_text'] : $this->t('more');
             $more_link_text = strtr(Xss::filterAdmin($more_link_text), $tokens);
             $more_link_path = $this->options['alter']['more_link_path'];
             $more_link_path = strip_tags(Html::decodeEntities($this->viewsTokenReplace($more_link_path, $tokens)));
             // Make sure that paths which were run through _url() work as well.
             $base_path = base_path();
             // Checks whether the path starts with the base_path.
             if (strpos($more_link_path, $base_path) === 0) {
                 $more_link_path = Unicode::substr($more_link_path, Unicode::strlen($base_path));
             }
             // @todo Views should expect and store a leading /. See
             //   https://www.drupal.org/node/2423913.
             $more_link = \Drupal::l($more_link_text, CoreUrl::fromUserInput('/' . $more_link_path, array('attributes' => array('class' => array('views-more-link')))));
             $suffix .= " " . $more_link;
         }
     }
     if (!empty($alter['nl2br'])) {
         $value = nl2br($value);
     }
     // Preserve whether or not the string is safe. Since $suffix comes from
     // \Drupal::l(), it is safe to append.
     if ($value_is_safe) {
         $value = ViewsRenderPipelineSafeString::create($value . $suffix);
     }
     $this->last_render_text = $value;
     if (!empty($alter['make_link']) && (!empty($alter['path']) || !empty($alter['url']))) {
         if (!isset($tokens)) {
             $tokens = $this->getRenderTokens($alter);
         }
         $value = $this->renderAsLink($alter, $value, $tokens);
     }
     // Preserve whether or not the string is safe. Since $suffix comes from
     // \Drupal::l(), it is safe to append.
     if ($value_is_safe) {
         return ViewsRenderPipelineSafeString::create($value . $suffix);
     } else {
         // If the string is not already marked safe, it is still OK to return it
         // because it will be sanitized by Twig.
         return $value . $suffix;
     }
 }