Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring #13

Merged
merged 17 commits into from Sep 2, 2015
Merged
12 changes: 12 additions & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

### [Unreleased]

* Break: `VersionConstraint` renamed to `Constraint`.
* Break: `SpecificConstraint` renamed to `AbstractConstraint`.
* Break: `LinkConstraintInterface` renamed to `ConstraintInterface`.
* Break: `VersionParser::parseNameVersionPairs` was removed.
* Changed: `VersionParser::parseConstraints` allows (but ignores) build metadata now.
* Changed: `VersionParser::parseConstraints` allows (but ignores) prefixing numeric versions with a 'v' now.
* Changed: Fixed namespace(s) of test files.
* Changed: `Comparator::compare` no longer throws `InvalidArgumentException`.
* Changed: `VersionConstraint` now throws `InvalidArgumentException`.

### [0.1.0] 2015-07-23

* Added: `Composer\Semver\Comparator`, various methods to compare versions.
Expand Down
36 changes: 28 additions & 8 deletions README.md
Expand Up @@ -8,6 +8,7 @@ now extracted and made available as a stand-alone library.

[![Build Status](https://travis-ci.org/composer/semver.svg?branch=master)](https://travis-ci.org/composer/semver)


Installation
------------

Expand All @@ -17,23 +18,33 @@ Install the latest version with:
$ composer require composer/semver
```


Requirements
------------

* PHP 5.3.2 is required but using the latest version of PHP is highly recommended.


Version Comparison
------------------

For details on how versions are compared, refer to the [Versions](https://getcomposer.org/doc/articles/versions.md)
article in the documentation section of the [getcomposer.org](https://getcomposer.org) website.


Basic usage
-----------

The `Composer\Semver\Comparator` class provides the following high-level
functions for comparing versions:
### Comparator

The `Composer\Semver\Comparator` class provides the following methods for comparing versions:

* greaterThan
* greaterThanOrEqualTo
* lessThan
* lessThanOrEqualTo
* equalTo
* notEqualTo
* greaterThan($v1, $v2)
* greaterThanOrEqualTo($v1, $v2)
* lessThan($v1, $v2)
* lessThanOrEqualTo($v1, $v2)
* equalTo($v1, $v2)
* notEqualTo($v1, $v2)

Each function takes two version strings as arguments. For example:

Expand All @@ -43,6 +54,15 @@ use Composer\Semver\Comparator;
Comparator::greaterThan('1.25.0', '1.24.0'); // 1.25.0 > 1.24.0
```

### Semver

The `Composer\Semver\Semver` class providers the following methods:

* satisfies($version, $constraints)
* satisfiedBy($constraint, array $versions)
* sort($versions)
* rsort($versions)


License
-------
Expand Down
32 changes: 11 additions & 21 deletions src/Comparator.php
Expand Up @@ -11,12 +11,12 @@

namespace Composer\Semver;

use Composer\Semver\Constraint\VersionConstraint;
use Composer\Semver\Constraint\Constraint;

class Comparator
{
/**
* Whether $version1 > $version2.
* Evaluates the expression: $version1 > $version2.
*
* @param string $version1
* @param string $version2
Expand All @@ -29,7 +29,7 @@ public static function greaterThan($version1, $version2)
}

/**
* Whether $version1 >= $version2.
* Evaluates the expression: $version1 >= $version2.
*
* @param string $version1
* @param string $version2
Expand All @@ -42,7 +42,7 @@ public static function greaterThanOrEqualTo($version1, $version2)
}

/**
* Whether $version1 < $version2.
* Evaluates the expression: $version1 < $version2.
*
* @param string $version1
* @param string $version2
Expand All @@ -55,7 +55,7 @@ public static function lessThan($version1, $version2)
}

/**
* Whether $version1 <= $version2.
* Evaluates the expression: $version1 <= $version2.
*
* @param string $version1
* @param string $version2
Expand All @@ -68,7 +68,7 @@ public static function lessThanOrEqualTo($version1, $version2)
}

/**
* Whether $version1 == $version2.
* Evaluates the expression: $version1 == $version2.
*
* @param string $version1
* @param string $version2
Expand All @@ -81,7 +81,7 @@ public static function equalTo($version1, $version2)
}

/**
* Whether $version1 != $version2.
* Evaluates the expression: $version1 != $version2.
*
* @param string $version1
* @param string $version2
Expand All @@ -94,28 +94,18 @@ public static function notEqualTo($version1, $version2)
}

/**
* Evaluate $version1 $operator $version2.
* Evaluates the expression: $version1 $operator $version2.
*
* @param string $version1
* @param string $operator Comparison operator like ">" or "<=", etc.
* @param string $operator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove the comment?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it should probably list all operators possible then. I would prefer to just assume the user knows what a valid operator is. Though in most cases I suspect they will use the methods that actually call compare() and not call compare() directly. The operators can be derived from the function description of all other methods.

* @param string $version2
*
* @throws \InvalidArgumentException
*
* @return bool
*/
public static function compare($version1, $operator, $version2)
{
if (!in_array($operator, VersionConstraint::getSupportedOperators())) {
throw new \InvalidArgumentException(sprintf(
'Operator "%s" not supported, expected one of: %s',
$operator,
implode(', ', VersionConstraint::getSupportedOperators())
));
}

$constraint = new VersionConstraint($operator, $version2);
$constraint = new Constraint($operator, $version2);

return $constraint->matches(new VersionConstraint('==', $version1));
return $constraint->matches(new Constraint('==', $version1));
}
}
Expand Up @@ -12,26 +12,26 @@
namespace Composer\Semver\Constraint;

/**
* Provides a common basis for specific package link constraints.
*
* @author Nils Adermann <naderman@naderman.de>
* Base constraint class.
*/
abstract class SpecificConstraint implements LinkConstraintInterface
abstract class AbstractConstraint implements ConstraintInterface
{
/** @var string */
protected $prettyString;

/**
* @param LinkConstraintInterface $provider
* @param ConstraintInterface $provider
*
* @return bool
*/
public function matches(LinkConstraintInterface $provider)
public function matches(ConstraintInterface $provider)
{
if ($provider instanceof MultiConstraint) {
// turn matching around to find a match
return $provider->matches($this);
} elseif ($provider instanceof $this) {
}

if ($provider instanceof $this) {
// see note at bottom of this class declaration
return $this->matchSpecific($provider);
}
Expand Down
Expand Up @@ -12,21 +12,23 @@
namespace Composer\Semver\Constraint;

/**
* Constrains a package link based on package version.
*
* Version numbers must be compatible with version_compare
*
* @author Nils Adermann <naderman@naderman.de>
* Defines a constraint.
*/
class VersionConstraint extends SpecificConstraint
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,
Expand All @@ -38,6 +40,11 @@ class VersionConstraint extends SpecificConstraint
'!=' => self::OP_NE,
);

/**
* Integer to operator translation table.
*
* @var array
*/
private static $transOpInt = array(
self::OP_EQ => '==',
self::OP_LT => '<',
Expand All @@ -47,7 +54,10 @@ class VersionConstraint extends SpecificConstraint
self::OP_NE => '!=',
);

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

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

/**
Expand All @@ -61,13 +71,23 @@ public static function getSupportedOperators()
}

/**
* Sets operator and version to compare a package with.
* Sets operator and version to compare with.
*
* @param string $operator A comparison operator
* @param string $version A version to compare to
* @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;
}
Expand All @@ -76,14 +96,25 @@ public function __construct($operator, $version)
* @param string $a
* @param string $b
* @param string $operator
* @param bool|false $compareBranches
* @param bool $compareBranches
*
* @throws \InvalidArgumentException if invalid operator is given.
*
* @return bool|mixed
* @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;
}
Expand All @@ -97,12 +128,12 @@ public function versionCompare($a, $b, $operator, $compareBranches = false)
}

/**
* @param VersionConstraint $provider
* @param Constraint $provider
* @param bool $compareBranches
*
* @return bool
*/
public function matchSpecific(VersionConstraint $provider, $compareBranches = false)
public function matchSpecific(Constraint $provider, $compareBranches = false)
{
$noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
$providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
Expand Down
Expand Up @@ -11,18 +11,27 @@

namespace Composer\Semver\Constraint;

/**
* Defines a constraint on a link between two packages.
*
* @author Nils Adermann <naderman@naderman.de>
*/
interface LinkConstraintInterface
interface ConstraintInterface
{
public function matches(LinkConstraintInterface $provider);
/**
* @param ConstraintInterface $provider
*
* @return bool
*/
public function matches(ConstraintInterface $provider);

/**
* @param string $prettyString
*/
public function setPrettyString($prettyString);

/**
* @return string
*/
public function getPrettyString();

/**
* @return string
*/
public function __toString();
}
10 changes: 4 additions & 6 deletions src/Constraint/EmptyConstraint.php
Expand Up @@ -12,21 +12,19 @@
namespace Composer\Semver\Constraint;

/**
* Defines an absence of constraints.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* Defines the absence of a constraint.
*/
class EmptyConstraint implements LinkConstraintInterface
class EmptyConstraint implements ConstraintInterface
{
/** @var string */
protected $prettyString;

/**
* @param LinkConstraintInterface $provider
* @param ConstraintInterface $provider
*
* @return bool
*/
public function matches(LinkConstraintInterface $provider)
public function matches(ConstraintInterface $provider)
{
return true;
}
Expand Down