ConstraintManager.php

Contains \Drupal\Core\Validation\ConstraintManager.

Namespace

Drupal\Core\Validation

File

drupal/core/lib/Drupal/Core/Validation/ConstraintManager.php
View source
<?php

/**
 * @file
 * Contains \Drupal\Core\Validation\ConstraintManager.
 */
namespace Drupal\Core\Validation;

use Drupal\Component\Plugin\Factory\DefaultFactory;
use Drupal\Component\Plugin\PluginManagerBase;
use Drupal\Component\Plugin\Discovery\StaticDiscoveryDecorator;
use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator;
use Drupal\Component\Plugin\Discovery\ProcessDecorator;
use Drupal\Core\Language\Language;
use Drupal\Core\Plugin\Discovery\AlterDecorator;
use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
use Drupal\Core\Plugin\Discovery\CacheDecorator;

/**
 * Constraint plugin manager.
 *
 * Manages validation constraints based upon
 * \Symfony\Component\Validator\Constraint, whereas Symfony constraints are
 * added in manually during construction. Constraint options are passed on as
 * plugin configuration during plugin instantiation.
 *
 * While core does not prefix constraint plugins, modules have to prefix them
 * with the module name in order to avoid any naming conflicts. E.g. a "profile"
 * module would have to prefix any constraints with "Profile".
 *
 * Constraint plugins may specify data types to which support is limited via the
 * 'type' key of plugin definitions. Valid values are any types registered via
 * the typed data API, or an array of multiple type names. For supporting all
 * types FALSE may be specified. The key defaults to an empty array, i.e. no
 * types are supported.
 */
class ConstraintManager extends PluginManagerBase {

  /**
   * Overrides \Drupal\Component\Plugin\PluginManagerBase::__construct().
   *
   * @param \Traversable $namespaces
   *   An object that implements \Traversable which contains the root paths
   *   keyed by the corresponding namespace to look for plugin implementations,
   */
  public function __construct(\Traversable $namespaces) {
    $this->discovery = new AnnotatedClassDiscovery('Validation/Constraint', $namespaces);
    $this->discovery = new StaticDiscoveryDecorator($this->discovery, array(
      $this,
      'registerDefinitions',
    ));
    $this->discovery = new DerivativeDiscoveryDecorator($this->discovery);
    $this->discovery = new ProcessDecorator($this->discovery, array(
      $this,
      'processDefinition',
    ));
    $this->discovery = new AlterDecorator($this->discovery, 'validation_constraint');
    $this->discovery = new CacheDecorator($this->discovery, 'validation_constraints:' . language(Language::TYPE_INTERFACE)->langcode);
    $this->factory = new DefaultFactory($this);
  }

  /**
   * Creates a validation constraint.
   *
   * @param string $name
   *   The name or plugin id of the constraint.
   * @param mixed $options
   *   The options to pass to the constraint class. Required and supported
   *   options depend on the constraint class.
   *
   * @return \Symfony\Component\Validator\Constraint
   *   A validation constraint plugin.
   */
  public function create($name, $options) {
    if (!is_array($options)) {

      // Plugins need an array as configuration, so make sure we have one.
      // The constraint classes support passing the options as part of the
      // 'value' key also.
      $options = array(
        'value' => $options,
      );
    }
    return $this
      ->createInstance($name, $options);
  }

  /**
   * Callback for registering definitions for constraints shipped with Symfony.
   *
   * @see ConstraintManager::__construct()
   */
  public function registerDefinitions() {
    $this->discovery
      ->setDefinition('Null', array(
      'label' => t('Null'),
      'class' => '\\Symfony\\Component\\Validator\\Constraints\\Null',
      'type' => FALSE,
    ));
    $this->discovery
      ->setDefinition('NotNull', array(
      'label' => t('Not null'),
      'class' => '\\Symfony\\Component\\Validator\\Constraints\\NotNull',
      'type' => FALSE,
    ));
    $this->discovery
      ->setDefinition('Blank', array(
      'label' => t('Blank'),
      'class' => '\\Symfony\\Component\\Validator\\Constraints\\Blank',
      'type' => FALSE,
    ));
    $this->discovery
      ->setDefinition('NotBlank', array(
      'label' => t('Not blank'),
      'class' => '\\Symfony\\Component\\Validator\\Constraints\\NotBlank',
      'type' => FALSE,
    ));
    $this->discovery
      ->setDefinition('Email', array(
      'label' => t('E-mail'),
      'class' => '\\Symfony\\Component\\Validator\\Constraints\\Email',
      'type' => array(
        'string',
      ),
    ));
  }

  /**
   * Process definition callback for the ProcessDecorator.
   */
  public function processDefinition(&$definition, $plugin_id) {

    // Make sure 'type' is set and either an array or FALSE.
    if (!isset($definition['type'])) {
      $definition['type'] = array();
    }
    elseif ($definition['type'] !== FALSE && !is_array($definition['type'])) {
      $definition['type'] = array(
        $definition['type'],
      );
    }
  }

  /**
   * Returns a list of constraints that support the given type.
   *
   * @param string $type
   *   The type to filter on.
   *
   * @return array
   *   An array of constraint plugin definitions supporting the given type,
   *   keyed by constraint name (plugin ID).
   */
  public function getDefinitionsByType($type) {
    $definitions = array();
    foreach ($this
      ->getDefinitions() as $plugin_id => $definition) {
      if ($definition['type'] === FALSE || in_array($type, $definition['type'])) {
        $definitions[$plugin_id] = $definition;
      }
    }
    return $definitions;
  }

}

Classes

Namesort descending Description
ConstraintManager Constraint plugin manager.