views_streaming_data-8.x-1.x-dev/src/StreamingViewExecutable.php

src/StreamingViewExecutable.php
<?php

namespace Drupal\views_streaming_data;

use Drupal\views\ViewExecutable;
use Drupal\views_streaming_data\Plugin\views\display\StreamingDisplayInterface;

/**
 * Class StreamingViewExecutable.
 *
 * The $result property is an \Traversable instead of array.
 */
class StreamingViewExecutable extends ViewExecutable implements \IteratorAggregate {

  /**
   * Renders this view for a certain display.
   *
   * @param string $display_id
   *   The machine name of the display, which should be rendered.
   *
   * @return array|null
   *   A renderable array containing the view output or NULL if the build
   *   process failed.
   */
  public function render($display_id = NULL) {
    $success = $this->execute($display_id);

    // Check to see if the build failed.
    if (!$success || !empty($this->build_info['fail'])) {
      return;
    }
    if (!empty($this->build_info['denied'])) {
      return;
    }
    // Initialize the style plugin.
    $this->initStyle();

    $this->result = [];
    return $this->display_handler->render();
  }

  /**
   * Code copied from \Drupal\views\ViewExecutable::render()
   *
   * @param \Drupal\views\ResultRow[] $result
   *   An array of ResultRow objects returned from the query.
   */
  protected function renderResult(array &$result) {
    // Give field handlers the opportunity to perform additional queries
    // using the entire resultset prior to rendering.
    if ($this->style_plugin->usesFields()) {
      foreach ($this->field as $id => $handler) {
        if (!empty($this->field[$id])) {
          $this->field[$id]->preRender($result);
        }
      }
    }

    $this->style_plugin->preRender($result);
  }

  /**
   * Executes the view's query.
   *
   * @param string $display_id
   *   The machine name of the display, which should be executed.
   *
   * @return bool
   *   TRUE if the view execution was successful, FALSE otherwise. For example,
   *   an argument could stop the process.
   */
  public function execute($display_id = NULL) {
    if (empty($this->built)) {
      if (!$this->build($display_id)) {
        return FALSE;
      }
    }

    // Never actually run the query when in live preview mode.
    if (!empty($this->live_preview)) {
      $this->result = [];
      $this->executed = TRUE;
    }
    if (!empty($this->executed)) {
      return TRUE;
    }

    // Don't allow deactivated displays, but display them on the live preview.
    if (!$this->display_handler->isEnabled() && empty($this->live_preview)) {
      $this->build_info['fail'] = TRUE;
      return FALSE;
    }

    // Let modules modify the view just prior to executing it.
    // @phpstan-ignore globalDrupalDependencyInjection.useDependencyInjection
    $module_handler = \Drupal::moduleHandler();
    $module_handler->invokeAll('views_pre_execute', [$this]);

    $this->query->execute($this);

    // We may not want to call this.
    $this->_postExecute();

    // Let modules modify the view just after executing it.
    $module_handler->invokeAll('views_post_execute', [$this]);

    return $this->executed = TRUE;
  }

  /**
   * Get the iterator. Generator magic happens here.
   *
   * @throws \ReflectionException
   */
  public function getIterator(): \Traversable {
    $i = 0;
    $chunk_size = $this->display_handler->getOption('chunk_size') ?: StreamingDisplayInterface::DEFAULT_CHUNK_SIZE;
    do {
      $result = [];
      $j = 0;
      do {
        $row = $this->query->result->fetch();
        if ($row) {
          $row->index = $i;
          $result[$i] = $row;
          $i++;
        }
        $j++;
      } while ($row && $j < $chunk_size);
      // Load all entities contained in the results.
      $this->query->loadEntities($result);
      $this->renderResult($result);
      $this->result = $result;
      foreach ($result as $index => $row) {
        yield $index => $row;
      }
      // This ugliness is because of the behavior in
      // \Drupal\views\Entity\Render\EntityFieldRenderer::render() where
      // it saves a build after rendering every row in the $view->result.
      // We are trying to get chunks of 50 rendered at a time, so we need to
      // force reinitialize the build.
      foreach ($this->field as $obj) {
        $reflected = new \ReflectionClass($obj);
        if ($reflected->hasProperty('entityFieldRenderer')) {
          $efr = $reflected->getProperty('entityFieldRenderer');
          $efr->setAccessible(TRUE);
          $efr->setValue($obj, NULL);
        }
      }

    } while ($result);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc