Skip to content

Commit acb782e

Browse files
committed
feat: optimize preview rendering to only process changed blocks
1 parent eb18a6a commit acb782e

File tree

4 files changed

+95
-35
lines changed

4 files changed

+95
-35
lines changed

src/Http/Controllers/Admin/ThemeEditorController.php

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function index($themeCode)
4444
'config' => [
4545
'baseUrl' => parse_url(route('visual.admin.editor', ['theme' => $themeCode]), PHP_URL_PATH),
4646
'imagesBaseUrl' => Storage::disk(config('bagisto_visual.images_storage'))->url(''),
47-
'storefrontUrl' => url('/').'?'.http_build_query(['_designMode' => $themeCode]),
47+
'storefrontUrl' => url('/') . '?' . http_build_query(['_designMode' => $themeCode]),
4848
'channels' => $this->getChannels(),
4949
'defaultChannel' => core()->getDefaultChannelCode(),
5050
'blockSchemas' => $this->loadBlocks(),
@@ -87,11 +87,17 @@ public function persistUpdates(Request $request)
8787
'updates.regions' => ['present', 'array'],
8888
]);
8989

90-
$this->persistEditorUpdates->handle($validated);
90+
$result = $this->persistEditorUpdates->handle($validated);
91+
$loadedBlocks = $result['loadedBlocks'] ?? [];
92+
93+
$changedBlockIds = $this->extractChangedBlockIds(
94+
$validated['updates'],
95+
$loadedBlocks
96+
);
9197

9298
$url = $request->input('template.url');
9399

94-
return $this->renderPreview->execute($url);
100+
return $this->renderPreview->execute($url, $changedBlockIds);
95101
}
96102

97103
public function persistThemeSettings(Request $request)
@@ -134,7 +140,7 @@ public function uploadImages(Request $request)
134140
return $images->map(function ($image) {
135141
$originalName = pathinfo($image->getClientOriginalName(), PATHINFO_FILENAME);
136142
$extension = $image->guessExtension();
137-
$storedName = bin2hex($originalName).'_'.uniqid().'.'.$extension;
143+
$storedName = bin2hex($originalName) . '_' . uniqid() . '.' . $extension;
138144

139145
$path = $image->storeAs(
140146
config('bagisto_visual.images_directory'),
@@ -209,15 +215,15 @@ public function icons(Request $request, Factory $factory, IconsManifest $iconsMa
209215

210216
$icons->push([
211217
'name' => $name,
212-
'id' => $set['prefix'].'-'.$name,
218+
'id' => $set['prefix'] . '-' . $name,
213219
'svg' => File::get($file->getRealPath()),
214220
]);
215221
}
216222
}
217223

218224
return [
219225
'currentSet' => $selectedSet,
220-
'sets' => collect($sets)->map(fn ($set, $key) => ['id' => $key, 'prefix' => $set['prefix'], 'name' => Str::headline($key)])->values(),
226+
'sets' => collect($sets)->map(fn($set, $key) => ['id' => $key, 'prefix' => $set['prefix'], 'name' => Str::headline($key)])->values(),
221227
'icons' => $icons->values(),
222228
];
223229
}
@@ -260,7 +266,7 @@ protected function loadBlocks()
260266
'category' => $blockSchema->category,
261267
'description' => $blockSchema->description,
262268
'previewImageUrl' => asset($blockSchema->previewImageUrl),
263-
'isSection' => collect([SimpleSection::class, BladeSection::class, LivewireSection::class])->some(fn ($class) => is_subclass_of($blockSchema->class, $class)),
269+
'isSection' => collect([SimpleSection::class, BladeSection::class, LivewireSection::class])->some(fn($class) => is_subclass_of($blockSchema->class, $class)),
264270
'enabledOn' => $blockSchema->enabledOn ?? [],
265271
'disabledOn' => $blockSchema->disabledOn ?? [],
266272
],
@@ -292,7 +298,7 @@ protected function loadTheme($themeCode)
292298
protected function loadTemplates()
293299
{
294300
return collect(app(\BagistoPlus\Visual\ThemeEditor::class)->getTemplates())
295-
->map(fn ($template) => [
301+
->map(fn($template) => [
296302
'template' => $template->template,
297303
'label' => $template->label,
298304
'icon' => $template->icon,
@@ -329,7 +335,7 @@ protected function translateSettingsSchema(array $settingsSchema): array
329335

330336
protected function getChannels()
331337
{
332-
return core()->getAllChannels()->map(fn ($channel) => [
338+
return core()->getAllChannels()->map(fn($channel) => [
333339
'code' => $channel->code,
334340
'name' => $channel->name,
335341
'locales' => $channel->locales,
@@ -340,7 +346,7 @@ protected function getChannels()
340346
protected function getChannelCodes(): array
341347
{
342348
return $this->getChannels()
343-
->map(fn ($channel) => $channel['code'])
349+
->map(fn($channel) => $channel['code'])
344350
->toArray();
345351
}
346352

@@ -352,14 +358,48 @@ protected function getLocaleCodes(string $channel): array
352358
return [];
353359
}
354360

355-
return $channel['locales']->map(fn ($locale) => $locale['code'])->toArray();
361+
return $channel['locales']->map(fn($locale) => $locale['code'])->toArray();
356362
}
357363

358364
protected function getVisualThemes(): array
359365
{
360366
return collect(config('themes.shop', []))
361-
->filter(fn ($config) => $config['visual_theme'] ?? false)
362-
->map(fn ($config) => $config['code'])
367+
->filter(fn($config) => $config['visual_theme'] ?? false)
368+
->map(fn($config) => $config['code'])
363369
->toArray();
364370
}
371+
372+
/**
373+
* Extract changed block IDs from updates and include all parent blocks.
374+
*/
375+
protected function extractChangedBlockIds(array $updates, array $loadedBlocks): array
376+
{
377+
$changes = $updates['changes'] ?? [];
378+
379+
$changedIds = array_merge($changes['added'] ?? [], $changes['updated'] ?? []);
380+
381+
return $this->includeParentBlocks($changedIds, $loadedBlocks);
382+
}
383+
384+
/**
385+
* Include all parent blocks for the given block IDs.
386+
*/
387+
protected function includeParentBlocks(array $blockIds, array $loadedBlocks): array
388+
{
389+
$result = [];
390+
391+
foreach ($blockIds as $id) {
392+
$result[] = $id;
393+
394+
// Walk up the parent chain using parentId
395+
$currentId = $id;
396+
while (isset($loadedBlocks[$currentId]['parentId']) && $loadedBlocks[$currentId]['parentId'] !== null) {
397+
$parentId = $loadedBlocks[$currentId]['parentId'];
398+
$result[] = $parentId;
399+
$currentId = $parentId;
400+
}
401+
}
402+
403+
return array_unique($result);
404+
}
365405
}

src/Persistence/PersistEditorUpdates.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public function handle(array $data): array
2222
$sources = decrypt($data['template']['sources']);
2323
$updateRequest = UpdateRequest::make($data['updates']);
2424

25-
$sharedRegions = collect($updateRequest->regions)->filter(fn ($region) => isset($region['shared']) && $region['shared'] === true);
26-
$nonSharedRegions = collect($updateRequest->regions)->filter(fn ($region) => ! isset($region['shared']) || $region['shared'] === false);
25+
$sharedRegions = collect($updateRequest->regions)->filter(fn($region) => isset($region['shared']) && $region['shared'] === true);
26+
$nonSharedRegions = collect($updateRequest->regions)->filter(fn($region) => ! isset($region['shared']) || $region['shared'] === false);
2727

2828
$allBlocks = [];
2929

@@ -132,12 +132,12 @@ protected function getRegionFilePath(string $theme, string $channel, string $loc
132132
protected function getRegionSourcePath(string $regionName, array $sources): ?string
133133
{
134134
return collect($sources)
135-
->first(fn ($sourcePath) => str_contains($sourcePath, "/regions/{$regionName}."));
135+
->first(fn($sourcePath) => str_contains($sourcePath, "/regions/{$regionName}."));
136136
}
137137

138138
protected function getTemplateSourcePath(string $template, array $sources): ?string
139139
{
140140
return collect($sources)
141-
->first(fn ($sourcePath) => str_contains($sourcePath, "/templates/{$template}."));
141+
->first(fn($sourcePath) => str_contains($sourcePath, "/templates/{$template}."));
142142
}
143143
}

src/Persistence/RenderPreview.php

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,26 @@ class RenderPreview
1111
{
1212
/**
1313
* Render a preview by making a sub-request with design mode enabled.
14+
*
15+
* @param string $url The URL to render
16+
* @param array|null $blockIds Optional array of block IDs to render (null = render all)
1417
*/
15-
public function execute(string $url): string
18+
public function execute(string $url, ?array $blockIds = null): string
1619
{
20+
$baseUrl = rtrim(config('app.url'));
21+
$basePath = parse_url($baseUrl, PHP_URL_PATH);
22+
23+
// Handle subdirectory installs by redirecting
24+
if ($basePath !== null) {
25+
return redirect($url);
26+
}
27+
28+
// Append _blocks query parameter if specific blocks are requested
29+
if ($blockIds !== null && count($blockIds) > 0) {
30+
$separator = str_contains($url, '?') ? '&' : '?';
31+
$url .= $separator.'_blocks='.implode(',', $blockIds);
32+
}
33+
1734
// Reset Craftile's preview mode cache before sub-request
1835
Craftile::detectPreviewUsing(function () {
1936
return \BagistoPlus\Visual\Facades\ThemeEditor::inDesignMode();
@@ -22,14 +39,6 @@ public function execute(string $url): string
2239
app(JsonViewParser::class)->clearCache();
2340
app(ThemeSettingsLoader::class)->clearCache();
2441

25-
// Handle subdirectory installs by redirecting
26-
$baseUrl = rtrim(config('app.url'));
27-
$basePath = parse_url($baseUrl, PHP_URL_PATH);
28-
29-
if ($basePath !== null) {
30-
return redirect($url);
31-
}
32-
3342
$request = Request::create($url, 'GET');
3443
$response = app()->handle($request);
3544

src/Providers/CoreServiceProvider.php

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use BagistoPlus\Visual\Commands;
66
use BagistoPlus\Visual\Components\Svg;
7+
use BagistoPlus\Visual\Data\BlockData;
78
use BagistoPlus\Visual\Facades\ThemeEditor;
89
use BagistoPlus\Visual\Facades\Visual;
910
use BagistoPlus\Visual\Middlewares\DisableResponseCacheInDesignMode;
@@ -103,6 +104,16 @@ protected function bootCraftile(): void
103104

104105
Craftile::normalizeTemplateUsing(new \BagistoPlus\Visual\Support\TemplateNormalizer);
105106

107+
Craftile::checkIfBlockCanRenderUsing(function (BlockData $blockData) {
108+
if (ThemeEditor::inDesignMode() && request()->has('_blocks')) {
109+
$blocksToRender = explode(',', request()->query('_blocks'));
110+
111+
return in_array($blockData->id, $blocksToRender);
112+
}
113+
114+
return ! $blockData->disabled;
115+
});
116+
106117
$this->registerPropertyTransformers();
107118
$this->registerBlockCompilers();
108119
}
@@ -138,7 +149,7 @@ protected function registerBlockCompilers(): void
138149
// Register Livewire blocks as Livewire components when they're discovered
139150
Event::listen(BlockSchemaRegistered::class, function (BlockSchemaRegistered $event) {
140151
if ($event->schema->class && is_subclass_of($event->schema->class, \Livewire\Component::class)) {
141-
$componentName = 'craftile-'.$event->schema->slug;
152+
$componentName = 'craftile-' . $event->schema->slug;
142153
\Livewire\Livewire::component($componentName, $event->schema->class);
143154
}
144155
});
@@ -149,13 +160,13 @@ protected function bootShopRoutes(): void
149160
{
150161
Route::prefix('/visual/template-preview')
151162
->middleware(['web', 'locale', 'theme', 'currency'])
152-
->group(__DIR__.'/../../routes/shop.php');
163+
->group(__DIR__ . '/../../routes/shop.php');
153164
}
154165

155166
protected function bootViewsAndTranslations(): void
156167
{
157-
$this->loadViewsFrom(__DIR__.'/../../resources/views', 'visual');
158-
$this->loadTranslationsFrom(__DIR__.'/../../resources/lang', 'visual');
168+
$this->loadViewsFrom(__DIR__ . '/../../resources/views', 'visual');
169+
$this->loadTranslationsFrom(__DIR__ . '/../../resources/lang', 'visual');
159170
}
160171

161172
protected function bootMiddlewares(): void
@@ -201,11 +212,11 @@ protected function bootCommands(): void
201212
protected function bootPublishAssets(): void
202213
{
203214
$this->publishes([
204-
__DIR__.'/../../public/vendor/bagistoplus' => public_path('vendor/bagistoplus'),
215+
__DIR__ . '/../../public/vendor/bagistoplus' => public_path('vendor/bagistoplus'),
205216
], ['public', 'visual', 'visual-assets']);
206217

207218
$this->publishes([
208-
__DIR__.'/../../config/bagisto-visual.php' => config_path('bagisto_visual.php'),
219+
__DIR__ . '/../../config/bagisto-visual.php' => config_path('bagisto_visual.php'),
209220
], ['config', 'visual', 'visual-config']);
210221
}
211222

@@ -229,8 +240,8 @@ protected function bootTemplates(): void
229240

230241
protected function registerConfigs(): void
231242
{
232-
$this->mergeConfigFrom(__DIR__.'/../../config/bagisto-visual.php', 'bagisto_visual');
233-
$this->mergeConfigFrom(__DIR__.'/../../config/svg-iconmap.php', 'bagisto_visual_iconmap');
243+
$this->mergeConfigFrom(__DIR__ . '/../../config/bagisto-visual.php', 'bagisto_visual');
244+
$this->mergeConfigFrom(__DIR__ . '/../../config/svg-iconmap.php', 'bagisto_visual_iconmap');
234245
}
235246

236247
protected function registerSingletons(): void
@@ -250,7 +261,7 @@ protected function registerCustomUrlGenerator(): void
250261

251262
return new UrlGenerator(
252263
$routes,
253-
$app->rebinding('request', fn ($app, $request) => $app['url']->setRequest($request)),
264+
$app->rebinding('request', fn($app, $request) => $app['url']->setRequest($request)),
254265
$app['config']['app.asset_url']
255266
);
256267
});

0 commit comments

Comments
 (0)