<?php /** * This file is part of Dockerize, a PHP Experts, Inc., Project. * * Copyright © 2024 PHP Experts, Inc. * Author: Theodore R. Smith <theodore@phpexperts.pro> * GPG Fingerprint: 4BF8 2613 1C34 87AC D28F 2AD8 EB24 A91D D612 5690 * https://www.phpexperts.pro/ * https://github.com/PHPExpertsInc/dockerize * * This file is licensed under the MIT License. */ class PhpVersionExtractor { private $allVersions = ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']; private $composerJson; public $versionConstraint; public function __construct($composerJson) { $this->composerJson = $composerJson; } public function getPhpVersionConstraint() { if ($this->versionConstraint === null) { $this->getPhpVersions(); } return $this->versionConstraint; } public function getPhpVersions() { $phpConstraint = $this->extractPhpConstraint(); $this->versionConstraint = $phpConstraint; if (is_null($phpConstraint)) { return implode(' ', $this->allVersions); } $selectedVersions = []; foreach ($this->allVersions as $version) { if ($this->versionSatisfies($version, $phpConstraint)) { $selectedVersions[] = $version; } } return implode(' ', $selectedVersions); } private function extractPhpConstraint() { if (!is_readable($this->composerJson)) { return null; } $data = json_decode(file_get_contents($this->composerJson), true); if (isset($data['require']) && isset($data['require']['php'])) { return $data['require']['php']; } return null; } private function versionSatisfies($version, $constraints) { $constraints = str_replace(' ', '', $constraints); $constraints = explode(',', $constraints); foreach ($constraints as $constraint) { if (preg_match('/^(>=|<=|>|<|=|~|\^)?(\d+\.\d+)/', $constraint, $matches)) { $operator = isset($matches[1]) ? $matches[1] : '='; $constraintVersion = $matches[2]; if (!$this->compareVersion($version, $operator, $constraintVersion)) { return false; } } } return true; } private function compareVersion($version, $operator, $constraintVersion) { switch ($operator) { case '>=': return version_compare($version, $constraintVersion, '>='); case '<=': return version_compare($version, $constraintVersion, '<='); case '>': return version_compare($version, $constraintVersion, '>'); case '<': return version_compare($version, $constraintVersion, '<'); case '~': case '^': return version_compare($version, $constraintVersion, '>=') && version_compare($version, $this->getUpperVersionLimit($constraintVersion, $operator), '<'); case '=': default: return version_compare($version, $constraintVersion, '=='); } } private function getUpperVersionLimit($version, $operator) { list($major, $minor) = explode('.', $version); if ($operator === '^') { return ($major + 1) . '.0'; } elseif ($operator === '~') { return $major . '.' . ($minor + 1); } return $version; } } // Usage example $composerJson = 'composer.json'; $extractor = new PhpVersionExtractor($composerJson); echo $extractor->getPhpVersions();