You are here

class Xml in Views XML Backend 8

Views query plugin for an XML query.

Plugin annotation


@ViewsQuery(
  id = "views_xml_backend",
  title = @Translation("XML Query"),
  help = @Translation("Query will be generated and run using the XML backend.")
)

Hierarchy

Expanded class hierarchy of Xml

6 files declare their use of Xml
DateTest.php in tests/src/Unit/Plugin/views/sort/DateTest.php
Contains \Drupal\Tests\views_xml_backend\Unit\Plugin\views\sort\DateTest.
NumericTest.php in tests/src/Unit/Plugin/views/sort/NumericTest.php
Contains \Drupal\Tests\views_xml_backend\Unit\Plugin\views\sort\NumericTest.
StandardTest.php in tests/src/Unit/Plugin/views/sort/StandardTest.php
Contains \Drupal\Tests\views_xml_backend\Unit\Plugin\views\sort\StandardTest.
StandardTest.php in tests/src/Unit/Plugin/views/field/StandardTest.php
Contains \Drupal\Tests\views_xml_backend\Unit\Plugin\views\field\StandardTest.
views_xml_backend.module in ./views_xml_backend.module
Hook implementations for views_xml_backend.

... See full list

File

src/Plugin/views/query/Xml.php, line 39
Contains \Drupal\views_xml_backend\Plugin\views\query\Xml.

Namespace

Drupal\views_xml_backend\Plugin\views\query
View source
class Xml extends QueryPluginBase {

  /**
   * The default cache directory.
   *
   * @var string
   */
  const DEFAULT_CACHE_DIR = 'public://views_xml_backend';

  /**
   * A simple array of order by clauses.
   *
   * @var array
   */
  public $orderby = [];

  /**
   * A list of added arguments.
   *
   * @var \Drupal\views_xml_backend\Plugin\views\argument\XmlArgumentInterface[]
   */
  protected $arguments = [];

  /**
   * The cache backend.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $cacheBackend;

  /**
   * Extra fields to query. Added from sorters.
   *
   * @var string[]
   */
  protected $extraFields = [];

  /**
   * The HTTP client.
   *
   * @var \GuzzleHttp\ClientInterface
   */
  protected $httpClient;

  /**
   * The applied filters.
   *
   * @var XmlFilterInterface[]
   */
  protected $filters = [];

  /**
   * Whether the current view is in preview.
   *
   * @var bool
   */
  protected $livePreview = FALSE;

  /**
   * The logger.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * The messenger used for drupal_set_message().
   *
   * @var \Drupal\views_xml_backend\MessengerInterface
   */
  protected $messenger;

  /**
   * Constructs an Xml object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \GuzzleHttp\ClientInterface $http_client
   *   The HTTP client.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
   *   The cache backend.
   * @param \Psr\Log\LoggerInterface $logger
   *   The logger.
   * @param \Drupal\views_xml_backend\MessengerInterface $messenger
   *   The messenger used to display messages to the user.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, ClientInterface $http_client, CacheBackendInterface $cache_backend, LoggerInterface $logger, MessengerInterface $messenger) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->httpClient = $http_client;
    $this->cacheBackend = $cache_backend;
    $this->logger = $logger;
    $this->messenger = $messenger;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container
      ->get('http_client'), $container
      ->get('cache.views_xml_backend_download'), $container
      ->get('logger.factory')
      ->get('views_xml_backend'), new Messenger());
  }

  /**
   * {@inheritdoc}
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['xml_file']['default'] = '';
    $options['row_xpath']['default'] = '';
    $options['default_namespace']['default'] = 'default';
    $options['show_errors']['default'] = TRUE;
    return $options;
  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);
    $form['xml_file'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('XML File'),
      '#default_value' => $this->options['xml_file'],
      '#description' => $this
        ->t('The URL or path to the XML file.'),
      '#maxlength' => 1024,
      '#required' => TRUE,
    ];
    $form['row_xpath'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Row Xpath'),
      '#default_value' => $this->options['row_xpath'],
      '#description' => $this
        ->t('An xpath function that selects rows.'),
      '#maxlength' => 1024,
      '#required' => TRUE,
    ];
    $form['default_namespace'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Default namespace'),
      '#default_value' => $this->options['default_namespace'],
      '#description' => $this
        ->t("If the xml contains a default namespace, it will be accessible as 'default:element'. If you want something different, declare it here."),
    ];
    $form['show_errors'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Show XML errors'),
      '#default_value' => $this->options['show_errors'],
      '#description' => $this
        ->t('If there were any errors during XML parsing, display them. It is recommended to leave this on during development.'),
    ];
  }

  /**
   * Ensures a table exists in the queue.
   *
   * If it already exists it won't do anything, but if it doesn't it will add
   * the table queue. It will ensure a path leads back to the relationship
   * table.
   *
   * @param string $table
   *   The unaliased name of the table to ensure.
   * @param string $relationship
   *   The relationship to ensure the table links to. Each relationship will
   *   get a unique instance of the table being added. If not specified,
   *   will be the primary table.
   * @param \Drupal\views\Plugin\views\join\JoinPluginBase $join
   *   A Join object (or derived object) to join the alias in.
   *
   * @return string
   *   The alias used to refer to this specific table, or NULL if the table
   *   cannot be ensured.
   */
  public function ensureTable($table, $relationship = NULL, JoinPluginBase $join = NULL) {
    return $table;
  }

  /**
   * Adds an argument.
   *
   * @param \Drupal\views_xml_backend\Plugin\views\argument\XmlArgumentInterface $argument
   *   The argument to add.
   */
  public function addArgument(XmlArgumentInterface $argument) {
    $this->arguments[] = $argument;
  }

  /**
   * Adds a new field to be queried.
   *
   * @param string $field
   *   The field name.
   * @param string $xpath
   *   The XPath selector to query the field value.
   */
  public function addField($field, $xpath) {
    $this->extraFields[$field] = $xpath;
  }

  /**
   * Adds a filter.
   *
   * @param \Drupal\views_xml_backend\Plugin\views\filter\XmlFilterInterface $filter
   *   The filter to add.
   */
  public function addFilter(XmlFilterInterface $filter) {
    $this->filters[] = $filter;
  }

  /**
   * Add an ORDER BY clause to the query.
   *
   * This is only used to support the built-in random sort plugin.
   *
   * @param string $table
   *   The table this field is part of. If a formula, enter NULL.
   *   If you want to orderby random use "rand" as table and nothing else.
   * @param string $field
   *   The field or formula to sort on. If already a field, enter NULL
   *   and put in the alias.
   * @param string $order
   *   Either ASC or DESC.
   * @param string $alias
   *   The alias to add the field as. In SQL, all fields in the order by
   *   must also be in the SELECT portion. If an $alias isn't specified
   *   one will be generated for from the $field; however, if the
   *   $field is a formula, this alias will likely fail.
   * @param array $params
   *   Any params that should be passed through to the addField.
   */
  public function addOrderBy($table, $field = NULL, $order = 'ASC', $alias = '', $params = []) {
    if ($table === 'rand') {
      $this->orderby[] = 'shuffle';
    }
  }

  /**
   * Adds a sorter callable.
   *
   * @param callable $callback
   *   A callable that can sort a views result.
   *
   * @see \Drupal\views_xml_backend\Sorter\SorterInterface
   */
  public function addSort(callable $callback) {
    $this->orderby[] = $callback;
  }

  /**
   * Adds a simple WHERE clause to the query.
   *
   * The caller is responsible for ensuring that all fields are fully qualified
   * (TABLE.FIELD) and that the table already exists in the query.
   *
   * @param $group
   *   The WHERE group to add these to; groups are used to create AND/OR
   *   sections. Groups cannot be nested. Use 0 as the default group.
   *   If the group does not yet exist it will be created as an AND group.
   * @param $field
   *   The name of the field to check.
   * @param $value
   *   The value to test the field against. In most cases, this is a scalar. For more
   *   complex options, it is an array. The meaning of each element in the array is
   *   dependent on the $operator.
   * @param $operator
   *   The comparison operator, such as =, <, or >=. It also accepts more
   *   complex options such as IN, LIKE, LIKE BINARY, or BETWEEN. Defaults to =.
   *   If $field is a string you have to use 'formula' here.
   */
  public function addWhere($group, $field, $value = NULL, $operator = NULL) {
    if ($group && $operator === 'in') {
      if (strpos($field, '.') !== FALSE) {
        list(, $field) = explode('.', $field);
      }
      if (!isset($this->view->field[$field])) {
        return;
      }
      $xpath = $this->view->field[$field]->options['xpath_selector'];
      $values = [];
      foreach ($value as $v) {
        $v = Xpath::escapeXpathString($v);
        $values[] = "{$xpath} = {$v}";
      }
      $this->filters[] = implode(' or ', $values);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function query($get_count = FALSE) {
    $row_xpath = $this->options['row_xpath'];
    if ($this->filters) {

      // @todo Add an option for the filters to be 'and' or 'or'.
      $row_xpath .= '[' . implode(' and ', $this->filters) . ']';
    }
    if ($this->arguments) {
      $row_xpath .= '[' . implode(' and ', $this->arguments) . ']';
    }
    return $row_xpath;
  }

  /**
   * {@inheritdoc}
   */
  public function build(ViewExecutable $view) {
    $this->view = $view;
    $view
      ->initPager();

    // Let the pager modify the query to add limits.
    $view->pager
      ->query();
    $view->build_info['query'] = $this
      ->query();
    $view->build_info['count_query'] = '';
    $this->livePreview = !empty($view->live_preview);
  }

  /**
   * {@inheritdoc}
   */
  public function execute(ViewExecutable $view) {

    // When creating a new view, there won't be a query set yet.
    if ($view->build_info['query'] === '') {
      $this->messenger
        ->setMessage($this
        ->t('Please configure the query settings.'), 'warning');
      return;
    }
    $start = microtime(TRUE);
    libxml_clear_errors();
    $use_errors = libxml_use_internal_errors(TRUE);
    $this
      ->doExecute($view);
    if ($this->livePreview && $this->options['show_errors']) {
      foreach (libxml_get_errors() as $error) {
        $type = $error->level === LIBXML_ERR_FATAL ? 'error' : 'warning';
        $args = [
          '%error' => trim($error->message),
          '%num' => $error->line,
          '%code' => $error->code,
        ];
        $this->messenger
          ->setMessage($this
          ->t('%error on line %num. Error code: %code', $args), $type);
      }
    }
    libxml_use_internal_errors($use_errors);
    libxml_clear_errors();
    $view->execute_time = microtime(TRUE) - $start;
  }

  /**
   * Performs the actual view execution.
   *
   * @param ViewExecutable $view
   *   The view to execute.
   *
   * @see Xml::execute()
   */
  protected function doExecute(ViewExecutable $view) {
    $xpath = $this
      ->getXpath($this
      ->fetchFileContents($this
      ->getXmlDocumentPath($view)));
    if ($view->pager
      ->useCountQuery() || !empty($view->get_total_rows)) {

      // Normall we would call $view->pager->executeCountQuery($count_query);
      // but we can't in this case, so do the calculation ourselves.
      $view->pager->total_items = $xpath
        ->query($view->build_info['query'])->length;
      $view->pager->total_items -= $view->pager
        ->getOffset();
    }
    foreach ($xpath
      ->query($view->build_info['query']) as $row) {
      $result_row = new ResultRow();
      $view->result[] = $result_row;
      foreach ($view->field as $field_name => $field) {
        if (!isset($field->options['xpath_selector']) || $field->options['xpath_selector'] === '') {
          continue;
        }
        $result_row->{$field_name} = $this
          ->executeRowQuery($xpath, $field->options['xpath_selector'], $row);
      }
      foreach ($this->extraFields as $field_name => $selector) {
        $result_row->{$field_name} = $this
          ->executeRowQuery($xpath, $selector, $row);
      }
    }
    $this
      ->executeSorts($view);
    if (!empty($this->limit) || !empty($this->offset)) {

      // @todo Re-implement the performance optimization. For the case with no
      // sorts, we can avoid parsing the whole file.
      $view->result = array_slice($view->result, (int) $this->offset, (int) $this->limit);
    }

    // Set the index values after all manipulation is done.
    $this
      ->reIndexResults($view);
    $view->pager
      ->postExecute($view->result);
    $view->pager
      ->updatePageInfo();
    $view->total_rows = $view->pager
      ->getTotalItems();
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheMaxAge() {
    return 0;
  }

  /**
   * Returns the path to the XML file after token substitution.
   *
   * @param \Drupal\views\ViewExecutable $view
   *   The view.
   *
   * @return string
   *   The file path or URL.
   */
  protected function getXmlDocumentPath(ViewExecutable $view) {

    // This should be safe from malicious user input since the URL is internal
    // and an invalid one will just produce a download error.
    return strtr($this->options['xml_file'], $view
      ->getDisplay()
      ->getArgumentsTokens());
  }

  /**
   * Returns the XPath object for this query.
   *
   * @param string $contents
   *   The XML file contents.
   *
   * @return \DOMXPath
   *   An XPath object.
   */
  protected function getXpath($contents) {
    if ($contents === '') {
      return new \DOMXPath(new \DOMDocument());
    }
    $xpath = new \DOMXPath($this
      ->createDomDocument($contents));
    $this
      ->registerNamespaces($xpath);
    $xpath
      ->registerPhpFunctions('views_xml_backend_date');
    $xpath
      ->registerPhpFunctions('views_xml_backend_format_value');
    return $xpath;
  }

  /**
   * Creates a very forgiving DOMDocument.
   *
   * @param string $contents
   *   The XML content of the DOMDocument.
   *
   * @return \DOMDocument
   *   A new DOMDocument.
   */
  protected function createDomDocument($contents) {

    // Try to make the XML loading as forgiving as possible.
    $document = new \DOMDocument();
    $document->strictErrorChecking = FALSE;
    $document->resolveExternals = FALSE;

    // Libxml specific.
    $document->substituteEntities = TRUE;
    $document->recover = TRUE;
    $options = LIBXML_NONET;
    if (defined('LIBXML_COMPACT')) {
      $options |= LIBXML_COMPACT;
    }
    if (defined('LIBXML_PARSEHUGE')) {
      $options |= LIBXML_PARSEHUGE;
    }
    if (defined('LIBXML_BIGLINES')) {
      $options |= LIBXML_BIGLINES;
    }

    // @see http://symfony.com/blog/security-release-symfony-2-0-11-released
    $disable_entities = libxml_disable_entity_loader(TRUE);
    $document
      ->loadXML($contents, $options);

    // @see http://symfony.com/blog/security-release-symfony-2-0-17-released
    foreach ($document->childNodes as $child) {
      if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
        if ($this->livePreview) {
          $this->messenger
            ->setMessage($this
            ->t('A suspicious document was detected.'), 'error');
        }

        // @todo Add more context. The specific view? A link to the page?
        $this->logger
          ->error('A suspicious document was detected.');

        // Overwrite the document to allow processing to continue.
        $document = new \DOMDocument();
        break;
      }
    }
    libxml_disable_entity_loader($disable_entities);
    return $document;
  }

  /**
   * Returns the contents of an XML file.
   *
   * @param string $uri
   *   A URL, or local file path.
   *
   * @return string
   *   The contents of the XML file.
   */
  protected function fetchFileContents($uri) {
    if ($uri === '') {
      if ($this->livePreview) {
        $this->messenger
          ->setMessage($this
          ->t('Please enter a file path or URL in the query settings.'));
      }
      return '';
    }
    $parsed = parse_url($uri);

    // Check for local file.
    if (empty($parsed['host'])) {
      return $this
        ->fetchLocalFile($uri);
    }
    return $this
      ->fetchRemoteFile($uri);
  }

  /**
   * Returns the contents of a local file.
   *
   * @param string $uri
   *   The local file path.
   *
   * @return string
   *   The file contents.
   */
  protected function fetchLocalFile($uri) {
    if (file_exists($uri)) {
      return file_get_contents($uri);
    }
    if ($this->livePreview) {
      $this->messenger
        ->setMessage($this
        ->t('Local file not found: @uri', [
        '@uri' => $uri,
      ]), 'error');
    }
    $this->logger
      ->error('Local file not found: @uri', [
      '@uri' => $uri,
    ]);
    return '';
  }

  /**
   * Returns the contents of a remote file.
   *
   * @param string $uri
   *   The remote file URL.
   *
   * @return string
   *   The file contents.
   */
  protected function fetchRemoteFile($uri) {
    $destination = Settings::get('views_xml_backend_cache_directory', static::DEFAULT_CACHE_DIR);
    if (!file_prepare_directory($destination, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
      if ($this->livePreview) {
        $this->messenger
          ->setMessage($this
          ->t('File cache directory either cannot be created or is not writable.'), 'error');
      }
      $this->logger
        ->error('File cache directory either cannot be created or is not writable.');
      return (string) $this
        ->doGetRequest($uri)
        ->getBody();
    }
    $cache_key = hash('sha256', $uri);
    $cache_file = "{$destination}/{$cache_key}";
    $options = [];

    // Add cached headers if requested.
    if ($cache = $this->cacheBackend
      ->get($cache_key)) {
      if (isset($cache->data['etag'])) {
        $options[RequestOptions::HEADERS]['If-None-Match'] = $cache->data['etag'];
      }
      if (isset($cache->data['last-modified'])) {
        $options[RequestOptions::HEADERS]['If-Modified-Since'] = $cache->data['last-modified'];
      }
    }
    $response = $this
      ->doGetRequest($uri, $options);
    if ($response
      ->getStatusCode() === 304) {
      if (file_exists($cache_file)) {
        return file_get_contents($cache_file);
      }

      // We have the headers but no cache file. Run it again.
      $this->cacheBackend
        ->delete($cache_key);
      return $this
        ->fetchRemoteFile($uri);
    }

    // We had a failed requset. Try to return the old result.
    if ($response
      ->getStatusCode() === -100) {
      if (file_exists($cache_file)) {
        return file_get_contents($cache_file);
      }
    }
    $data = trim($response
      ->getBody());
    file_unmanaged_save_data($data, $cache_file, FILE_EXISTS_REPLACE);
    $this->cacheBackend
      ->set($cache_key, array_change_key_case($response
      ->getHeaders()));
    return $data;
  }

  /**
   * Performs a GET request.
   *
   * @param string $url
   *   The URL to GET.
   * @param array $options
   *   Options to pass to Guzzle.
   *
   * @return \Psr\Http\Message\ResponseInterface
   *   An HTTP response.
   */
  protected function doGetRequest($url, $options = []) {
    try {
      return $this->httpClient
        ->get($url, $options);
    } catch (\RuntimeException $e) {

      // @todo We can add more granular error messages based on Guzzle exception
      // types. We could also display this error with dsm() if we're in preview.
      $args = [
        '@url' => $url,
        '%message' => $e
          ->getMessage(),
      ];
      $this->logger
        ->error('An error occured while downloading @url: %message.', $args);
      if ($this->livePreview) {
        $this->messenger
          ->setMessage($this
          ->t('An error occured while downloading @url: %message.', $args), 'error');
      }
    }

    // Fake a response.
    return new Response(-100, [], '');
  }

  /**
   * Registers available namespaces.
   *
   * @param \DOMXPath $xpath
   *   The XPath object.
   */
  protected function registerNamespaces(\DOMXPath $xpath) {
    $xpath
      ->registerNamespace('php', 'http://php.net/xpath');
    if (!($simple = @simplexml_import_dom($xpath->document))) {
      return;
    }
    foreach ($simple
      ->getNamespaces(TRUE) as $prefix => $namespace) {
      if ($prefix === '') {
        $prefix = $this->options['default_namespace'];
      }
      $xpath
        ->registerNamespace($prefix, $namespace);
    }
  }

  /**
   * This is currently unused as it's a performance enhancement.
   */
  protected function calculatePager(ViewExecutable $view) {
    if (empty($this->limit) && empty($this->offset)) {
      return;
    }
    $limit = intval(!empty($this->limit) ? $this->limit : 999999);
    $offset = intval(!empty($this->offset) ? $this->offset : 0);
    $limit += $offset;
    $view->build_info['query'] .= "[position() > {$offset} and not(position() > {$limit})]";
  }

  /**
   * Executes an XPath query on a given row.
   *
   * @param \DOMXPath $xpath
   *   The XPath object.
   * @param string $selector
   *   The XPath selector.
   * @param \DOMNode $row
   *   The row as.
   *
   * @return string[]
   *   Returns a list of values from the row.
   */
  protected function executeRowQuery(\DOMXPath $xpath, $selector, \DOMNode $row) {
    $node_list = $xpath
      ->query($selector, $row);
    if ($node_list === FALSE) {
      return [];
    }
    $values = [];
    foreach ($node_list as $node) {
      $values[] = $node->nodeValue;
    }
    return $values;
  }

  /**
   * Executes all added sorts to a view.
   *
   * @param \Drupal\views\ViewExecutable $view
   *   The view to sort.
   */
  protected function executeSorts(ViewExecutable $view) {
    foreach (array_reverse($this->orderby) as $sort) {

      // We need to re-index the results before each sort because the index is
      // used to maintain a stable sort.
      $this
        ->reIndexResults($view);
      $sort($view->result);
    }
  }

  /**
   * Re-indexes the results of a view.
   *
   * @param \Drupal\views\ViewExecutable $view
   *   The view to re-index.
   */
  protected function reIndexResults(ViewExecutable $view) {
    $index = 0;
    foreach ($view->result as $row) {
      $row->index = $index++;
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$definition public property Plugins's definition
PluginBase::$displayHandler public property The display object this plugin is for.
PluginBase::$options public property Options for this plugin will be held here.
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::$renderer protected property Stores the render API renderer. 3
PluginBase::$usesOptions protected property Denotes whether the plugin has an additional options form. 8
PluginBase::$view public property The top object of a view. 1
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::destroy public function Clears a plugin. Overrides ViewsPluginInterface::destroy 2
PluginBase::doFilterByDefinedOptions protected function Do the work to filter out stored options depending on the defined options.
PluginBase::filterByDefinedOptions public function Filter out stored options depending on the defined options. Overrides ViewsPluginInterface::filterByDefinedOptions
PluginBase::getAvailableGlobalTokens public function Returns an array of available token replacements. Overrides ViewsPluginInterface::getAvailableGlobalTokens
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::getProvider public function Returns the plugin provider. Overrides ViewsPluginInterface::getProvider
PluginBase::getRenderer protected function Returns the render API renderer. 1
PluginBase::globalTokenForm public function Adds elements for available core tokens to a form. Overrides ViewsPluginInterface::globalTokenForm
PluginBase::globalTokenReplace public function Returns a string with any core tokens replaced. Overrides ViewsPluginInterface::globalTokenReplace
PluginBase::INCLUDE_ENTITY constant Include entity row languages when listing languages.
PluginBase::INCLUDE_NEGOTIATED constant Include negotiated languages when listing languages.
PluginBase::init public function Initialize the plugin. Overrides ViewsPluginInterface::init 8
PluginBase::isConfigurable public function Determines if the plugin is configurable.
PluginBase::listLanguages protected function Makes an array of languages, optionally including special languages.
PluginBase::pluginTitle public function Return the human readable name of the display. Overrides ViewsPluginInterface::pluginTitle
PluginBase::preRenderAddFieldsetMarkup public static function Moves form elements into fieldsets for presentation purposes. Overrides ViewsPluginInterface::preRenderAddFieldsetMarkup
PluginBase::preRenderFlattenData public static function Flattens the structure of form elements. Overrides ViewsPluginInterface::preRenderFlattenData
PluginBase::queryLanguageSubstitutions public static function Returns substitutions for Views queries for languages.
PluginBase::setOptionDefaults protected function Fills up the options of the plugin with defaults.
PluginBase::themeFunctions public function Provide a full list of possible theme templates used by this style. Overrides ViewsPluginInterface::themeFunctions 1
PluginBase::trustedCallbacks public static function Lists the trusted callbacks provided by the implementing class. Overrides TrustedCallbackInterface::trustedCallbacks 6
PluginBase::unpackOptions public function Unpack options over our existing defaults, drilling down into arrays so that defaults don't get totally blown away. Overrides ViewsPluginInterface::unpackOptions
PluginBase::usesOptions public function Returns the usesOptions property. Overrides ViewsPluginInterface::usesOptions 8
PluginBase::validate public function Validate that the plugin is correct and can be saved. Overrides ViewsPluginInterface::validate 6
PluginBase::viewsTokenReplace protected function Replaces Views' tokens in a given string. The resulting string will be sanitized with Xss::filterAdmin. 1
PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT constant Query string to indicate the site default language.
QueryPluginBase::$limit protected property Stores the limit of items that should be requested in the query.
QueryPluginBase::$pager public property A pager plugin that should be provided by the display.
QueryPluginBase::addSignature public function Add a signature to the query, if such a thing is feasible. 1
QueryPluginBase::alter public function Let modules modify the query just prior to finalizing it. 1
QueryPluginBase::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides PluginBase::calculateDependencies 1
QueryPluginBase::getAggregationInfo public function Get aggregation info for group by queries. 1
QueryPluginBase::getCacheContexts public function The cache contexts associated with this object. Overrides CacheableDependencyInterface::getCacheContexts
QueryPluginBase::getCacheTags public function The cache tags associated with this object. Overrides CacheableDependencyInterface::getCacheTags 1
QueryPluginBase::getDateField public function Returns a Unix timestamp to database native timestamp expression. 1
QueryPluginBase::getDateFormat public function Creates cross-database date formatting. 1
QueryPluginBase::getEntityTableInfo public function Returns an array of all tables from the query that map to an entity type.
QueryPluginBase::getLimit public function Returns the limit of the query.
QueryPluginBase::getTimezoneOffset public function Get the timezone offset in seconds.
QueryPluginBase::loadEntities public function Loads all entities contained in the passed-in $results. . If the entity belongs to the base table, then it gets stored in $result->_entity. Otherwise, it gets stored in $result->_relationship_entities[$relationship_id]; 1
QueryPluginBase::setFieldTimezoneOffset public function Applies a timezone offset to the given field. 2
QueryPluginBase::setGroupOperator public function Control how all WHERE and HAVING groups are put together.
QueryPluginBase::setLimit public function Set a LIMIT on the query, specifying a maximum number of results.
QueryPluginBase::setOffset public function Set an OFFSET on the query, specifying a number of results to skip
QueryPluginBase::setupTimezone public function Set the database to the current user timezone. 1
QueryPluginBase::setWhereGroup public function Create a new grouping for the WHERE or HAVING clause.
QueryPluginBase::submitOptionsForm public function Handle any special handling on the validate form. Overrides PluginBase::submitOptionsForm 1
QueryPluginBase::summaryTitle public function Returns the summary of the settings in the display. Overrides PluginBase::summaryTitle
QueryPluginBase::validateOptionsForm public function Validate the options form. Overrides PluginBase::validateOptionsForm
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
TrustedCallbackInterface::THROW_EXCEPTION constant Untrusted callbacks throw exceptions.
TrustedCallbackInterface::TRIGGER_SILENCED_DEPRECATION constant Untrusted callbacks trigger silenced E_USER_DEPRECATION errors.
TrustedCallbackInterface::TRIGGER_WARNING constant Untrusted callbacks trigger E_USER_WARNING errors.
Xml::$arguments protected property A list of added arguments.
Xml::$cacheBackend protected property The cache backend.
Xml::$extraFields protected property Extra fields to query. Added from sorters.
Xml::$filters protected property The applied filters.
Xml::$httpClient protected property The HTTP client.
Xml::$livePreview protected property Whether the current view is in preview.
Xml::$logger protected property The logger.
Xml::$messenger protected property The messenger used for drupal_set_message(). Overrides MessengerTrait::$messenger
Xml::$orderby public property A simple array of order by clauses.
Xml::addArgument public function Adds an argument.
Xml::addField public function Adds a new field to be queried.
Xml::addFilter public function Adds a filter.
Xml::addOrderBy public function Add an ORDER BY clause to the query.
Xml::addSort public function Adds a sorter callable.
Xml::addWhere public function Adds a simple WHERE clause to the query.
Xml::build public function Builds the necessary info to execute the query. Overrides QueryPluginBase::build
Xml::buildOptionsForm public function Provide a form to edit options for this plugin. Overrides PluginBase::buildOptionsForm
Xml::calculatePager protected function This is currently unused as it's a performance enhancement.
Xml::create public static function Creates an instance of the plugin. Overrides PluginBase::create
Xml::createDomDocument protected function Creates a very forgiving DOMDocument.
Xml::DEFAULT_CACHE_DIR constant The default cache directory.
Xml::defineOptions protected function Information about options for all kinds of purposes will be held here. Overrides PluginBase::defineOptions
Xml::doExecute protected function Performs the actual view execution.
Xml::doGetRequest protected function Performs a GET request.
Xml::ensureTable public function Ensures a table exists in the queue.
Xml::execute public function Executes the query and fills the associated view object with according values. Overrides QueryPluginBase::execute
Xml::executeRowQuery protected function Executes an XPath query on a given row.
Xml::executeSorts protected function Executes all added sorts to a view.
Xml::fetchFileContents protected function Returns the contents of an XML file.
Xml::fetchLocalFile protected function Returns the contents of a local file.
Xml::fetchRemoteFile protected function Returns the contents of a remote file.
Xml::getCacheMaxAge public function The maximum age for which this object may be cached. Overrides QueryPluginBase::getCacheMaxAge
Xml::getXmlDocumentPath protected function Returns the path to the XML file after token substitution.
Xml::getXpath protected function Returns the XPath object for this query.
Xml::query public function Generate a query and a countquery from all of the information supplied to the object. Overrides QueryPluginBase::query
Xml::registerNamespaces protected function Registers available namespaces.
Xml::reIndexResults protected function Re-indexes the results of a view.
Xml::__construct public function Constructs an Xml object. Overrides PluginBase::__construct