110 lines
2.8 KiB
PHP
110 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Pest\Plugin;
|
|
|
|
use JsonException;
|
|
use Pest\Support\Container;
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
final class Loader
|
|
{
|
|
/**
|
|
* Determines if the plugin cache file was loaded.
|
|
*
|
|
* @var bool
|
|
*/
|
|
private static $loaded = false;
|
|
|
|
/**
|
|
* Holds the list of cached plugin instances.
|
|
*
|
|
* @var array<int, object>
|
|
*/
|
|
private static $instances = [];
|
|
|
|
/**
|
|
* returns an array of pest plugins to execute.
|
|
*
|
|
* @param string $interface the interface for the hook to execute
|
|
* @return array<int, object> list of plugins
|
|
*/
|
|
public static function getPlugins(string $interface): array
|
|
{
|
|
return array_values(
|
|
array_filter(
|
|
self::getPluginInstances(),
|
|
function ($plugin) use ($interface): bool {
|
|
return $plugin instanceof $interface;
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
public static function reset(): void
|
|
{
|
|
self::$loaded = false;
|
|
self::$instances = [];
|
|
}
|
|
|
|
/**
|
|
* returns the list of plugins instances.
|
|
*
|
|
* @return array<int, object>
|
|
*/
|
|
private static function getPluginInstances(): array
|
|
{
|
|
if (! self::$loaded) {
|
|
$cachedPlugins = sprintf(
|
|
'%s/../pest-plugins.json',
|
|
$GLOBALS['_composer_bin_dir'] ?? getcwd().'/vendor/bin',
|
|
);
|
|
$container = Container::getInstance();
|
|
|
|
if (! file_exists($cachedPlugins)) {
|
|
return [];
|
|
}
|
|
|
|
$content = file_get_contents($cachedPlugins);
|
|
if ($content === false) {
|
|
return [];
|
|
}
|
|
|
|
try {
|
|
/** @var array<int, class-string> $pluginClasses */
|
|
$pluginClasses = json_decode($content, false, 512, JSON_THROW_ON_ERROR);
|
|
} catch (JsonException $ex) {
|
|
$pluginClasses = [];
|
|
}
|
|
|
|
usort($pluginClasses, function (string $pluginA, string $pluginB) {
|
|
$isOfficialPlugin = fn (string $plugin) => str_starts_with($plugin, 'Pest\\Plugins\\');
|
|
|
|
return match (true) {
|
|
$isOfficialPlugin($pluginA) && $isOfficialPlugin($pluginB),
|
|
! $isOfficialPlugin($pluginA) && ! $isOfficialPlugin($pluginB) => 0,
|
|
$isOfficialPlugin($pluginA) => 1,
|
|
default => -1,
|
|
};
|
|
});
|
|
|
|
self::$instances = array_map(
|
|
function ($class) use ($container) {
|
|
/** @var object $object */
|
|
$object = $container->get($class);
|
|
|
|
return $object;
|
|
},
|
|
$pluginClasses,
|
|
);
|
|
|
|
self::$loaded = true;
|
|
}
|
|
|
|
return self::$instances;
|
|
}
|
|
}
|