Skip to content

Commit

Permalink
🧑‍💻 Improve Composer console generation (#278)
Browse files Browse the repository at this point in the history
  • Loading branch information
Log1x authored Oct 24, 2024
2 parents 1ae59bb + f687925 commit 5b25b6b
Show file tree
Hide file tree
Showing 10 changed files with 373 additions and 135 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,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.
Expand Down
14 changes: 14 additions & 0 deletions config/acf.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 20 additions & 4 deletions src/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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,
Expand Down
118 changes: 115 additions & 3 deletions src/Console/BlockMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
/**
Expand All @@ -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}';

/**
Expand All @@ -34,15 +40,121 @@ 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.
*
* @return string
*/
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');
Expand Down
5 changes: 4 additions & 1 deletion src/Console/MakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,10 @@ protected function createView()
*/
protected function summary()
{
$this->line('');
if (! Str::contains($this->type, ['Block', 'Widget'])) {
$this->newLine();
}

$this->line("🎉 <fg=blue;options=bold>{$this->getNameInput()}</> {$this->getType()} successfully composed.");
$this->line(" ⮑ <fg=blue>{$this->shortenPath($this->path)}</>");

Expand Down
29 changes: 29 additions & 0 deletions src/Console/WidgetMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace Log1x\AcfComposer\Console;

use Illuminate\Support\Str;

use function Laravel\Prompts\text;

class WidgetMakeCommand extends MakeCommand
{
/**
Expand Down Expand Up @@ -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.
*
Expand Down
108 changes: 0 additions & 108 deletions src/Console/stubs/block.construct.stub

This file was deleted.

Loading

0 comments on commit 5b25b6b

Please sign in to comment.