ajustement alignement toggle-mode ordi fix #42

This commit is contained in:
antonin gallon 2025-11-28 18:25:43 +01:00
parent 8e9464f248
commit 20e305744f
22 changed files with 3354 additions and 4 deletions

View file

@ -0,0 +1,30 @@
{
"name": "getkirby/composer-installer",
"description": "Kirby's custom Composer installer for the Kirby CMS and for Kirby plugins",
"type": "composer-plugin",
"license": "MIT",
"homepage": "https://getkirby.com",
"require": {
"composer-plugin-api": "^1.0 || ^2.0"
},
"require-dev": {
"composer/composer": "^1.8 || ^2.0"
},
"autoload": {
"psr-4": {
"Kirby\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Kirby\\": "tests/"
}
},
"scripts": {
"fix": "php-cs-fixer fix --config .php_cs",
"test": "--stderr --coverage-html=tests/coverage"
},
"extra": {
"class": "Kirby\\ComposerInstaller\\Plugin"
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,104 @@
# Kirby Composer Installer
[![CI Status](https://flat.badgen.net/github/checks/getkirby/composer-installer/master)](https://github.com/getkirby/composer-installer/actions?query=workflow%3ACI)
[![Coverage Status](https://flat.badgen.net/coveralls/c/github/getkirby/composer-installer)](https://coveralls.io/github/getkirby/composer-installer)
This is Kirby's custom [Composer installer](https://getcomposer.org/doc/articles/custom-installers.md) for the Kirby CMS.
It is responsible for automatically choosing the correct installation paths if you install the CMS via Composer.
It can also be used to automatically install Kirby plugins to the `site/plugins` directory.
## Installing the CMS
### Default configuration
If you `require` the `getkirby/cms` package in your own `composer.json`, there is nothing else you need to do:
```js
{
"require": {
"getkirby/cms": "^3.0"
}
}
```
Kirby's Composer installer (this repo) will run automatically and will install the CMS to the `kirby` directory.
### Custom installation path
You might want to use a different installation path. The path can be configured like this in your `composer.json`:
```js
{
"require": {
"getkirby/cms": "^3.0"
},
"extra": {
"kirby-cms-path": "kirby" // change this to your custom path
}
}
```
### Disable the installer for the CMS
If you prefer to have the CMS installed to the `vendor` directory, you can disable the custom path entirely:
```js
{
"require": {
"getkirby/cms": "^3.0"
},
"extra": {
"kirby-cms-path": false
}
}
```
Please note that you will need to modify your site's `index.php` to load the `vendor/autoload.php` file instead of Kirby's `bootstrap.php`.
## Installing plugins
### Support in published plugins
Plugins need to require this installer as a Composer dependency to make use of the automatic installation to the `site/plugins` directory.
You can find out more about this in our [plugin documentation](https://getkirby.com/docs/guide/plugins/plugin-setup-basic).
### Usage for plugin users
As a user of Kirby plugins that support this installer, you only need to `require` the plugins in your site's `composer.json`:
```js
{
"require": {
"getkirby/cms": "^3.0",
"superwoman/superplugin": "^1.0"
}
}
```
The installer (this repo) will run automatically, as the plugin dev added it to the plugin's `composer.json`.
### Custom installation path
If your `site/plugins` directory is at a custom path, you can configure the installation path like this in your `composer.json`:
```js
{
"require": {
"getkirby/cms": "^3.0",
"superwoman/superplugin": "^1.0"
},
"extra": {
"kirby-plugin-path": "site/plugins" // change this to your custom path
}
}
```
## License
<http://www.opensource.org/licenses/mit-license.php>
## Author
Lukas Bestle <https://getkirby.com>

View file

@ -0,0 +1,64 @@
<?php
namespace Kirby\ComposerInstaller;
use Composer\Config;
use Composer\Package\PackageInterface;
use InvalidArgumentException;
/**
* @package Kirby Composer Installer
* @author Lukas Bestle <lukas@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier GmbH
* @license https://opensource.org/licenses/MIT
*/
class CmsInstaller extends Installer
{
/**
* Decides if the installer supports the given type
*
* @param string $packageType
* @return bool
*/
public function supports($packageType): bool
{
return $packageType === 'kirby-cms';
}
/**
* Returns the installation path of a package
*
* @param \Composer\Package\PackageInterface $package
* @return string
*/
public function getInstallPath(PackageInterface $package): string
{
// get the extra configuration of the top-level package
if ($rootPackage = $this->composer->getPackage()) {
$extra = $rootPackage->getExtra();
} else {
$extra = [];
}
// use path from configuration, otherwise fall back to default
if (isset($extra['kirby-cms-path']) === true) {
$path = $extra['kirby-cms-path'];
} else {
$path = 'kirby';
}
// if explicitly set to something invalid (e.g. `false`), install to vendor dir
if (is_string($path) !== true) {
return parent::getInstallPath($package);
}
// don't allow unsafe directories
$vendorDir = $this->composer->getConfig()->get('vendor-dir', Config::RELATIVE_PATHS) ?? 'vendor';
if ($path === $vendorDir || $path === '.') {
throw new InvalidArgumentException('The path ' . $path . ' is an unsafe installation directory for ' . $package->getPrettyName() . '.');
}
return $path;
}
}

View file

@ -0,0 +1,105 @@
<?php
namespace Kirby\ComposerInstaller;
use Composer\Installer\LibraryInstaller;
use Composer\Package\PackageInterface;
use Composer\Repository\InstalledRepositoryInterface;
use React\Promise\PromiseInterface;
use RuntimeException;
/**
* @package Kirby Composer Installer
* @author Lukas Bestle <lukas@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier GmbH
* @license https://opensource.org/licenses/MIT
*/
class Installer extends LibraryInstaller
{
/**
* Decides if the installer supports the given type
*
* @param string $packageType
* @return bool
*/
public function supports($packageType): bool
{
throw new RuntimeException('This method needs to be overridden.'); // @codeCoverageIgnore
}
/**
* Installs a specific package
*
* @param \Composer\Repository\InstalledRepositoryInterface $repo Repository in which to check
* @param \Composer\Package\PackageInterface $package Package instance to install
* @return \React\Promise\PromiseInterface|null
*/
public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
{
// first install the package normally...
$promise = parent::install($repo, $package);
// ...then run custom code
$postInstall = function () use ($package): void {
$this->postInstall($package);
};
// Composer 2 in async mode
if ($promise instanceof PromiseInterface) {
return $promise->then($postInstall);
}
// Composer 1 or Composer 2 without async
$postInstall();
}
/**
* Updates a specific package
*
* @param \Composer\Repository\InstalledRepositoryInterface $repo Repository in which to check
* @param \Composer\Package\PackageInterface $initial Already installed package version
* @param \Composer\Package\PackageInterface $target Updated version
* @return \React\Promise\PromiseInterface|null
*
* @throws \InvalidArgumentException if $initial package is not installed
*/
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
{
// first update the package normally...
$promise = parent::update($repo, $initial, $target);
// ...then run custom code
$postInstall = function () use ($target): void {
$this->postInstall($target);
};
// Composer 2 in async mode
if ($promise instanceof PromiseInterface) {
return $promise->then($postInstall);
}
// Composer 1 or Composer 2 without async
$postInstall();
}
/**
* Custom handler that will be called after each package
* installation or update
*
* @param \Composer\Package\PackageInterface $package
* @return void
*/
protected function postInstall(PackageInterface $package)
{
// remove the package's `vendor` directory to avoid duplicated autoloader and vendor code
$packageVendorDir = $this->getInstallPath($package) . '/vendor';
if (is_dir($packageVendorDir) === true) {
$success = $this->filesystem->removeDirectory($packageVendorDir);
if ($success !== true) {
throw new RuntimeException('Could not completely delete ' . $packageVendorDir . ', aborting.'); // @codeCoverageIgnore
}
}
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace Kirby\ComposerInstaller;
use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
/**
* @package Kirby Composer Installer
* @author Lukas Bestle <lukas@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier GmbH
* @license https://opensource.org/licenses/MIT
*/
class Plugin implements PluginInterface
{
/**
* Apply plugin modifications to Composer
*
* @param \Composer\Composer $composer
* @param \Composer\IO\IOInterface $io
* @return void
*/
public function activate(Composer $composer, IOInterface $io): void
{
$installationManager = $composer->getInstallationManager();
$installationManager->addInstaller(new CmsInstaller($io, $composer));
$installationManager->addInstaller(new PluginInstaller($io, $composer));
}
/**
* Remove any hooks from Composer
*
* @codeCoverageIgnore
*
* @param \Composer\Composer $composer
* @param \Composer\IO\IOInterface $io
* @return void
*/
public function deactivate(Composer $composer, IOInterface $io): void
{
// nothing to do
}
/**
* Prepare the plugin to be uninstalled
*
* @codeCoverageIgnore
*
* @param Composer $composer
* @param IOInterface $io
* @return void
*/
public function uninstall(Composer $composer, IOInterface $io): void
{
// nothing to do
}
}

View file

@ -0,0 +1,112 @@
<?php
namespace Kirby\ComposerInstaller;
use Composer\Package\PackageInterface;
use InvalidArgumentException;
/**
* @package Kirby Composer Installer
* @author Lukas Bestle <lukas@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier GmbH
* @license https://opensource.org/licenses/MIT
*/
class PluginInstaller extends Installer
{
/**
* Decides if the installer supports the given type
*
* @param string $packageType
* @return bool
*/
public function supports($packageType): bool
{
return $packageType === 'kirby-plugin';
}
/**
* Returns the installation path of a package
*
* @param \Composer\Package\PackageInterface $package
* @return string path
*/
public function getInstallPath(PackageInterface $package): string
{
// place into `vendor` directory as usual if Pluginkit is not supported
if ($this->supportsPluginkit($package) !== true) {
return parent::getInstallPath($package);
}
// get the extra configuration of the top-level package
if ($rootPackage = $this->composer->getPackage()) {
$extra = $rootPackage->getExtra();
} else {
$extra = [];
}
// use base path from configuration, otherwise fall back to default
$basePath = $extra['kirby-plugin-path'] ?? 'site/plugins';
if (is_string($basePath) !== true) {
throw new InvalidArgumentException('Invalid "kirby-plugin-path" option');
}
// determine the plugin name from its package name;
// can be overridden in the plugin's `composer.json`
$prettyName = $package->getPrettyName();
$pluginExtra = $package->getExtra();
if (empty($pluginExtra['installer-name']) === false) {
$name = $pluginExtra['installer-name'];
if (is_string($name) !== true) {
throw new InvalidArgumentException('Invalid "installer-name" option in plugin ' . $prettyName);
}
} elseif (strpos($prettyName, '/') !== false) {
// use name after the slash
$name = explode('/', $prettyName)[1];
} else {
$name = $prettyName;
}
// build destination path from base path and plugin name
return $basePath . '/' . $name;
}
/**
* Custom handler that will be called after each package
* installation or update
*
* @param \Composer\Package\PackageInterface $package
* @return void
*/
protected function postInstall(PackageInterface $package): void
{
// only continue if Pluginkit is supported
if ($this->supportsPluginkit($package) !== true) {
return;
}
parent::postInstall($package);
}
/**
* Checks if the package has explicitly required this installer;
* otherwise (if the Pluginkit is not yet supported by the plugin)
* the installer will fall back to the behavior of the LibraryInstaller
*
* @param \Composer\Package\PackageInterface $package
* @return bool
*/
protected function supportsPluginkit(PackageInterface $package): bool
{
foreach ($package->getRequires() as $link) {
if ($link->getTarget() === 'getkirby/composer-installer') {
return true;
}
}
// no required package is the installer
return false;
}
}