*/ protected $fillable = [ 'seo_title', 'seo_description', 'title', 'slug', 'subtitle', 'content', 'data', 'locales', 'order', ]; /** * The attributes that should be cast. * * @var array */ protected $casts = [ 'data' => 'object', 'locales' => 'array', 'status' => 'bool', 'publish_at' => 'datetime', 'unpublish_at' => 'datetime' ]; /** * The translatable columns. * * @var array */ public $translatable = [ 'seo_title', 'seo_description', 'title', 'slug', 'subtitle', 'content', 'data' ]; // * EVENTS /** * Perform any actions required after the model boots. * * @return void */ protected static function booted() { static::creating(function (self $model) { // * ASSERTIONS self::assertTitleIsUnique($model->title); ToolboxHelper::assertNoInternalBoUrls('content', $model->content); // * TRANSFORMATIONS self::setSlug($model); $model->content = FileStorageHelper::storeModelFilesFromHtml($model, $model->content); $model->makeStatusSense(); self::setOrder($model); }); static::updating(function (self $model) { // * ASSERTIONS self::assertTitleIsUnique($model->title); ToolboxHelper::assertNoInternalBoUrls('content', $model->content); // * TRANSFORMATIONS self::setSlug($model); $model->content = FileStorageHelper::storeModelFilesFromHtml($model, $model->content); $model->makeStatusSense(); }); static::updated(function (self $model) { FileStorageHelper::removeOldModelFilesFromHtml( $model->content, ToolboxHelper::getOriginal($model, 'content') ); }); static::deleted(function (self $model) { FileStorageHelper::removeModelFilesOfHtml($model->content); $model->minicrudDeleted(); }); } // * METHODS /** * Apply function on data typed text while on deleted event * * @return void */ public function minicrudDeleted() { /** @var array */ foreach ($this->data as $input) { switch ($input['inputType']) { case InputType::text->value: FileStorageHelper::removeModelFilesOfHtml($input['text']); break; } } } /** * Get picture_list attribute * * @return \Illuminate\Support\Collection */ public function getPictureListAttribute(): Collection { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed return \collect($this->data)->filter(fn($value, $key) => \preg_match('/bloc[0-9]+/u', $key) !== false) // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed ->groupBy(fn($value, $key) => \collect(\explode('_', $key))->take(2)->implode('_')) ->filter(fn(Collection $blocks) => \collect($blocks->first())->get('value')) ->map(function (Collection $blocks) { $pictureBlock = (object) $blocks->last(); return (object) [ 'value' => $pictureBlock->value, 'title' => $pictureBlock->title, 'alt' => $pictureBlock->alt ]; })->values(); } /** * Set the slug. * * @param self $model * * @return void */ private static function setSlug(self $model) { $model->slug = Str::slug($model->title); } /** * Set order after the last element of the list. * * @param self $model * @return void */ private static function setOrder(self $model): void { $model->order = \intval(self::query()->max('order')) + 1; } /** * Asserts using validation that the title is unique * * @param string|integer|float|boolean|null|array $title * @param integer|null $id * @return void * @throws \Illuminate\Validation\ValidationException If an news title already exists. */ private static function assertTitleIsUnique(string|int|float|bool|null|array $title, ?int $id = null) { $table = (new self())->getTable(); ToolboxHelper::assertFieldIsUnique($table, 'title', $title, $id); ToolboxHelper::assertFieldIsUnique($table, 'slug', Str::slug($title), $id); } /** * Return the structure necessary of data. * * @param string $img * @param string $imgAlt * @param string $imgTitle * @return ((string|\App\Enums\InputType)[]|(string|int[]|\App\Enums\InputType)[]|(string|\App\Enums\InputType|int|(string|\Illuminate\Validation\Rules\Enum)[])[])[] */ public static function getEmptyData( string $img = '', string $imgAlt = '', string $imgTitle = '' ) { $data = []; $data = self::emptyDataBloc( '1', $data, $img, $imgAlt, $imgTitle, true ); for ($i = 2; $i <= 3; $i++) { $data = self::emptyDataBloc( strval($i), $data, $img, $imgAlt, $imgTitle, false ); } //end for return $data; } /** * Empty data bloc * * @param string $index * @param array $data * @param string $img * @param string $imgAlt * @param string $imgTitle * @param boolean $required * @return array */ public static function emptyDataBloc( string $index, array $data, string $img = '', string $imgAlt = '', string $imgTitle = '', bool $required = false, ): array { $data["bloc_{$index}_display_picture"] = [ 'label' => "Bloc {$index} - Display picture", 'inputType' => InputType::boolean->value, 'value' => $required ]; $data["bloc_{$index}_image"] = [ 'label' => "Bloc {$index} - Image", 'dimensions' => ['width' => 770, 'height' => 770], 'inputType' => InputType::image->value, 'alt' => $imgAlt, 'title' => $imgTitle, 'value' => $img, 'validate' => "required_if:data.bloc_{$index}_display_picture.value,true|nullable", 'required' => $required ]; return $data; } /** * Create a SchemaOrg. * * @return \Spatie\SchemaOrg\NewsArticle */ public function toSchemaOrg(): \Spatie\SchemaOrg\NewsArticle { return Schema::NewsArticle() ->headline($this->seo_title) ->description($this->seo_description) ->name($this->title) ->inLanguage(config('schema-org.website.languages')[app()->currentLocale()]) ->abstract($this->subtitle) ->dateCreated($this->created_at) ->dateModified($this->updated_at) ->datePublished($this->publish_at) ->articleBody(strip_tags($this->content)) ->wordCount(str_word_count(strip_tags($this->content))) ->url(route('news.show', $this)) ->author($this->getOrganizationSchema()) ->creator($this->getOrganizationSchema()) ->copyrightYear($this->created_at->year) ->image( Schema::imageObject() ->url(asset($this->data['bloc_1_image']['value'])) ->headline($this->data['bloc_1_image']['title']) ); } /** * Get the SEO object. * * @return \Uwil\Seo\Laravel\Objects\SeoItem */ public function toSeoItem(): \Uwil\Seo\Laravel\Objects\SeoItem { return new SeoItem( \trans($this->getTable()), $this->seo_title, $this->seo_description, $this->status, \route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this), \route(Str::singular($this->getTable()) . '.show', $this) ); } /** * To sitemap tag . * * @return \Spatie\Sitemap\Tags\Url|string|array */ public function toSitemapTag(): \Spatie\Sitemap\Tags\Url|string|array { return SitemapHelper::generateUrl('news.show', ['publishedNews' => $this], $this); } }