252 lines
8.5 KiB
PHP
252 lines
8.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\PageBlock;
|
|
use App\Models\PreregistrationPage;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class PreregistrationPageBlockWriter
|
|
{
|
|
/**
|
|
* @param array<int, array<string, mixed>> $blocks
|
|
*/
|
|
public function replaceBlocks(PreregistrationPage $page, array $blocks, Request $request): void
|
|
{
|
|
DB::transaction(function () use ($page, $blocks, $request): void {
|
|
$page->load('blocks');
|
|
$oldPaths = $this->collectBlockImagePaths($page);
|
|
$page->blocks()->delete();
|
|
|
|
$orderedKeys = array_keys($blocks);
|
|
usort($orderedKeys, function (string|int $a, string|int $b) use ($blocks): int {
|
|
/** @var array<string, mixed> $rowA */
|
|
$rowA = $blocks[$a];
|
|
/** @var array<string, mixed> $rowB */
|
|
$rowB = $blocks[$b];
|
|
|
|
return ((int) ($rowA['sort_order'] ?? 0)) <=> ((int) ($rowB['sort_order'] ?? 0));
|
|
});
|
|
|
|
$allNewPaths = [];
|
|
foreach ($orderedKeys as $blockKey) {
|
|
/** @var array<string, mixed> $blockRow */
|
|
$blockRow = $blocks[$blockKey];
|
|
$type = (string) $blockRow['type'];
|
|
/** @var array<string, mixed> $content */
|
|
$content = is_array($blockRow['content'] ?? null) ? $blockRow['content'] : [];
|
|
if ($type === 'text' && array_key_exists('body', $content) && is_string($content['body'])) {
|
|
$content['body'] = ltrim($content['body']);
|
|
}
|
|
if ($type === 'image') {
|
|
$content = $this->mergeImageBlockFiles($page, (string) $blockKey, $content, $request);
|
|
}
|
|
$allNewPaths = array_merge($allNewPaths, $this->pathsFromImageTypeContent($type, $content));
|
|
|
|
PageBlock::query()->create([
|
|
'preregistration_page_id' => $page->id,
|
|
'type' => $type,
|
|
'content' => $content,
|
|
'sort_order' => (int) ($blockRow['sort_order'] ?? 0),
|
|
'is_visible' => (bool) ($blockRow['is_visible'] ?? true),
|
|
]);
|
|
}
|
|
|
|
$allNewPaths = array_values(array_unique($allNewPaths));
|
|
foreach (array_diff($oldPaths, $allNewPaths) as $orphan) {
|
|
if (is_string($orphan) && $orphan !== '') {
|
|
Storage::disk('public')->delete($orphan);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
public function seedDefaultBlocks(PreregistrationPage $page): void
|
|
{
|
|
$rows = [
|
|
[
|
|
'type' => 'hero',
|
|
'sort_order' => 0,
|
|
'is_visible' => true,
|
|
'content' => [
|
|
'headline' => $page->title,
|
|
'subheadline' => '',
|
|
'eyebrow_text' => '',
|
|
'eyebrow_style' => 'badge',
|
|
'text_alignment' => 'center',
|
|
],
|
|
],
|
|
];
|
|
|
|
$next = 1;
|
|
if ($page->start_date->isFuture()) {
|
|
$rows[] = [
|
|
'type' => 'countdown',
|
|
'sort_order' => $next,
|
|
'is_visible' => true,
|
|
'content' => [
|
|
'target_datetime' => $page->start_date->toIso8601String(),
|
|
'title' => 'De pre-registratie opent over:',
|
|
'expired_action' => 'reload',
|
|
'style' => 'large',
|
|
'show_labels' => true,
|
|
'labels' => [
|
|
'days' => 'dagen',
|
|
'hours' => 'uren',
|
|
'minutes' => 'minuten',
|
|
'seconds' => 'seconden',
|
|
],
|
|
],
|
|
];
|
|
$next++;
|
|
}
|
|
|
|
$rows[] = [
|
|
'type' => 'benefits',
|
|
'sort_order' => $next,
|
|
'is_visible' => true,
|
|
'content' => [
|
|
'title' => 'Waarom voorregistreren?',
|
|
'items' => [
|
|
['icon' => 'ticket', 'text' => 'Exclusieve korting op tickets'],
|
|
['icon' => 'clock', 'text' => 'Eerder toegang tot de ticketshop'],
|
|
],
|
|
'layout' => 'list',
|
|
'max_columns' => 2,
|
|
],
|
|
];
|
|
$next++;
|
|
|
|
$rows[] = [
|
|
'type' => 'social_proof',
|
|
'sort_order' => $next,
|
|
'is_visible' => true,
|
|
'content' => [
|
|
'template' => 'Al {count} bezoekers aangemeld!',
|
|
'min_count' => 10,
|
|
'show_animation' => true,
|
|
'style' => 'pill',
|
|
],
|
|
];
|
|
$next++;
|
|
|
|
$rows[] = [
|
|
'type' => 'form',
|
|
'sort_order' => $next,
|
|
'is_visible' => true,
|
|
'content' => [
|
|
'title' => 'Registreer nu',
|
|
'description' => '',
|
|
'button_label' => 'Registreer nu!',
|
|
'button_color' => '#F47B20',
|
|
'button_text_color' => '#FFFFFF',
|
|
'fields' => [
|
|
'first_name' => [
|
|
'enabled' => true,
|
|
'required' => true,
|
|
'label' => 'Voornaam',
|
|
'placeholder' => 'Je voornaam',
|
|
],
|
|
'last_name' => [
|
|
'enabled' => true,
|
|
'required' => true,
|
|
'label' => 'Achternaam',
|
|
'placeholder' => 'Je achternaam',
|
|
],
|
|
'email' => [
|
|
'enabled' => true,
|
|
'required' => true,
|
|
'label' => 'E-mailadres',
|
|
'placeholder' => 'je@email.nl',
|
|
],
|
|
'phone' => [
|
|
'enabled' => false,
|
|
'required' => false,
|
|
'label' => 'Mobiel',
|
|
'placeholder' => '+31 6 12345678',
|
|
],
|
|
],
|
|
'show_field_icons' => true,
|
|
'privacy_text' => 'Door je te registreren ga je akkoord met onze privacyverklaring.',
|
|
'privacy_url' => '',
|
|
],
|
|
];
|
|
|
|
$page->blocks()->createMany($rows);
|
|
}
|
|
|
|
/**
|
|
* @return list<string>
|
|
*/
|
|
private function collectBlockImagePaths(PreregistrationPage $page): array
|
|
{
|
|
$paths = [];
|
|
foreach ($page->blocks as $b) {
|
|
if ($b->type !== 'image') {
|
|
continue;
|
|
}
|
|
$paths = array_merge($paths, $this->pathsFromImageTypeContent('image', is_array($b->content) ? $b->content : []));
|
|
}
|
|
|
|
return array_values(array_unique($paths));
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $content
|
|
* @return list<string>
|
|
*/
|
|
private function pathsFromImageTypeContent(string $type, array $content): array
|
|
{
|
|
if ($type !== 'image') {
|
|
return [];
|
|
}
|
|
$p = data_get($content, 'image');
|
|
if (is_string($p) && $p !== '') {
|
|
return [$p];
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $content
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function mergeImageBlockFiles(PreregistrationPage $page, string $blockKey, array $content, Request $request): array
|
|
{
|
|
$disk = Storage::disk('public');
|
|
$dir = "preregister/pages/{$page->id}";
|
|
|
|
$link = $content['link_url'] ?? null;
|
|
$content['link_url'] = is_string($link) && trim($link) !== '' ? trim($link) : null;
|
|
|
|
if ($request->boolean("blocks.$blockKey.remove_block_image")) {
|
|
$prev = $content['image'] ?? null;
|
|
if (is_string($prev) && $prev !== '') {
|
|
$disk->delete($prev);
|
|
}
|
|
$content['image'] = null;
|
|
}
|
|
|
|
$file = $request->file("blocks.$blockKey.block_image");
|
|
if ($this->isValidUpload($file)) {
|
|
if (isset($content['image']) && is_string($content['image']) && $content['image'] !== '') {
|
|
$disk->delete($content['image']);
|
|
}
|
|
$content['image'] = $file->store($dir, 'public');
|
|
}
|
|
|
|
return $content;
|
|
}
|
|
|
|
private function isValidUpload(?UploadedFile $file): bool
|
|
{
|
|
return $file !== null && $file->isValid();
|
|
}
|
|
}
|