Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. Constraint.php

class Constraint

Same name in this branch
  1. 11.1.x vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php \PHPUnit\Framework\Constraint\Constraint
  2. 11.1.x vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php \JsonSchema\Constraints\Constraint
  3. 11.1.x vendor/symfony/validator/Constraint.php \Symfony\Component\Validator\Constraint
  4. 11.1.x core/lib/Drupal/Core/Validation/Annotation/Constraint.php \Drupal\Core\Validation\Annotation\Constraint
  5. 11.1.x core/lib/Drupal/Core/Validation/Attribute/Constraint.php \Drupal\Core\Validation\Attribute\Constraint
  6. 11.1.x core/lib/Drupal/Component/Version/Constraint.php \Drupal\Component\Version\Constraint

Defines a constraint.

Hierarchy

  • class \Composer\Semver\Constraint\Constraint implements \Composer\Semver\Constraint\ConstraintInterface

Expanded class hierarchy of Constraint

31 files declare their use of Constraint
AliasPackage.php in vendor/composer/composer/src/Composer/Package/AliasPackage.php
ArrayRepository.php in vendor/composer/composer/src/Composer/Repository/ArrayRepository.php
CakePHPInstaller.php in vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php
CheckPlatformReqsCommand.php in vendor/composer/composer/src/Composer/Command/CheckPlatformReqsCommand.php
Comparator.php in vendor/composer/semver/src/Comparator.php

... See full list

2 string references to 'Constraint'
Problem::getMissingPackageReason in vendor/composer/composer/src/Composer/DependencyResolver/Problem.php
@internal
RuleReasonDataReturnTypeExtension::getTypeFromMethodCall in vendor/composer/composer/src/Composer/PHPStan/RuleReasonDataReturnTypeExtension.php

File

vendor/composer/semver/src/Constraint/Constraint.php, line 17

Namespace

Composer\Semver\Constraint
View source
class Constraint implements ConstraintInterface {
    
    /* operator integer values */
    const OP_EQ = 0;
    const OP_LT = 1;
    const OP_LE = 2;
    const OP_GT = 3;
    const OP_GE = 4;
    const OP_NE = 5;
    
    /* operator string values */
    const STR_OP_EQ = '==';
    const STR_OP_EQ_ALT = '=';
    const STR_OP_LT = '<';
    const STR_OP_LE = '<=';
    const STR_OP_GT = '>';
    const STR_OP_GE = '>=';
    const STR_OP_NE = '!=';
    const STR_OP_NE_ALT = '<>';
    
    /**
     * Operator to integer translation table.
     *
     * @var array
     * @phpstan-var array<self::STR_OP_*, self::OP_*>
     */
    private static $transOpStr = array(
        '=' => self::OP_EQ,
        '==' => self::OP_EQ,
        '<' => self::OP_LT,
        '<=' => self::OP_LE,
        '>' => self::OP_GT,
        '>=' => self::OP_GE,
        '<>' => self::OP_NE,
        '!=' => self::OP_NE,
    );
    
    /**
     * Integer to operator translation table.
     *
     * @var array
     * @phpstan-var array<self::OP_*, self::STR_OP_*>
     */
    private static $transOpInt = array(
        self::OP_EQ => '==',
        self::OP_LT => '<',
        self::OP_LE => '<=',
        self::OP_GT => '>',
        self::OP_GE => '>=',
        self::OP_NE => '!=',
    );
    
    /**
     * @var int
     * @phpstan-var self::OP_*
     */
    protected $operator;
    
    /** @var string */
    protected $version;
    
    /** @var string|null */
    protected $prettyString;
    
    /** @var Bound */
    protected $lowerBound;
    
    /** @var Bound */
    protected $upperBound;
    
    /**
     * Sets operator and version to compare with.
     *
     * @param string $operator
     * @param string $version
     *
     * @throws \InvalidArgumentException if invalid operator is given.
     *
     * @phpstan-param self::STR_OP_* $operator
     */
    public function __construct($operator, $version) {
        if (!isset(self::$transOpStr[$operator])) {
            throw new \InvalidArgumentException(sprintf('Invalid operator "%s" given, expected one of: %s', $operator, implode(', ', self::getSupportedOperators())));
        }
        $this->operator = self::$transOpStr[$operator];
        $this->version = $version;
    }
    
    /**
     * @return string
     */
    public function getVersion() {
        return $this->version;
    }
    
    /**
     * @return string
     *
     * @phpstan-return self::STR_OP_*
     */
    public function getOperator() {
        return self::$transOpInt[$this->operator];
    }
    
    /**
     * @param ConstraintInterface $provider
     *
     * @return bool
     */
    public function matches(ConstraintInterface $provider) {
        if ($provider instanceof self) {
            return $this->matchSpecific($provider);
        }
        // turn matching around to find a match
        return $provider->matches($this);
    }
    
    /**
     * {@inheritDoc}
     */
    public function setPrettyString($prettyString) {
        $this->prettyString = $prettyString;
    }
    
    /**
     * {@inheritDoc}
     */
    public function getPrettyString() {
        if ($this->prettyString) {
            return $this->prettyString;
        }
        return $this->__toString();
    }
    
    /**
     * Get all supported comparison operators.
     *
     * @return array
     *
     * @phpstan-return list<self::STR_OP_*>
     */
    public static function getSupportedOperators() {
        return array_keys(self::$transOpStr);
    }
    
    /**
     * @param  string $operator
     * @return int
     *
     * @phpstan-param  self::STR_OP_* $operator
     * @phpstan-return self::OP_*
     */
    public static function getOperatorConstant($operator) {
        return self::$transOpStr[$operator];
    }
    
    /**
     * @param string $a
     * @param string $b
     * @param string $operator
     * @param bool   $compareBranches
     *
     * @throws \InvalidArgumentException if invalid operator is given.
     *
     * @return bool
     *
     * @phpstan-param self::STR_OP_* $operator
     */
    public function versionCompare($a, $b, $operator, $compareBranches = false) {
        if (!isset(self::$transOpStr[$operator])) {
            throw new \InvalidArgumentException(sprintf('Invalid operator "%s" given, expected one of: %s', $operator, implode(', ', self::getSupportedOperators())));
        }
        $aIsBranch = strpos($a, 'dev-') === 0;
        $bIsBranch = strpos($b, 'dev-') === 0;
        if ($operator === '!=' && ($aIsBranch || $bIsBranch)) {
            return $a !== $b;
        }
        if ($aIsBranch && $bIsBranch) {
            return $operator === '==' && $a === $b;
        }
        // when branches are not comparable, we make sure dev branches never match anything
        if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
            return false;
        }
        return \version_compare($a, $b, $operator);
    }
    
    /**
     * {@inheritDoc}
     */
    public function compile($otherOperator) {
        if (strpos($this->version, 'dev-') === 0) {
            if (self::OP_EQ === $this->operator) {
                if (self::OP_EQ === $otherOperator) {
                    return sprintf('$b && $v === %s', \var_export($this->version, true));
                }
                if (self::OP_NE === $otherOperator) {
                    return sprintf('!$b || $v !== %s', \var_export($this->version, true));
                }
                return 'false';
            }
            if (self::OP_NE === $this->operator) {
                if (self::OP_EQ === $otherOperator) {
                    return sprintf('!$b || $v !== %s', \var_export($this->version, true));
                }
                if (self::OP_NE === $otherOperator) {
                    return 'true';
                }
                return '!$b';
            }
            return 'false';
        }
        if (self::OP_EQ === $this->operator) {
            if (self::OP_EQ === $otherOperator) {
                return sprintf('\\version_compare($v, %s, \'==\')', \var_export($this->version, true));
            }
            if (self::OP_NE === $otherOperator) {
                return sprintf('$b || \\version_compare($v, %s, \'!=\')', \var_export($this->version, true));
            }
            return sprintf('!$b && \\version_compare(%s, $v, \'%s\')', \var_export($this->version, true), self::$transOpInt[$otherOperator]);
        }
        if (self::OP_NE === $this->operator) {
            if (self::OP_EQ === $otherOperator) {
                return sprintf('$b || (!$b && \\version_compare($v, %s, \'!=\'))', \var_export($this->version, true));
            }
            if (self::OP_NE === $otherOperator) {
                return 'true';
            }
            return '!$b';
        }
        if (self::OP_LT === $this->operator || self::OP_LE === $this->operator) {
            if (self::OP_LT === $otherOperator || self::OP_LE === $otherOperator) {
                return '!$b';
            }
        }
        else {
            // $this->operator must be self::OP_GT || self::OP_GE here
            if (self::OP_GT === $otherOperator || self::OP_GE === $otherOperator) {
                return '!$b';
            }
        }
        if (self::OP_NE === $otherOperator) {
            return 'true';
        }
        $codeComparison = sprintf('\\version_compare($v, %s, \'%s\')', \var_export($this->version, true), self::$transOpInt[$this->operator]);
        if ($this->operator === self::OP_LE) {
            if ($otherOperator === self::OP_GT) {
                return sprintf('!$b && \\version_compare($v, %s, \'!=\') && ', \var_export($this->version, true)) . $codeComparison;
            }
        }
        elseif ($this->operator === self::OP_GE) {
            if ($otherOperator === self::OP_LT) {
                return sprintf('!$b && \\version_compare($v, %s, \'!=\') && ', \var_export($this->version, true)) . $codeComparison;
            }
        }
        return sprintf('!$b && %s', $codeComparison);
    }
    
    /**
     * @param Constraint $provider
     * @param bool       $compareBranches
     *
     * @return bool
     */
    public function matchSpecific(Constraint $provider, $compareBranches = false) {
        $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
        $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
        $isEqualOp = self::OP_EQ === $this->operator;
        $isNonEqualOp = self::OP_NE === $this->operator;
        $isProviderEqualOp = self::OP_EQ === $provider->operator;
        $isProviderNonEqualOp = self::OP_NE === $provider->operator;
        // '!=' operator is match when other operator is not '==' operator or version is not match
        // these kinds of comparisons always have a solution
        if ($isNonEqualOp || $isProviderNonEqualOp) {
            if ($isNonEqualOp && !$isProviderNonEqualOp && !$isProviderEqualOp && strpos($provider->version, 'dev-') === 0) {
                return false;
            }
            if ($isProviderNonEqualOp && !$isNonEqualOp && !$isEqualOp && strpos($this->version, 'dev-') === 0) {
                return false;
            }
            if (!$isEqualOp && !$isProviderEqualOp) {
                return true;
            }
            return $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
        }
        // an example for the condition is <= 2.0 & < 1.0
        // these kinds of comparisons always have a solution
        if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
            return !(strpos($this->version, 'dev-') === 0 || strpos($provider->version, 'dev-') === 0);
        }
        $version1 = $isEqualOp ? $this->version : $provider->version;
        $version2 = $isEqualOp ? $provider->version : $this->version;
        $operator = $isEqualOp ? $provider->operator : $this->operator;
        if ($this->versionCompare($version1, $version2, self::$transOpInt[$operator], $compareBranches)) {
            // special case, e.g. require >= 1.0 and provide < 1.0
            // 1.0 >= 1.0 but 1.0 is outside of the provided interval
            return !(self::$transOpInt[$provider->operator] === $providerNoEqualOp && self::$transOpInt[$this->operator] !== $noEqualOp && \version_compare($provider->version, $this->version, '=='));
        }
        return false;
    }
    
    /**
     * @return string
     */
    public function __toString() {
        return self::$transOpInt[$this->operator] . ' ' . $this->version;
    }
    
    /**
     * {@inheritDoc}
     */
    public function getLowerBound() {
        $this->extractBounds();
        return $this->lowerBound;
    }
    
    /**
     * {@inheritDoc}
     */
    public function getUpperBound() {
        $this->extractBounds();
        return $this->upperBound;
    }
    
    /**
     * @return void
     */
    private function extractBounds() {
        if (null !== $this->lowerBound) {
            return;
        }
        // Branches
        if (strpos($this->version, 'dev-') === 0) {
            $this->lowerBound = Bound::zero();
            $this->upperBound = Bound::positiveInfinity();
            return;
        }
        switch ($this->operator) {
            case self::OP_EQ:
                $this->lowerBound = new Bound($this->version, true);
                $this->upperBound = new Bound($this->version, true);
                break;
            case self::OP_LT:
                $this->lowerBound = Bound::zero();
                $this->upperBound = new Bound($this->version, false);
                break;
            case self::OP_LE:
                $this->lowerBound = Bound::zero();
                $this->upperBound = new Bound($this->version, true);
                break;
            case self::OP_GT:
                $this->lowerBound = new Bound($this->version, false);
                $this->upperBound = Bound::positiveInfinity();
                break;
            case self::OP_GE:
                $this->lowerBound = new Bound($this->version, true);
                $this->upperBound = Bound::positiveInfinity();
                break;
            case self::OP_NE:
                $this->lowerBound = Bound::zero();
                $this->upperBound = Bound::positiveInfinity();
                break;
        }
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
Constraint::$lowerBound protected property @var Bound
Constraint::$operator protected property @phpstan-var self::OP_*
Constraint::$prettyString protected property @var string|null
Constraint::$transOpInt private static property Integer to operator translation table.
Constraint::$transOpStr private static property Operator to integer translation table.
Constraint::$upperBound protected property @var Bound
Constraint::$version protected property @var string
Constraint::compile public function Provides a compiled version of the constraint for the given operator
The compiled version must be a PHP expression.
Executor of compile version must provide 2 variables:
Overrides ConstraintInterface::compile
Constraint::extractBounds private function
Constraint::getLowerBound public function Overrides ConstraintInterface::getLowerBound
Constraint::getOperator public function @phpstan-return self::STR_OP_*
Constraint::getOperatorConstant public static function @phpstan-param self::STR_OP_* $operator
@phpstan-return self::OP_*
Constraint::getPrettyString public function Overrides ConstraintInterface::getPrettyString
Constraint::getSupportedOperators public static function Get all supported comparison operators.
Constraint::getUpperBound public function Overrides ConstraintInterface::getUpperBound
Constraint::getVersion public function
Constraint::matches public function Overrides ConstraintInterface::matches
Constraint::matchSpecific public function
Constraint::OP_EQ constant
Constraint::OP_GE constant
Constraint::OP_GT constant
Constraint::OP_LE constant
Constraint::OP_LT constant
Constraint::OP_NE constant
Constraint::setPrettyString public function Overrides ConstraintInterface::setPrettyString
Constraint::STR_OP_EQ constant
Constraint::STR_OP_EQ_ALT constant
Constraint::STR_OP_GE constant
Constraint::STR_OP_GT constant
Constraint::STR_OP_LE constant
Constraint::STR_OP_LT constant
Constraint::STR_OP_NE constant
Constraint::STR_OP_NE_ALT constant
Constraint::versionCompare public function @phpstan-param self::STR_OP_* $operator
Constraint::__construct public function Sets operator and version to compare with.
Constraint::__toString public function Overrides ConstraintInterface::__toString
RSS feed
Powered by Drupal