PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, May 20, 2022

[FIXED] How to verify a required version is supported in Composer version constraint?

 May 20, 2022     composer-php, php     No comments   

Issue

Given any versions constraint for requirements in a composer.json, I would like to verify that a given version is supported by the requirement definition. Let's say a composer.json requires "php": "^7.4". Then I would expect that checking version 7.4 will succeed and 8.0 will fail.

My implementation so far is using composer/semver.

version-checker.php

use Composer\Semver\Comparator;
use Composer\Semver\VersionParser;

require_once __DIR__ . '/vendor/autoload.php';

$expectations = [
    [true, '7.3.0', '^7.3 || ~8.0.0 || ~8.1.0'],
    [true, '7.3.0', '^7.3 || ^8.0'],
    [false, '7.3.0', '^7.2'],
    [false, '7.3.0', '^7.1'],
    [false, '7.3.0', '^5.6 || ^7.0'],
    [true, '8.1.0', '^7.3 || ~8.0.0 || ~8.1.0'],
    [true, '8.1.0', '>=7.2.5'],
    [false, '8.1.0', '^7.3 || ^8.0'],
    [false, '8.1.0', '^7.2'],
    [false, '8.1.0', '^7.1'],
    [false, '8.1.0', '^5.6 || ^7.0'],
];

$versionParser = new VersionParser();

foreach ($expectations as [$expected, $requiredVersion, $actualVersion]) {
    $constraint   = $versionParser->parseConstraints($actualVersion);
    $lowerVersion = $constraint->getLowerBound()->getVersion();

    $compareResult = Comparator::greaterThanOrEqualTo($lowerVersion, $requiredVersion);

    if ($expected !== $compareResult) {
        printf(
            'Failed to assert that required version (%s) with actual version (%s) is %s.' . PHP_EOL,
            $requiredVersion,
            $actualVersion,
            var_export($expected, true)
        );
    }
}

The output is:

Failed to assert that required version (8.1.0) with actual version (^7.3 || ~8.0.0 || ~8.1.0) is true.
Failed to assert that required version (8.1.0) with actual version (>=7.2.5) is true.

How can proper verification be achieved?


Solution

You have two problems.

First, wrong expectations.

These four, are wrong:

[
    [false, '7.3.0', '^7.2'],
    [false, '7.3.0', '^7.1'],
    [false, '7.3.0', '^5.6 || ^7.0'],
    [false, '8.1.0', '^7.3 || ^8.0'],
]

Those constraints do match the version.

Here you have the docs for caret version range. Basically, ^7.2 is equal to >=7.2 && < 8 (etc).

The second problem is that you are using the wrong way of checking the validity of the constraints:

Instead of using this:

$compareResult = Comparator::greaterThanOrEqualTo($lowerVersion, $requiredVersion);

(and note that you are using the operands the wrong way around, since this would be equivalent of saying $lowerVersion >= $requiredVersion, which does not make sense).

You should be doing:

$actualConstraint   = $versionParser->parseConstraints($actualVersion);
$compareResult      = $actualConstraint->matches($requiredConstraint);

The whole thing put together would be:

use Composer\Semver\VersionParser;

require_once __DIR__ . '/vendor/autoload.php';

$expectations = [
    [true, '7.3.0', '^7.3 || ~8.0.0 || ~8.1.0'],
    [true, '7.3.0', '^7.3 || ^8.0'],
    [true, '8.1.0', '^7.3 || ~8.0.0 || ~8.1.0'],
    [true, '8.1.0', '>=7.2.5'],
    [true, '7.3.0', '^7.2'],
    [true, '7.3.0', '^7.1'],
    [true, '7.3.0', '^5.6 || ^7.0'],
    [true, '8.1.0', '^7.3 || ^8.0'],
    [false, '8.1.0', '^7.2'],
    [false, '8.1.0', '^7.1'],
    [false, '8.1.0', '^5.6 || ^7.0'],
];

$versionParser = new VersionParser();

foreach ($expectations as [$expected, $requiredVersion, $actualVersion]) {
    $actualConstraint   = $versionParser->parseConstraints($actualVersion);
    $requiredConstraint = $versionParser->parseConstraints($requiredVersion);

    $compareResult = $actualConstraint->matches($requiredConstraint);

    if ($expected !== $compareResult) {
        printf(
            'Failed to assert that required version (%s) with actual version (%s) is %s.' . PHP_EOL,
            $requiredVersion,
            $actualVersion,
            var_export($expected, true)
        );
    }
}


Answered By - yivi
Answer Checked By - Marie Seifert (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing