Skip to content

Commit

Permalink
Refactor and improve list of available blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
Tofandel committed Mar 1, 2024
1 parent ce0fbf1 commit 43847c8
Show file tree
Hide file tree
Showing 15 changed files with 315 additions and 88 deletions.
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
11 changes: 11 additions & 0 deletions src/Facades/TwillBlocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@

namespace A17\Twill\Facades;

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

/**
* @method static void globallyExcludeBlocks(array|callable $blocks)
* @method static array getGloballyExcludedBlocks
* @method static Collection<Block>getBlocks
* @method static Collection<Block>getSettingsBlocks
* @method static Collection<Block>getRepeaters
* @method static registerManualBlock(string $blockClass, string $source = Block::SOURCE_APP)
* @method static Collection<Block>generateListOfAvailableBlocks(?array $blocks = null, ?array $groups = null, bool $settingsOnly = false, array|callable $excludeBlocks = [])
*/
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
2 changes: 2 additions & 0 deletions src/Http/Controllers/Admin/ModuleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace A17\Twill\Http\Controllers\Admin;

use A17\Twill\Exceptions\NoCapsuleFoundException;
use A17\Twill\Facades\TwillBlocks;
use A17\Twill\Facades\TwillCapsules;
use A17\Twill\Facades\TwillPermissions;
use A17\Twill\Helpers\FlashLevel;
Expand Down Expand Up @@ -2261,6 +2262,7 @@ protected function form(?int $id, ?TwillModelContract $item = null): array
'translateTitle' => $this->titleIsTranslatable(),
'permalink' => $this->getIndexOption('permalink', $item),
'createWithoutModal' => ! $itemId && $this->getIndexOption('skipCreateModal'),
'allBlocks' => TwillBlocks::generateListOfAllBlocks()->keyBy('name'),
'form_fields' => $this->repository->getFormFields($item),
'baseUrl' => $baseUrl,
'localizedPermalinkBase' => $localizedPermalinkBase,
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())) {
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
13 changes: 9 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 Expand Up @@ -206,6 +206,11 @@ public function newInstance(): static
);
}

public function getPosition(): float|int|string
{
return $this->componentClass && is_callable([$this->componentClass, 'getPosition']) ? $this->componentClass::getPosition() : 0;
}

/**
* Gets the first match being a block or repeater.
*/
Expand Down
28 changes: 26 additions & 2 deletions src/Services/Forms/Fields/BlockEditor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

namespace A17\Twill\Services\Forms\Fields;

use A17\Twill\Services\Blocks\Block;

class BlockEditor extends BaseFormField
{
protected array $blocks = [];
protected array $groups = [];

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

protected bool $isSettings = false;

Expand Down Expand Up @@ -48,15 +51,36 @@ public function isSettings(bool $isSettings = true): static
*/
public function blocks(array $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 getBlocks(): array
{
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

0 comments on commit 43847c8

Please sign in to comment.