Chris@0: Chris@0: */ Chris@0: class StabilityFlags Chris@0: { Chris@0: Chris@0: /** Chris@0: * @var array Current package name => stability mappings Chris@0: */ Chris@0: protected $stabilityFlags; Chris@0: Chris@0: /** Chris@0: * @var int Current default minimum stability Chris@0: */ Chris@0: protected $minimumStability; Chris@0: Chris@0: /** Chris@0: * @var string Regex to extract an explict stability flag (eg '@dev') Chris@0: */ Chris@0: protected $explicitStabilityRe; Chris@0: Chris@0: Chris@0: /** Chris@0: * @param array $stabilityFlags Current package name => stability mappings Chris@0: * @param int $minimumStability Current default minimum stability Chris@0: */ Chris@0: public function __construct( Chris@0: array $stabilityFlags = array(), Chris@0: $minimumStability = BasePackage::STABILITY_STABLE Chris@0: ) { Chris@0: $this->stabilityFlags = $stabilityFlags; Chris@0: $this->minimumStability = $this->getStabilityInt($minimumStability); Chris@0: $this->explicitStabilityRe = '/^[^@]*?@(' . Chris@0: implode('|', array_keys(BasePackage::$stabilities)) . Chris@0: ')$/i'; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the stability value for a given string. Chris@0: * Chris@0: * @param string $name Stability name Chris@0: * @return int Stability value Chris@0: */ Chris@0: protected function getStabilityInt($name) Chris@0: { Chris@0: $name = VersionParser::normalizeStability($name); Chris@0: return isset(BasePackage::$stabilities[$name]) ? Chris@0: BasePackage::$stabilities[$name] : Chris@0: BasePackage::STABILITY_STABLE; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Extract and merge stability flags from the given collection of Chris@0: * requires with another collection of stability flags. Chris@0: * Chris@0: * @param array $requires New package name => link mappings Chris@0: * @return array Unified package name => stability mappings Chris@0: */ Chris@0: public function extractAll(array $requires) Chris@0: { Chris@0: $flags = array(); Chris@0: Chris@0: foreach ($requires as $name => $link) { Chris@0: $name = strtolower($name); Chris@0: $version = $link->getPrettyConstraint(); Chris@0: Chris@0: $stability = $this->getExplicitStability($version); Chris@0: Chris@0: if ($stability === null) { Chris@0: $stability = $this->getParsedStability($version); Chris@0: } Chris@0: Chris@0: $flags[$name] = max($stability, $this->getCurrentStability($name)); Chris@0: } Chris@0: Chris@0: // Filter out null stability values Chris@0: return array_filter($flags, function ($v) { Chris@0: return $v !== null; Chris@0: }); Chris@0: } Chris@0: Chris@0: Chris@0: /** Chris@0: * Extract the most unstable explicit stability (eg '@dev') from a version Chris@0: * specification. Chris@0: * Chris@0: * @param string $version Chris@0: * @return int|null Stability or null if no explict stability found Chris@0: */ Chris@0: protected function getExplicitStability($version) Chris@0: { Chris@0: $found = null; Chris@0: $constraints = $this->splitConstraints($version); Chris@0: foreach ($constraints as $constraint) { Chris@0: if (preg_match($this->explicitStabilityRe, $constraint, $match)) { Chris@0: $stability = $this->getStabilityInt($match[1]); Chris@0: $found = max($stability, $found); Chris@0: } Chris@0: } Chris@0: return $found; Chris@0: } Chris@0: Chris@0: Chris@0: /** Chris@0: * Split a version specification into a list of version constraints. Chris@0: * Chris@0: * @param string $version Chris@0: * @return array Chris@0: */ Chris@0: protected function splitConstraints($version) Chris@0: { Chris@0: $found = array(); Chris@0: $orConstraints = preg_split('/\s*\|\|?\s*/', trim($version)); Chris@0: foreach ($orConstraints as $constraints) { Chris@0: $andConstraints = preg_split( Chris@0: '/(?< ,]) *(?getStabilityInt( Chris@0: VersionParser::parseStability($version) Chris@0: ); Chris@0: Chris@0: if ($stability === BasePackage::STABILITY_STABLE || Chris@0: $this->minimumStability > $stability Chris@0: ) { Chris@0: // Ignore if 'stable' or more stable than the global Chris@0: // minimum Chris@0: $stability = null; Chris@0: } Chris@0: Chris@0: return $stability; Chris@0: } Chris@0: Chris@0: Chris@0: /** Chris@0: * Get the current stability of a given package. Chris@0: * Chris@0: * @param string $name Chris@0: * @return int|null Stability of null if not set Chris@0: */ Chris@0: protected function getCurrentStability($name) Chris@0: { Chris@0: return isset($this->stabilityFlags[$name]) ? Chris@0: $this->stabilityFlags[$name] : null; Chris@0: } Chris@0: } Chris@0: // vim:sw=4:ts=4:sts=4:et: