Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and improve list of available blocks #2513

Open
wants to merge 20 commits into
base: 3.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions config/block_editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,11 @@
'repeaters' => resource_path('views/twill/repeaters'),
],
],
'blocks' => [],
'block_rules' => [
// List of block identifiers to globally disallow
'disable' => [],
// List of block identifiers to order blocks by if no order is provided
'order' => [],
]
];
9 changes: 7 additions & 2 deletions frontend/js/store/modules/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ const state = {
*/
editorNames: window[process.env.VUE_APP_NAME].STORE.form.editorNames || [],
/**
* An object with all the blocks available to add
* An object with all the blocks name available to add keyed by availibityId
* @type {Object}
*/
available: window[process.env.VUE_APP_NAME].STORE.form.availableBlocks || {},
/**
* An object with all the blocks available to add
* @type {Object}
*/
allAvailable: window[process.env.VUE_APP_NAME].STORE.form.allAvailableBlocks || {},
/**
* An array with all the blocks created
* @type {Object.Array}
Expand All @@ -55,7 +60,7 @@ const state = {
const getters = {
previewsById: state => (id) => state.previews[id] ? state.previews[id] : '',
blocks: state => editorName => state.blocks[editorName] || [],
availableBlocks: state => editorName => state.available[editorName] || [],
availableBlocks: state => editorName => state.available[editorName] && state.available[editorName].length ? state.available[editorName].map((k) => state.allAvailable[k]) : [],
blockIndex: (state, getters) => (block, editorName) => getters.blocks(editorName).findIndex(b => b.id === block.id)
}

Expand Down
16 changes: 16 additions & 0 deletions src/Facades/TwillBlocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,24 @@

namespace A17\Twill\Facades;

use A17\Twill\Services\Blocks\Block;
use A17\Twill\Services\Blocks\BlockCollection;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Facade;

/**
* @method static void globallyExcludeBlocks(array|callable $blocks)
* @method static array getGloballyExcludedBlocks
* @method static void setGloballyExcludedBlocks(array $exclude = [])
* @method static Collection<Block>getBlocks
* @method static BlockCollection getBlockCollection
* @method static Collection<Block>getSettingsBlocks
* @method static Collection<Block>getRepeaters
* @method static registerManualBlock(string $blockClass, string $source = Block::SOURCE_APP)
* @method static Collection<Block>generateListOfAllBlocks(bool $settingsOnly = false)
* @method static Collection<Block>getListOfUsedBlocks()
* @method static Collection<Block>generateListOfAvailableBlocks(array|callable $blocks = null, ?array $groups = null, bool $settingsOnly = false, array|callable $excludeBlocks = null, bool $defaultOrder = false)
*/
class TwillBlocks extends Facade
{
protected static function getFacadeAccessor(): string
Expand Down
6 changes: 6 additions & 0 deletions src/Facades/TwillCapsules.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

namespace A17\Twill\Facades;

use A17\Twill\Helpers\Capsule;
use Illuminate\Support\Facades\Facade;

/**
* @method static string capsuleNamespace(string $capsuleName, string $type = null)
* @method static string capsuleNamespaceToPath(string $namespace, string $capsuleNamespace, string $rootPath)
* @method static Capsule registerPackageCapsule(string $name, string $namespace, string $path, string $singular = null, bool $enabled = true, bool $automaticNavigation = true)
*/
class TwillCapsules extends Facade
{
protected static function getFacadeAccessor(): string
Expand Down
3 changes: 2 additions & 1 deletion src/Helpers/Capsule.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public function __construct(
protected bool $automaticNavigation = true
) {
$this->boot();
$this->singular = $this->singular ?? Str::singular($this->name);
}

public function boot(): void
Expand Down Expand Up @@ -128,7 +129,7 @@ public function getPlural(): string

public function getSingular(): string
{
return $this->singular ?? Str::singular($this->name);
return $this->singular;
}

public function getBaseNamespace(): string
Expand Down
52 changes: 5 additions & 47 deletions src/Helpers/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,56 +219,14 @@ function twillModel($model): string

if (! function_exists('generate_list_of_available_blocks')) {
/**
* @param array $blocks
* @param array $groups
* @return array
* TODO remove in v4
* @deprecated use TwillBlocks::generateListOfAvailableBlocks instead
*/
function generate_list_of_available_blocks($blocks, $groups, bool $settingsOnly = false, array $excludeBlocks = []): array
function generate_list_of_available_blocks(?array $blocks = null, ?array $groups = null, bool $settingsOnly = false, array|callable $excludeBlocks = []): array
{
if ($settingsOnly) {
$blockList = TwillBlocks::getSettingsBlocks();
} else {
$blockList = TwillBlocks::getBlocks();
}

$appBlocksList = $blockList->filter(function (Block $block) {
return $block->source !== A17\Twill\Services\Blocks\Block::SOURCE_TWILL;
});

$finalBlockList = $blockList->filter(
function (Block $block) use ($blocks, $groups, $appBlocksList, $excludeBlocks) {
if ($block->group === A17\Twill\Services\Blocks\Block::SOURCE_TWILL) {
if (! collect(config('twill.block_editor.use_twill_blocks'))->contains($block->name)) {
return false;
}

/** @var \Illuminate\Support\Collection<Block> $appBlocksList */
if (
count($appBlocksList) > 0 && $appBlocksList->contains(
function ($appBlock) use ($block) {
return $appBlock->name === $block->name;
}
)
) {
return false;
}
}

if (in_array($block->name, $excludeBlocks)) {
return false;
}

return (filled($blocks) ? collect($blocks)->contains($block->name) || collect($blocks)->contains(ltrim($block->componentClass, '\\')) : true)
&& (filled($groups) ? collect($groups)->contains($block->group) : true);
}
);
trigger_deprecation('area17/twill', '3.3', __FUNCTION__ . ' is deprecated and will be removed in 4.x, use TwillBlocks::generateListOfAvailableBlocks instead');

// Sort them by the original definition
return $finalBlockList->sortBy(function (Block $b) use ($blocks) {
return collect($blocks)->search(function ($id, $key) use ($b) {
return $id == $b->name || $id == ltrim($b->componentClass, '\\');
});
})->values()->toArray();
return TwillBlocks::generateListOfAvailableBlocks($blocks, $groups, $settingsOnly, $excludeBlocks)->all();
}
}

Expand Down
21 changes: 7 additions & 14 deletions src/Http/Requests/Admin/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ protected function rulesForTranslatedFields(array $existingRules, array $transla
* @param bool $localeActive
* @return array
*/
private function updateRules($rules, $fields, $locale, $localeActive = true)
private function updateRules($rules, $fields, $locale, $localeActive = true): array
{
$fieldNames = array_keys($fields);

Expand All @@ -93,25 +93,18 @@ private function updateRules($rules, $fields, $locale, $localeActive = true)
$fieldRules = explode('|', $fieldRules);
}

$fieldRules = Collection::make($fieldRules);
$fieldRules = collect($fieldRules);

// Remove required rules, when locale is not active
// Remove required rules and add nullable rules, when locale is not active
if (! $localeActive) {
$hasRequiredRule = $fieldRules->contains(function ($rule) {
return $this->ruleStartsWith($rule, 'required');
});
$fieldRules = $fieldRules->reject(fn ($rule) => $this->ruleStartsWith($rule, 'required'));

$fieldRules = $fieldRules->reject(function ($rule) {
return $this->ruleStartsWith($rule, 'required');
});

// @TODO: Can be replaced with doesntContain in twill 3.x
if ($hasRequiredRule && !in_array($fieldRules, $fieldRules->toArray())) {
Copy link
Contributor Author

@Tofandel Tofandel Mar 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is meant for a different PR, but if you're okay with it we can leave it in direclty as well, I was just chasing bugs and I stumbled accross
!in_array($fieldRules, $fieldRules->toArray()) which is very weird and also always true

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This used to be a check against 'nullable', see 315082b#diff-0408ed612a5dd9175dea4ee82126a50940e6809907eae490aa1abf94e10a9986R94 and it looks like it was wrongly replaced during another change.

I'm fine with keeping this in this PR.

if (!$fieldRules->contains(fn ($rule) => $this->ruleStartsWith($rule, 'nullable'))) {
$fieldRules->add('nullable');
}
}

$rules["{$field}.{$locale}"] = $fieldRules->map(function ($rule) use ($locale, $fieldNames) {
$rules["$field.$locale"] = $fieldRules->map(function ($rule) use ($locale, $fieldNames) {
// allows using validation rule that references other fields even for translated fields
if ($this->ruleStartsWith($rule, 'required_') && Str::contains($rule, $fieldNames)) {
foreach ($fieldNames as $fieldName) {
Expand All @@ -120,7 +113,7 @@ private function updateRules($rules, $fields, $locale, $localeActive = true)
}

return $rule;
})->toArray();
})->all();
}

return $rules;
Expand Down
8 changes: 4 additions & 4 deletions src/Services/Blocks/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,18 +143,19 @@ class Block
public ?InlineRepeater $inlineRepeater = null;

/**
* @param TwillBlockComponent $componentClass
* @param class-string<TwillBlockComponent> $componentClass
*/
public static function forComponent(string $componentClass): self
public static function forComponent(string $componentClass, string $source = self::SOURCE_APP): self
{
$class = new self(
file: null,
type: 'block',
source: $componentClass::getBlockGroup(),
source: $source,
name: $componentClass::getBlockIdentifier(),
componentClass: $componentClass
);

$class->group = $componentClass::getBlockGroup();
$class->title = $componentClass::getBlockTitle();
$class->icon = $componentClass::getBlockIcon();
$class->titleField = $componentClass::getBlockTitleField();
Expand All @@ -172,7 +173,6 @@ public static function forComponent(string $componentClass): self
* @param $type
* @param $source
* @param $name
* @param string $renderNamespace
* Mainly for packages, but this will get the preview/render view file from that namespace.
* @return static
*/
Expand Down
3 changes: 0 additions & 3 deletions src/Services/Forms/Fields/BaseFormField.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ abstract class BaseFormField implements CanRenderForBlocks
{
use RenderForBlocks;

/**
* @var \A17\Twill\View\Components\Fields\TwillFormComponent
*/
protected function __construct(
protected string $component,
protected ?string $name = null,
Expand Down
41 changes: 37 additions & 4 deletions src/Services/Forms/Fields/BlockEditor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@

namespace A17\Twill\Services\Forms\Fields;

use A17\Twill\Services\Blocks\Block;

class BlockEditor extends BaseFormField
{
protected array $blocks = [];
/** @var callable|array */
protected mixed $blocks = [];
protected array $groups = [];

protected array $excludeBlocks = [];
protected mixed $excludeBlocks = null;

protected bool $isSettings = false;

protected bool $withoutSeparator = false;
protected bool $usingDefaultOrder = false;

public static function make(): static
{
Expand Down Expand Up @@ -46,17 +51,45 @@ public function isSettings(bool $isSettings = true): static
/**
* Default is all, but using this method you can limit the block types the field can use.
*/
public function blocks(array $blocks): static
public function blocks(array|callable $blocks): static
{
// For backward compatibility, clear the list of excludeBlocks in case both ->excludeBlocks()->blocks() were called
$this->excludeBlocks = [];
$this->blocks = $blocks;

return $this;
}

public function usingDefaultOrder(bool $usingDefaultOrder = true): static
{
$this->usingDefaultOrder = $usingDefaultOrder;

return $this;
}

public function getBlocks(): mixed
{
return $this->blocks;
}

public function groups(array $groups)
{
$this->groups = $groups;

return $this;
}

public function getGroups(): array
{
return $this->groups;
}

/**
* Use this method if you want to exclude any block types
*
* @param array<string>|callable<Block> $blocks
*/
public function excludeBlocks(array $blocks): static
public function excludeBlocks(array|callable $blocks): static
{
$this->excludeBlocks = $blocks;

Expand Down
Loading
Loading