You are here

private function VersionParser::parseConstraint in Automatic Updates 7

Parameters

string $constraint:

Return value

array

Throws

\UnexpectedValueException

1 call to VersionParser::parseConstraint()
VersionParser::parseConstraints in vendor/composer/semver/src/VersionParser.php
Parses a constraint string into MultiConstraint and/or Constraint objects.

File

vendor/composer/semver/src/VersionParser.php, line 301

Class

VersionParser
Version parser.

Namespace

Composer\Semver

Code

private function parseConstraint($constraint) {
  if (preg_match('{^([^,\\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
    $constraint = $match[1];
    if ($match[2] !== 'stable') {
      $stabilityModifier = $match[2];
    }
  }
  if (preg_match('{^v?[xX*](\\.[xX*])*$}i', $constraint)) {
    return array(
      new EmptyConstraint(),
    );
  }
  $versionRegex = 'v?(\\d++)(?:\\.(\\d++))?(?:\\.(\\d++))?(?:\\.(\\d++))?' . self::$modifierRegex . '(?:\\+[^\\s]+)?';

  // Tilde Range
  //
  // Like wildcard constraints, unsuffixed tilde constraints say that they must be greater than the previous
  // version, to ensure that unstable instances of the current version are allowed. However, if a stability
  // suffix is added to the constraint, then a >= match on the current version is used instead.
  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
    if (strpos($constraint, '~>') === 0) {
      throw new \UnexpectedValueException('Could not parse version constraint ' . $constraint . ': ' . 'Invalid operator "~>", you probably meant to use the "~" operator');
    }

    // Work out which position in the version we are operating at
    if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) {
      $position = 4;
    }
    elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
      $position = 3;
    }
    elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
      $position = 2;
    }
    else {
      $position = 1;
    }

    // Calculate the stability suffix
    $stabilitySuffix = '';
    if (empty($matches[5]) && empty($matches[7])) {
      $stabilitySuffix .= '-dev';
    }
    $lowVersion = $this
      ->normalize(substr($constraint . $stabilitySuffix, 1));
    $lowerBound = new Constraint('>=', $lowVersion);

    // For upper bound, we increment the position of one more significance,
    // but highPosition = 0 would be illegal
    $highPosition = max(1, $position - 1);
    $highVersion = $this
      ->manipulateVersionString($matches, $highPosition, 1) . '-dev';
    $upperBound = new Constraint('<', $highVersion);
    return array(
      $lowerBound,
      $upperBound,
    );
  }

  // Caret Range
  //
  // Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple.
  // In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for
  // versions 0.X >=0.1.0, and no updates for versions 0.0.X
  if (preg_match('{^\\^' . $versionRegex . '($)}i', $constraint, $matches)) {

    // Work out which position in the version we are operating at
    if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) {
      $position = 1;
    }
    elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) {
      $position = 2;
    }
    else {
      $position = 3;
    }

    // Calculate the stability suffix
    $stabilitySuffix = '';
    if (empty($matches[5]) && empty($matches[7])) {
      $stabilitySuffix .= '-dev';
    }
    $lowVersion = $this
      ->normalize(substr($constraint . $stabilitySuffix, 1));
    $lowerBound = new Constraint('>=', $lowVersion);

    // For upper bound, we increment the position of one more significance,
    // but highPosition = 0 would be illegal
    $highVersion = $this
      ->manipulateVersionString($matches, $position, 1) . '-dev';
    $upperBound = new Constraint('<', $highVersion);
    return array(
      $lowerBound,
      $upperBound,
    );
  }

  // X Range
  //
  // Any of X, x, or * may be used to "stand in" for one of the numeric values in the [major, minor, patch] tuple.
  // A partial version range is treated as an X-Range, so the special character is in fact optional.
  if (preg_match('{^v?(\\d++)(?:\\.(\\d++))?(?:\\.(\\d++))?(?:\\.[xX*])++$}', $constraint, $matches)) {
    if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
      $position = 3;
    }
    elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
      $position = 2;
    }
    else {
      $position = 1;
    }
    $lowVersion = $this
      ->manipulateVersionString($matches, $position) . '-dev';
    $highVersion = $this
      ->manipulateVersionString($matches, $position, 1) . '-dev';
    if ($lowVersion === '0.0.0.0-dev') {
      return array(
        new Constraint('<', $highVersion),
      );
    }
    return array(
      new Constraint('>=', $lowVersion),
      new Constraint('<', $highVersion),
    );
  }

  // Hyphen Range
  //
  // Specifies an inclusive set. If a partial version is provided as the first version in the inclusive range,
  // then the missing pieces are replaced with zeroes. If a partial version is provided as the second version in
  // the inclusive range, then all versions that start with the supplied parts of the tuple are accepted, but
  // nothing that would be greater than the provided tuple parts.
  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {

    // Calculate the stability suffix
    $lowStabilitySuffix = '';
    if (empty($matches[6]) && empty($matches[8])) {
      $lowStabilitySuffix = '-dev';
    }
    $lowVersion = $this
      ->normalize($matches['from']);
    $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
    $empty = function ($x) {
      return $x === 0 || $x === '0' ? false : empty($x);
    };
    if (!$empty($matches[11]) && !$empty($matches[12]) || !empty($matches[14]) || !empty($matches[16])) {
      $highVersion = $this
        ->normalize($matches['to']);
      $upperBound = new Constraint('<=', $highVersion);
    }
    else {
      $highMatch = array(
        '',
        $matches[10],
        $matches[11],
        $matches[12],
        $matches[13],
      );
      $highVersion = $this
        ->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
      $upperBound = new Constraint('<', $highVersion);
    }
    return array(
      $lowerBound,
      $upperBound,
    );
  }

  // Basic Comparators
  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\\s*(.*)}', $constraint, $matches)) {
    try {
      $version = $this
        ->normalize($matches[2]);
      if (!empty($stabilityModifier) && self::parseStability($version) === 'stable') {
        $version .= '-' . $stabilityModifier;
      }
      elseif ('<' === $matches[1] || '>=' === $matches[1]) {
        if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
          if (strpos($matches[2], 'dev-') !== 0) {
            $version .= '-dev';
          }
        }
      }
      return array(
        new Constraint($matches[1] ?: '=', $version),
      );
    } catch (\Exception $e) {
    }
  }
  $message = 'Could not parse version constraint ' . $constraint;
  if (isset($e)) {
    $message .= ': ' . $e
      ->getMessage();
  }
  throw new \UnexpectedValueException($message);
}