/** * @param $vulnerabilities * @param $version * @param null $found_vulnerabilities * * @return bool */ public function isVulnerable($vulnerabilities, $version, &$found_vulnerabilities = null) { $found_vulnerabilities = Collection::make($vulnerabilities)->filter(function ($v) use($version) { return $this->semver->lessThan($version, $v->fixed_in); }); return $found_vulnerabilities->count() > 0; }
/** * {@inheritdoc} */ public function getOutput(OperationInterface $operation, UrlGenerator $urlGenerator = null) { if (!$operation instanceof UpdateOperation) { throw new \LogicException('Operation should be an instance of UpdateOperation'); } $output = []; $initialPackage = $operation->getInitialPackage(); $targetPackage = $operation->getTargetPackage(); $versionFrom = new Version($initialPackage->getVersion(), $initialPackage->getPrettyVersion(), method_exists($initialPackage, 'getFullPrettyVersion') ? $initialPackage->getFullPrettyVersion() : VersionParser::formatVersion($initialPackage)); $versionTo = new Version($targetPackage->getVersion(), $targetPackage->getPrettyVersion(), method_exists($targetPackage, 'getFullPrettyVersion') ? $targetPackage->getFullPrettyVersion() : VersionParser::formatVersion($targetPackage)); $action = 'updated'; if (Comparator::greaterThan($versionFrom->getName(), $versionTo->getName())) { $action = 'downgraded'; } $output[] = sprintf(' - <fg=green>%s</fg=green> %s from <fg=yellow>%s</fg=yellow> to <fg=yellow>%s</fg=yellow>', $initialPackage->getName(), $action, $versionFrom->getPretty(), $versionTo->getPretty()); if ($urlGenerator) { $compareUrl = $urlGenerator->generateCompareUrl($initialPackage->getSourceUrl(), $versionFrom, $targetPackage->getSourceUrl(), $versionTo); if (!empty($compareUrl)) { $output[] = sprintf(' See changes: %s', $compareUrl); } $releaseUrl = $urlGenerator->generateReleaseUrl($this->extractSourceUrl($operation), $versionTo); if (!empty($releaseUrl)) { $output[] = sprintf(' Release notes: %s', $releaseUrl); } } return $output; }
/** * Checks a composer.lock file. * * @param string $lock The path to the composer.lock file * * @return array Result array * * @throws \InvalidArgumentException When the output format is unsupported * @throws \RuntimeException When the lock file does not exist * @throws \RuntimeException When curl does not work or is unavailable */ public function check($lock) { if (is_dir($lock) && file_exists($lock . '/composer.lock')) { $lock = $lock . '/composer.lock'; } elseif (preg_match('/composer\\.json$/', $lock)) { $lock = str_replace('composer.json', 'composer.lock', $lock); } if (!is_file($lock)) { throw new \RuntimeException('Lock file does not exist.'); } $results = array(); $client = new Client(); $vp = new VersionParser(); $data = json_decode(file_get_contents($lock), 1); foreach ($data['packages'] as $package) { $name = $package['name']; $status = 'found'; $localVersion = $vp->normalize($package['version']); $localStatus = $this->parseStatus($localVersion); $stableVersion = 0; $stableStatus = ''; $devVersion = 0; $devStatus = ''; $remoteData = null; try { $response = $client->get("https://packagist.org/packages/{$name}.json"); $body = $response->getBody(); $statusCode = $response->getStatusCode(); if (200 === $statusCode) { $remoteData = json_decode($body, true); } else { $status = 'error'; } } catch (\Exception $e) { $status = 'error'; } if ($remoteData) { foreach ($remoteData['package']['versions'] as $versionName => $versionData) { if ($this->isStable($versionData['version_normalized']) && Comparator::greaterThan($versionData['version_normalized'], $stableVersion)) { $stableVersion = $versionData['version_normalized']; $stableStatus = $this->diffVersion($localVersion, $stableVersion); } } foreach ($remoteData['package']['versions'] as $versionName => $versionData) { if ($this->isTaggedDev($versionData['version_normalized']) && Comparator::greaterThan($versionData['version_normalized'], $devVersion) && Comparator::greaterThan($versionData['version_normalized'], $stableVersion) && ($localVersion === '9999999-dev' || Comparator::greaterThan($versionData['version_normalized'], $localVersion))) { $devVersion = $versionData['version_normalized']; $devStatus = $this->diffVersion($localVersion, $devVersion); } } } else { $stableVersion = 'Not found'; $stableStatus = 'error'; $devVersion = 'Not found'; $devStatus = 'error'; } $results[$name] = array('name' => $name, 'status' => $status, 'localVersion' => $localVersion, 'localStatus' => $localStatus, 'stableVersion' => $stableVersion, 'stableStatus' => $stableStatus, 'devVersion' => $devVersion, 'devStatus' => $devStatus); } return $results; }
/** * Checks if the installed version of Composer is compatible. * * Composer 1.0.0 and higher consider a `composer install` without having a * lock file present as equal to `composer update`. We do not ship with a lock * file to avoid merge conflicts downstream, meaning that if a project is * installed with an older version of Composer the scaffolding of Drupal will * not be triggered. We check this here instead of in drupal-scaffold to be * able to give immediate feedback to the end user, rather than failing the * installation after going through the lengthy process of compiling and * downloading the Composer dependencies. * * @see https://github.com/composer/composer/pull/5035 */ public static function checkComposerVersion(Event $event) { $composer = $event->getComposer(); $io = $event->getIO(); $version = $composer::VERSION; // If Composer is installed through git we have no easy way to determine if // it is new enough, just display a warning. if ($version === '@package_version@') { $io->writeError('<warning>You are running a development version of Composer. If you experience problems, please update Composer to the latest stable version.</warning>'); } elseif (Comparator::lessThan($version, '1.0.0')) { $io->writeError('<error>Drupal-project requires Composer version 1.0.0 or higher. Please update your Composer before continuing</error>.'); exit(1); } }
public static function findMax(array $versions) { $versions = array_values(array_unique($versions)); if (count($versions) < 2) { return reset($versions); } $max = $versions[0]; for ($i = 1; $i < count($versions); ++$i) { $cur = $versions[$i]; if (Comparator::compare($cur, '>', $max)) { $max = $cur; } } return trim($max); }
/** * Get the last version number from a list of versions. * * @param array $versions * * @return string */ public static function latest(array $versions) { // Normalize version numbers. $versions = array_map(function ($version) { return static::normalize($version); }, $versions); // Get the highest version number. $latest = array_reduce($versions, function ($carry, $item) { // Skip unstable versions. if (VersionParser::parseStability($item) !== 'stable') { return $carry; } return Comparator::greaterThan($carry, $item) ? $carry : $item; }, '0.0.0'); return $latest; }
/** * Checks if the installed version of Composer is compatible. * * Composer 1.0.0 and higher consider a `composer install` without having a * lock file present as equal to `composer update`. We do not ship with a lock * file to avoid merge conflicts downstream, meaning that if a project is * installed with an older version of Composer the scaffolding of Drupal will * not be triggered. We check this here instead of in drupal-scaffold to be * able to give immediate feedback to the end user, rather than failing the * installation after going through the lengthy process of compiling and * downloading the Composer dependencies. * * @see https://github.com/composer/composer/pull/5035 */ public static function checkComposerVersion(Event $event) { $composer = $event->getComposer(); $io = $event->getIO(); $version = $composer::VERSION; // The dev-channel of composer uses the git revision as version number, // try to the branch alias instead. if (preg_match('/^[0-9a-f]{40}$/i', $version)) { $version = $composer::BRANCH_ALIAS_VERSION; } // If Composer is installed through git we have no easy way to determine if // it is new enough, just display a warning. if ($version === '@package_version@' || $version === '@package_branch_alias_version@') { $io->writeError('<warning>You are running a development version of Composer. If you experience problems, please update Composer to the latest stable version.</warning>'); } elseif (Comparator::lessThan($version, '1.0.0')) { $io->writeError('<error>Drupal-project requires Composer version 1.0.0 or higher. Please update your Composer before continuing</error>.'); exit(1); } }
/** * Create the module manager * * @param ServiceLocatorInterface $serviceLocator * @return array */ public function createService(ServiceLocatorInterface $serviceLocator) { $manager = new ModuleManager(); $iniReader = new IniReader(); $connection = $serviceLocator->get('Omeka\\Connection'); // Get all modules from the filesystem. foreach (new DirectoryIterator(OMEKA_PATH . '/modules') as $dir) { // Module must be a directory if (!$dir->isDir() || $dir->isDot()) { continue; } $module = $manager->registerModule($dir->getBasename()); // Module directory must contain config/module.ini $iniFile = new SplFileInfo($dir->getPathname() . '/config/module.ini'); if (!$iniFile->isReadable() || !$iniFile->isFile()) { $module->setState(ModuleManager::STATE_INVALID_INI); continue; } $module->setIni($iniReader->fromFile($iniFile->getRealPath())); // Module INI must be valid if (!$manager->iniIsValid($module)) { $module->setState(ModuleManager::STATE_INVALID_INI); continue; } // Module directory must contain Module.php $moduleFile = new SplFileInfo($dir->getPathname() . '/Module.php'); if (!$moduleFile->isReadable() || !$moduleFile->isFile()) { $module->setState(ModuleManager::STATE_INVALID_MODULE); continue; } // Module class must extend Omeka\Module\AbstractModule require_once $moduleFile->getRealPath(); $moduleClass = $dir->getBasename() . '\\Module'; if (!class_exists($moduleClass) || !is_subclass_of($moduleClass, 'Omeka\\Module\\AbstractModule')) { $module->setState(ModuleManager::STATE_INVALID_MODULE); continue; } } // Get all modules from the database, if installed. $dbModules = []; if ($serviceLocator->get('Omeka\\Status')->isInstalled()) { $statement = $connection->prepare("SELECT * FROM module"); $statement->execute(); $dbModules = $statement->fetchAll(); } foreach ($dbModules as $moduleRow) { if (!$manager->isRegistered($moduleRow['id'])) { // Module installed but not in filesystem $module = $manager->registerModule($moduleRow['id']); $module->setDb($moduleRow); $module->setState(ModuleManager::STATE_NOT_FOUND); continue; } $module = $manager->getModule($moduleRow['id']); $module->setDb($moduleRow); if ($module->getState()) { // Module already has state. continue; } $moduleIni = $module->getIni(); if (Comparator::greaterThan($moduleIni['version'], $moduleRow['version'])) { // Module in filesystem is newer version than the installed one. $module->setState(ModuleManager::STATE_NEEDS_UPGRADE); continue; } if ($moduleRow['is_active']) { // Module valid, installed, and active $module->setState(ModuleManager::STATE_ACTIVE); } else { // Module valid, installed, and not active $module->setState(ModuleManager::STATE_NOT_ACTIVE); } } foreach ($manager->getModules() as $id => $module) { if (!$module->getState()) { // Module in filesystem but not installed $module->setState(ModuleManager::STATE_NOT_INSTALLED); } } return $manager; }
/** * Selects the upgrade functions applicable for this upgrade. * * The upgrade functions are specified by the `upgradeList` * hook. This variable is an associative array containing version numbers * as keys and an array of upgrade function names as values. This function * merges all the upgrade function names of the version between the current * installed version and the upgraded version. * * @param string $version the version of SimpleID to upgrade from, calls * {@link getVersion()} if not specified * @return array an array of strings, containing the list of upgrade functions * to call. The functions should be called in the same order as they appear * in this array * @see SimpleID\API\ModuleHooks::upgradeListHook() */ protected function getUpgradeList($version = NULL) { $mgr = ModuleManager::instance(); $upgrade_data = array(); foreach ($mgr->getModules() as $name => $module) { $data = $mgr->invoke($name, 'upgradeList'); if ($data != NULL) { $upgrade_data = array_merge_recursive($upgrade_data, $data); } } if ($version == NULL) { $version = $this->getVersion(); } $list = array(); // Sorts versions from newest to oldest $versions = array_keys($upgrade_data); $versions = Semver::rsort($versions); foreach ($versions as $upgrade_version) { if (Comparator::lessThan($version, $upgrade_version)) { $list = array_merge($list, $upgrade_data[$upgrade_version]); } } if (Comparator::lessThan($version, SIMPLEID_VERSION)) { $list[] = 'SimpleID\\Upgrade->setVersion'; } return $list; }
/** * Returns update information. */ private function get_updates($assoc_args) { $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases'; $options = array('timeout' => 30); $headers = array('Accept' => 'application/json'); $response = Utils\http_request('GET', $url, $headers, $options); if (!$response->success || 200 !== $response->status_code) { WP_CLI::error(sprintf("Failed to get latest version (HTTP code %d).", $response->status_code)); } $release_data = json_decode($response->body); $updates = array('major' => false, 'minor' => false, 'patch' => false); foreach ($release_data as $release) { // Get rid of leading "v" if there is one set. $release_version = $release->tag_name; if ('v' === substr($release_version, 0, 1)) { $release_version = ltrim($release_version, 'v'); } $update_type = Utils\get_named_sem_ver($release_version, WP_CLI_VERSION); if (!$update_type) { continue; } if (!empty($updates[$update_type]) && !Comparator::greaterThan($release_version, $updates[$update_type]['version'])) { continue; } $updates[$update_type] = array('version' => $release_version, 'update_type' => $update_type, 'package_url' => $release->assets[0]->browser_download_url); } foreach ($updates as $type => $value) { if (empty($value)) { unset($updates[$type]); } } foreach (array('major', 'minor', 'patch') as $type) { if (true === \WP_CLI\Utils\get_flag_value($assoc_args, $type)) { return !empty($updates[$type]) ? array($updates[$type]) : false; } } if (empty($updates) && preg_match('#-alpha-(.+)$#', WP_CLI_VERSION, $matches)) { $version_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/NIGHTLY_VERSION'; $response = Utils\http_request('GET', $version_url); if (!$response->success || 200 !== $response->status_code) { WP_CLI::error(sprintf("Failed to get current nightly version (HTTP code %d)", $response->status_code)); } $nightly_version = trim($response->body); if (WP_CLI_VERSION != $nightly_version) { $updates['nightly'] = array('version' => $nightly_version, 'update_type' => 'nightly', 'package_url' => 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar'); } } return array_values($updates); }
/** * Returns update information */ private function get_updates($assoc_args) { global $wp_version; $versions_path = ABSPATH . 'wp-includes/version.php'; include $versions_path; $url = 'https://api.wordpress.org/core/stable-check/1.0/'; $options = array('timeout' => 30); $headers = array('Accept' => 'application/json'); $response = Utils\http_request('GET', $url, $headers, $options); if (!$response->success || 200 !== $response->status_code) { WP_CLI::error("Failed to get latest version list."); } $release_data = json_decode($response->body); $release_versions = array_keys((array) $release_data); usort($release_versions, function ($a, $b) { return 1 === version_compare($a, $b); }); $locale = get_locale(); $compare_version = str_replace('-src', '', $GLOBALS['wp_version']); $updates = array('major' => false, 'minor' => false); foreach ($release_versions as $release_version) { $update_type = Utils\get_named_sem_ver($release_version, $compare_version); if (!$update_type) { continue; } // WordPress follow its own versioning which is roughly equivalent to semver if ('minor' === $update_type) { $update_type = 'major'; } else { if ('patch' === $update_type) { $update_type = 'minor'; } } if (!empty($updates[$update_type]) && !Comparator::greaterThan($release_version, $updates[$update_type]['version'])) { continue; } $updates[$update_type] = array('version' => $release_version, 'update_type' => $update_type, 'package_url' => $this->get_download_url($release_version, $locale)); } foreach ($updates as $type => $value) { if (empty($value)) { unset($updates[$type]); } } foreach (array('major', 'minor') as $type) { if (true === \WP_CLI\Utils\get_flag_value($assoc_args, $type)) { return !empty($updates[$type]) ? array($updates[$type]) : false; } } return array_values($updates); }
/** * {@inheritdoc} */ public function deploy($version, $stage) { $successfulDeploy = true; $hosts = $this->configuration->getHostsByStage($stage); foreach ($hosts as $host) { $exception = null; $deployEventName = AccompliEvents::DEPLOY_RELEASE; $deployCompleteEventName = AccompliEvents::DEPLOY_RELEASE_COMPLETE; $deployFailedEventName = AccompliEvents::DEPLOY_RELEASE_FAILED; $title = new Title($this->logger->getOutput(), sprintf('Deploying release "%s" to "%s":', $version, $host->getHostname())); $title->render(); try { $this->eventDispatcher->dispatch(AccompliEvents::CREATE_CONNECTION, new HostEvent($host)); $workspaceEvent = new WorkspaceEvent($host); $this->eventDispatcher->dispatch(AccompliEvents::GET_WORKSPACE, $workspaceEvent); $workspace = $workspaceEvent->getWorkspace(); if ($workspace instanceof Workspace) { $prepareDeployReleaseEvent = new PrepareDeployReleaseEvent($workspace, $version); $this->eventDispatcher->dispatch(AccompliEvents::PREPARE_DEPLOY_RELEASE, $prepareDeployReleaseEvent); $release = $prepareDeployReleaseEvent->getRelease(); if ($release instanceof Release) { $currentRelease = $prepareDeployReleaseEvent->getCurrentRelease(); if ($currentRelease instanceof Release && Comparator::lessThan($release->getVersion(), $currentRelease->getVersion())) { $deployEventName = AccompliEvents::ROLLBACK_RELEASE; $deployCompleteEventName = AccompliEvents::ROLLBACK_RELEASE_COMPLETE; $deployFailedEventName = AccompliEvents::ROLLBACK_RELEASE_FAILED; } $deployReleaseEvent = new DeployReleaseEvent($release, $currentRelease); $this->eventDispatcher->dispatch($deployEventName, $deployReleaseEvent); $this->eventDispatcher->dispatch($deployCompleteEventName, $deployReleaseEvent); continue; } throw new RuntimeException(sprintf('No task configured to initialize release version "%s" for deployment.', $version)); } throw new RuntimeException('No task configured to initialize the workspace.'); } catch (Exception $exception) { } $successfulDeploy = false; $failedEvent = new FailedEvent($this->eventDispatcher->getLastDispatchedEventName(), $this->eventDispatcher->getLastDispatchedEvent(), $exception); $this->eventDispatcher->dispatch($deployFailedEventName, $failedEvent); } return $successfulDeploy; }
/** * Get outdated packages with their current and latest version. * * @throws \Vinkla\Climb\ClimbException * * @return array */ public function getOutdatedPackages() { // Get all installed and required packages. $installed = $this->getInstalledPackages(); $required = $this->getRequiredPackages(); // Get the installed version number of the required packages. $packages = array_intersect_key($installed, $required); $outdated = []; foreach ($packages as $package => $version) { if (!($latest = $this->getLatestVersion($package))) { continue; } if (Comparator::lessThan($version, $latest)) { $constraint = $required[$package]; $outdated[$package] = [$constraint, $version, $latest]; } } return $outdated; }
/** * Check whether Omeka needs a version update. * * An update is needed when the code version is more recent than the * installed version. * * @return bool */ public function needsVersionUpdate() { return Comparator::greaterThan($this->getVersion(), $this->getInstalledVersion()); }
/** * @return bool */ public static function isWhitelistSupported() { return Comparator::greaterThanOrEqualTo(\PHPUnit_Runner_Version::id(), '5.0.0'); }
/** * Get sql file list ordered by floats * @param string $module * @param string $action * @param float specific version * @param float current version * @return array array sorted according to version */ public function getSqlFileListOrdered($module, $action, $specific = null, $current = null) { $ary = $this->getSqlFileList($module, $action); asort($ary); $sem = new Comparator(); if (strpos($current, 'v') === 0) { $current = substr($current, 1); } if (isset($specific)) { $ary = array_reverse($ary); if ($specific == 1) { foreach ($ary as $key => $val) { $val = substr($val, 0, -4); if (strpos($val, 'v') === 0) { $val = substr($val, 1); } if ($sem->greaterThan($val, $current)) { unset($ary[$key]); } } } else { foreach ($ary as $key => $val) { $val = substr($val, 0, -4); if (strpos($val, 'v') === 0) { $val = substr($val, 1); } if ($sem->lessThan($val, $specific)) { unset($ary[$key]); } if ($sem->greaterThan($val, $current)) { unset($ary[$key]); } } } } return $ary; }
/** * Returns update information */ private function get_updates($assoc_args) { wp_version_check(); $from_api = get_site_transient('update_core'); if (!$from_api) { return array(); } $compare_version = str_replace('-src', '', $GLOBALS['wp_version']); $updates = array('major' => false, 'minor' => false); foreach ($from_api->updates as $offer) { $update_type = Utils\get_named_sem_ver($offer->version, $compare_version); if (!$update_type) { continue; } // WordPress follow its own versioning which is roughly equivalent to semver if ('minor' === $update_type) { $update_type = 'major'; } else { if ('patch' === $update_type) { $update_type = 'minor'; } } if (!empty($updates[$update_type]) && !Comparator::greaterThan($offer->version, $updates[$update_type]['version'])) { continue; } $updates[$update_type] = array('version' => $offer->version, 'update_type' => $update_type, 'package_url' => !empty($offer->packages->partial) ? $offer->packages->partial : $offer->packages->full); } foreach ($updates as $type => $value) { if (empty($value)) { unset($updates[$type]); } } foreach (array('major', 'minor') as $type) { if (true === \WP_CLI\Utils\get_flag_value($assoc_args, $type)) { return !empty($updates[$type]) ? array($updates[$type]) : false; } } return array_values($updates); }
/** * @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; }
/** * @param string $latestVersion * @return bool */ protected function isLatestVersion($latestVersion) { return Comparator::greaterThanOrEqualTo(Core\Application\BootstrapInterface::VERSION, $latestVersion); }
/** * Check if the package is outdated. * * @return bool */ public function isOutdated() { return Comparator::lessThan($this->version, $this->getLatestVersion()); }
/** * Compare two version strings to get the named semantic version. * * @access public * * @param string $new_version * @param string $original_version * @return string $name 'major', 'minor', 'patch' */ function get_named_sem_ver($new_version, $original_version) { if (!Comparator::greaterThan($new_version, $original_version)) { return ''; } $parts = explode('-', $original_version); list($major, $minor, $patch) = explode('.', $parts[0]); if (Semver::satisfies($new_version, "{$major}.{$minor}.x")) { return 'patch'; } else { if (Semver::satisfies($new_version, "{$major}.x.x")) { return 'minor'; } else { return 'major'; } } }
/** * Compare two version strings to get the named semantic version. * * @access public * * @param string $new_version * @param string $original_version * @return string $name 'major', 'minor', 'patch' */ function get_named_sem_ver($new_version, $original_version) { if (!Comparator::greaterThan($new_version, $original_version)) { return ''; } $parts = explode('-', $original_version); $bits = explode('.', $parts[0]); $major = $bits[0]; if (isset($bits[1])) { $minor = $bits[1]; } if (isset($bits[2])) { $patch = $bits[2]; } if (!is_null($minor) && Semver::satisfies($new_version, "{$major}.{$minor}.x")) { return 'patch'; } else { if (Semver::satisfies($new_version, "{$major}.x.x")) { return 'minor'; } else { return 'major'; } } }