diff --git a/README.md b/README.md index d20eb4d3..019648a6 100644 --- a/README.md +++ b/README.md @@ -253,10 +253,10 @@ class ExampleBlock extends Block } ``` -You may also pass `--construct` to the command above to generate a stub with the block properties set within an `attributes` method. This can be useful for localization, etc. +You may also pass `--localize` to the command above to generate a block stub with the name and description ready for translation. ```bash -$ wp acorn acf:block Example --construct +$ wp acorn acf:block Example --localize ``` When running the block generator, one difference to a generic field is an accompanied `View` is generated in the `resources/views/blocks` directory. diff --git a/config/acf.php b/config/acf.php index ff399921..5de60126 100644 --- a/config/acf.php +++ b/config/acf.php @@ -37,6 +37,20 @@ // 'phoneNumber' => 'phone_number', ], + /* + |-------------------------------------------------------------------------- + | Generators + |-------------------------------------------------------------------------- + | + | Here you may specify defaults used when generating Composer classes in + | your application. + | + */ + + 'generators' => [ + 'supports' => ['align', 'mode', 'multiple', 'jsx'], + ], + /* |-------------------------------------------------------------------------- | Cache Manifest Path diff --git a/src/Block.php b/src/Block.php index 93b10f0e..43ea75d9 100644 --- a/src/Block.php +++ b/src/Block.php @@ -284,6 +284,22 @@ public function mergeAttributes(): void } } + /** + * Retrieve the block name. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Retrieve the block description. + */ + public function getDescription(): string + { + return $this->description; + } + /** * Retrieve the active block style. */ @@ -464,11 +480,11 @@ public function compose(): ?self { $this->mergeAttributes(); - if (empty($this->name)) { + if (blank($this->getName())) { return null; } - $this->slug = $this->slug ?: Str::slug(Str::kebab($this->name)); + $this->slug = $this->slug ?: Str::slug(Str::kebab($this->getName())); $this->view = $this->view ?: Str::start($this->slug, 'blocks.'); $this->namespace = $this->namespace ?? Str::start($this->slug, $this->prefix); @@ -506,8 +522,8 @@ public function settings(): Collection $settings = Collection::make([ 'name' => $this->slug, - 'title' => $this->name, - 'description' => $this->description, + 'title' => $this->getName(), + 'description' => $this->getDescription(), 'category' => $this->category, 'icon' => $this->getIcon(), 'keywords' => $this->keywords, diff --git a/src/Console/BlockMakeCommand.php b/src/Console/BlockMakeCommand.php index 4f66a339..b8d1b365 100644 --- a/src/Console/BlockMakeCommand.php +++ b/src/Console/BlockMakeCommand.php @@ -2,6 +2,12 @@ namespace Log1x\AcfComposer\Console; +use Illuminate\Support\Str; + +use function Laravel\Prompts\multiselect; +use function Laravel\Prompts\select; +use function Laravel\Prompts\text; + class BlockMakeCommand extends MakeCommand { /** @@ -10,7 +16,7 @@ class BlockMakeCommand extends MakeCommand * @var string */ protected $signature = 'acf:block {name* : The name of the block} - {--construct : Generate block properties inside of `__construct`} + {--localize : Localize the block name and description} {--force : Overwrite any existing files}'; /** @@ -34,6 +40,112 @@ class BlockMakeCommand extends MakeCommand */ protected $view = 'block'; + /** + * The block supports array. + */ + protected array $supports = [ + 'align', + 'align_text', + 'align_content', + 'full_height', + 'anchor', + 'mode', + 'multiple', + 'jsx', + 'color' => ['background', 'text', 'gradient'], + ]; + + /** + * {@inheritdoc} + */ + public function buildClass($name) + { + $stub = parent::buildClass($name); + + $name = Str::of($name) + ->afterLast('\\') + ->kebab() + ->headline() + ->replace('-', ' '); + + $description = "A beautiful {$name} block."; + + $description = text( + label: 'Enter the block description', + placeholder: $description, + ) ?: $description; + + $categories = get_default_block_categories(); + + $category = select( + label: 'Select the block category', + options: collect($categories)->mapWithKeys(fn ($category) => [$category['slug'] => $category['title']]), + default: 'common', + ); + + $postTypes = multiselect( + label: 'Select the supported post types', + options: collect( + get_post_types(['public' => true]) + )->mapWithKeys(fn ($postType) => [$postType => Str::headline($postType)])->all(), + hint: 'Leave empty to support all post types.', + ); + + $postTypes = collect($postTypes) + ->map(fn ($postType) => sprintf("'%s'", $postType)) + ->join(', '); + + $supports = multiselect( + label: 'Select the supported block features', + options: $this->getSupports(), + default: config('acf.generators.supports', []), + scroll: 8, + ); + + $stub = str_replace( + ['DummySupports', 'DummyDescription', 'DummyCategory', 'DummyPostTypes'], + [$this->buildSupports($supports), $description, $category, $postTypes], + $stub + ); + + return $stub; + } + + /** + * Build the block supports array. + */ + protected function buildSupports(array $selected): string + { + return collect($this->supports)->map(function ($value, $key) use ($selected) { + if (is_int($key)) { + return sprintf("'%s' => %s,", $value, in_array($value, $selected) ? 'true' : 'false'); + } + + $options = collect($value) + ->map(fn ($option) => sprintf( + "%s'%s' => %s,", + Str::repeat(' ', 12), + $option, + in_array($option, $selected) ? 'true' : 'false' + )) + ->join("\n"); + + return sprintf("'%s' => [\n%s\n ],", $key, $options); + })->join("\n "); + } + + /** + * Retrieve the support options. + */ + protected function getSupports(): array + { + return collect($this->supports) + ->mapWithKeys(fn ($value, $key) => is_array($value) + ? collect($value)->mapWithKeys(fn ($option) => [$option => Str::of($option)->finish(" {$key}")->headline()->toString()])->all() + : [$value => Str::headline($value)] + )->all(); + } + /** * Get the stub file for the generator. * @@ -41,8 +153,8 @@ class BlockMakeCommand extends MakeCommand */ protected function getStub() { - if ($this->option('construct')) { - return $this->resolveStub('block.construct'); + if ($this->option('localize')) { + return $this->resolveStub('block.localized'); } return $this->resolveStub('block'); diff --git a/src/Console/MakeCommand.php b/src/Console/MakeCommand.php index 7ab19e74..70ee0af1 100644 --- a/src/Console/MakeCommand.php +++ b/src/Console/MakeCommand.php @@ -227,7 +227,10 @@ protected function createView() */ protected function summary() { - $this->line(''); + if (! Str::contains($this->type, ['Block', 'Widget'])) { + $this->newLine(); + } + $this->line("🎉 {$this->getNameInput()} {$this->getType()} successfully composed."); $this->line(" ⮑ {$this->shortenPath($this->path)}"); diff --git a/src/Console/WidgetMakeCommand.php b/src/Console/WidgetMakeCommand.php index 9f29ca18..6e74becc 100644 --- a/src/Console/WidgetMakeCommand.php +++ b/src/Console/WidgetMakeCommand.php @@ -2,6 +2,10 @@ namespace Log1x\AcfComposer\Console; +use Illuminate\Support\Str; + +use function Laravel\Prompts\text; + class WidgetMakeCommand extends MakeCommand { /** @@ -33,6 +37,31 @@ class WidgetMakeCommand extends MakeCommand */ protected $view = 'widget'; + /** + * {@inheritdoc} + */ + public function buildClass($name) + { + $stub = parent::buildClass($name); + + $name = Str::of($name) + ->afterLast('\\') + ->kebab() + ->headline() + ->replace('-', ' '); + + $description = "A beautiful {$name} widget."; + + $description = text( + label: 'Enter the widget description', + placeholder: $description, + ) ?: $description; + + $stub = str_replace('DummyDescription', $description, $stub); + + return $stub; + } + /** * Get the stub file for the generator. * diff --git a/src/Console/stubs/block.construct.stub b/src/Console/stubs/block.construct.stub deleted file mode 100644 index 1a22fd62..00000000 --- a/src/Console/stubs/block.construct.stub +++ /dev/null @@ -1,108 +0,0 @@ - __('DummyTitle', 'sage'), - 'description' => __('A simple DummyTitle block.', 'sage'), - 'category' => 'formatting', - 'icon' => 'editor-ul', - 'keywords' => [], - 'post_types' => [], - 'parent' => [], - 'ancestor' => [], - 'mode' => 'preview', - 'align' => '', - 'align_text' => '', - 'align_content' => '', - 'supports' => [ - 'align' => true, - 'align_text' => false, - 'align_content' => false, - 'full_height' => false, - 'anchor' => false, - 'mode' => false, - 'multiple' => true, - 'jsx' => true, - 'color' => [ - 'background' => true, - 'text' => true, - 'gradient' => true, - ], - ], - 'styles' => ['light', 'dark'], - 'template' => [ - 'core/heading' => ['placeholder' => 'Hello World'], - 'core/paragraph' => ['placeholder' => 'Welcome to the DummyTitle block.'], - ], - ]; - } - - /** - * The example data. - */ - public function example(): array - { - return [ - 'items' => [ - ['item' => 'Item one'], - ['item' => 'Item two'], - ['item' => 'Item three'], - ], - ]; - } - - /** - * Data to be passed to the block before rendering. - */ - public function with(): array - { - return [ - 'items' => $this->items(), - ]; - } - - /** - * The block field group. - */ - public function fields(): array - { - $fields = Builder::make('DummySnake'); - - $fields - ->addRepeater('items') - ->addText('item') - ->endRepeater(); - - return $fields->build(); - } - - /** - * Return the items field. - * - * @return array - */ - public function items() - { - return get_field('items') ?: $this->example['items']; - } - - /** - * Assets enqueued when rendering the block. - */ - public function assets(array $block): void - { - // - } -} diff --git a/src/Console/stubs/block.localized.stub b/src/Console/stubs/block.localized.stub new file mode 100644 index 00000000..48ffb55d --- /dev/null +++ b/src/Console/stubs/block.localized.stub @@ -0,0 +1,184 @@ + [ + ['item' => 'Item one'], + ['item' => 'Item two'], + ['item' => 'Item three'], + ], + ]; + + /** + * The block template. + * + * @var array + */ + public $template = [ + 'core/heading' => ['placeholder' => 'Hello World'], + 'core/paragraph' => ['placeholder' => 'Welcome to the DummyTitle block.'], + ]; + + /** + * The block name. + */ + public function getName(): string + { + return __('DummyTitle', 'sage'); + } + + /** + * The block description. + */ + public function getDescription(): string + { + return __('DummyDescription', 'sage'); + } + + /** + * Data to be passed to the block before rendering. + */ + public function with(): array + { + return [ + 'items' => $this->items(), + ]; + } + + /** + * The block field group. + */ + public function fields(): array + { + $fields = Builder::make('DummySnake'); + + $fields + ->addRepeater('items') + ->addText('item') + ->endRepeater(); + + return $fields->build(); + } + + /** + * Retrieve the items. + * + * @return array + */ + public function items() + { + return get_field('items') ?: $this->example['items']; + } + + /** + * Assets enqueued when rendering the block. + */ + public function assets(array $block): void + { + // + } +} diff --git a/src/Console/stubs/block.stub b/src/Console/stubs/block.stub index 4c4002c9..76e30013 100644 --- a/src/Console/stubs/block.stub +++ b/src/Console/stubs/block.stub @@ -19,14 +19,14 @@ class DummyClass extends Block * * @var string */ - public $description = 'A simple DummyTitle block.'; + public $description = 'DummyDescription'; /** * The block category. * * @var string */ - public $category = 'formatting'; + public $category = 'DummyCategory'; /** * The block icon. @@ -47,7 +47,7 @@ class DummyClass extends Block * * @var array */ - public $post_types = []; + public $post_types = [DummyPostTypes]; /** * The parent block type allow list. @@ -97,19 +97,7 @@ class DummyClass extends Block * @var array */ public $supports = [ - 'align' => true, - 'align_text' => false, - 'align_content' => false, - 'full_height' => false, - 'anchor' => false, - 'mode' => false, - 'multiple' => true, - 'jsx' => true, - 'color' => [ - 'background' => true, - 'text' => true, - 'gradient' => true, - ], + DummySupports ]; /** diff --git a/src/Console/stubs/widget.stub b/src/Console/stubs/widget.stub index 947c83f4..35c47385 100644 --- a/src/Console/stubs/widget.stub +++ b/src/Console/stubs/widget.stub @@ -19,7 +19,7 @@ class DummyClass extends Widget * * @var string */ - public $description = 'This is a DummyTitle widget.'; + public $description = 'DummyDescription'; /** * Data to be passed to the widget before rendering.