2025-09-26 15:08:37 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Helpers;
|
|
|
|
|
|
|
|
|
|
use App\Enums\DynamicFieldTypes;
|
2025-12-29 16:27:46 +01:00
|
|
|
use App\Enums\DynamicPages\PageStatusEnum;
|
|
|
|
|
use App\Models\DynamicPage;
|
|
|
|
|
use Illuminate\Database\Eloquent\Collection;
|
2025-09-26 15:08:37 +02:00
|
|
|
use Illuminate\Database\Eloquent\Model;
|
2026-02-03 14:33:08 +01:00
|
|
|
use Illuminate\Support\Facades\Storage;
|
2026-02-12 17:14:08 +01:00
|
|
|
use Illuminate\Support\Str;
|
2025-09-26 15:08:37 +02:00
|
|
|
use Uwil\LaravelCommon\Helpers\FileHelper;
|
2026-02-03 14:33:08 +01:00
|
|
|
use Uwil\LaravelCommon\Helpers\ToolboxHelper;
|
2025-09-26 15:08:37 +02:00
|
|
|
|
|
|
|
|
class DynamicPageHelper
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* Remove imgs from wysiwyg OR dynamic wysiwyg OR image input.
|
|
|
|
|
*
|
2025-10-29 10:29:57 +01:00
|
|
|
* @param \Illuminate\Database\Eloquent\Model $model
|
|
|
|
|
* @param boolean $forceDeleteImage
|
|
|
|
|
* In forceDelete event we need to ensure all the images will be destroyed
|
2025-09-26 15:08:37 +02:00
|
|
|
* @return void
|
|
|
|
|
*/
|
2026-02-03 14:33:08 +01:00
|
|
|
public static function manageImgs(Model $model, bool $forceDeleteImage = false): void
|
2025-09-26 15:08:37 +02:00
|
|
|
{
|
|
|
|
|
$locale = config('app.locale');
|
|
|
|
|
|
|
|
|
|
$currentContent = json_decode($model->getAttributes()['content'], true);
|
|
|
|
|
$originalContent = $model->getOriginal('content');
|
|
|
|
|
|
2026-02-03 14:33:08 +01:00
|
|
|
$availableLocales = array_keys(config('laravellocalization.supportedLocales', ['fr' => "Français"]));
|
2026-02-10 15:43:47 +01:00
|
|
|
// On delete it's all the locales.
|
|
|
|
|
$localesToProcess = ($forceDeleteImage) ? $availableLocales : [$locale];
|
2026-02-03 14:33:08 +01:00
|
|
|
|
|
|
|
|
foreach ($localesToProcess as $lang) {
|
|
|
|
|
if (isset($originalContent[$lang])) {
|
|
|
|
|
$currentContentLocal = is_array($currentContent[$lang])
|
|
|
|
|
? $currentContent[$lang]
|
|
|
|
|
: [DynamicFieldTypes::wysiwyg->name . '_' => $currentContent[$lang]];
|
|
|
|
|
$originalContentLocal = is_array($originalContent[$lang])
|
|
|
|
|
? $originalContent[$lang]
|
|
|
|
|
: [DynamicFieldTypes::wysiwyg->name . '_' => $originalContent[$lang]];
|
|
|
|
|
static::removeDynamicImages($model, $originalContentLocal, $currentContentLocal, $forceDeleteImage);
|
|
|
|
|
static::removeWysiwygImages($originalContentLocal, $currentContentLocal, $forceDeleteImage);
|
|
|
|
|
}
|
2025-10-21 15:24:59 +02:00
|
|
|
}
|
2025-09-26 15:08:37 +02:00
|
|
|
}
|
|
|
|
|
|
2026-02-03 14:33:08 +01:00
|
|
|
|
2025-09-26 15:08:37 +02:00
|
|
|
/**
|
|
|
|
|
* Remove imgs from image inputs.
|
|
|
|
|
*
|
2025-10-29 10:29:57 +01:00
|
|
|
* @param \Illuminate\Database\Eloquent\Model $model
|
|
|
|
|
* @param array $oldContent
|
|
|
|
|
* @param array $newContent
|
|
|
|
|
* @param boolean $forceDeleteImage
|
|
|
|
|
* In forceDelete event we need to ensure all the images will be destroyed
|
2025-09-26 15:08:37 +02:00
|
|
|
* @return void
|
|
|
|
|
*/
|
2025-10-29 10:29:57 +01:00
|
|
|
protected static function removeDynamicImages(
|
|
|
|
|
Model $model,
|
|
|
|
|
array $oldContent,
|
|
|
|
|
array $newContent,
|
|
|
|
|
bool $forceDeleteImage
|
|
|
|
|
): void {
|
2026-02-10 15:43:47 +01:00
|
|
|
$prefix = DynamicFieldTypes::image->name . '_';
|
2025-10-29 10:29:57 +01:00
|
|
|
|
2026-02-03 14:33:08 +01:00
|
|
|
$oldImages = static::extractImagePaths($oldContent, $prefix);
|
|
|
|
|
$newImages = static::extractImagePaths($newContent, $prefix);
|
2026-02-10 15:43:47 +01:00
|
|
|
$allPaths = collect(array_keys($oldImages))
|
2026-02-03 14:33:08 +01:00
|
|
|
->merge(array_keys($newImages))
|
|
|
|
|
->unique();
|
2026-02-10 15:43:47 +01:00
|
|
|
foreach ($allPaths as $key) {
|
2026-02-03 14:33:08 +01:00
|
|
|
$old = $oldImages[$key] ?? null;
|
|
|
|
|
$new = $newImages[$key] ?? null;
|
2025-10-29 10:29:57 +01:00
|
|
|
// Case n°1 : Same values when force delete.
|
2025-09-26 15:08:37 +02:00
|
|
|
if ((is_string($old) === is_string($new)) && $forceDeleteImage) {
|
2026-02-03 14:33:08 +01:00
|
|
|
$path = ToolboxHelper::mbReplace('storage/', '', $new);
|
|
|
|
|
if (Storage::disk('public')->exists($path)) {
|
|
|
|
|
Storage::disk('public')->delete($path);
|
|
|
|
|
}
|
2025-09-26 15:08:37 +02:00
|
|
|
}
|
2025-10-29 10:29:57 +01:00
|
|
|
|
|
|
|
|
// Case n°2: old = string, new = null → deletion.
|
2025-09-26 15:08:37 +02:00
|
|
|
if (is_string($old) && is_null($new)) {
|
2025-10-29 10:29:57 +01:00
|
|
|
// Remove the original file.
|
2025-09-26 15:08:37 +02:00
|
|
|
FileHelper::removeOldFile($model, "content.$key");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-29 10:29:57 +01:00
|
|
|
// Case n°3: old = null, new = string → addition.
|
|
|
|
|
if (is_null($old) && is_string($new)) {
|
|
|
|
|
// Nothing to do.
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2025-09-26 15:08:37 +02:00
|
|
|
|
2025-10-29 10:29:57 +01:00
|
|
|
// Case n°4: old = string, new = other string → replacement.
|
2025-09-26 15:08:37 +02:00
|
|
|
if (is_string($old) && is_string($new) && $old !== $new) {
|
|
|
|
|
FileHelper::removeOldFile($model, "content.$key");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2025-10-29 10:29:57 +01:00
|
|
|
} //end foreach
|
2025-09-26 15:08:37 +02:00
|
|
|
}
|
2026-02-10 15:43:47 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Extract image path for fields with image key prefix.
|
|
|
|
|
*
|
|
|
|
|
* @param array $array
|
|
|
|
|
* @param string $prefix
|
|
|
|
|
* @param string $path
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
2026-02-03 14:33:08 +01:00
|
|
|
protected static function extractImagePaths(
|
|
|
|
|
array $array,
|
|
|
|
|
string $prefix,
|
|
|
|
|
string $path = ''
|
|
|
|
|
): array {
|
|
|
|
|
$result = [];
|
|
|
|
|
|
|
|
|
|
foreach ($array as $key => $value) {
|
|
|
|
|
$currentPath = $path === '' ? $key : "$path.$key";
|
|
|
|
|
|
|
|
|
|
if (Str::startsWith($key, $prefix) && is_string($value)) {
|
|
|
|
|
$result[$currentPath] = $value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_array($value)) {
|
|
|
|
|
$result += static::extractImagePaths($value, $prefix, $currentPath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
2025-09-26 15:08:37 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Remove imgs from wysiwygs.
|
|
|
|
|
*
|
2026-02-10 15:43:47 +01:00
|
|
|
* @param array $oldContent
|
|
|
|
|
* @param array $newContent
|
2026-02-03 14:33:08 +01:00
|
|
|
* @param boolean $forceDeleteImage
|
2025-09-26 15:08:37 +02:00
|
|
|
* @return void
|
|
|
|
|
*/
|
2026-02-03 14:33:08 +01:00
|
|
|
protected static function removeWysiwygImages(array $oldContent, array $newContent, bool $forceDeleteImage): void
|
2025-09-26 15:08:37 +02:00
|
|
|
{
|
2025-11-18 13:52:59 +01:00
|
|
|
$prefix = DynamicFieldTypes::wysiwyg->name . '_';
|
2025-09-26 15:08:37 +02:00
|
|
|
static::getDynamicFieldKeys($oldContent, $newContent, $prefix)
|
2026-02-03 14:33:08 +01:00
|
|
|
->each(function ($key) use ($oldContent, $newContent, $forceDeleteImage) {
|
|
|
|
|
$old = data_get($oldContent, $key);
|
|
|
|
|
$new = $forceDeleteImage
|
|
|
|
|
? ''
|
|
|
|
|
: data_get($newContent, $key, '');
|
|
|
|
|
if ($old) {
|
2026-02-17 16:48:44 +01:00
|
|
|
FileHelper::removeOldModelFilesFromHtml($new ?? '', $old);
|
2026-02-03 14:33:08 +01:00
|
|
|
}
|
2025-10-21 15:24:59 +02:00
|
|
|
});
|
2025-09-26 15:08:37 +02:00
|
|
|
}
|
|
|
|
|
|
2026-02-03 14:33:08 +01:00
|
|
|
|
2025-09-26 15:08:37 +02:00
|
|
|
/**
|
2025-10-29 10:29:57 +01:00
|
|
|
* Get all value that correspond to a prefix in field input and group them.
|
2025-09-26 15:08:37 +02:00
|
|
|
*
|
2025-10-29 10:29:57 +01:00
|
|
|
* @param array $oldContent
|
|
|
|
|
* @param array $newContent
|
|
|
|
|
* @param string $prefix
|
2025-09-26 15:08:37 +02:00
|
|
|
* @return \Illuminate\Support\Collection
|
|
|
|
|
*/
|
2025-10-29 10:29:57 +01:00
|
|
|
protected static function getDynamicFieldKeys(
|
|
|
|
|
array $oldContent,
|
|
|
|
|
array $newContent,
|
|
|
|
|
string $prefix
|
|
|
|
|
): \Illuminate\Support\Collection {
|
2026-02-03 14:33:08 +01:00
|
|
|
|
|
|
|
|
$oldFieldsPath = static::extractImagePaths($oldContent, $prefix);
|
|
|
|
|
$newFieldsPath = static::extractImagePaths($newContent, $prefix);
|
|
|
|
|
return collect(array_keys($oldFieldsPath))
|
|
|
|
|
->merge(array_keys($newFieldsPath))
|
|
|
|
|
->unique();
|
2025-09-26 15:08:37 +02:00
|
|
|
}
|
2025-12-29 16:27:46 +01:00
|
|
|
|
|
|
|
|
/**
|
2026-02-10 15:43:47 +01:00
|
|
|
* Get all segments url for dynamic pages.
|
2025-12-29 16:27:46 +01:00
|
|
|
*
|
2026-02-12 17:14:08 +01:00
|
|
|
* @param \App\Models\DynamicPage $page
|
|
|
|
|
* @param \Illuminate\Database\Eloquent\Collection $pages
|
|
|
|
|
* @param string $locale
|
2025-12-29 16:27:46 +01:00
|
|
|
* @return array|null
|
|
|
|
|
*/
|
|
|
|
|
public static function getAllDynamicPageSegments(DynamicPage $page, Collection $pages, string $locale): ?array
|
|
|
|
|
{
|
|
|
|
|
$segments = [];
|
|
|
|
|
$parentId = $page->page_id ?? ($page->parentPage->id ?? null);
|
|
|
|
|
|
|
|
|
|
// Browse all relationships.
|
|
|
|
|
while ($parentId) {
|
2026-02-10 15:43:47 +01:00
|
|
|
/** @var \App\Models\DynamicPage|null $parent */
|
2025-12-29 16:27:46 +01:00
|
|
|
$parent = $pages->find($parentId);
|
|
|
|
|
|
2026-02-10 15:43:47 +01:00
|
|
|
if (!$parent || !$parent->status->equals(PageStatusEnum::published)) {
|
2025-12-29 16:27:46 +01:00
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$parentSlug = $parent->getTranslation('slug', $locale);
|
|
|
|
|
|
|
|
|
|
if (! $parentSlug) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
array_unshift($segments, $parentSlug);
|
|
|
|
|
$parentId = $parent->page_id;
|
|
|
|
|
}
|
|
|
|
|
return $segments;
|
|
|
|
|
}
|
2025-09-26 15:08:37 +02:00
|
|
|
}
|