diff --git a/composer.lock b/composer.lock
index 131bf0a2f1fd00016fe473b94978f3769a781fb2..58c6e8e73dd538705edf9b3a288704716a04307a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -102,6 +102,67 @@
             ],
             "time": "2015-02-18 17:17:01"
         },
+        {
+            "name": "composer/semver",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/composer/semver.git",
+                "reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/composer/semver/zipball/d0e1ccc6d44ab318b758d709e19176037da6b1ba",
+                "reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.5",
+                "phpunit/phpunit-mock-objects": "~2.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "0.1-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Composer\\Semver\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Rob Bast",
+                    "email": "rob.bast@gmail.com"
+                },
+                {
+                    "name": "Nils Adermann",
+                    "email": "naderman@naderman.de",
+                    "homepage": "http://www.naderman.de"
+                },
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be",
+                    "homepage": "http://seld.be"
+                }
+            ],
+            "description": "Semver library that offers utilities, version constraint parsing and validation.",
+            "keywords": [
+                "semantic",
+                "semver",
+                "validation",
+                "versioning"
+            ],
+            "time": "2015-09-21 09:42:36"
+        },
         {
             "name": "doctrine/annotations",
             "version": "v1.2.7",
@@ -3550,6 +3611,7 @@
         "masterminds/html5": 0,
         "symfony/psr-http-message-bridge": 0,
         "zendframework/zend-diactoros": 0,
+        "composer/semver": 0,
         "behat/mink": 0,
         "behat/mink-goutte-driver": 0,
         "mikey179/vfsstream": 0,
diff --git a/core/composer.json b/core/composer.json
index a29b7f4102a3a31739d98e346f73cad78fae4057..49842ba40f0686232308c279516ec56fce89a888 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -28,7 +28,8 @@
     "egulias/email-validator": "1.2.*",
     "masterminds/html5": "~2.1",
     "symfony/psr-http-message-bridge": "v0.2",
-    "zendframework/zend-diactoros": "~1.1"
+    "zendframework/zend-diactoros": "~1.1",
+    "composer/semver": "~1.0"
   },
   "require-dev": {
     "behat/mink": "~1.6",
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
index e360efb7a97d20e6d81a73bfbb913c44e346d51a..f3dd55e5435021b3d60d3b6b22a31e850204f0e4 100644
--- a/vendor/composer/autoload_psr4.php
+++ b/vendor/composer/autoload_psr4.php
@@ -40,6 +40,7 @@
     'Drupal\\Core\\' => array($baseDir . '/core/lib/Drupal/Core'),
     'Drupal\\Component\\' => array($baseDir . '/core/lib/Drupal/Component'),
     'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
+    'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
     'Behat\\Mink\\Driver\\' => array($vendorDir . '/behat/mink-browserkit-driver/src', $vendorDir . '/behat/mink-goutte-driver/src'),
     'Behat\\Mink\\' => array($vendorDir . '/behat/mink/src'),
 );
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 660ca8d2d34120a5a5324406da266686b294e510..c29170ad1b75c8d5059d1370c6c939d1b4f53ea8 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -3634,5 +3634,68 @@
         ],
         "description": "Symfony BrowserKit Component",
         "homepage": "https://symfony.com"
+    },
+    {
+        "name": "composer/semver",
+        "version": "1.0.0",
+        "version_normalized": "1.0.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/composer/semver.git",
+            "reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/composer/semver/zipball/d0e1ccc6d44ab318b758d709e19176037da6b1ba",
+            "reference": "d0e1ccc6d44ab318b758d709e19176037da6b1ba",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.2"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "~4.5",
+            "phpunit/phpunit-mock-objects": "~2.3"
+        },
+        "time": "2015-09-21 09:42:36",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "0.1-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Composer\\Semver\\": "src"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Rob Bast",
+                "email": "rob.bast@gmail.com"
+            },
+            {
+                "name": "Nils Adermann",
+                "email": "naderman@naderman.de",
+                "homepage": "http://www.naderman.de"
+            },
+            {
+                "name": "Jordi Boggiano",
+                "email": "j.boggiano@seld.be",
+                "homepage": "http://seld.be"
+            }
+        ],
+        "description": "Semver library that offers utilities, version constraint parsing and validation.",
+        "keywords": [
+            "semantic",
+            "semver",
+            "validation",
+            "versioning"
+        ]
     }
 ]
diff --git a/vendor/composer/semver/CHANGELOG.md b/vendor/composer/semver/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..8352cb72d32ea3bc6e39c6c22958b88058a8238b
--- /dev/null
+++ b/vendor/composer/semver/CHANGELOG.md
@@ -0,0 +1,28 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+This project adheres to [Semantic Versioning](http://semver.org/).
+
+### [1.0.0] 2015-09-21
+
+  * 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.
+  * Added: various documents such as README.md, LICENSE, etc.
+  * Added: configuration files for Git, Travis, php-cs-fixer, phpunit.
+  * Break: the following namespaces were renamed:
+    - Namespace: `Composer\Package\Version` -> `Composer\Semver`
+    - Namespace: `Composer\Package\LinkConstraint` -> `Composer\Semver\Constraint`
+    - Namespace: `Composer\Test\Package\Version` -> `Composer\Test\Semver`
+    - Namespace: `Composer\Test\Package\LinkConstraint` -> `Composer\Test\Semver\Constraint`
+  * Changed: code style using php-cs-fixer.
diff --git a/vendor/composer/semver/LICENSE b/vendor/composer/semver/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..466975862624c73fa7ba3d55e0e05f7be6d6e0a6
--- /dev/null
+++ b/vendor/composer/semver/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2015 Composer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/composer/semver/README.md b/vendor/composer/semver/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c8b6979849ce671274486be2b6d085ee8bffa1f2
--- /dev/null
+++ b/vendor/composer/semver/README.md
@@ -0,0 +1,70 @@
+composer/semver
+===============
+
+Semver library that offers utilities, version constraint parsing and validation.
+
+Originally written as part of [composer/composer](https://github.com/composer/composer),
+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
+------------
+
+Install the latest version with:
+
+```bash
+$ 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
+-----------
+
+### Comparator
+
+The `Composer\Semver\Comparator` class provides the following methods for comparing versions:
+
+* 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:
+
+```php
+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
+-------
+
+composer/semver is licensed under the MIT License, see the LICENSE file for details.
diff --git a/vendor/composer/semver/composer.json b/vendor/composer/semver/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..b996186f21c9f2e3a8ce818cc0e209e42500b6c3
--- /dev/null
+++ b/vendor/composer/semver/composer.json
@@ -0,0 +1,57 @@
+{
+    "name": "composer/semver",
+    "description": "Semver library that offers utilities, version constraint parsing and validation.",
+    "type": "library",
+    "license": "MIT",
+    "keywords": [
+        "semver",
+        "semantic",
+        "versioning",
+        "validation"
+    ],
+    "authors": [
+        {
+            "name": "Nils Adermann",
+            "email": "naderman@naderman.de",
+            "homepage": "http://www.naderman.de"
+        },
+        {
+            "name": "Jordi Boggiano",
+            "email": "j.boggiano@seld.be",
+            "homepage": "http://seld.be"
+        },
+        {
+            "name": "Rob Bast",
+            "email": "rob.bast@gmail.com"
+        }
+    ],
+    "support": {
+        "irc": "irc://irc.freenode.org/composer",
+        "issues": "https://github.com/composer/semver/issues"
+    },
+    "require": {
+        "php": ">=5.3.2"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "~4.5",
+        "phpunit/phpunit-mock-objects": "~2.3"
+    },
+    "autoload": {
+        "psr-4": {
+            "Composer\\Semver\\": "src"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Composer\\Semver\\Test\\": "tests"
+        }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "0.1-dev"
+        }
+    },
+    "scripts": {
+        "test": "phpunit"
+    }
+}
diff --git a/vendor/composer/semver/src/Comparator.php b/vendor/composer/semver/src/Comparator.php
new file mode 100644
index 0000000000000000000000000000000000000000..a9d758f1c0ceea21c7a8fc6ffb865339cce6b12f
--- /dev/null
+++ b/vendor/composer/semver/src/Comparator.php
@@ -0,0 +1,111 @@
+<?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;
+
+use Composer\Semver\Constraint\Constraint;
+
+class Comparator
+{
+    /**
+     * Evaluates the expression: $version1 > $version2.
+     *
+     * @param string $version1
+     * @param string $version2
+     *
+     * @return bool
+     */
+    public static function greaterThan($version1, $version2)
+    {
+        return self::compare($version1, '>', $version2);
+    }
+
+    /**
+     * Evaluates the expression: $version1 >= $version2.
+     *
+     * @param string $version1
+     * @param string $version2
+     *
+     * @return bool
+     */
+    public static function greaterThanOrEqualTo($version1, $version2)
+    {
+        return self::compare($version1, '>=', $version2);
+    }
+
+    /**
+     * Evaluates the expression: $version1 < $version2.
+     *
+     * @param string $version1
+     * @param string $version2
+     *
+     * @return bool
+     */
+    public static function lessThan($version1, $version2)
+    {
+        return self::compare($version1, '<', $version2);
+    }
+
+    /**
+     * Evaluates the expression: $version1 <= $version2.
+     *
+     * @param string $version1
+     * @param string $version2
+     *
+     * @return bool
+     */
+    public static function lessThanOrEqualTo($version1, $version2)
+    {
+        return self::compare($version1, '<=', $version2);
+    }
+
+    /**
+     * Evaluates the expression: $version1 == $version2.
+     *
+     * @param string $version1
+     * @param string $version2
+     *
+     * @return bool
+     */
+    public static function equalTo($version1, $version2)
+    {
+        return self::compare($version1, '==', $version2);
+    }
+
+    /**
+     * Evaluates the expression: $version1 != $version2.
+     *
+     * @param string $version1
+     * @param string $version2
+     *
+     * @return bool
+     */
+    public static function notEqualTo($version1, $version2)
+    {
+        return self::compare($version1, '!=', $version2);
+    }
+
+    /**
+     * Evaluates the expression: $version1 $operator $version2.
+     *
+     * @param string $version1
+     * @param string $operator
+     * @param string $version2
+     *
+     * @return bool
+     */
+    public static function compare($version1, $operator, $version2)
+    {
+        $constraint = new Constraint($operator, $version2);
+
+        return $constraint->matches(new Constraint('==', $version1));
+    }
+}
diff --git a/vendor/composer/semver/src/Constraint/AbstractConstraint.php b/vendor/composer/semver/src/Constraint/AbstractConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..ccd834f6bb406839ba4e267078dabc4805f47a12
--- /dev/null
+++ b/vendor/composer/semver/src/Constraint/AbstractConstraint.php
@@ -0,0 +1,65 @@
+<?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;
+
+/**
+ * Base constraint class.
+ */
+abstract class AbstractConstraint implements ConstraintInterface
+{
+    /** @var string */
+    protected $prettyString;
+
+    /**
+     * @param ConstraintInterface $provider
+     *
+     * @return bool
+     */
+    public function matches(ConstraintInterface $provider)
+    {
+        if ($provider instanceof MultiConstraint) {
+            // turn matching around to find a match
+            return $provider->matches($this);
+        }
+
+        if ($provider instanceof $this) {
+            // see note at bottom of this class declaration
+            return $this->matchSpecific($provider);
+        }
+
+        return true;
+    }
+
+    /**
+     * @param string $prettyString
+     */
+    public function setPrettyString($prettyString)
+    {
+        $this->prettyString = $prettyString;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrettyString()
+    {
+        if ($this->prettyString) {
+            return $this->prettyString;
+        }
+
+        return $this->__toString();
+    }
+
+    // implementations must implement a method of this format:
+    // not declared abstract here because type hinting violates parameter coherence (TODO right word?)
+    // public function matchSpecific(<SpecificConstraintType> $provider);
+}
diff --git a/vendor/composer/semver/src/Constraint/Constraint.php b/vendor/composer/semver/src/Constraint/Constraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..8bc68db7b31eac596050be9f15bdc1973dcefe3a
--- /dev/null
+++ b/vendor/composer/semver/src/Constraint/Constraint.php
@@ -0,0 +1,181 @@
+<?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;
+    }
+}
diff --git a/vendor/composer/semver/src/Constraint/ConstraintInterface.php b/vendor/composer/semver/src/Constraint/ConstraintInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..78c099cec107c13e0dc96656e5758ca099f069a0
--- /dev/null
+++ b/vendor/composer/semver/src/Constraint/ConstraintInterface.php
@@ -0,0 +1,37 @@
+<?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;
+
+interface ConstraintInterface
+{
+    /**
+     * @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();
+}
diff --git a/vendor/composer/semver/src/Constraint/EmptyConstraint.php b/vendor/composer/semver/src/Constraint/EmptyConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..faba56bf0c814c0134558737bab3b598643c0879
--- /dev/null
+++ b/vendor/composer/semver/src/Constraint/EmptyConstraint.php
@@ -0,0 +1,59 @@
+<?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 the absence of a constraint.
+ */
+class EmptyConstraint implements ConstraintInterface
+{
+    /** @var string */
+    protected $prettyString;
+
+    /**
+     * @param ConstraintInterface $provider
+     *
+     * @return bool
+     */
+    public function matches(ConstraintInterface $provider)
+    {
+        return true;
+    }
+
+    /**
+     * @param $prettyString
+     */
+    public function setPrettyString($prettyString)
+    {
+        $this->prettyString = $prettyString;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrettyString()
+    {
+        if ($this->prettyString) {
+            return $this->prettyString;
+        }
+
+        return $this->__toString();
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return '[]';
+    }
+}
diff --git a/vendor/composer/semver/src/Constraint/MultiConstraint.php b/vendor/composer/semver/src/Constraint/MultiConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d769b7c1d5d63dfd969d942b7f9ba5f10d2227f
--- /dev/null
+++ b/vendor/composer/semver/src/Constraint/MultiConstraint.php
@@ -0,0 +1,96 @@
+<?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 conjunctive or disjunctive set of constraints.
+ */
+class MultiConstraint implements ConstraintInterface
+{
+    /** @var ConstraintInterface[] */
+    protected $constraints;
+
+    /** @var string */
+    protected $prettyString;
+
+    /** @var bool */
+    protected $conjunctive;
+
+    /**
+     * @param ConstraintInterface[] $constraints A set of constraints
+     * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive
+     */
+    public function __construct(array $constraints, $conjunctive = true)
+    {
+        $this->constraints = $constraints;
+        $this->conjunctive = $conjunctive;
+    }
+
+    /**
+     * @param ConstraintInterface $provider
+     *
+     * @return bool
+     */
+    public function matches(ConstraintInterface $provider)
+    {
+        if (false === $this->conjunctive) {
+            foreach ($this->constraints as $constraint) {
+                if ($constraint->matches($provider)) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        foreach ($this->constraints as $constraint) {
+            if (!$constraint->matches($provider)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * @param string $prettyString
+     */
+    public function setPrettyString($prettyString)
+    {
+        $this->prettyString = $prettyString;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrettyString()
+    {
+        if ($this->prettyString) {
+            return $this->prettyString;
+        }
+
+        return $this->__toString();
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        $constraints = array();
+        foreach ($this->constraints as $constraint) {
+            $constraints[] = (string) $constraint;
+        }
+
+        return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
+    }
+}
diff --git a/vendor/composer/semver/src/Semver.php b/vendor/composer/semver/src/Semver.php
new file mode 100644
index 0000000000000000000000000000000000000000..0225bb55ad645cdb9679d68a6e5c172b58ba13fe
--- /dev/null
+++ b/vendor/composer/semver/src/Semver.php
@@ -0,0 +1,127 @@
+<?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;
+
+use Composer\Semver\Constraint\Constraint;
+
+class Semver
+{
+    const SORT_ASC = 1;
+    const SORT_DESC = -1;
+
+    /** @var VersionParser */
+    private static $versionParser;
+
+    /**
+     * Determine if given version satisfies given constraints.
+     *
+     * @param string $version
+     * @param string $constraints
+     *
+     * @return bool
+     */
+    public static function satisfies($version, $constraints)
+    {
+        if (null === self::$versionParser) {
+            self::$versionParser = new VersionParser();
+        }
+
+        $versionParser = self::$versionParser;
+        $provider = new Constraint('==', $versionParser->normalize($version));
+        $constraints = $versionParser->parseConstraints($constraints);
+
+        return $constraints->matches($provider);
+    }
+
+    /**
+     * Return all versions that satisfy given constraints.
+     *
+     * @param array $versions
+     * @param string $constraints
+     *
+     * @return array
+     */
+    public static function satisfiedBy(array $versions, $constraints)
+    {
+        $versions = array_filter($versions, function ($version) use ($constraints) {
+            return Semver::satisfies($version, $constraints);
+        });
+
+        return array_values($versions);
+    }
+
+    /**
+     * Sort given array of versions.
+     *
+     * @param array $versions
+     *
+     * @return array
+     */
+    public static function sort(array $versions)
+    {
+        return self::usort($versions, self::SORT_ASC);
+    }
+
+    /**
+     * Sort given array of versions in reverse.
+     *
+     * @param array $versions
+     *
+     * @return array
+     */
+    public static function rsort(array $versions)
+    {
+        return self::usort($versions, self::SORT_DESC);
+    }
+
+    /**
+     * @param array $versions
+     * @param int $direction
+     *
+     * @return array
+     */
+    private static function usort(array $versions, $direction)
+    {
+        if (null === self::$versionParser) {
+            self::$versionParser = new VersionParser();
+        }
+
+        $versionParser = self::$versionParser;
+        $normalized = array();
+
+        // Normalize outside of usort() scope for minor performance increase.
+        // Creates an array of arrays: [[normalized, key], ...]
+        foreach ($versions as $key => $version) {
+            $normalized[] = array($versionParser->normalize($version), $key);
+        }
+
+        usort($normalized, function (array $left, array $right) use ($direction) {
+            if ($left[0] === $right[0]) {
+                return 0;
+            }
+
+            if (Comparator::lessThan($left[0], $right[0])) {
+                return -$direction;
+            }
+
+            return $direction;
+        });
+
+        // Recreate input array, using the original indexes which are now in sorted order.
+        $sorted = array();
+        foreach ($normalized as $item) {
+            $sorted[] = $versions[$item[1]];
+        }
+
+        return $sorted;
+    }
+}
diff --git a/vendor/composer/semver/src/VersionParser.php b/vendor/composer/semver/src/VersionParser.php
new file mode 100644
index 0000000000000000000000000000000000000000..269aee9487133b14168dca31b24b4e3b0c33e71b
--- /dev/null
+++ b/vendor/composer/semver/src/VersionParser.php
@@ -0,0 +1,520 @@
+<?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;
+
+use Composer\Semver\Constraint\ConstraintInterface;
+use Composer\Semver\Constraint\EmptyConstraint;
+use Composer\Semver\Constraint\MultiConstraint;
+use Composer\Semver\Constraint\Constraint;
+
+/**
+ * Version parser.
+ *
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class VersionParser
+{
+    /** @var string */
+    private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)(?:[.-]?(\d+))?)?([.-]?dev)?';
+
+    /** @var array */
+    private static $stabilities = array(
+        'stable', 'RC', 'beta', 'alpha', 'dev',
+    );
+
+    /**
+     * Returns the stability of a version.
+     *
+     * @param string $version
+     *
+     * @return string
+     */
+    public static function parseStability($version)
+    {
+        $version = preg_replace('{#.+$}i', '', $version);
+
+        if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
+            return 'dev';
+        }
+
+        preg_match('{' . self::$modifierRegex . '$}i', strtolower($version), $match);
+        if (!empty($match[3])) {
+            return 'dev';
+        }
+
+        if (!empty($match[1])) {
+            if ('beta' === $match[1] || 'b' === $match[1]) {
+                return 'beta';
+            }
+            if ('alpha' === $match[1] || 'a' === $match[1]) {
+                return 'alpha';
+            }
+            if ('rc' === $match[1]) {
+                return 'RC';
+            }
+        }
+
+        return 'stable';
+    }
+
+    /**
+     * @param string $stability
+     *
+     * @return string
+     */
+    public static function normalizeStability($stability)
+    {
+        $stability = strtolower($stability);
+
+        return $stability === 'rc' ? 'RC' : $stability;
+    }
+
+    /**
+     * Normalizes a version string to be able to perform comparisons on it.
+     *
+     * @param string $version
+     * @param string $fullVersion optional complete version string to give more context
+     *
+     * @throws \UnexpectedValueException
+     *
+     * @return string
+     */
+    public function normalize($version, $fullVersion = null)
+    {
+        $version = trim($version);
+        if (null === $fullVersion) {
+            $fullVersion = $version;
+        }
+
+        // strip off aliasing
+        if (preg_match('{^([^,\s]+) +as +([^,\s]+)$}', $version, $match)) {
+            $version = $match[1];
+        }
+
+        // strip off build metadata
+        if (preg_match('{^([^,\s+]+)\+[^\s]+$}', $version, $match)) {
+            $version = $match[1];
+        }
+
+        // match master-like branches
+        if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
+            return '9999999-dev';
+        }
+
+        if ('dev-' === strtolower(substr($version, 0, 4))) {
+            return 'dev-' . substr($version, 4);
+        }
+
+        // match classical versioning
+        if (preg_match('{^v?(\d{1,5})(\.\d+)?(\.\d+)?(\.\d+)?' . self::$modifierRegex . '$}i', $version, $matches)) {
+            $version = $matches[1]
+                . (!empty($matches[2]) ? $matches[2] : '.0')
+                . (!empty($matches[3]) ? $matches[3] : '.0')
+                . (!empty($matches[4]) ? $matches[4] : '.0');
+            $index = 5;
+        // match date(time) based versioning
+        } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
+            $version = preg_replace('{\D}', '-', $matches[1]);
+            $index = 2;
+        }
+
+        // add version modifiers if a version was matched
+        if (isset($index)) {
+            if (!empty($matches[$index])) {
+                if ('stable' === $matches[$index]) {
+                    return $version;
+                }
+                $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? $matches[$index + 1] : '');
+            }
+
+            if (!empty($matches[$index + 2])) {
+                $version .= '-dev';
+            }
+
+            return $version;
+        }
+
+        // match dev branches
+        if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
+            try {
+                return $this->normalizeBranch($match[1]);
+            } catch (\Exception $e) {
+            }
+        }
+
+        $extraMessage = '';
+        if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
+            $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
+        } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
+            $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
+        }
+
+        throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
+    }
+
+    /**
+     * Extract numeric prefix from alias, if it is in numeric format, suitable for version comparison.
+     *
+     * @param string $branch Branch name (e.g. 2.1.x-dev)
+     *
+     * @return string|false Numeric prefix if present (e.g. 2.1.) or false
+     */
+    public function parseNumericAliasPrefix($branch)
+    {
+        if (preg_match('{^(?P<version>(\d+\\.)*\d+)(?:\.x)?-dev$}i', $branch, $matches)) {
+            return $matches['version'] . '.';
+        }
+
+        return false;
+    }
+
+    /**
+     * Normalizes a branch name to be able to perform comparisons on it.
+     *
+     * @param string $name
+     *
+     * @return string
+     */
+    public function normalizeBranch($name)
+    {
+        $name = trim($name);
+
+        if (in_array($name, array('master', 'trunk', 'default'))) {
+            return $this->normalize($name);
+        }
+
+        if (preg_match('{^v?(\d+)(\.(?:\d+|[xX*]))?(\.(?:\d+|[xX*]))?(\.(?:\d+|[xX*]))?$}i', $name, $matches)) {
+            $version = '';
+            for ($i = 1; $i < 5; ++$i) {
+                $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
+            }
+
+            return str_replace('x', '9999999', $version) . '-dev';
+        }
+
+        return 'dev-' . $name;
+    }
+
+    /**
+     * Parses as constraint string into LinkConstraint objects.
+     *
+     * @param string $constraints
+     *
+     * @return ConstraintInterface
+     */
+    public function parseConstraints($constraints)
+    {
+        $prettyConstraint = $constraints;
+
+        if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
+            $constraints = empty($match[1]) ? '*' : $match[1];
+        }
+
+        if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
+            $constraints = $match[1];
+        }
+
+        $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
+        $orGroups = array();
+        foreach ($orConstraints as $constraints) {
+            $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
+            if (count($andConstraints) > 1) {
+                $constraintObjects = array();
+                foreach ($andConstraints as $constraint) {
+                    foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
+                        $constraintObjects[] = $parsedConstraint;
+                    }
+                }
+            } else {
+                $constraintObjects = $this->parseConstraint($andConstraints[0]);
+            }
+
+            if (1 === count($constraintObjects)) {
+                $constraint = $constraintObjects[0];
+            } else {
+                $constraint = new MultiConstraint($constraintObjects);
+            }
+
+            $orGroups[] = $constraint;
+        }
+
+        if (1 === count($orGroups)) {
+            $constraint = $orGroups[0];
+        } else {
+            $constraint = new MultiConstraint($orGroups, false);
+        }
+
+        $constraint->setPrettyString($prettyConstraint);
+
+        return $constraint;
+    }
+
+    /**
+     * @param string $constraint
+     *
+     * @throws \UnexpectedValueException
+     *
+     * @return array
+     */
+    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('{^[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 (substr($constraint, 0, 2) === '~>') {
+                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]) {
+                $position = 4;
+            } elseif (isset($matches[3]) && '' !== $matches[3]) {
+                $position = 3;
+            } elseif (isset($matches[2]) && '' !== $matches[2]) {
+                $position = 2;
+            } else {
+                $position = 1;
+            }
+
+            // Calculate the stability suffix
+            $stabilitySuffix = '';
+            if (!empty($matches[5])) {
+                $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : '');
+            }
+
+            if (!empty($matches[7])) {
+                $stabilitySuffix .= '-dev';
+            }
+
+            if (!$stabilitySuffix) {
+                $stabilitySuffix = '-dev';
+            }
+
+            $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix;
+            $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]) {
+                $position = 1;
+            } elseif ('0' !== $matches[2] || '' === $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('{^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.[xX*])+$}', $constraint, $matches)) {
+            if (isset($matches[3]) && '' !== $matches[3]) {
+                $position = 3;
+            } elseif (isset($matches[2]) && '' !== $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) && $this->parseStability($version) === 'stable') {
+                    $version .= '-' . $stabilityModifier;
+                } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
+                    if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
+                        if (substr($matches[2], 0, 4) !== 'dev-') {
+                            $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);
+    }
+
+    /**
+     * Increment, decrement, or simply pad a version number.
+     *
+     * Support function for {@link parseConstraint()}
+     *
+     * @param array $matches Array with version parts in array indexes 1,2,3,4
+     * @param int $position 1,2,3,4 - which segment of the version to increment/decrement
+     * @param int $increment
+     * @param string $pad The string to pad version parts after $position
+     *
+     * @return string The new version
+     */
+    private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
+    {
+        for ($i = 4; $i > 0; --$i) {
+            if ($i > $position) {
+                $matches[$i] = $pad;
+            } elseif ($i === $position && $increment) {
+                $matches[$i] += $increment;
+                // If $matches[$i] was 0, carry the decrement
+                if ($matches[$i] < 0) {
+                    $matches[$i] = $pad;
+                    --$position;
+
+                    // Return null on a carry overflow
+                    if ($i === 1) {
+                        return;
+                    }
+                }
+            }
+        }
+
+        return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
+    }
+
+    /**
+     * Expand shorthand stability string to long version.
+     *
+     * @param string $stability
+     *
+     * @return string
+     */
+    private function expandStability($stability)
+    {
+        $stability = strtolower($stability);
+
+        switch ($stability) {
+            case 'a':
+                return 'alpha';
+            case 'b':
+                return 'beta';
+            case 'p':
+            case 'pl':
+                return 'patch';
+            case 'rc':
+                return 'RC';
+            default:
+                return $stability;
+        }
+    }
+}