access_policy-1.0.x-dev/src/AccessRuleQueryHandler/EntityFieldBase.php

src/AccessRuleQueryHandler/EntityFieldBase.php
<?php

namespace Drupal\access_policy\AccessRuleQueryHandler;

use Drupal\access_policy\Validation\ExecutionContext;
use Drupal\Core\Entity\EntityInterface;

/**
 * Field value access rule query handler.
 */
class EntityFieldBase extends AccessRuleQueryHandlerBase {

  /**
   * {@inheritdoc}
   */
  public function query() {
    $this->ensureMyTable();

    $values = $this->getValue();

    switch ($this->definition->getSetting('empty_behavior')) {
      case 'deny':
        $this->queryDenyEmpty($values);
        break;

      case 'allow':
        $this->queryAllowEmpty($values);
        break;

      case 'ignore':
        $this->queryIgnoreEmpty($values);
        break;

      default:
        $this->queryCallback($values, $this->query);
        break;
    }

  }

  /**
   * Perform query when empty values are not allowed.
   *
   * @param array $values
   *   Array of values.
   */
  public function queryDenyEmpty(array $values) {
    // If values are empty then add a 0 because that will never be matched
    // and it will hide it from results.
    if (empty($values)) {
      $values = [0];
      $this->query->condition($this->realField, $values, 'IN');
    }
    else {
      $this->queryCallback($values, $this->query);
    }
  }

  /**
   * Perform regular query when empty values are ignored.
   *
   * @param array $values
   *   Array of values.
   */
  public function queryIgnoreEmpty(array $values) {
    // Ignore will mostly be used with other access rules. However, if there
    // is only one access rule and its set to ignore it's equivalent to
    // allow.
    $access_policy = $this->definition->getAccessPolicy();
    $policy = $this->entityTypeManager->getStorage('access_policy')->load($access_policy);
    $rules = $policy->getAccessRules();
    if (count($rules) == 1) {
      $this->queryAllowEmpty($values);
    }
    // If there is more than one access rule then we still want to filter
    // content that has values.
    else {
      if (!empty($values)) {
        $this->queryCallback($values, $this->query);
      }
      else {
        // If this access rule doesn't have any values, nor do any of the other
        // access rules have values then we can add an OR IS NULL to be less
        // restrictive.
        if (!$this->hasOtherAccessRuleValues($policy)) {
          $orGroup = $this->query->orConditionGroup();
          $orGroup->condition($this->realField, NULL, 'IS NULL');
          $this->query->condition($orGroup);
        }
      }
    }
  }

  /**
   * Determine whether any of the other access rules have values.
   *
   * If other access rules have values then we need to be more restrictive with
   * the ignore behavior. If they don't have values then we can be more
   * forgiving.
   *
   * @param \Drupal\Core\Entity\EntityInterface $access_policy
   *   The current access policy.
   *
   * @return bool
   *   TRUE if other access rules have values; FALSE otherwise.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function hasOtherAccessRuleValues(EntityInterface $access_policy) {
    $access_rules = \Drupal::service('plugin.manager.access_policy.access_rule')
      ->getHandlersFromPolicy($access_policy);

    $context = ExecutionContext::create('view', ['user' => $this->currentUser]);
    foreach ($access_rules as $id => $plugin) {
      $is_not_same_plugin = $id != $this->definition->getId();
      if ($is_not_same_plugin) {
        $plugin->setContext($context);
        $values = $plugin->getValue();
        if (!empty($values)) {
          return TRUE;
        }
      }
    }

    return FALSE;
  }

  /**
   * Perform query when empty values are allowed.
   *
   * @param array $values
   *   Array of values.
   */
  public function queryAllowEmpty(array $values) {
    $orGroup = $this->query->orConditionGroup();
    $orGroup->condition($this->realField, NULL, 'IS NULL');
    if (!empty($values)) {
      $this->queryCallback($values, $orGroup);
    }

    $this->query->condition($orGroup);
  }

  /**
   * Query method callback.
   *
   * @param array $values
   *   The array of values.
   * @param \Drupal\access_policy\QueryInterface|\Drupal\Core\Database\Query\ConditionInterface $query
   *   The condition/query object. This is set to NULL because the query could
   *   happen to a condition group or to the main query, they do not implement
   *   the same interface.
   */
  public function queryCallback(array $values, $query = NULL) {
    $operator = $this->getOperator();
    $info = $this->operators();
    if (!empty($info[$operator]['method'])) {
      $this->{$info[$operator]['method']}($values, $query);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function ensureMyTable() {
    $base_field_placeholder = $this->query->getBaseTable() . '.' . $this->query->getBaseField();
    $this->query->leftJoin($this->tableAlias, $this->tableAlias, $this->tableAlias . "." . $this->joinField . ' = ' . $base_field_placeholder);
  }

  /**
   * The default operators.
   *
   * @return array
   *   Array of operators and their methods.
   */
  public function operators() {
    return [
      'in' => [
        'method' => 'opIn',
      ],
      'not in' => [
        'method' => 'opNotIn',
      ],
    ];
  }

  /**
   * IN operator.
   *
   * @param array $values
   *   The current values.
   * @param \Drupal\access_policy\QueryInterface|\Drupal\Core\Database\Query\ConditionInterface $query
   *   The query or condition object.
   */
  public function opIn(array $values, $query) {
    $query->condition($this->realField, $values, 'IN');
  }

  /**
   * NOT IN operator.
   *
   * @param array $values
   *   The current values.
   * @param \Drupal\access_policy\QueryInterface|\Drupal\Core\Database\Query\ConditionInterface $query
   *   The query or condition object.
   */
  public function opNotIn(array $values, $query) {
    $query->condition($this->realField, $values, 'NOT IN');
  }

}

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

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