Skip to content

Commit 43847c8

Browse files
committed
Refactor and improve list of available blocks
1 parent ce0fbf1 commit 43847c8

File tree

15 files changed

+315
-88
lines changed

15 files changed

+315
-88
lines changed

frontend/js/store/modules/blocks.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,15 @@ const state = {
3030
*/
3131
editorNames: window[process.env.VUE_APP_NAME].STORE.form.editorNames || [],
3232
/**
33-
* An object with all the blocks available to add
33+
* An object with all the blocks name available to add keyed by availibityId
3434
* @type {Object}
3535
*/
3636
available: window[process.env.VUE_APP_NAME].STORE.form.availableBlocks || {},
37+
/**
38+
* An object with all the blocks available to add
39+
* @type {Object}
40+
*/
41+
allAvailable: window[process.env.VUE_APP_NAME].STORE.form.allAvailableBlocks || {},
3742
/**
3843
* An array with all the blocks created
3944
* @type {Object.Array}
@@ -55,7 +60,7 @@ const state = {
5560
const getters = {
5661
previewsById: state => (id) => state.previews[id] ? state.previews[id] : '',
5762
blocks: state => editorName => state.blocks[editorName] || [],
58-
availableBlocks: state => editorName => state.available[editorName] || [],
63+
availableBlocks: state => editorName => state.available[editorName] && state.available[editorName].length ? state.available[editorName].map((k) => state.allAvailable[k]) : [],
5964
blockIndex: (state, getters) => (block, editorName) => getters.blocks(editorName).findIndex(b => b.id === block.id)
6065
}
6166

src/Facades/TwillBlocks.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,19 @@
22

33
namespace A17\Twill\Facades;
44

5+
use A17\Twill\Services\Blocks\Block;
6+
use Illuminate\Support\Collection;
57
use Illuminate\Support\Facades\Facade;
68

9+
/**
10+
* @method static void globallyExcludeBlocks(array|callable $blocks)
11+
* @method static array getGloballyExcludedBlocks
12+
* @method static Collection<Block>getBlocks
13+
* @method static Collection<Block>getSettingsBlocks
14+
* @method static Collection<Block>getRepeaters
15+
* @method static registerManualBlock(string $blockClass, string $source = Block::SOURCE_APP)
16+
* @method static Collection<Block>generateListOfAvailableBlocks(?array $blocks = null, ?array $groups = null, bool $settingsOnly = false, array|callable $excludeBlocks = [])
17+
*/
718
class TwillBlocks extends Facade
819
{
920
protected static function getFacadeAccessor(): string

src/Facades/TwillCapsules.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22

33
namespace A17\Twill\Facades;
44

5+
use A17\Twill\Helpers\Capsule;
56
use Illuminate\Support\Facades\Facade;
67

8+
/**
9+
* @method static string capsuleNamespace(string $capsuleName, string $type = null)
10+
* @method static string capsuleNamespaceToPath(string $namespace, string $capsuleNamespace, string $rootPath)
11+
* @method static Capsule registerPackageCapsule(string $name, string $namespace, string $path, string $singular = null, bool $enabled = true, bool $automaticNavigation = true)
12+
*/
713
class TwillCapsules extends Facade
814
{
915
protected static function getFacadeAccessor(): string

src/Helpers/Capsule.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public function __construct(
3030
protected bool $automaticNavigation = true
3131
) {
3232
$this->boot();
33+
$this->singular = $this->singular ?? Str::singular($this->name);
3334
}
3435

3536
public function boot(): void
@@ -128,7 +129,7 @@ public function getPlural(): string
128129

129130
public function getSingular(): string
130131
{
131-
return $this->singular ?? Str::singular($this->name);
132+
return $this->singular;
132133
}
133134

134135
public function getBaseNamespace(): string

src/Helpers/helpers.php

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -219,56 +219,14 @@ function twillModel($model): string
219219

220220
if (! function_exists('generate_list_of_available_blocks')) {
221221
/**
222-
* @param array $blocks
223-
* @param array $groups
224-
* @return array
222+
* TODO remove in v4
223+
* @deprecated use TwillBlocks::generateListOfAvailableBlocks instead
225224
*/
226-
function generate_list_of_available_blocks($blocks, $groups, bool $settingsOnly = false, array $excludeBlocks = []): array
225+
function generate_list_of_available_blocks(?array $blocks = null, ?array $groups = null, bool $settingsOnly = false, array|callable $excludeBlocks = []): array
227226
{
228-
if ($settingsOnly) {
229-
$blockList = TwillBlocks::getSettingsBlocks();
230-
} else {
231-
$blockList = TwillBlocks::getBlocks();
232-
}
233-
234-
$appBlocksList = $blockList->filter(function (Block $block) {
235-
return $block->source !== A17\Twill\Services\Blocks\Block::SOURCE_TWILL;
236-
});
237-
238-
$finalBlockList = $blockList->filter(
239-
function (Block $block) use ($blocks, $groups, $appBlocksList, $excludeBlocks) {
240-
if ($block->group === A17\Twill\Services\Blocks\Block::SOURCE_TWILL) {
241-
if (! collect(config('twill.block_editor.use_twill_blocks'))->contains($block->name)) {
242-
return false;
243-
}
244-
245-
/** @var \Illuminate\Support\Collection<Block> $appBlocksList */
246-
if (
247-
count($appBlocksList) > 0 && $appBlocksList->contains(
248-
function ($appBlock) use ($block) {
249-
return $appBlock->name === $block->name;
250-
}
251-
)
252-
) {
253-
return false;
254-
}
255-
}
256-
257-
if (in_array($block->name, $excludeBlocks)) {
258-
return false;
259-
}
260-
261-
return (filled($blocks) ? collect($blocks)->contains($block->name) || collect($blocks)->contains(ltrim($block->componentClass, '\\')) : true)
262-
&& (filled($groups) ? collect($groups)->contains($block->group) : true);
263-
}
264-
);
227+
trigger_deprecation('area17/twill', '3.3', __FUNCTION__ . ' is deprecated and will be removed in 4.x, use TwillBlocks::generateListOfAvailableBlocks instead');
265228

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

src/Http/Controllers/Admin/ModuleController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace A17\Twill\Http\Controllers\Admin;
44

55
use A17\Twill\Exceptions\NoCapsuleFoundException;
6+
use A17\Twill\Facades\TwillBlocks;
67
use A17\Twill\Facades\TwillCapsules;
78
use A17\Twill\Facades\TwillPermissions;
89
use A17\Twill\Helpers\FlashLevel;
@@ -2261,6 +2262,7 @@ protected function form(?int $id, ?TwillModelContract $item = null): array
22612262
'translateTitle' => $this->titleIsTranslatable(),
22622263
'permalink' => $this->getIndexOption('permalink', $item),
22632264
'createWithoutModal' => ! $itemId && $this->getIndexOption('skipCreateModal'),
2265+
'allBlocks' => TwillBlocks::generateListOfAllBlocks()->keyBy('name'),
22642266
'form_fields' => $this->repository->getFormFields($item),
22652267
'baseUrl' => $baseUrl,
22662268
'localizedPermalinkBase' => $localizedPermalinkBase,

src/Http/Requests/Admin/Request.php

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ protected function rulesForTranslatedFields(array $existingRules, array $transla
8484
* @param bool $localeActive
8585
* @return array
8686
*/
87-
private function updateRules($rules, $fields, $locale, $localeActive = true)
87+
private function updateRules($rules, $fields, $locale, $localeActive = true): array
8888
{
8989
$fieldNames = array_keys($fields);
9090

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

96-
$fieldRules = Collection::make($fieldRules);
96+
$fieldRules = collect($fieldRules);
9797

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

104-
$fieldRules = $fieldRules->reject(function ($rule) {
105-
return $this->ruleStartsWith($rule, 'required');
106-
});
107-
108-
// @TODO: Can be replaced with doesntContain in twill 3.x
109-
if ($hasRequiredRule && !in_array($fieldRules, $fieldRules->toArray())) {
102+
if (!$fieldRules->contains(fn ($rule) => $this->ruleStartsWith($rule, 'nullable'))) {
110103
$fieldRules->add('nullable');
111104
}
112105
}
113106

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

122115
return $rule;
123-
})->toArray();
116+
})->all();
124117
}
125118

126119
return $rules;

src/Services/Blocks/Block.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,19 @@ class Block
143143
public ?InlineRepeater $inlineRepeater = null;
144144

145145
/**
146-
* @param TwillBlockComponent $componentClass
146+
* @param class-string<TwillBlockComponent> $componentClass
147147
*/
148-
public static function forComponent(string $componentClass): self
148+
public static function forComponent(string $componentClass, string $source = self::SOURCE_APP): self
149149
{
150150
$class = new self(
151151
file: null,
152152
type: 'block',
153-
source: $componentClass::getBlockGroup(),
153+
source: $source,
154154
name: $componentClass::getBlockIdentifier(),
155155
componentClass: $componentClass
156156
);
157157

158+
$class->group = $componentClass::getBlockGroup();
158159
$class->title = $componentClass::getBlockTitle();
159160
$class->icon = $componentClass::getBlockIcon();
160161
$class->titleField = $componentClass::getBlockTitleField();
@@ -172,7 +173,6 @@ public static function forComponent(string $componentClass): self
172173
* @param $type
173174
* @param $source
174175
* @param $name
175-
* @param string $renderNamespace
176176
* Mainly for packages, but this will get the preview/render view file from that namespace.
177177
* @return static
178178
*/
@@ -206,6 +206,11 @@ public function newInstance(): static
206206
);
207207
}
208208

209+
public function getPosition(): float|int|string
210+
{
211+
return $this->componentClass && is_callable([$this->componentClass, 'getPosition']) ? $this->componentClass::getPosition() : 0;
212+
}
213+
209214
/**
210215
* Gets the first match being a block or repeater.
211216
*/

src/Services/Forms/Fields/BlockEditor.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
namespace A17\Twill\Services\Forms\Fields;
44

5+
use A17\Twill\Services\Blocks\Block;
6+
57
class BlockEditor extends BaseFormField
68
{
79
protected array $blocks = [];
10+
protected array $groups = [];
811

9-
protected array $excludeBlocks = [];
12+
protected mixed $excludeBlocks = [];
1013

1114
protected bool $isSettings = false;
1215

@@ -48,15 +51,36 @@ public function isSettings(bool $isSettings = true): static
4851
*/
4952
public function blocks(array $blocks): static
5053
{
54+
// For backward compatibility, clear the list of excludeBlocks in case both ->excludeBlocks()->blocks() were called
55+
$this->excludeBlocks = [];
5156
$this->blocks = $blocks;
5257

5358
return $this;
5459
}
5560

61+
public function getBlocks(): array
62+
{
63+
return $this->blocks;
64+
}
65+
66+
public function groups(array $groups)
67+
{
68+
$this->groups = $groups;
69+
70+
return $this;
71+
}
72+
73+
public function getGroups(): array
74+
{
75+
return $this->groups;
76+
}
77+
5678
/**
5779
* Use this method if you want to exclude any block types
80+
*
81+
* @param array<string>|callable<Block> $blocks
5882
*/
59-
public function excludeBlocks(array $blocks): static
83+
public function excludeBlocks(array|callable $blocks): static
6084
{
6185
$this->excludeBlocks = $blocks;
6286

0 commit comments

Comments
 (0)