You are here

Constraint.php in Zircon Profile 8

File

vendor/composer/semver/src/Constraint/Constraint.php
View source
<?php

/*
 * This file is part of composer/semver.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */
namespace Composer\Semver\Constraint;


/**
 * Defines a constraint.
 */
class Constraint extends AbstractConstraint {

  /* 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 to integer translation table.
   *
   * @var array
   */
  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
   */
  private static $transOpInt = array(
    self::OP_EQ => '==',
    self::OP_LT => '<',
    self::OP_LE => '<=',
    self::OP_GT => '>',
    self::OP_GE => '>=',
    self::OP_NE => '!=',
  );

  /** @var string */
  private $operator;

  /** @var string */
  private $version;

  /**
   * Get all supported comparison operators.
   *
   * @return array
   */
  public static function getSupportedOperators() {
    return array_keys(self::$transOpStr);
  }

  /**
   * Sets operator and version to compare with.
   *
   * @param string $operator
   * @param string $version
   *
   * @throws \InvalidArgumentException if invalid operator is given.
   */
  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;
  }

  /**
   * @param string $a
   * @param string $b
   * @param string $operator
   * @param bool $compareBranches
   *
   * @throws \InvalidArgumentException if invalid operator is given.
   *
   * @return bool
   */
  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 = 'dev-' === substr($a, 0, 4);
    $bIsBranch = 'dev-' === substr($b, 0, 4);
    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);
  }

  /**
   * @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) {
      return !$isEqualOp && !$isProviderEqualOp || $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 true;
    }
    if ($this
      ->versionCompare($provider->version, $this->version, self::$transOpInt[$this->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
      if ($provider->version === $this->version && self::$transOpInt[$provider->operator] === $providerNoEqualOp && self::$transOpInt[$this->operator] !== $noEqualOp) {
        return false;
      }
      return true;
    }
    return false;
  }

  /**
   * @return string
   */
  public function __toString() {
    return self::$transOpInt[$this->operator] . ' ' . $this->version;
  }

}

Classes

Namesort descending Description
Constraint Defines a constraint.