clean install

This commit is contained in:
2024-12-10 15:08:16 +01:00
commit e14eb2d8fd
31193 changed files with 3555714 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Ondřej Mirtes
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.

View File

@@ -0,0 +1,93 @@
# PHPStan Extension Installer
[![Build](https://github.com/phpstan/extension-installer/workflows/Build/badge.svg)](https://github.com/phpstan/extension-installer/actions)
[![Latest Stable Version](https://poser.pugx.org/phpstan/extension-installer/v/stable)](https://packagist.org/packages/phpstan/extension-installer)
[![License](https://poser.pugx.org/phpstan/extension-installer/license)](https://packagist.org/packages/phpstan/extension-installer)
Composer plugin for automatic installation of [PHPStan](https://phpstan.org/) extensions.
# Motivation
```diff
diff --git a/phpstan.neon b/phpstan.neon
index db4e3df32e..2ca30fa20a 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -1,12 +1,3 @@
-includes:
- - vendor/phpstan/phpstan-doctrine/extension.neon
- - vendor/phpstan/phpstan-doctrine/rules.neon
- - vendor/phpstan/phpstan-nette/extension.neon
- - vendor/phpstan/phpstan-nette/rules.neon
- - vendor/phpstan/phpstan-phpunit/extension.neon
- - vendor/phpstan/phpstan-phpunit/rules.neon
- - vendor/phpstan/phpstan-strict-rules/rules.neon
-
parameters:
autoload_directories:
- %rootDir%/../../../build/SlevomatSniffs
diff --git a/composer.json b/composer.json
index 1b578dd624..f6ebf6e477 100644
--- a/composer.json
+++ b/composer.json
@@ -142,6 +142,7 @@
"jakub-onderka/php-parallel-lint": "1.0.0",
"justinrainbow/json-schema": "5.2.8",
"ondrejmirtes/mocktainer": "0.8",
+ "phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.11.7",
"phpstan/phpstan-doctrine": "^0.11.3",
"phpstan/phpstan-nette": "^0.11.1",
```
## Usage
```bash
composer require --dev phpstan/extension-installer
```
Starting from Composer 2.2.0 you'll get the following question:
```
phpstan/extension-installer contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins
Do you trust "phpstan/extension-installer" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?]
```
Answer with `y` to allow the plugin.
## Instructions for extension developers
It's best (but optional) to set the extension's composer package [type](https://getcomposer.org/doc/04-schema.md#type) to `phpstan-extension` for this plugin to be able to recognize it and to be [discoverable on Packagist](https://packagist.org/explore/?type=phpstan-extension).
Add `phpstan` key in the extension `composer.json`'s `extra` section:
```json
{
"extra": {
"phpstan": {
"includes": [
"extension.neon"
]
}
}
}
```
## Ignoring a particular extension
You may want to disable auto-installation of a particular extension to handle installation manually. Ignore an extension by adding an `extra.phpstan/extension-installer.ignore` array in `composer.json` that specifies a list of packages to ignore:
```json
{
"extra": {
"phpstan/extension-installer": {
"ignore": [
"phpstan/phpstan-phpunit"
]
}
}
}
```
## Limitations
The extension installer depends on Composer script events, therefore you cannot use `--no-scripts` flag.

View File

@@ -0,0 +1,33 @@
{
"name": "phpstan/extension-installer",
"type": "composer-plugin",
"description": "Composer plugin for automatic installation of PHPStan extensions",
"license": [
"MIT"
],
"keywords": ["dev", "static analysis"],
"require": {
"php": "^7.2 || ^8.0",
"composer-plugin-api": "^2.0",
"phpstan/phpstan": "^1.9.0 || ^2.0"
},
"require-dev": {
"composer/composer": "^2.0",
"php-parallel-lint/php-parallel-lint": "^1.2.0",
"phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"ocramius/package-versions": true
}
},
"extra": {
"class": "PHPStan\\ExtensionInstaller\\Plugin"
},
"autoload": {
"psr-4": {
"PHPStan\\ExtensionInstaller\\": "src/"
}
}
}

View File

@@ -0,0 +1,54 @@
<?php declare(strict_types = 1);
namespace PHPStan\ExtensionInstaller;
/**
* This class is generated by phpstan/extension-installer.
* @internal
*/
final class GeneratedConfig
{
public const EXTENSIONS = array (
'mglaman/phpstan-drupal' =>
array (
'install_path' => '/home/spider_pig/src/php/farmOS-dev/vendor/mglaman/phpstan-drupal',
'relative_install_path' => '../../../mglaman/phpstan-drupal',
'extra' =>
array (
'includes' =>
array (
0 => 'extension.neon',
1 => 'rules.neon',
),
),
'version' => '1.3.1',
'phpstanVersionConstraint' => '>=1.10.56.0-dev, <2.0.0.0-dev',
),
'phpstan/phpstan-deprecation-rules' =>
array (
'install_path' => '/home/spider_pig/src/php/farmOS-dev/vendor/phpstan/phpstan-deprecation-rules',
'relative_install_path' => '../../phpstan-deprecation-rules',
'extra' =>
array (
'includes' =>
array (
0 => 'rules.neon',
),
),
'version' => '1.2.1',
'phpstanVersionConstraint' => '>=1.12.0.0-dev, <2.0.0.0-dev',
),
);
public const NOT_INSTALLED = array (
);
/** @var string|null */
public const PHPSTAN_VERSION_CONSTRAINT = '>=1.12.0.0-dev, <2.0.0.0-dev';
private function __construct()
{
}
}

View File

@@ -0,0 +1,228 @@
<?php declare(strict_types = 1);
namespace PHPStan\ExtensionInstaller;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\Intervals;
use Composer\Util\Filesystem;
use function array_key_exists;
use function array_keys;
use function class_exists;
use function count;
use function dirname;
use function file_exists;
use function file_put_contents;
use function getcwd;
use function in_array;
use function is_file;
use function ksort;
use function md5;
use function md5_file;
use function sort;
use function sprintf;
use function strpos;
use function var_export;
use const DIRECTORY_SEPARATOR;
final class Plugin implements PluginInterface, EventSubscriberInterface
{
/** @var string */
private static $generatedFileTemplate = <<<'PHP'
<?php declare(strict_types = 1);
namespace PHPStan\ExtensionInstaller;
/**
* This class is generated by phpstan/extension-installer.
* @internal
*/
final class GeneratedConfig
{
public const EXTENSIONS = %s;
public const NOT_INSTALLED = %s;
/** @var string|null */
public const PHPSTAN_VERSION_CONSTRAINT = %s;
private function __construct()
{
}
}
PHP;
public function activate(Composer $composer, IOInterface $io): void
{
// noop
}
public function deactivate(Composer $composer, IOInterface $io): void
{
// noop
}
public function uninstall(Composer $composer, IOInterface $io): void
{
// noop
}
/**
* @return array<string, string>
*/
public static function getSubscribedEvents(): array
{
return [
ScriptEvents::POST_INSTALL_CMD => 'process',
ScriptEvents::POST_UPDATE_CMD => 'process',
];
}
public function process(Event $event): void
{
$io = $event->getIO();
if (!file_exists(__DIR__)) {
$io->write('<info>phpstan/extension-installer:</info> Package not found (probably scheduled for removal); extensions installation skipped.');
return;
}
$composer = $event->getComposer();
$installationManager = $composer->getInstallationManager();
$generatedConfigFilePath = __DIR__ . '/GeneratedConfig.php';
$oldGeneratedConfigFileHash = null;
if (is_file($generatedConfigFilePath)) {
$oldGeneratedConfigFileHash = md5_file($generatedConfigFilePath);
}
$notInstalledPackages = [];
$installedPackages = [];
$ignoredPackages = [];
$data = [];
$fs = new Filesystem();
$ignore = [];
$packageExtra = $composer->getPackage()->getExtra();
if (isset($packageExtra['phpstan/extension-installer']['ignore'])) {
$ignore = $packageExtra['phpstan/extension-installer']['ignore'];
}
$phpstanVersionConstraints = [];
foreach ($composer->getRepositoryManager()->getLocalRepository()->getPackages() as $package) {
if (
$package->getType() !== 'phpstan-extension'
&& !isset($package->getExtra()['phpstan'])
) {
if (
strpos($package->getName(), 'phpstan') !== false
&& !in_array($package->getName(), [
'phpstan/phpstan',
'phpstan/phpstan-shim',
'phpstan/phpdoc-parser',
'phpstan/extension-installer',
], true)
) {
$notInstalledPackages[$package->getName()] = $package->getFullPrettyVersion();
}
continue;
}
if (in_array($package->getName(), $ignore, true)) {
$ignoredPackages[] = $package->getName();
continue;
}
$installPath = $installationManager->getInstallPath($package);
if ($installPath === null) {
continue;
}
$absoluteInstallPath = $fs->isAbsolutePath($installPath)
? $installPath
: getcwd() . DIRECTORY_SEPARATOR . $installPath;
$packageRequires = $package->getRequires();
$phpstanConstraint = null;
if (array_key_exists('phpstan/phpstan', $packageRequires)) {
$phpstanConstraint = $packageRequires['phpstan/phpstan']->getConstraint();
if ($phpstanConstraint->getLowerBound()->isZero()) {
continue;
}
if ($phpstanConstraint->getUpperBound()->isPositiveInfinity()) {
continue;
}
$phpstanVersionConstraints[] = $phpstanConstraint;
}
$data[$package->getName()] = [
'install_path' => $absoluteInstallPath,
'relative_install_path' => $fs->findShortestPath(dirname($generatedConfigFilePath), $absoluteInstallPath, true),
'extra' => $package->getExtra()['phpstan'] ?? null,
'version' => $package->getFullPrettyVersion(),
'phpstanVersionConstraint' => $phpstanConstraint !== null ? $this->constraintIntoString($phpstanConstraint) : null,
];
$installedPackages[$package->getName()] = true;
}
$phpstanVersionConstraint = null;
if (count($phpstanVersionConstraints) > 0 && class_exists(Intervals::class)) {
if (count($phpstanVersionConstraints) === 1) {
$multiConstraint = $phpstanVersionConstraints[0];
} else {
$multiConstraint = new MultiConstraint($phpstanVersionConstraints);
}
$phpstanVersionConstraint = $this->constraintIntoString(Intervals::compactConstraint($multiConstraint));
}
ksort($data);
ksort($installedPackages);
ksort($notInstalledPackages);
sort($ignoredPackages);
$generatedConfigFileContents = sprintf(self::$generatedFileTemplate, var_export($data, true), var_export($notInstalledPackages, true), var_export($phpstanVersionConstraint, true));
file_put_contents($generatedConfigFilePath, $generatedConfigFileContents);
$io->write('<info>phpstan/extension-installer:</info> Extensions installed');
if ($oldGeneratedConfigFileHash === md5($generatedConfigFileContents)) {
return;
}
foreach (array_keys($installedPackages) as $name) {
$io->write(sprintf('> <info>%s:</info> installed', $name));
}
foreach (array_keys($notInstalledPackages) as $name) {
$io->write(sprintf('> <comment>%s:</comment> not supported', $name));
}
foreach ($ignoredPackages as $name) {
$io->write(sprintf('> <comment>%s:</comment> ignored', $name));
}
}
private function constraintIntoString(ConstraintInterface $constraint): string
{
return sprintf(
'%s%s, %s%s',
$constraint->getLowerBound()->isInclusive() ? '>=' : '>',
$constraint->getLowerBound()->getVersion(),
$constraint->getUpperBound()->isInclusive() ? '<=' : '<',
$constraint->getUpperBound()->getVersion()
);
}
}