Skip to content

Commit

Permalink
add event generation
Browse files Browse the repository at this point in the history
  • Loading branch information
dwjordan committed Oct 29, 2024
1 parent d4f6884 commit 03b0ec6
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 25 deletions.
8 changes: 7 additions & 1 deletion config/paragon.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@
'abstract-class' => 'Enum',

'paths' => [
'php' => '',
'php' => 'Enums',
'ignore' => [],
'generated' => 'js/enums',
'methods' => 'js/vendors/paragon/enums',
],
],
'events' => [
'paths' => [
'php' => 'Events',
'generated' => 'js/events',
],
],
];
15 changes: 11 additions & 4 deletions src/Commands/GenerateEnumsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Kirschbaum\Paragon\Commands;

use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
Expand All @@ -25,11 +26,17 @@ class GenerateEnumsCommand extends Command
*/
public function handle(): int
{
$builder = $this->builder();
try {
$builder = $this->builder();

$generatedEnums = $this->enums()
->map(fn ($enum) => app(EnumGenerator::class, ['enum' => $enum, 'builder' => $builder])())
->filter();
$generatedEnums = $this->enums()
->map(fn ($enum) => app(EnumGenerator::class, ['enum' => $enum, 'builder' => $builder])())
->filter();
} catch (Exception $e) {
$this->components->error($e->getMessage());

return self::FAILURE;
}

$this->components->info("{$generatedEnums->count()} enums have been (re)generated.");

Expand Down
33 changes: 33 additions & 0 deletions src/Commands/GenerateEventsCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Kirschbaum\Paragon\Commands;

use Exception;
use Illuminate\Console\Command;
use Kirschbaum\Paragon\Concerns\DiscoverBroadcastEvents;
use Kirschbaum\Paragon\Generators\EventGenerator;
use Symfony\Component\Console\Attribute\AsCommand;

#[AsCommand(name: 'paragon:generate-events', description: 'Generate Javascript versions of existing Laravel Events')]
class GenerateEventsCommand extends Command
{
/**
* Execute the console command.
*/
public function handle(): int
{
try {
$events = DiscoverBroadcastEvents::within(app_path(config()->string('paragon.events.paths.php')));

app(EventGenerator::class, ['events' => $events])();
} catch (Exception $e) {
$this->components->error($e->getMessage());

return self::FAILURE;
}

$this->components->info("{$events->count()} events have been (re)generated.");

return self::SUCCESS;
}
}
27 changes: 27 additions & 0 deletions src/Concerns/CanGetClassFromFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Kirschbaum\Paragon\Concerns;

use const DIRECTORY_SEPARATOR;

use SplFileInfo;

trait CanGetClassFromFile
{
/**
* Extract the class name from the given file path.
*/
protected static function classFromFile(SplFileInfo $file): string
{
return str($file->getRealPath())
->replaceFirst(base_path(), '')
->trim(DIRECTORY_SEPARATOR)
->replaceLast('.php', '')
->ucfirst()
->replace(
search: [DIRECTORY_SEPARATOR, ucfirst(basename(app()->path())) . '\\'],
replace: ['\\', app()->getNamespace()]
)
->toString();
}
}
43 changes: 43 additions & 0 deletions src/Concerns/DiscoverBroadcastEvents.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Kirschbaum\Paragon\Concerns;

use Illuminate\Support\Collection;
use ReflectionClass;
use ReflectionException;
use Symfony\Component\Finder\Finder;

class DiscoverBroadcastEvents
{
use CanGetClassFromFile;

/**
* Get all the events by searching the given directory.
*/
public static function within(array|string $path): Collection
{
return static::getBroadcastEvents(Finder::create()->files()->in($path));
}

/**
* Filter the files down to only concrete classes that implement ShouldBroadcast.
*/
protected static function getBroadcastEvents($files): Collection
{
return collect($files)
->mapWithKeys(function ($file) {
try {
$reflector = new ReflectionClass($event = static::classFromFile($file));
} catch (ReflectionException) {
return [];
}

return $reflector->isInstantiable()
&& $reflector->implementsInterface('Illuminate\Contracts\Broadcasting\ShouldBroadcast')
? [$file->getRealPath() => $event]
: [];
})
->sort()
->filter();
}
}
21 changes: 1 addition & 20 deletions src/Concerns/DiscoverEnums.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

class DiscoverEnums
{
use CanGetClassFromFile;
/**
* Get all the enums by searching the given directory.
*
Expand Down Expand Up @@ -52,24 +53,4 @@ protected static function getEnums(Finder $files): Collection
})
->filter();
}

/**
* Extract the class name from the given file path.
*
* @return class-string<\UnitEnum>
*/
protected static function classFromFile(SplFileInfo $file): string
{
/** @var class-string<\UnitEnum> */
return str($file->getRealPath())
->replaceFirst(base_path(), '')
->trim(DIRECTORY_SEPARATOR)
->replaceLast('.php', '')
->ucfirst()
->replace(
search: [DIRECTORY_SEPARATOR, ucfirst(basename(app()->path())) . '\\'],
replace: ['\\', app()->getNamespace()]
)
->toString();
}
}
62 changes: 62 additions & 0 deletions src/Generators/EventGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Kirschbaum\Paragon\Generators;

use const JSON_PRETTY_PRINT;

use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;

class EventGenerator
{
protected Filesystem $cache;

protected Filesystem $files;

/**
* Create new EventGenerator instance.
*/
public function __construct(protected Collection $events)
{
$this->files = Storage::createLocalDriver([
'root' => resource_path(config('paragon.events.paths.generated')),
]);
}

public function __invoke(): bool
{
$this->files->put($this->path(), $this->contents());

return true;
}

/**
* Typescript event file contents.
*/
protected function contents(): string
{
$content = $this->events
->mapWithKeys(fn ($value, $key) => [str($value)->replace('\\', '.')->toString() => $value])
->undot();

return str(file_get_contents($this->stubPath()))
->replace('{{ Events }}', json_encode($content, JSON_PRETTY_PRINT));
}

/**
* Get the path to the stubs.
*/
public function stubPath(): string
{
return __DIR__ . '/../../stubs/event.stub';
}

/**
* Path where the events will be saved.
*/
protected function path(): string
{
return str('Events.ts');
}
}
2 changes: 2 additions & 0 deletions src/ParagonServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Support\ServiceProvider;
use Kirschbaum\Paragon\Commands\ClearCacheCommand;
use Kirschbaum\Paragon\Commands\GenerateEnumsCommand;
use Kirschbaum\Paragon\Commands\GenerateEventsCommand;
use Kirschbaum\Paragon\Commands\MakeEnumMethodCommand;

class ParagonServiceProvider extends ServiceProvider
Expand Down Expand Up @@ -32,6 +33,7 @@ public function boot(): void
$this->commands([
ClearCacheCommand::class,
GenerateEnumsCommand::class,
GenerateEventsCommand::class,
MakeEnumMethodCommand::class,
]);
}
Expand Down
1 change: 1 addition & 0 deletions stubs/event.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default {{ Events }};

0 comments on commit 03b0ec6

Please sign in to comment.