220 lines
6.9 KiB
PHP
220 lines
6.9 KiB
PHP
<?php
|
||
|
||
/*
|
||
* This file is part of the Fxp Composer Asset Plugin package.
|
||
*
|
||
* (c) François Pluchino <francois.pluchino@gmail.com>
|
||
*
|
||
* For the full copyright and license information, please view the LICENSE
|
||
* file that was distributed with this source code.
|
||
*/
|
||
|
||
namespace Fxp\Composer\AssetPlugin\Converter;
|
||
|
||
/**
|
||
* Converter for Semver syntax version to composer syntax version.
|
||
*
|
||
* @author François Pluchino <francois.pluchino@gmail.com>
|
||
*/
|
||
class SemverConverter implements VersionConverterInterface
|
||
{
|
||
/**
|
||
* {@inheritdoc}
|
||
*/
|
||
public function convertVersion($version)
|
||
{
|
||
if (in_array($version, array(null, '', 'latest'))) {
|
||
return ('latest' === $version ? 'default || ' : '').'*';
|
||
}
|
||
|
||
$version = str_replace('–', '-', $version);
|
||
$prefix = preg_match('/^[a-z]/', $version) && 0 !== strpos($version, 'dev-') ? substr($version, 0, 1) : '';
|
||
$version = substr($version, strlen($prefix));
|
||
$version = SemverUtil::convertVersionMetadata($version);
|
||
$version = SemverUtil::convertDateVersion($version);
|
||
|
||
return $prefix.$version;
|
||
}
|
||
|
||
/**
|
||
* {@inheritdoc}
|
||
*/
|
||
public function convertRange($range)
|
||
{
|
||
$range = $this->cleanRange(strtolower($range));
|
||
|
||
return $this->matchRange($range);
|
||
}
|
||
|
||
/**
|
||
* Clean the raw range.
|
||
*
|
||
* @param string $range
|
||
*
|
||
* @return string
|
||
*/
|
||
protected function cleanRange($range)
|
||
{
|
||
foreach (array('<', '>', '=', '~', '^', '||', '&&') as $character) {
|
||
$range = str_replace($character.' ', $character, $range);
|
||
}
|
||
|
||
$range = preg_replace('/(?:[vV])(\d+)/', '${1}', $range);
|
||
$range = str_replace(' ||', '||', $range);
|
||
$range = str_replace(array(' &&', '&&'), ',', $range);
|
||
|
||
return $range;
|
||
}
|
||
|
||
/**
|
||
* Match the range.
|
||
*
|
||
* @param string $range The range cleaned
|
||
*
|
||
* @return string The range
|
||
*/
|
||
protected function matchRange($range)
|
||
{
|
||
$pattern = '/(\ -\ )|(<)|(>)|(=)|(\|\|)|(\ )|(,)|(\~)|(\^)/';
|
||
$matches = preg_split($pattern, $range, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||
$special = null;
|
||
$replace = null;
|
||
$first = true;
|
||
|
||
foreach ($matches as $i => $match) {
|
||
if ($first && '' !== $match) {
|
||
$first = false;
|
||
$match = '=' === $match ? 'EQUAL' : $match;
|
||
}
|
||
|
||
$this->matchRangeToken($i, $match, $matches, $special, $replace);
|
||
}
|
||
|
||
return implode('', $matches);
|
||
}
|
||
|
||
/**
|
||
* Converts the token of the matched range.
|
||
*
|
||
* @param int $i
|
||
* @param string $match
|
||
* @param array $matches
|
||
* @param string|null $special
|
||
* @param string|null $replace
|
||
*/
|
||
protected function matchRangeToken($i, $match, array &$matches, &$special, &$replace)
|
||
{
|
||
if (' - ' === $match) {
|
||
$matches[$i - 1] = '>='.str_replace(array('*', 'x', 'X'), '0', $matches[$i - 1]);
|
||
|
||
if (false !== strpos($matches[$i + 1], '.') && strpos($matches[$i + 1], '*') === false
|
||
&& strpos($matches[$i + 1], 'x') === false && strpos($matches[$i + 1], 'X') === false) {
|
||
$matches[$i] = ',<=';
|
||
} else {
|
||
$matches[$i] = ',<';
|
||
$special = ',<~';
|
||
}
|
||
} else {
|
||
$this->matchRangeTokenStep2($i, $match, $matches, $special, $replace);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Step2: Converts the token of the matched range.
|
||
*
|
||
* @param int $i
|
||
* @param string $match
|
||
* @param array $matches
|
||
* @param string|null $special
|
||
* @param string|null $replace
|
||
*/
|
||
protected function matchRangeTokenStep2($i, $match, array &$matches, &$special, &$replace)
|
||
{
|
||
if (in_array($match, array('', '<', '>', '=', ','))) {
|
||
$replace = in_array($match, array('<', '>')) ? $match : $replace;
|
||
$matches[$i] = '~' === $special && in_array($replace, array('<', '>')) ? '' : $matches[$i];
|
||
} elseif ('~' === $match) {
|
||
$special = $match;
|
||
} elseif (in_array($match, array('EQUAL', '^'))) {
|
||
$special = $match;
|
||
$matches[$i] = '';
|
||
} else {
|
||
$this->matchRangeTokenStep3($i, $match, $matches, $special, $replace);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Step3: Converts the token of the matched range.
|
||
*
|
||
* @param int $i
|
||
* @param string $match
|
||
* @param array $matches
|
||
* @param string|null $special
|
||
* @param string|null $replace
|
||
*/
|
||
protected function matchRangeTokenStep3($i, $match, array &$matches, &$special, &$replace)
|
||
{
|
||
if (' ' === $match) {
|
||
$matches[$i] = ',';
|
||
} elseif ('||' === $match) {
|
||
$matches[$i] = '|';
|
||
} elseif (in_array($special, array('^'))) {
|
||
$matches[$i] = SemverRangeUtil::replaceSpecialRange($this, $match);
|
||
$special = null;
|
||
} else {
|
||
$this->matchRangeTokenStep4($i, $match, $matches, $special, $replace);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Step4: Converts the token of the matched range.
|
||
*
|
||
* @param int $i
|
||
* @param string $match
|
||
* @param array $matches
|
||
* @param string|null $special
|
||
* @param string|null $replace
|
||
*/
|
||
protected function matchRangeTokenStep4($i, $match, array &$matches, &$special, &$replace)
|
||
{
|
||
if ($special === ',<~') {
|
||
// Version range contains x in last place.
|
||
$match .= (false === strpos($match, '.') ? '.x' : '');
|
||
$version = explode('.', $match);
|
||
$change = count($version) - 2;
|
||
$version[$change] = (int) ($version[$change]) + 1;
|
||
$match = str_replace(array('*', 'x', 'X'), '0', implode('.', $version));
|
||
} elseif (null === $special && $i === 0 && false === strpos($match, '.') && is_numeric($match)) {
|
||
$match = isset($matches[$i + 1]) && (' - ' === $matches[$i + 1] || '-' === $matches[$i + 1])
|
||
? $match
|
||
: '~'.$match;
|
||
} else {
|
||
$match = '~' === $special ? str_replace(array('*', 'x', 'X'), '0', $match) : $match;
|
||
}
|
||
|
||
$this->matchRangeTokenStep5($i, $match, $matches, $special, $replace);
|
||
}
|
||
|
||
/**
|
||
* Step5: Converts the token of the matched range.
|
||
*
|
||
* @param int $i
|
||
* @param string $match
|
||
* @param array $matches
|
||
* @param string|null $special
|
||
* @param string|null $replace
|
||
*/
|
||
protected function matchRangeTokenStep5($i, $match, array &$matches, &$special, &$replace)
|
||
{
|
||
$matches[$i] = $this->convertVersion($match);
|
||
$matches[$i] = $replace
|
||
? SemverUtil::replaceAlias($matches[$i], $replace)
|
||
: $matches[$i];
|
||
$matches[$i] .= '~' === $special && in_array($replace, array('<', '>'))
|
||
? ','.$replace.$matches[$i]
|
||
: '';
|
||
$special = null;
|
||
$replace = null;
|
||
}
|
||
}
|