Files
php-flasher/src/Laravel/Command/InstallCommand.php
T
Younes ENNAJI d7234c64a2 Simplify verbose PHPDoc class descriptions across 76 files
Remove descriptive class/interface-level documentation that duplicates
what the class/interface names already convey, while keeping all
type annotations (@param, @return, @var, @throws, @phpstan-, @mixin,
@template, @internal).

Files modified:
- Symfony integration (18 files): Attribute, Translation, Template,
  Component, Storage, Support, Http, Profiler, Command, Twig,
  EventListener, FlasherSymfonyBundle
- Laravel integration (13 files): ServiceProvider, Storage, Middleware,
  Http, Facade, Template, Translation, Command, Component, EventListener
- Prime/EventDispatcher (17 files): Events and EventListeners
- Prime/Storage (11 files): Filter/Criteria and Bag interfaces
- Prime/Stamp (4 files): Interface and stamp classes
- Prime/Factory (5 files): Factory interfaces and implementations
- Prime/Notification (2 files): Envelope and Notification
- Prime/Support/Traits (1 file): ForwardsCalls
2026-01-16 01:46:44 +01:00

179 lines
7.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Flasher\Laravel\Command;
use Flasher\Laravel\Support\PluginServiceProvider;
use Flasher\Prime\Asset\AssetManagerInterface;
use Flasher\Prime\Plugin\PluginInterface;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\App;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Finder\Finder;
final class InstallCommand extends Command
{
/**
* Command description.
*
* @var string
*/
protected $description = 'Installs all <fg=blue;options=bold>PHPFlasher</> resources to the <comment>public</comment> and <comment>config</comment> directories.';
public function __construct(private readonly AssetManagerInterface $assetManager)
{
parent::__construct();
}
protected function configure(): void
{
$this
->setName('flasher:install')
->setDescription('Installs all <fg=blue;options=bold>PHPFlasher</> resources to the <comment>public</comment> and <comment>config</comment> directories.')
->setHelp('The command copies <fg=blue;options=bold>PHPFlasher</> assets to <comment>public/vendor/flasher/</comment> directory and config files to the <comment>config/</comment> directory without overwriting any existing config files.')
->addOption('config', 'c', InputOption::VALUE_NONE, 'Publish all config files to the <comment>config/packages/</comment> directory.')
->addOption('symlink', 's', InputOption::VALUE_NONE, 'Symlink <fg=blue;options=bold>PHPFlasher</> assets instead of copying them.');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('');
$output->writeln('<fg=blue;options=bold>
██████╗ ██╗ ██╗██████╗ ███████╗██╗ █████╗ ███████╗██╗ ██╗███████╗██████╗
██╔══██╗██║ ██║██╔══██╗██╔════╝██║ ██╔══██╗██╔════╝██║ ██║██╔════╝██╔══██╗
██████╔╝███████║██████╔╝█████╗ ██║ ███████║███████╗███████║█████╗ ██████╔╝
██╔═══╝ ██╔══██║██╔═══╝ ██╔══╝ ██║ ██╔══██║╚════██║██╔══██║██╔══╝ ██╔══██╗
██║ ██║ ██║██║ ██║ ███████╗██║ ██║███████║██║ ██║███████╗██║ ██║
╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
</>');
$output->writeln('');
$output->writeln('');
$output->writeln('<bg=blue;options=bold> INFO </> Copying <fg=blue;options=bold>PHPFlasher</> resources...');
$output->writeln('');
$useSymlinks = (bool) $input->getOption('symlink');
if ($useSymlinks) {
$output->writeln('<info>Using symlinks to publish assets.</info>');
} else {
$output->writeln('<info>Copying assets to the public directory.</info>');
}
$publishConfig = (bool) $input->getOption('config');
if ($publishConfig) {
$output->writeln('<info>Publishing configuration files.</info>');
}
$publicDir = App::publicPath('/vendor/flasher/');
$filesystem = new Filesystem();
$filesystem->deleteDirectory($publicDir);
$filesystem->makeDirectory($publicDir, recursive: true);
$files = [];
$exitCode = self::SUCCESS;
foreach (array_keys(App::getLoadedProviders()) as $provider) {
if (!is_a($provider, PluginServiceProvider::class, true)) {
continue;
}
/** @var PluginServiceProvider $provider */
$provider = App::getProvider($provider);
$plugin = $provider->createPlugin();
$configFile = $provider->getConfigurationFile();
try {
$files[] = $this->publishAssets($plugin, $publicDir, $useSymlinks);
if ($publishConfig) {
$this->publishConfig($plugin, $configFile);
}
$status = \sprintf('<fg=green;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */);
$output->writeln(\sprintf(' %s <fg=blue;options=bold>%s</>', $status, $plugin->getAlias()));
} catch (\Exception $e) {
$exitCode = self::FAILURE;
$status = \sprintf('<fg=red;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */);
$output->writeln(\sprintf(' %s <fg=blue;options=bold>%s</> <error>%s</error>', $status, $plugin->getAlias(), $e->getMessage()));
}
}
$output->writeln('');
if (self::SUCCESS === $exitCode) {
$message = '<fg=blue;options=bold>PHPFlasher</> resources have been successfully installed.';
if ($publishConfig) {
$message .= ' Configuration files have been published.';
}
if ($useSymlinks) {
$message .= ' Assets were symlinked.';
}
$output->writeln("<bg=green;options=bold> SUCCESS </> {$message}");
} else {
$output->writeln('<bg=red;options=bold> ERROR </> An error occurred during the installation of <fg=blue;options=bold>PHPFlasher</> resources.');
}
$this->assetManager->createManifest(array_merge([], ...$files));
$output->writeln('');
return $exitCode;
}
/**
* @return string[]
*/
private function publishAssets(PluginInterface $plugin, string $publicDir, bool $useSymlinks): array
{
$originDir = $plugin->getAssetsDir();
if (!is_dir($originDir)) {
return [];
}
$filesystem = new Filesystem();
$finder = new Finder();
$finder->files()->in($originDir);
$files = [];
foreach ($finder as $file) {
$relativePath = trim(str_replace($originDir, '', $file->getRealPath()), \DIRECTORY_SEPARATOR);
$targetPath = $publicDir.$relativePath;
$filesystem->makeDirectory(\dirname($targetPath), recursive: true, force: true);
if ($useSymlinks) {
$filesystem->link($file->getRealPath(), $targetPath);
} else {
$filesystem->copy($file->getRealPath(), $targetPath);
}
$files[] = $targetPath;
}
return $files;
}
private function publishConfig(PluginInterface $plugin, string $configFile): void
{
if (!file_exists($configFile)) {
return;
}
$target = App::configPath($plugin->getName().'.php');
if (file_exists($target)) {
return;
}
$filesystem = new Filesystem();
$filesystem->copy($configFile, $target);
}
}