update project

This commit is contained in:
root
2026-05-30 01:11:35 -04:00
parent 3a0628ecc7
commit 2225f6bc72
9743 changed files with 1122482 additions and 59 deletions
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env php
<?php
define('CANVAS_WORKING_PATH', $workingPath = getcwd());
define('TESTBENCH_WORKING_PATH', $workingPath);
require $_composer_autoload_path ?? __DIR__.'/vendor/autoload.php';
$config = Orchestra\Testbench\Foundation\Config::loadFromYaml(
workingPath: $workingPath,
defaults: [
'providers' => [],
'dont-discover' => [],
],
);
$commander = new Orchestra\Canvas\Console\Commander($config->getAttributes(), $workingPath);
$commander->handle();
+90
View File
@@ -0,0 +1,90 @@
{
"$schema": "https://getcomposer.org/schema.json",
"name": "orchestra/canvas",
"description": "Code Generators for Laravel Applications and Packages",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
},
{
"name": "Mior Muhammad Zaki",
"email": "crynobone@gmail.com"
}
],
"bin": [
"canvas"
],
"autoload": {
"psr-4": {
"Orchestra\\Canvas\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Orchestra\\Canvas\\Tests\\": "tests/",
"Illuminate\\Tests\\Integration\\Generators\\": "workbench/tests/"
}
},
"require": {
"php": "^8.3",
"composer-runtime-api": "^2.2",
"composer/semver": "^3.0",
"illuminate/console": "^13.0.0",
"illuminate/database": "^13.0.0",
"illuminate/filesystem": "^13.0.0",
"illuminate/support": "^13.0.0",
"orchestra/canvas-core": "^11.0.0",
"orchestra/sidekick": "~1.1.23|~1.2.20",
"orchestra/testbench-core": "^11.0.0",
"symfony/yaml": "^7.4.0|^8.0.0"
},
"require-dev": {
"laravel/framework": "^13.0.0",
"laravel/pint": "^1.24",
"mockery/mockery": "^1.6.10",
"phpstan/phpstan": "^2.1.14",
"phpunit/phpunit": "^11.5.50|^12.5.8|^13.0.0"
},
"config": {
"preferred-install": {
"laravel/framework": "source",
"*": "auto"
},
"sort-packages": true
},
"extra": {
"laravel": {
"providers": [
"Orchestra\\Canvas\\LaravelServiceProvider"
]
}
},
"scripts": {
"post-autoload-dump": [
"@clear",
"@prepare"
],
"clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
"prepare": "@php vendor/bin/testbench package:discover --ansi",
"lint": [
"@php vendor/bin/pint --ansi --parallel",
"@php vendor/bin/phpstan analyse --verbose"
],
"test": [
"@composer dump-autoload",
"@php vendor/bin/phpunit --no-coverage --no-configuration --bootstrap vendor/autoload.php --color ./tests ./workbench/tests"
],
"sync": "@php bin/sync",
"ci": [
"@composer audit",
"@prepare",
"@lint",
"@test"
]
},
"prefer-stable": true,
"minimum-stability": "dev"
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace Orchestra\Canvas;
use Illuminate\Support\Arr;
use InvalidArgumentException;
class Canvas
{
/**
* Make Preset from configuration.
*
* @param array<string, mixed> $config
*/
public static function preset(array $config, string $basePath): Presets\Preset
{
/** @var array<string, mixed> $configuration */
$configuration = Arr::except($config, 'preset');
/** @var string|class-string<\Orchestra\Canvas\Presets\Preset> $preset */
$preset = $config['preset'] ?? 'laravel';
/** @phpstan-ignore return.type */
return match (true) {
$preset === 'package' => new Presets\Package($configuration, $basePath),
$preset === 'laravel' => new Presets\Laravel($configuration, $basePath),
class_exists($preset) => new $preset($configuration, $basePath),
default => throw new InvalidArgumentException(\sprintf('Unable to resolve %s preset', $preset)),
};
}
}
+73
View File
@@ -0,0 +1,73 @@
<?php
namespace Orchestra\Canvas;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;
use Orchestra\Canvas\Core\PresetManager;
use Symfony\Component\Yaml\Yaml;
use function Orchestra\Sidekick\join_paths;
class CanvasServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register services.
*/
public function register(): void
{
$this->callAfterResolving(PresetManager::class, static function ($manager, $app) {
$manager->extend('canvas', fn ($app) => new GeneratorPreset($app));
$manager->setDefaultDriver('canvas');
});
$this->app->singleton('orchestra.canvas', static function (Application $app) {
$workingPath = \defined('CANVAS_WORKING_PATH') ? CANVAS_WORKING_PATH : $app->basePath();
$filesystem = $app->make('files');
$config = ['preset' => 'laravel'];
if (file_exists(join_paths($workingPath, 'canvas.yaml'))) {
$config = Yaml::parseFile(join_paths($workingPath, 'canvas.yaml'));
} else {
Arr::set($config, 'testing.extends', [
'unit' => 'PHPUnit\Framework\TestCase',
'feature' => 'Tests\TestCase',
]);
$config['namespace'] = rescue(fn () => rtrim($app->getNamespace(), '\\'), null, false);
}
return Canvas::preset($config, $workingPath);
});
}
/**
* Bootstrap services.
*/
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->commands([
Console\GeneratorMakeCommand::class,
Console\PresetMakeCommand::class,
]);
}
}
/**
* Get the services provided by the provider.
*
* @return array<int, string>
*/
public function provides()
{
return [
'orchestra.canvas',
];
}
}
@@ -0,0 +1,57 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\MigrationGenerator;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Queue/Console/BatchesTableCommand.php
*/
#[AsCommand(name: 'make:queue-batches-table', description: 'Create a migration for the batches database table', aliases: ['queue:batches-table'])]
class BatchesTableCommand extends \Illuminate\Queue\Console\BatchesTableCommand
{
use MigrationGenerator;
/**
* The console command name.
*
* @var string
*/
protected $name = 'make:queue-batches-table';
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Create a base migration file for the table.
*
* @param string $table
* @return string
*/
#[\Override]
protected function createBaseMigration($table)
{
return $this->createBaseMigrationUsingCanvas($table);
}
/**
* Determine whether a migration for the table already exists.
*
* @param string $table
* @return bool
*/
#[\Override]
protected function migrationExists($table)
{
return $this->migrationExistsUsingCanvas($table);
}
}
@@ -0,0 +1,50 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\MigrationGenerator;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Cache/Console/CacheTableCommand.php
*/
#[AsCommand(name: 'make:cache-table', description: 'Create a migration for the cache database table', aliases: ['cache:table'])]
class CacheTableCommand extends \Illuminate\Cache\Console\CacheTableCommand
{
use MigrationGenerator;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Create a base migration file for the table.
*
* @param string $table
* @return string
*/
#[\Override]
protected function createBaseMigration($table)
{
return $this->createBaseMigrationUsingCanvas($table);
}
/**
* Determine whether a migration for the table already exists.
*
* @param string $table
* @return bool
*/
#[\Override]
protected function migrationExists($table)
{
return $this->migrationExistsUsingCanvas($table);
}
}
+65
View File
@@ -0,0 +1,65 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/CastMakeCommand.php
*/
#[AsCommand(name: 'make:cast', description: 'Create a new custom Eloquent cast class')]
class CastMakeCommand extends \Illuminate\Foundation\Console\CastMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,67 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ChannelMakeCommand.php
*/
#[AsCommand(name: 'make:channel', description: 'Create a new channel class')]
class ChannelMakeCommand extends \Illuminate\Foundation\Console\ChannelMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,65 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ClassMakeCommand.php
*/
#[AsCommand(name: 'make:class', description: 'Create a new class')]
class ClassMakeCommand extends \Illuminate\Foundation\Console\ClassMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
+56
View File
@@ -0,0 +1,56 @@
<?php
namespace Orchestra\Canvas\Console;
use Illuminate\Contracts\Console\Kernel as ConsoleKernel;
use Illuminate\Foundation\Application as LaravelApplication;
use Illuminate\Support\Collection;
use Orchestra\Canvas\CanvasServiceProvider;
use Orchestra\Canvas\Core\Concerns\CreatesUsingGeneratorPreset;
use Orchestra\Canvas\LaravelServiceProvider;
use Symfony\Component\Console\Command\Command as SymfonyCommand;
/**
* @codeCoverageIgnore
*/
class Commander extends \Orchestra\Testbench\Console\Commander
{
/** {@inheritDoc} */
protected string $environmentFile = '.env';
/** {@inheritDoc} */
protected array $providers = [];
/** {@inheritDoc} */
#[\Override]
protected function resolveApplicationCallback()
{
return static function ($app) {
$app->register(CanvasServiceProvider::class);
};
}
/** {@inheritDoc} */
#[\Override]
public function laravel()
{
if (! $this->app instanceof LaravelApplication) {
$app = parent::laravel();
/** @var \Illuminate\Contracts\Console\Kernel $kernel */
$kernel = $app->make(ConsoleKernel::class);
$app->register(LaravelServiceProvider::class);
Collection::make($kernel->all())
->reject(
static fn (SymfonyCommand $command, string $name) => \in_array(CreatesUsingGeneratorPreset::class, class_uses_recursive($command))
)->each(static function (SymfonyCommand $command) {
$command->setHidden(true);
});
}
/** @phpstan-ignore return.type */
return $this->app;
}
}
@@ -0,0 +1,89 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ComponentMakeCommand.php
*/
#[AsCommand(name: 'make:component', description: 'Create a new view component class')]
class ComponentMakeCommand extends \Illuminate\Foundation\Console\ComponentMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Run after code successfully generated.
*/
public function afterCodeHasBeenGenerated(string $className, string $path): void
{
if ($this->option('view') || ! $this->option('inline')) {
$this->writeView();
}
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
/**
* Get the first view directory path from the application configuration.
*
* @param string $path
* @return string
*/
#[\Override]
protected function viewPath($path = '')
{
return $this->viewPathUsingCanvas($path);
}
}
@@ -0,0 +1,79 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ConsoleMakeCommand.php
*/
#[AsCommand(name: 'make:command', description: 'Create a new Artisan command')]
class ConsoleMakeCommand extends \Illuminate\Foundation\Console\ConsoleMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
#[\Override]
protected function getDefaultNamespace($rootNamespace)
{
return rtrim($this->generatorPreset()->commandNamespace(), '\\');
}
}
@@ -0,0 +1,184 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Routing/Console/ControllerMakeCommand.php
*/
#[AsCommand(name: 'make:controller', description: 'Create a new controller class')]
class ControllerMakeCommand extends \Illuminate\Routing\Console\ControllerMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Qualify the given model class base name.
*
* @return string
*/
#[\Override]
protected function qualifyModel(string $model)
{
return $this->qualifyModelUsingCanvas($model);
}
/**
* Build the replacements for a parent controller.
*
* @return array
*/
#[\Override]
protected function buildParentReplacements()
{
/** @var class-string|string $parentModelClass */
/** @phpstan-ignore argument.type */
$parentModelClass = $this->parseModel($this->option('parent'));
if (! class_exists($parentModelClass) &&
$this->components->confirm("A {$parentModelClass} model does not exist. Do you want to generate it?", true)) {
$this->call('make:model', ['name' => $parentModelClass, '--preset' => $this->option('preset')]);
}
return [
'ParentDummyFullModelClass' => $parentModelClass,
'{{ namespacedParentModel }}' => $parentModelClass,
'{{namespacedParentModel}}' => $parentModelClass,
'ParentDummyModelClass' => class_basename($parentModelClass),
'{{ parentModel }}' => class_basename($parentModelClass),
'{{parentModel}}' => class_basename($parentModelClass),
'ParentDummyModelVariable' => lcfirst(class_basename($parentModelClass)),
'{{ parentModelVariable }}' => lcfirst(class_basename($parentModelClass)),
'{{parentModelVariable}}' => lcfirst(class_basename($parentModelClass)),
];
}
/**
* Build the model replacement values.
*
* @return array
*/
#[\Override]
protected function buildModelReplacements(array $replace)
{
/** @var class-string|string $modelClass */
/** @phpstan-ignore argument.type */
$modelClass = $this->parseModel($this->option('model'));
if (! class_exists($modelClass) && $this->components->confirm("A {$modelClass} model does not exist. Do you want to generate it?", true)) {
$this->call('make:model', ['name' => $modelClass, '--preset' => $this->option('preset')]);
}
$replace = $this->buildFormRequestReplacements($replace, $modelClass);
if ($this->option('requests')) {
$namespace = $this->rootNamespace();
$replace['{{ namespacedRequests }}'] = str_replace('App\\', $namespace, $replace['{{ namespacedRequests }}']);
$replace['{{namespacedRequests}}'] = str_replace('App\\', $namespace, $replace['{{namespacedRequests}}']);
}
return array_merge($replace, [
'DummyFullModelClass' => $modelClass,
'{{ namespacedModel }}' => $modelClass,
'{{namespacedModel}}' => $modelClass,
'DummyModelClass' => class_basename($modelClass),
'{{ model }}' => class_basename($modelClass),
'{{model}}' => class_basename($modelClass),
'DummyModelVariable' => lcfirst(class_basename($modelClass)),
'{{ modelVariable }}' => lcfirst(class_basename($modelClass)),
'{{modelVariable}}' => lcfirst(class_basename($modelClass)),
]);
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
/**
* Get a list of possible model names.
*
* @return array<int, string>
*/
#[\Override]
protected function findAvailableModels()
{
return $this->findAvailableModelsUsingCanvas();
}
/**
* Generate the form requests for the given model and classes.
*
* @param string $modelClass
* @param string $storeRequestClass
* @param string $updateRequestClass
* @return array
*/
#[\Override]
protected function generateFormRequests($modelClass, $storeRequestClass, $updateRequestClass)
{
$storeRequestClass = 'Store'.class_basename($modelClass).'Request';
$this->call('make:request', [
'name' => $storeRequestClass,
'--preset' => $this->option('preset'),
]);
$updateRequestClass = 'Update'.class_basename($modelClass).'Request';
$this->call('make:request', [
'name' => $updateRequestClass,
'--preset' => $this->option('preset'),
]);
return [$storeRequestClass, $updateRequestClass];
}
}
+65
View File
@@ -0,0 +1,65 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Routing/Console/EnumMakeCommand.php
*/
#[AsCommand(name: 'make:enum', description: 'Create a new enum')]
class EnumMakeCommand extends \Illuminate\Foundation\Console\EnumMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,65 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/EventMakeCommand.php
*/
#[AsCommand(name: 'make:event', description: 'Create a new event class')]
class EventMakeCommand extends \Illuminate\Foundation\Console\EventMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,65 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ExceptionMakeCommand.php
*/
#[AsCommand(name: 'make:exception', description: 'Create a new custom exception class')]
class ExceptionMakeCommand extends \Illuminate\Foundation\Console\ExceptionMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,127 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\ResolvesPresetStubs;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
use function Orchestra\Sidekick\Filesystem\join_paths;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Database/Console/Factories/FactoryMakeCommand.php
*/
#[AsCommand(name: 'make:factory', description: 'Create a new model factory')]
class FactoryMakeCommand extends \Illuminate\Database\Console\Factories\FactoryMakeCommand
{
use CodeGenerator;
use ResolvesPresetStubs;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Resolve the default fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
protected function resolveDefaultStubPath($stub)
{
return join_paths(__DIR__, $stub);
}
/**
* Get the full namespace for a given class, without the class name.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getNamespace($name)
{
return rtrim($this->generatorPreset()->factoryNamespace(), '\\');
}
/**
* Get the generator preset source path.
*/
protected function getGeneratorSourcePath(): string
{
return $this->generatorPreset()->factoryPath();
}
/**
* Guess the model name from the Factory name or return a default model name.
*
* @param string $name
* @return string
*/
#[\Override]
protected function guessModelName($name)
{
if (str_ends_with($name, 'Factory')) {
$name = substr($name, 0, -7);
}
return $this->qualifyModelUsingCanvas($name);
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
/**
* Get the model for the default guard's user provider.
*
* @return string|null
*/
#[\Override]
protected function userProviderModel()
{
return $this->userProviderModelUsingCanvas();
}
}
@@ -0,0 +1,50 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\MigrationGenerator;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Queue/Console/FailedTableCommand.php
*/
#[AsCommand(name: 'make:queue-failed-table', description: 'Create a migration for the failed queue jobs database table', aliases: ['queue:failed-table'])]
class FailedTableCommand extends \Illuminate\Queue\Console\FailedTableCommand
{
use MigrationGenerator;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Create a base migration file for the table.
*
* @param string $table
* @return string
*/
#[\Override]
protected function createBaseMigration($table)
{
return $this->createBaseMigrationUsingCanvas($table);
}
/**
* Determine whether a migration for the table already exists.
*
* @param string $table
* @return bool
*/
#[\Override]
protected function migrationExists($table)
{
return $this->migrationExistsUsingCanvas($table);
}
}
@@ -0,0 +1,90 @@
<?php
namespace Orchestra\Canvas\Console;
use Illuminate\Support\Str;
use Orchestra\Canvas\Core\Commands\GeneratorCommand;
use Orchestra\Canvas\Core\Concerns\ResolvesPresetStubs;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputOption;
use function Orchestra\Sidekick\Filesystem\join_paths;
#[AsCommand(name: 'make:generator', description: 'Create a new generator command')]
class GeneratorMakeCommand extends GeneratorCommand
{
use ResolvesPresetStubs;
/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Generator';
/**
* Replace the class name for the given stub.
*
* @param string $stub
* @param string $name
* @return string
*/
#[\Override]
protected function replaceClass($stub, $name)
{
$stub = parent::replaceClass($stub, $name);
/** @var string $command */
$command = $this->option('command') ?: 'make:'.Str::of($name)->classBasename()->kebab()->value();
return str_replace(['dummy:command', '{{ command }}'], $command, $stub);
}
/**
* Get the stub file for the generator.
*
* @return string
*/
#[\Override]
protected function getStub()
{
return $this->resolveStubPath(join_paths('stubs', 'generator.stub'));
}
/**
* Resolve the default fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
protected function resolveDefaultStubPath($stub)
{
return join_paths(__DIR__, $stub);
}
/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
#[\Override]
protected function getDefaultNamespace($rootNamespace)
{
return rtrim($this->generatorPreset()->commandNamespace(), '\\');
}
/**
* Get the console command options.
*
* @return array<int, array>
*/
#[\Override]
protected function getOptions()
{
return [
['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the generator already exists'],
['command', null, InputOption::VALUE_OPTIONAL, 'The terminal command that should be assigned', 'make:name'],
];
}
}
@@ -0,0 +1,65 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/InterfaceMakeCommand.php
*/
#[AsCommand(name: 'make:interface', description: 'Create a new interface')]
class InterfaceMakeCommand extends \Illuminate\Foundation\Console\InterfaceMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
+67
View File
@@ -0,0 +1,67 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/JobMakeCommand.php
*/
#[AsCommand(name: 'make:job', description: 'Create a new job class')]
class JobMakeCommand extends \Illuminate\Foundation\Console\JobMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,67 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/JobMiddlewareMakeCommand.php
*/
#[AsCommand(name: 'make:job-middleware', description: 'Create a new job middleware class')]
class JobMiddlewareMakeCommand extends \Illuminate\Foundation\Console\JobMiddlewareMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,78 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ListenerMakeCommand.php
*/
#[AsCommand(name: 'make:listener', description: 'Create a new event listener class')]
class ListenerMakeCommand extends \Illuminate\Foundation\Console\ListenerMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
/**
* Get a list of possible event names.
*
* @return array<int, string>
*/
#[\Override]
protected function possibleEvents()
{
return $this->possibleEventsUsingCanvas();
}
}
+81
View File
@@ -0,0 +1,81 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/MailMakeCommand.php
*/
#[AsCommand(name: 'make:mail', description: 'Create a new email class')]
class MailMakeCommand extends \Illuminate\Foundation\Console\MailMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Run after code successfully generated.
*/
public function afterCodeHasBeenGenerated(string $className, string $path): void
{
if ($this->option('markdown') !== false) {
$this->writeMarkdownTemplate();
}
if ($this->option('view') !== false) {
$this->writeView();
}
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,67 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Routing/Console/MiddlewareMakeCommand.php
*/
#[AsCommand(name: 'make:middleware', description: 'Create a new middleware class')]
class MiddlewareMakeCommand extends \Illuminate\Routing\Console\MiddlewareMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,52 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Commands\Command;
use Orchestra\Canvas\Core\Concerns\CreatesUsingGeneratorPreset;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Database/Console/Migrations/MigrateMakeCommand.php
*/
#[AsCommand(name: 'make:migration', description: 'Create a new migration file')]
class MigrateMakeCommand extends \Illuminate\Database\Console\Migrations\MigrateMakeCommand
{
use CreatesUsingGeneratorPreset;
/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Migration';
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return void
*/
#[\Override]
public function handle()
{
$preset = $this->generatorPreset();
if (! $preset->is('laravel')) {
$this->input->setOption('path', $preset->migrationPath());
$this->input->setOption('realpath', true);
}
parent::handle();
}
}
+219
View File
@@ -0,0 +1,219 @@
<?php
namespace Orchestra\Canvas\Console;
use Illuminate\Support\Str;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ModelMakeCommand.php
*/
#[AsCommand(name: 'make:model', description: 'Create a new Eloquent model class')]
class ModelMakeCommand extends \Illuminate\Foundation\Console\ModelMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Run after code successfully generated.
*/
protected function afterCodeHasBeenGenerated(): void
{
if ($this->option('all')) {
$this->input->setOption('factory', true);
$this->input->setOption('seed', true);
$this->input->setOption('migration', true);
$this->input->setOption('controller', true);
$this->input->setOption('policy', true);
$this->input->setOption('resource', true);
}
if ($this->option('factory')) {
$this->createFactory();
}
if ($this->option('migration')) {
$this->createMigration();
}
if ($this->option('seed')) {
$this->createSeeder();
}
if ($this->option('controller') || $this->option('resource') || $this->option('api')) {
$this->createController();
}
if ($this->option('policy')) {
$this->createPolicy();
}
}
/**
* Create a model factory for the model.
*
* @return void
*/
#[\Override]
protected function createFactory()
{
$factory = Str::studly($this->getNameInput());
$this->call('make:factory', [
'name' => "{$factory}Factory",
'--model' => $this->qualifyClass($this->getNameInput()),
'--preset' => $this->option('preset'),
]);
}
/**
* Create a migration file for the model.
*
* @return void
*/
#[\Override]
protected function createMigration()
{
$table = Str::snake(Str::pluralStudly(class_basename($this->getNameInput())));
if ($this->option('pivot')) {
$table = Str::singular($table);
}
$this->call('make:migration', [
'name' => "create_{$table}_table",
'--create' => $table,
'--fullpath' => true,
'--preset' => $this->option('preset'),
]);
}
/**
* Create a seeder file for the model.
*
* @return void
*/
#[\Override]
protected function createSeeder()
{
$seeder = Str::studly(class_basename($this->getNameInput()));
$this->call('make:seeder', [
'name' => "{$seeder}Seeder",
'--preset' => $this->option('preset'),
]);
}
/**
* Create a controller for the model.
*
* @return void
*/
#[\Override]
protected function createController()
{
$controller = Str::studly(class_basename($this->getNameInput()));
$modelName = $this->qualifyClass($this->getNameInput());
$this->call('make:controller', array_filter([
'name' => "{$controller}Controller",
'--model' => $this->option('resource') || $this->option('api') ? $modelName : null,
'--api' => $this->option('api'),
'--requests' => $this->option('requests') || $this->option('all'),
'--preset' => $this->option('preset'),
]));
}
/**
* Create a policy file for the model.
*
* @return void
*/
#[\Override]
protected function createPolicy()
{
$policy = Str::studly(class_basename($this->getNameInput()));
$this->call('make:policy', [
'name' => "{$policy}Policy",
'--model' => $this->qualifyClass($this->getNameInput()),
'--preset' => $this->option('preset'),
]);
}
/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
#[\Override]
protected function getDefaultNamespace($rootNamespace)
{
return rtrim($this->generatorPreset()->modelNamespace(), '\\');
}
/**
* Qualify the given model class base name.
*
* @return string
*/
#[\Override]
protected function qualifyModel(string $model)
{
return $this->qualifyModelUsingCanvas($model);
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,77 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/NotificationMakeCommand.php
*/
#[AsCommand(name: 'make:notification', description: 'Create a new notification class')]
class NotificationMakeCommand extends \Illuminate\Foundation\Console\NotificationMakeCommand
{
use CodeGenerator;
use TestGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Run after code successfully generated.
*/
public function afterCodeHasBeenGenerated(string $className, string $path): void
{
if ($this->option('markdown')) {
$this->writeMarkdownTemplate();
}
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,50 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\MigrationGenerator;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Notifications/Console/NotificationTableCommand.php
*/
#[AsCommand(name: 'make:notifications-table', description: 'Create a migration for the notifications table', aliases: ['notifications:table'])]
class NotificationTableCommand extends \Illuminate\Notifications\Console\NotificationTableCommand
{
use MigrationGenerator;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Create a base migration file for the table.
*
* @param string $table
* @return string
*/
#[\Override]
protected function createBaseMigration($table)
{
return $this->createBaseMigrationUsingCanvas($table);
}
/**
* Determine whether a migration for the table already exists.
*
* @param string $table
* @return bool
*/
#[\Override]
protected function migrationExists($table)
{
return $this->migrationExistsUsingCanvas($table);
}
}
@@ -0,0 +1,87 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ObserverMakeCommand.php
*/
#[AsCommand(name: 'make:observer', description: 'Create a new observer class')]
class ObserverMakeCommand extends \Illuminate\Foundation\Console\ObserverMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Qualify the given model class base name.
*
* @return string
*/
#[\Override]
protected function qualifyModel(string $model)
{
return $this->qualifyModelUsingCanvas($model);
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
/**
* Get a list of possible model names.
*
* @return array<int, string>
*/
#[\Override]
protected function findAvailableModels()
{
return $this->findAvailableModelsUsingCanvas();
}
}
@@ -0,0 +1,101 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/PolicyMakeCommand.php
*/
#[AsCommand(name: 'make:policy', description: 'Create a new policy class')]
class PolicyMakeCommand extends \Illuminate\Foundation\Console\PolicyMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Qualify the given model class base name.
*
* @return string
*/
#[\Override]
protected function qualifyModel(string $model)
{
return $this->qualifyModelUsingCanvas($model);
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
/**
* Get the model for the default guard's user provider.
*
* @return string|null
*/
#[\Override]
protected function userProviderModel()
{
/** @var string|null $guard */
$guard = $this->option('guard');
return $this->userProviderModelUsingCanvas($guard);
}
/**
* Get a list of possible model names.
*
* @return array<int, string>
*/
#[\Override]
protected function findAvailableModels()
{
return $this->findAvailableModelsUsingCanvas();
}
}
@@ -0,0 +1,140 @@
<?php
namespace Orchestra\Canvas\Console;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Orchestra\Canvas\Core\Commands\GeneratorCommand;
use Orchestra\Canvas\Core\Concerns\ResolvesPresetStubs;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use function Laravel\Prompts\select;
use function Orchestra\Sidekick\Filesystem\join_paths;
use function Orchestra\Testbench\package_path;
/**
* @codeCoverageIgnore
*/
#[AsCommand(name: 'preset', description: 'Create canvas.yaml for the project')]
class PresetMakeCommand extends GeneratorCommand
{
use ResolvesPresetStubs;
/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Preset';
/**
* Interact with the user before validating the input.
*/
#[\Override]
protected function interact(InputInterface $input, OutputInterface $output): void
{
if (\is_null($input->getArgument('name'))) {
$input->setArgument('name', select(
label: 'The preset type?',
options: [
'laravel' => 'Application',
'package' => 'Package',
],
required: true,
));
}
if (\is_null($input->getOption('namespace'))) {
$files = new Filesystem;
$composer = $files->json(package_path('composer.json'));
$namespaces = Collection::make(Arr::wrap(data_get($composer, 'autoload.psr-4')))
->keys()
->transform(static fn ($namespace) => rtrim($namespace, '\\'))
->mapWithKeys(static fn ($namespace) => [$namespace => $namespace]);
if ($namespaces->isNotEmpty()) {
if ($namespaces->count() === 1) {
$input->setOption('namespace', $namespaces->first());
} else {
$input->setOption('namespace', select(
label: 'The root namespace for your package?',
options: $namespaces->all(),
required: true,
));
}
}
}
parent::interact($input, $output);
}
/**
* Get the stub file for the generator.
*
* @return string
*/
#[\Override]
protected function getStub()
{
$name = Str::lower($this->getNameInput());
$stub = join_paths(__DIR__, 'stubs', 'preset');
return $this->files->exists("{$stub}.{$name}.stub")
? "{$stub}.{$name}.stub"
: "{$stub}.laravel.stub";
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return join_paths($this->generatorPreset()->basePath(), 'canvas.yaml');
}
/**
* Get the root namespace for the class.
*/
#[\Override]
protected function rootNamespace(): string
{
/** @var string $namespace */
$namespace = transform(
$this->option('namespace'), static fn (string $namespace) => trim($namespace) /** @phpstan-ignore argument.type */
);
if (! empty($namespace)) {
return $namespace;
}
return match ($this->argument('name')) {
'package' => 'PackageName',
/* 'laravel' */
default => rtrim($this->laravel->getNamespace(), '\\'),
};
}
/**
* Get the console command options.
*
* @return array<int, array>
*/
#[\Override]
protected function getOptions()
{
return [
['namespace', null, InputOption::VALUE_OPTIONAL, 'Root namespace'],
];
}
}
@@ -0,0 +1,77 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ProviderMakeCommand.php
*/
#[AsCommand(name: 'make:provider', description: 'Create a new service provider class')]
class ProviderMakeCommand extends \Illuminate\Foundation\Console\ProviderMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
#[\Override]
protected function getDefaultNamespace($rootNamespace)
{
return rtrim($this->generatorPreset()->providerNamespace(), '\\');
}
}
@@ -0,0 +1,51 @@
<?php
namespace Orchestra\Canvas\Console;
use Illuminate\Queue\Console\TableCommand;
use Orchestra\Canvas\Core\Concerns\MigrationGenerator;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Queue/Console/TableCommand.php
*/
#[AsCommand(name: 'make:queue-table', description: 'Create a migration for the queue jobs database table', aliases: ['queue:table'])]
class QueueTableCommand extends TableCommand
{
use MigrationGenerator;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Create a base migration file for the table.
*
* @param string $table
* @return string
*/
#[\Override]
protected function createBaseMigration($table)
{
return $this->createBaseMigrationUsingCanvas($table);
}
/**
* Determine whether a migration for the table already exists.
*
* @param string $table
* @return bool
*/
#[\Override]
protected function migrationExists($table)
{
return $this->migrationExistsUsingCanvas($table);
}
}
@@ -0,0 +1,65 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/RequestMakeCommand.php
*/
#[AsCommand(name: 'make:request', description: 'Create a new form request class')]
class RequestMakeCommand extends \Illuminate\Foundation\Console\RequestMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,65 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ResourceMakeCommand.php
*/
#[AsCommand(name: 'make:resource', description: 'Create a new resource')]
class ResourceMakeCommand extends \Illuminate\Foundation\Console\ResourceMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
+65
View File
@@ -0,0 +1,65 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/RuleMakeCommand.php
*/
#[AsCommand(name: 'make:rule', description: 'Create a new validation rule')]
class RuleMakeCommand extends \Illuminate\Foundation\Console\RuleMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,76 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/ScopeMakeCommand.php
*/
#[AsCommand(name: 'make:scope', description: 'Create a new class')]
class ScopeMakeCommand extends \Illuminate\Foundation\Console\ScopeMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Qualify the given model class base name.
*
* @return string
*/
#[\Override]
protected function qualifyModel(string $model)
{
return $this->qualifyModelUsingCanvas($model);
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
}
@@ -0,0 +1,73 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Database/Console/Seeds/SeederMakeCommand.php
*/
#[AsCommand(name: 'make:seeder', description: 'Create a new seeder class')]
class SeederMakeCommand extends \Illuminate\Database\Console\Seeds\SeederMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Get the generator preset source path.
*/
protected function getGeneratorSourcePath(): string
{
return $this->generatorPreset()->seederPath();
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->generatorPreset()->seederNamespace();
}
}
@@ -0,0 +1,50 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\MigrationGenerator;
use Symfony\Component\Console\Attribute\AsCommand;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Session/Console/SessionTableCommand.php
*/
#[AsCommand(name: 'make:session-table', description: 'Create a migration for the session database table', aliases: ['session:table'])]
class SessionTableCommand extends \Illuminate\Session\Console\SessionTableCommand
{
use MigrationGenerator;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Create a base migration file for the table.
*
* @param string $table
* @return string
*/
#[\Override]
protected function createBaseMigration($table)
{
return $this->createBaseMigrationUsingCanvas($table);
}
/**
* Determine whether a migration for the table already exists.
*
* @param string $table
* @return bool
*/
#[\Override]
protected function migrationExists($table)
{
return $this->migrationExistsUsingCanvas($table);
}
}
+154
View File
@@ -0,0 +1,154 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Orchestra\Canvas\GeneratorPreset;
use Symfony\Component\Console\Attribute\AsCommand;
use function Orchestra\Sidekick\Filesystem\join_paths;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Console/TestMakeCommand.php
*/
#[AsCommand(name: 'make:test', description: 'Create a new test class')]
class TestMakeCommand extends \Illuminate\Foundation\Console\TestMakeCommand
{
use CodeGenerator;
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Replace the class name for the given stub.
*
* @param string $stub
* @param string $name
* @return string
*/
protected function generatingCode($stub, $name)
{
$preset = $this->generatorPreset();
if (! $preset instanceof GeneratorPreset) {
return $stub;
}
$testCase = $this->option('unit')
? $preset->canvas()->config('testing.extends.unit', 'PHPUnit\Framework\TestCase')
: $preset->canvas()->config(
'testing.extends.feature',
$preset->canvas()->is('laravel') ? 'Tests\TestCase' : 'Orchestra\Testbench\TestCase'
);
return $this->replaceTestCase($stub, $testCase);
}
/**
* Replace the model for the given stub.
*/
protected function replaceTestCase(string $stub, string $testCase): string
{
$namespaceTestCase = $testCase = str_replace('/', '\\', $testCase);
if (str_starts_with($testCase, '\\')) {
$stub = str_replace('NamespacedDummyTestCase', trim($testCase, '\\'), $stub);
} else {
$stub = str_replace('NamespacedDummyTestCase', $namespaceTestCase, $stub);
}
$stub = str_replace(
"use {$namespaceTestCase};\nuse {$namespaceTestCase};", "use {$namespaceTestCase};", $stub
);
$testCase = class_basename(trim($testCase, '\\'));
return str_replace('DummyTestCase', $testCase, $stub);
}
/**
* Resolve the fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
#[\Override]
protected function resolveStubPath($stub)
{
$preset = $this->generatorPreset();
if (! $preset instanceof GeneratorPreset) {
return parent::resolveStubPath($stub);
}
return $preset->hasCustomStubPath() && file_exists($customPath = join_paths($preset->basePath(), $stub))
? $customPath
: $this->resolveDefaultStubPath($stub);
}
/**
* Resolve the default fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
protected function resolveDefaultStubPath($stub)
{
return join_paths(__DIR__, $stub);
}
/**
* Get the generator preset source path.
*/
protected function getGeneratorSourcePath(): string
{
return $this->generatorPreset()->testingPath();
}
/**
* Get the destination class path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
return $this->getPathUsingCanvas($name);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->generatorPreset()->testingNamespace();
}
}
@@ -0,0 +1,117 @@
<?php
namespace Orchestra\Canvas\Console;
use Orchestra\Canvas\Core\Commands\GeneratorCommand;
use Orchestra\Canvas\Core\Concerns\ResolvesPresetStubs;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputOption;
use function Orchestra\Sidekick\Filesystem\join_paths;
#[AsCommand(name: 'make:user-factory', description: 'Create the User factory class')]
class UserFactoryMakeCommand extends GeneratorCommand
{
use ResolvesPresetStubs;
/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Factory';
/**
* Get the stub file for the generator.
*
* @return string
*/
#[\Override]
protected function getStub()
{
return $this->resolveStubPath(join_paths('stubs', 'user-factory.stub'));
}
/**
* Resolve the default fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
protected function resolveDefaultStubPath($stub)
{
return join_paths(__DIR__, $stub);
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->generatorPreset()->factoryNamespace();
}
/**
* Get the generator preset source path.
*/
protected function getGeneratorSourcePath(): string
{
return $this->generatorPreset()->factoryPath();
}
/**
* Handle generating code.
*/
public function generatingCode(string $stub, string $className): string
{
$preset = $this->generatorPreset();
return str_replace([
'{{ factoryNamespace }}',
'{{ namespacedModel }}',
'{{ model }}',
], [
rtrim($preset->factoryNamespace(), '\\'),
$preset->modelNamespace().'User',
'User',
], $stub);
}
/**
* Get the desired class name from the input.
*
* @return string
*/
#[\Override]
protected function getNameInput()
{
return 'UserFactory';
}
/**
* Get the console command arguments.
*
* @return array
*/
#[\Override]
protected function getArguments()
{
return [];
}
/**
* Get the console command options.
*
* @return array<int, array>
*/
#[\Override]
protected function getOptions()
{
return [
['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the generator already exists'],
];
}
}
@@ -0,0 +1,114 @@
<?php
namespace Orchestra\Canvas\Console;
use Composer\InstalledVersions;
use Orchestra\Canvas\Core\Commands\GeneratorCommand;
use Orchestra\Canvas\Core\Concerns\ResolvesPresetStubs;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputOption;
use function Orchestra\Sidekick\Filesystem\join_paths;
#[AsCommand(name: 'make:user-model', description: 'Create the User model class')]
class UserModelMakeCommand extends GeneratorCommand
{
use ResolvesPresetStubs;
/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Model';
/**
* Build the class with the given name.
*
* @param string $name
* @return string
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
protected function buildClass($name)
{
$stub = parent::buildClass($name);
if (! InstalledVersions::isInstalled('laravel/sanctum')) {
$stub = str_replace(
' use HasApiTokens, HasFactory, Notifiable;'.PHP_EOL,
' use HasFactory, Notifiable;'.PHP_EOL,
$stub
);
}
return $stub;
}
/**
* Get the stub file for the generator.
*
* @return string
*/
#[\Override]
protected function getStub()
{
return $this->resolveStubPath(join_paths('stubs', 'user-model.stub'));
}
/**
* Resolve the default fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
protected function resolveDefaultStubPath($stub)
{
return join_paths(__DIR__, $stub);
}
/**
* Get the default namespace for the class.
*/
#[\Override]
public function getDefaultNamespace($rootNamespace)
{
return rtrim($this->generatorPreset()->modelNamespace(), '\\');
}
/**
* Get the desired class name from the input.
*
* @return string
*/
#[\Override]
protected function getNameInput()
{
return 'User';
}
/**
* Get the console command arguments.
*
* @return array
*/
#[\Override]
protected function getArguments()
{
return [];
}
/**
* Get the console command options.
*
* @return array<int, array>
*/
#[\Override]
protected function getOptions()
{
return [
['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the generator already exists'],
];
}
}
+206
View File
@@ -0,0 +1,206 @@
<?php
namespace Orchestra\Canvas\Console;
use Illuminate\Support\Str;
use Orchestra\Canvas\Core\Concerns\CodeGenerator;
use Orchestra\Canvas\Core\Concerns\TestGenerator;
use Orchestra\Canvas\Core\Concerns\UsesGeneratorOverrides;
use Orchestra\Canvas\GeneratorPreset;
use Symfony\Component\Console\Attribute\AsCommand;
use function Orchestra\Sidekick\Filesystem\join_paths;
#[AsCommand(name: 'make:view', description: 'Create a new view')]
class ViewMakeCommand extends \Illuminate\Foundation\Console\ViewMakeCommand
{
use CodeGenerator;
use TestGenerator {
handleTestCreationUsingCanvas as protected handleTestCreationUsingCanvasFromTrait;
}
use UsesGeneratorOverrides;
/**
* Configures the current command.
*/
#[\Override]
protected function configure(): void
{
parent::configure();
$this->addGeneratorPresetOptions();
}
/**
* Execute the console command.
*
* @return bool|null
*
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
#[\Override]
public function handle()
{
/** @phpstan-ignore return.type */
return $this->generateCode() ? self::SUCCESS : self::FAILURE;
}
/**
* Resolve the fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
#[\Override]
protected function resolveStubPath($stub)
{
$preset = $this->generatorPreset();
if (! $preset instanceof GeneratorPreset) {
return parent::resolveStubPath($stub);
}
return $preset->hasCustomStubPath() && file_exists($customPath = join_paths($preset->basePath(), $stub))
? $customPath
: $this->resolveDefaultStubPath($stub);
}
/**
* Resolve the default fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
protected function resolveDefaultStubPath($stub)
{
return join_paths(__DIR__, $stub);
}
/**
* Get the destination view path.
*
* @param string $name
* @return string
*/
#[\Override]
protected function getPath($name)
{
/** @var string $extension */
/** @phpstan-ignore argument.type */
$extension = transform($this->option('extension'), fn (string $extension) => trim($extension));
return $this->viewPath(
$this->getNameInput().'.'.$extension,
);
}
/**
* Get the first view directory path from the application configuration.
*
* @param string $path
* @return string
*/
#[\Override]
protected function viewPath($path = '')
{
return $this->viewPathUsingCanvas($path);
}
/**
* Get the desired view name from the input.
*
* @return string
*/
#[\Override]
protected function getNameInput()
{
/** @phpstan-ignore argument.type, return.type */
return transform($this->argument('name'), function (string $name) {
return str_replace(['\\', '.'], '/', trim($name));
});
}
/**
* Create the matching test case if requested.
*
* @param string $path
*/
protected function handleTestCreationUsingCanvas($path): bool
{
if (! $this->option('test') && ! $this->option('pest')) {
return false;
}
$preset = $this->generatorPreset();
if (! $preset instanceof GeneratorPreset) {
return $this->handleTestCreationUsingCanvasFromTrait($path);
}
$namespaceTestCase = $testCase = $preset->canvas()->config(
'testing.extends.feature',
$preset->canvas()->is('laravel') ? 'Tests\TestCase' : 'Orchestra\Testbench\TestCase'
);
$stub = $this->files->get($this->getTestStub());
if (Str::startsWith($testCase, '\\')) {
$stub = str_replace('NamespacedDummyTestCase', trim($testCase, '\\'), $stub);
} else {
$stub = str_replace('NamespacedDummyTestCase', $namespaceTestCase, $stub);
}
$contents = str_replace(
['{{ namespace }}', '{{ class }}', '{{ name }}', 'DummyTestCase'],
[$this->testNamespace(), $this->testClassName(), $this->testViewName(), class_basename(trim($testCase, '\\'))],
$stub,
);
$this->files->ensureDirectoryExists(\dirname($this->getTestPath()), 0755, true);
return $this->files->put($this->getTestPath(), $contents) !== false;
}
/**
* Get the root namespace for the class.
*
* @return string
*/
#[\Override]
protected function rootNamespace()
{
return $this->rootNamespaceUsingCanvas();
}
/**
* Get the destination test case path.
*
* @return string
*/
#[\Override]
protected function getTestPath()
{
$preset = $this->generatorPreset();
$testPath = Str::of($this->testClassFullyQualifiedName())
->replace('\\', DIRECTORY_SEPARATOR)
->replaceFirst(join_paths('Tests', 'Feature'), join_paths(str_replace($preset->basePath(), '', $preset->testingPath()), 'Feature'))
->append('Test.php')
->value();
return $preset->basePath().$testPath;
}
/**
* Get the test stub file for the generator.
*
* @return string
*/
#[\Override]
protected function getTestStub()
{
$stubName = 'view.'.($this->option('pest') ? 'pest' : 'test').'.stub';
return $this->resolveStubPath(join_paths('stubs', $stubName));
}
}
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace DummyNamespace;
class DummyClass
{
//
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace {{ factoryNamespace }};
use {{ namespacedModel }};
use Illuminate\Database\Eloquent\Factories\Factory;
use {{ namespacedModel }};
/**
* @extends Factory<{{ model }}>
*/
class {{ factory }}Factory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var class-string<{{ model }}>
*/
protected $model = {{ model }}::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
];
}
}
@@ -0,0 +1,46 @@
<?php
namespace DummyNamespace;
use Orchestra\Canvas\Core\Commands\GeneratorCommand;
use Symfony\Component\Console\Attribute\AsCommand;
#[AsCommand(name: 'dummy:command', description: 'Create a new class')]
class DummyClass extends GeneratorCommand
{
/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Class';
/**
* Get the stub file for the generator.
*
* @return string
*/
protected function getStub()
{
// ...
}
/**
* Resolve the default fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
protected function resolveDefaultStubPath($stub)
{
return __DIR__.$stub;
}
/**
* Get the default namespace for the class.
*/
public function getDefaultNamespace($rootNamespace)
{
return $rootNamespace;
}
}
+7
View File
@@ -0,0 +1,7 @@
<?php
test('example', function () {
$response = $this->get('/');
$response->assertStatus(200);
});
@@ -0,0 +1,5 @@
<?php
test('example', function () {
expect(true)->toBeTrue();
});
@@ -0,0 +1,7 @@
preset: laravel
namespace: DummyNamespace
model:
namespace: DummyNamespace
@@ -0,0 +1,27 @@
preset: package
namespace: DummyNamespace
user-auth-model: App\Models\User
paths:
src: src
resource: resources
factory:
path: database/factories
migration:
path: database/migrations
prefix: ''
console:
namespace: DummyNamespace\Console
model:
namespace: DummyNamespace\Models
provider:
namespace: DummyNamespace\Providers
testing:
namespace: DummyNamespace\Tests
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace {{ namespace }};
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use NamespacedDummyTestCase;
class {{ class }} extends DummyTestCase
{
/**
* A basic feature test example.
*/
public function test_example(): void
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
@@ -0,0 +1,16 @@
<?php
namespace {{ namespace }};
use NamespacedDummyTestCase;
class {{ class }} extends DummyTestCase
{
/**
* A basic unit test example.
*/
public function test_example(): void
{
$this->assertTrue(true);
}
}
@@ -0,0 +1,52 @@
<?php
namespace {{ factoryNamespace }};
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use {{ namespacedModel }};
/**
* @extends Factory<User>
*/
class UserFactory extends Factory
{
/**
* The current password being used by the factory.
*/
protected static ?string $password;
/**
* The name of the factory's corresponding model.
*
* @var class-string<{{ model }}>
*/
protected $model = {{ model }}::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}
@@ -0,0 +1,32 @@
<?php
namespace {{ namespace }};
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
#[Fillable(['name', 'email', 'password'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable
{
/** @use HasFactory<UserFactory> */
use HasFactory, Notifiable;
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
}
@@ -0,0 +1,9 @@
<?php
it('can render', function () {
$contents = $this->view('{{ name }}', [
//
]);
$contents->assertSee('');
});
+3
View File
@@ -0,0 +1,3 @@
<div>
<!-- {{ quote }} -->
</div>
@@ -0,0 +1,23 @@
<?php
namespace {{ namespace }};
use NamespacedDummyTestCase;
use Illuminate\Foundation\Testing\Concerns\InteractsWithViews;
class {{ class }} extends DummyTestCase
{
use InteractsWithViews;
/**
* A basic view test example.
*/
public function test_it_can_render(): void
{
$contents = $this->view('{{ name }}', [
//
]);
$contents->assertSee('');
}
}
+167
View File
@@ -0,0 +1,167 @@
<?php
namespace Orchestra\Canvas;
use Orchestra\Canvas\Core\Presets\Preset;
use function Orchestra\Sidekick\join_paths;
class GeneratorPreset extends Preset
{
/**
* Preset name.
*/
public function name(): string
{
return 'canvas';
}
/**
* Get the path to the base working directory.
*/
public function basePath(): string
{
return $this->canvas()->basePath();
}
/**
* Get the path to the source directory.
*/
public function sourcePath(): string
{
return $this->canvas()->sourcePath();
}
/**
* Get the path to the testing directory.
*/
public function testingPath(): string
{
return $this->canvas()->testingPath();
}
/**
* Get the path to the resource directory.
*/
public function resourcePath(): string
{
return $this->canvas()->resourcePath();
}
/**
* Get the path to the view directory.
*/
public function viewPath(): string
{
return join_paths($this->resourcePath(), 'views');
}
/**
* Get the path to the factory directory.
*/
public function factoryPath(): string
{
return $this->canvas()->factoryPath();
}
/**
* Get the path to the migration directory.
*/
public function migrationPath(): string
{
return $this->canvas()->migrationPath();
}
/**
* Get the path to the seeder directory.
*/
public function seederPath(): string
{
return $this->canvas()->seederPath();
}
/**
* Preset namespace.
*/
public function rootNamespace(): string
{
return $this->canvas()->rootNamespace().'\\';
}
/**
* Command namespace.
*/
public function commandNamespace(): string
{
return $this->canvas()->commandNamespace().'\\';
}
/**
* Model namespace.
*/
public function modelNamespace(): string
{
return $this->canvas()->modelNamespace().'\\';
}
/**
* Provider namespace.
*/
public function providerNamespace(): string
{
return $this->canvas()->providerNamespace().'\\';
}
/**
* Database factory namespace.
*/
public function factoryNamespace(): string
{
return $this->canvas()->factoryNamespace().'\\';
}
/**
* Database seeder namespace.
*/
public function seederNamespace(): string
{
return $this->canvas()->seederNamespace().'\\';
}
/**
* Testing namespace.
*/
public function testingNamespace(): string
{
return $this->canvas()->testingNamespace().'\\';
}
/**
* Preset has custom stub path.
*/
public function hasCustomStubPath(): bool
{
return ! \is_null($this->canvas()->getCustomStubPath());
}
/** {@inheritDoc} */
#[\Override]
public function userProviderModel(?string $guard = null): ?string
{
if (\is_null($guard) || $guard === $this->app->make('config')->get('auth.defaults.guard')) {
return $this->canvas()->config('user-auth-model')
?? $this->canvas()->config('user-auth-provider')
?? parent::userProviderModel($guard);
}
return parent::userProviderModel($guard);
}
/**
* Get canvas preset.
*/
public function canvas(): Presets\Preset
{
return $this->app->make('orchestra.canvas');
}
}
+596
View File
@@ -0,0 +1,596 @@
<?php
namespace Orchestra\Canvas;
use Illuminate\Cache\Console\CacheTableCommand;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Database\Console\Factories\FactoryMakeCommand;
use Illuminate\Database\Console\Seeds\SeederMakeCommand;
use Illuminate\Foundation\Console\CastMakeCommand;
use Illuminate\Foundation\Console\ChannelMakeCommand;
use Illuminate\Foundation\Console\ClassMakeCommand;
use Illuminate\Foundation\Console\ComponentMakeCommand;
use Illuminate\Foundation\Console\ConsoleMakeCommand;
use Illuminate\Foundation\Console\EnumMakeCommand;
use Illuminate\Foundation\Console\EventMakeCommand;
use Illuminate\Foundation\Console\ExceptionMakeCommand;
use Illuminate\Foundation\Console\InterfaceMakeCommand;
use Illuminate\Foundation\Console\JobMakeCommand;
use Illuminate\Foundation\Console\JobMiddlewareMakeCommand;
use Illuminate\Foundation\Console\ListenerMakeCommand;
use Illuminate\Foundation\Console\MailMakeCommand;
use Illuminate\Foundation\Console\ModelMakeCommand;
use Illuminate\Foundation\Console\NotificationMakeCommand;
use Illuminate\Foundation\Console\ObserverMakeCommand;
use Illuminate\Foundation\Console\PolicyMakeCommand;
use Illuminate\Foundation\Console\ProviderMakeCommand;
use Illuminate\Foundation\Console\RequestMakeCommand;
use Illuminate\Foundation\Console\ResourceMakeCommand;
use Illuminate\Foundation\Console\RuleMakeCommand;
use Illuminate\Foundation\Console\ScopeMakeCommand;
use Illuminate\Foundation\Console\TestMakeCommand;
use Illuminate\Foundation\Console\ViewMakeCommand;
use Illuminate\Notifications\Console\NotificationTableCommand;
use Illuminate\Queue\Console\BatchesTableCommand;
use Illuminate\Queue\Console\FailedTableCommand;
use Illuminate\Queue\Console\TableCommand as QueueTableCommand;
use Illuminate\Routing\Console\ControllerMakeCommand;
use Illuminate\Routing\Console\MiddlewareMakeCommand;
use Illuminate\Session\Console\SessionTableCommand;
use Illuminate\Support\ServiceProvider;
/**
* @see https://github.com/laravel/framework/blob/11.x/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php
*/
class LaravelServiceProvider extends ServiceProvider implements DeferrableProvider
{
/**
* Register the service provider.
*/
public function boot(): void
{
$this->registerCastMakeCommand();
$this->registerChannelMakeCommand();
$this->registerClassMakeCommand();
$this->registerComponentMakeCommand();
$this->registerConsoleMakeCommand();
$this->registerControllerMakeCommand();
$this->registerEnumMakeCommand();
$this->registerEventMakeCommand();
$this->registerExceptionMakeCommand();
$this->registerFactoryMakeCommand();
$this->registerJobMakeCommand();
$this->registerJobMiddlewareMakeCommand();
$this->registerInterfaceMakeCommand();
$this->registerListenerMakeCommand();
$this->registerMailMakeCommand();
$this->registerMiddlewareMakeCommand();
$this->registerMigrateMakeCommand();
$this->registerModelMakeCommand();
$this->registerNotificationMakeCommand();
$this->registerObserverMakeCommand();
$this->registerPolicyMakeCommand();
$this->registerProviderMakeCommand();
$this->registerRequestMakeCommand();
$this->registerResourceMakeCommand();
$this->registerRuleMakeCommand();
$this->registerScopeMakeCommand();
$this->registerSeederMakeCommand();
$this->registerTestMakeCommand();
$this->registerViewMakeCommand();
$this->registerCacheTableCommand();
$this->registerNotificationTableCommand();
$this->registerQueueBatchesTableCommand();
$this->registerQueueFailedTableCommand();
$this->registerQueueTableCommand();
$this->registerSessionTableCommand();
$this->registerUserFactoryMakeCommand();
$this->registerUserModelMakeCommand();
$this->commands([
Console\CastMakeCommand::class,
Console\ChannelMakeCommand::class,
Console\ComponentMakeCommand::class,
Console\ConsoleMakeCommand::class,
Console\ClassMakeCommand::class,
Console\ControllerMakeCommand::class,
Console\EnumMakeCommand::class,
Console\EventMakeCommand::class,
Console\ExceptionMakeCommand::class,
Console\FactoryMakeCommand::class,
Console\JobMakeCommand::class,
Console\InterfaceMakeCommand::class,
Console\ListenerMakeCommand::class,
Console\MailMakeCommand::class,
Console\MiddlewareMakeCommand::class,
Console\MigrateMakeCommand::class,
Console\ModelMakeCommand::class,
Console\NotificationMakeCommand::class,
Console\ObserverMakeCommand::class,
Console\PolicyMakeCommand::class,
Console\ProviderMakeCommand::class,
Console\RequestMakeCommand::class,
Console\ResourceMakeCommand::class,
Console\RuleMakeCommand::class,
Console\ScopeMakeCommand::class,
Console\SeederMakeCommand::class,
Console\TestMakeCommand::class,
Console\ViewMakeCommand::class,
Console\BatchesTableCommand::class,
Console\CacheTableCommand::class,
Console\FailedTableCommand::class,
Console\NotificationTableCommand::class,
Console\QueueTableCommand::class,
Console\SessionTableCommand::class,
Console\UserFactoryMakeCommand::class,
Console\UserModelMakeCommand::class,
]);
}
/**
* Register the command.
*/
protected function registerCastMakeCommand(): void
{
$this->app->singleton(
CastMakeCommand::class, static fn ($app) => new Console\CastMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerChannelMakeCommand(): void
{
$this->app->singleton(
ChannelMakeCommand::class, static fn ($app) => new Console\ChannelMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerClassMakeCommand(): void
{
$this->app->singleton(
ClassMakeCommand::class, static fn ($app) => new Console\ClassMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerComponentMakeCommand(): void
{
$this->app->singleton(
ComponentMakeCommand::class, static fn ($app) => new Console\ComponentMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerConsoleMakeCommand(): void
{
$this->app->singleton(
ConsoleMakeCommand::class, static fn ($app) => new Console\ConsoleMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerControllerMakeCommand(): void
{
$this->app->singleton(
ControllerMakeCommand::class, static fn ($app) => new Console\ControllerMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerEnumMakeCommand(): void
{
$this->app->singleton(
EnumMakeCommand::class, fn ($app) => new Console\EnumMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerEventMakeCommand(): void
{
$this->app->singleton(
EventMakeCommand::class, static fn ($app) => new Console\EventMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerExceptionMakeCommand(): void
{
$this->app->singleton(
ExceptionMakeCommand::class, static fn ($app) => new Console\ExceptionMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerFactoryMakeCommand(): void
{
$this->app->singleton(
FactoryMakeCommand::class, static fn ($app) => new Console\FactoryMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerJobMakeCommand(): void
{
$this->app->singleton(
JobMakeCommand::class, static fn ($app) => new Console\JobMakeCommand($app['files'])
);
}
/**
* Register the command.
*
* @return void
*/
protected function registerJobMiddlewareMakeCommand()
{
$this->app->singleton(
JobMiddlewareMakeCommand::class, static fn ($app) => new Console\JobMiddlewareMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerInterfaceMakeCommand(): void
{
$this->app->singleton(
InterfaceMakeCommand::class, static fn ($app) => new Console\InterfaceMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerListenerMakeCommand(): void
{
$this->app->singleton(
ListenerMakeCommand::class, static fn ($app) => new Console\ListenerMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerMailMakeCommand(): void
{
$this->app->singleton(
MailMakeCommand::class, static fn ($app) => new Console\MailMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerMiddlewareMakeCommand(): void
{
$this->app->singleton(
MiddlewareMakeCommand::class, static fn ($app) => new Console\MiddlewareMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerMigrateMakeCommand(): void
{
$this->app->singleton(Console\MigrateMakeCommand::class, static function ($app) {
// Once we have the migration creator registered, we will create the command
// and inject the creator. The creator is responsible for the actual file
// creation of the migrations, and may be extended by these developers.
$creator = $app['migration.creator'];
$composer = $app['composer'];
return new Console\MigrateMakeCommand($creator, $composer);
});
}
/**
* Register the command.
*/
protected function registerModelMakeCommand(): void
{
$this->app->singleton(
ModelMakeCommand::class, static fn ($app) => new Console\ModelMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerNotificationMakeCommand(): void
{
$this->app->singleton(
NotificationMakeCommand::class, static fn ($app) => new Console\NotificationMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerObserverMakeCommand(): void
{
$this->app->singleton(
ObserverMakeCommand::class, static fn ($app) => new Console\ObserverMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerPolicyMakeCommand(): void
{
$this->app->singleton(
PolicyMakeCommand::class, static fn ($app) => new Console\PolicyMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerProviderMakeCommand(): void
{
$this->app->singleton(
ProviderMakeCommand::class, static fn ($app) => new Console\ProviderMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerRequestMakeCommand(): void
{
$this->app->singleton(
RequestMakeCommand::class, static fn ($app) => new Console\RequestMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerResourceMakeCommand(): void
{
$this->app->singleton(
ResourceMakeCommand::class, static fn ($app) => new Console\ResourceMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerRuleMakeCommand(): void
{
$this->app->singleton(
RuleMakeCommand::class, static fn ($app) => new Console\RuleMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerScopeMakeCommand(): void
{
$this->app->singleton(
ScopeMakeCommand::class, static fn ($app) => new Console\ScopeMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerSeederMakeCommand(): void
{
$this->app->singleton(
SeederMakeCommand::class, static fn ($app) => new Console\SeederMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerTestMakeCommand(): void
{
$this->app->singleton(
TestMakeCommand::class, static fn ($app) => new Console\TestMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerViewMakeCommand(): void
{
$this->app->singleton(
ViewMakeCommand::class, static fn ($app) => new Console\ViewMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerCacheTableCommand(): void
{
$this->app->singleton(
CacheTableCommand::class, static fn ($app) => new Console\CacheTableCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerNotificationTableCommand(): void
{
$this->app->singleton(
NotificationTableCommand::class, static fn ($app) => new Console\NotificationTableCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerQueueBatchesTableCommand(): void
{
$this->app->singleton(
BatchesTableCommand::class, static fn ($app) => new Console\BatchesTableCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerQueueFailedTableCommand(): void
{
$this->app->singleton(
FailedTableCommand::class, static fn ($app) => new Console\FailedTableCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerQueueTableCommand(): void
{
$this->app->singleton(
QueueTableCommand::class, static fn ($app) => new Console\QueueTableCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerSessionTableCommand(): void
{
$this->app->singleton(
SessionTableCommand::class, static fn ($app) => new Console\SessionTableCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerUserFactoryMakeCommand(): void
{
$this->app->singleton(
Console\UserFactoryMakeCommand::class, static fn ($app) => new Console\UserFactoryMakeCommand($app['files'])
);
}
/**
* Register the command.
*/
protected function registerUserModelMakeCommand(): void
{
$this->app->singleton(
Console\UserModelMakeCommand::class, static fn ($app) => new Console\UserModelMakeCommand($app['files'])
);
}
/**
* Get the services provided by the provider.
*
* @return array<int, class-string>
*/
public function provides()
{
return [
CastMakeCommand::class,
Console\CastMakeCommand::class,
ChannelMakeCommand::class,
Console\ChannelMakeCommand::class,
ClassMakeCommand::class,
Console\ClassMakeCommand::class,
ComponentMakeCommand::class,
Console\ComponentMakeCommand::class,
ConsoleMakeCommand::class,
Console\ConsoleMakeCommand::class,
ControllerMakeCommand::class,
Console\ControllerMakeCommand::class,
EnumMakeCommand::class,
Console\EnumMakeCommand::class,
EventMakeCommand::class,
Console\EventMakeCommand::class,
ExceptionMakeCommand::class,
Console\ExceptionMakeCommand::class,
FactoryMakeCommand::class,
Console\FactoryMakeCommand::class,
InterfaceMakeCommand::class,
Console\InterfaceMakeCommand::class,
JobMakeCommand::class,
Console\JobMakeCommand::class,
JobMiddlewareMakeCommand::class,
Console\JobMiddlewareMakeCommand::class,
ListenerMakeCommand::class,
Console\ListenerMakeCommand::class,
MailMakeCommand::class,
Console\MailMakeCommand::class,
MiddlewareMakeCommand::class,
Console\MiddlewareMakeCommand::class,
Console\MigrateMakeCommand::class,
ModelMakeCommand::class,
Console\ModelMakeCommand::class,
NotificationMakeCommand::class,
Console\NotificationMakeCommand::class,
ObserverMakeCommand::class,
Console\ObserverMakeCommand::class,
PolicyMakeCommand::class,
Console\PolicyMakeCommand::class,
ProviderMakeCommand::class,
Console\ProviderMakeCommand::class,
RequestMakeCommand::class,
Console\RequestMakeCommand::class,
ResourceMakeCommand::class,
Console\ResourceMakeCommand::class,
RuleMakeCommand::class,
Console\RuleMakeCommand::class,
ScopeMakeCommand::class,
Console\ScopeMakeCommand::class,
SeederMakeCommand::class,
Console\SeederMakeCommand::class,
TestMakeCommand::class,
Console\TestMakeCommand::class,
ViewMakeCommand::class,
Console\ViewMakeCommand::class,
BatchesTableCommand::class,
Console\BatchesTableCommand::class,
CacheTableCommand::class,
Console\CacheTableCommand::class,
FailedTableCommand::class,
Console\FailedTableCommand::class,
NotificationTableCommand::class,
Console\NotificationTableCommand::class,
QueueTableCommand::class,
Console\QueueTableCommand::class,
SessionTableCommand::class,
Console\SessionTableCommand::class,
Console\UserFactoryMakeCommand::class,
Console\UserModelMakeCommand::class,
];
}
}
+72
View File
@@ -0,0 +1,72 @@
<?php
namespace Orchestra\Canvas\Presets;
use function Orchestra\Sidekick\join_paths;
class Laravel extends Preset
{
/**
* Preset name.
*/
public function name(): string
{
return 'laravel';
}
/**
* Get the path to the source directory.
*/
public function sourcePath(): string
{
return join_paths($this->basePath(), $this->config('paths.src', 'app'));
}
/**
* Preset namespace.
*/
public function rootNamespace(): string
{
return $this->config['namespace'] ?? 'App';
}
/**
* Command namespace.
*/
public function commandNamespace(): string
{
return $this->config('console.namespace', $this->rootNamespace().'\Console\Commands');
}
/**
* Model namespace.
*/
public function modelNamespace(): string
{
return $this->config('model.namespace', $this->rootNamespace().'\Models');
}
/**
* Provider namespace.
*/
public function providerNamespace(): string
{
return $this->config('provider.namespace', $this->rootNamespace().'\Providers');
}
/**
* Testing namespace.
*/
public function testingNamespace(): string
{
return $this->config('testing.namespace', 'Tests');
}
/**
* Get custom stub path.
*/
public function getCustomStubPath(): ?string
{
return join_paths($this->basePath(), 'stubs');
}
}
+83
View File
@@ -0,0 +1,83 @@
<?php
namespace Orchestra\Canvas\Presets;
use InvalidArgumentException;
use function Orchestra\Sidekick\join_paths;
class Package extends Preset
{
/**
* Preset name.
*/
public function name(): string
{
return 'package';
}
/**
* Get the path to the source directory.
*/
public function sourcePath(): string
{
return join_paths(
$this->basePath(),
$this->config('paths.src', 'src')
);
}
/**
* Preset namespace.
*/
public function rootNamespace(): string
{
$namespace = trim($this->config['namespace'] ?? '');
if (empty($namespace)) {
throw new InvalidArgumentException("Please configure namespace configuration under 'canvas.yaml'");
}
return $namespace;
}
/**
* Command namespace.
*/
public function commandNamespace(): string
{
return $this->config('console.namespace', $this->rootNamespace().'\Console');
}
/**
* Model namespace.
*/
public function modelNamespace(): string
{
return $this->config('model.namespace', $this->rootNamespace());
}
/**
* Provider namespace.
*/
public function providerNamespace(): string
{
return $this->config('provider.namespace', $this->rootNamespace());
}
/**
* Testing namespace.
*/
public function testingNamespace(): string
{
return $this->config('testing.namespace', $this->rootNamespace().'\Tests');
}
/**
* Get custom stub path.
*/
public function getCustomStubPath(): ?string
{
return null;
}
}
+160
View File
@@ -0,0 +1,160 @@
<?php
namespace Orchestra\Canvas\Presets;
use Illuminate\Support\Arr;
use function Orchestra\Sidekick\join_paths;
abstract class Preset
{
/**
* Construct a new preset.
*
* @param array<string, mixed> $config
*/
public function __construct(
protected array $config,
protected string $basePath
) {
//
}
/**
* Check if preset name equal to $name.
*/
public function is(string $name): bool
{
return $this->name() === $name;
}
/**
* Get configuration.
*
* @param mixed|null $default
*/
public function config(?string $key = null, $default = null): mixed
{
if (\is_null($key)) {
return $this->config;
}
return Arr::get($this->config, $key, $default);
}
/**
* Get the path to the base working directory.
*/
public function basePath(): string
{
return $this->basePath;
}
/**
* Get the path to the testing directory.
*/
public function testingPath(): string
{
return join_paths($this->basePath, 'tests');
}
/**
* Get the path to the resource directory.
*/
public function resourcePath(): string
{
return join_paths(
$this->basePath(),
$this->config('paths.resource', 'resources')
);
}
/**
* Get the path to the factory directory.
*/
public function factoryPath(): string
{
return join_paths(
$this->basePath(),
$this->config('factory.path', join_paths('database', 'factories'))
);
}
/**
* Get the path to the migration directory.
*/
public function migrationPath(): string
{
return join_paths(
$this->basePath(),
$this->config('migration.path', join_paths('database', 'migrations'))
);
}
/**
* Get the path to the seeder directory.
*/
public function seederPath(): string
{
return join_paths(
$this->basePath(),
$this->config('seeder.path', join_paths('database', 'seeders'))
);
}
/**
* Database factory namespace.
*/
public function factoryNamespace(): string
{
return $this->config('factory.namespace', 'Database\Factories');
}
/**
* Database seeder namespace.
*/
public function seederNamespace(): string
{
return $this->config('seeder.namespace', 'Database\Seeders');
}
/**
* Preset name.
*/
abstract public function name(): string;
/**
* Get the path to the source directory.
*/
abstract public function sourcePath(): string;
/**
* Preset namespace.
*/
abstract public function rootNamespace(): string;
/**
* Command namespace.
*/
abstract public function commandNamespace(): string;
/**
* Model namespace.
*/
abstract public function modelNamespace(): string;
/**
* Provider namespace.
*/
abstract public function providerNamespace(): string;
/**
* Testing namespace.
*/
abstract public function testingNamespace(): string;
/**
* Get custom stub path.
*/
abstract public function getCustomStubPath(): ?string;
}