260 lines
7.0 KiB
PHP
260 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Helpers\StringHelper;
|
|
use App\Models\Category;
|
|
use App\Models\Image;
|
|
use App\Models\Meeting;
|
|
use App\Models\PostTranslation;
|
|
use Cog\Contracts\Love\Reactable\Models\Reactable as ReactableInterface;
|
|
use Cog\Laravel\Love\Reactable\Models\Traits\Reactable;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Laravel\Scout\Searchable;
|
|
use Spatie\MediaLibrary\HasMedia;
|
|
use Spatie\MediaLibrary\InteractsWithMedia;
|
|
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
|
use Znck\Eloquent\Traits\BelongsToThrough;
|
|
|
|
|
|
class Post extends Model implements HasMedia, ReactableInterface
|
|
{
|
|
use HasFactory;
|
|
use BelongsToThrough;
|
|
use InteractsWithMedia;
|
|
use SoftDeletes;
|
|
use Searchable; // laravel/scout with ElasticSearch
|
|
use Reactable; // cybercog/laravel-love
|
|
|
|
|
|
|
|
protected $fillable = ['postable_id', 'postable_type', 'category_id', 'author_id', 'author_model'];
|
|
|
|
/**
|
|
* Get the index name for the model.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function searchableAs()
|
|
{
|
|
return 'posts_index';
|
|
}
|
|
|
|
|
|
/**
|
|
* Convert the this model to a searchable array.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function toSearchableArray()
|
|
{
|
|
return [
|
|
'id' => $this->id,
|
|
'category_id' => $this->category_id,
|
|
|
|
'postable' => [
|
|
'id' => $this->postable ? $this->postable->id : '',
|
|
'name' => $this->postable ? $this->postable->name : '',
|
|
],
|
|
|
|
'post_translations' => $this->translations->mapWithKeys(function ($translation) {
|
|
// mapWithKeys() as translations is a collection
|
|
return [
|
|
'title_' . $translation->locale => $translation->title,
|
|
'excerpt_' . $translation->locale => $translation->excerpt,
|
|
'content_' . $translation->locale => $translation->content,
|
|
// Add publication fields
|
|
'from_' . $translation->locale => $translation->from,
|
|
'till_' . $translation->locale => $translation->till,
|
|
'deleted_at_' . $translation->locale => $translation->deleted_at,
|
|
'status_' . $translation->locale => $translation->status,
|
|
];
|
|
})->toArray(),
|
|
|
|
'post_category' => $this->category ? [
|
|
'id' => $this->category->id,
|
|
'names' => $this->category->translations->mapWithKeys(function ($translation) {
|
|
// Include the locale in the field name for categories
|
|
return ['name_' . $translation->locale => StringHelper::DutchTitleCase($translation->name)];
|
|
})->toArray(),
|
|
] : [],
|
|
];
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Get the creator of the post (i.e. user or organization).
|
|
*
|
|
* @return void
|
|
*/
|
|
public function postable()
|
|
{
|
|
return $this->morphTo();
|
|
}
|
|
|
|
/**
|
|
* Get the author of the post (polymorphic: User, Organization, or Bank).
|
|
*
|
|
* @return void
|
|
*/
|
|
public function author()
|
|
{
|
|
return $this->morphTo('author', 'author_model', 'author_id');
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the related translations of the post
|
|
* One-to-many relationship
|
|
* @return void
|
|
*/
|
|
public function translations()
|
|
{
|
|
return $this->hasMany(PostTranslation::class);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the related category of the post
|
|
*
|
|
* @return void
|
|
*/
|
|
public function category()
|
|
{
|
|
return $this->belongsTo(Category::class);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Get the related images of the posts
|
|
*
|
|
* @return void
|
|
*/
|
|
public function images()
|
|
{
|
|
return $this->morphToMany(Image::class, 'imageable');
|
|
}
|
|
|
|
|
|
public static function last()
|
|
{
|
|
return static::all()->last();
|
|
}
|
|
|
|
|
|
/**
|
|
* Spatie Media Library media conversions
|
|
* When updated you can use:
|
|
* php artisan media-library:regenerate
|
|
* to regenerate media disk and database of all media stored (make sure you restart the queue worker first)
|
|
*
|
|
* @param mixed $media
|
|
* @return void
|
|
*/
|
|
public function registerMediaConversions(Media $media = null): void
|
|
{
|
|
$this->addMediaConversion('favicon') //1:1
|
|
->focalCrop(32, 32, 50, 50)
|
|
->optimize()
|
|
->format('gif')
|
|
->performOnCollections('posts');
|
|
|
|
$this->addMediaConversion('logo') //1:1
|
|
->focalCrop(160, 160, 50, 50)
|
|
->optimize()
|
|
->format('webp')
|
|
->performOnCollections('posts');
|
|
|
|
$this->addMediaConversion('thumbnail') // 1:1
|
|
->focalCrop(150, 150, 50, 50)
|
|
->optimize()
|
|
->format('webp')
|
|
->performOnCollections('posts');
|
|
|
|
$this->addMediaConversion('blog') //3:2
|
|
->focalCrop(1200, 630, 50, 50)
|
|
->withResponsiveImages()
|
|
->optimize()
|
|
->format('webp')
|
|
->performOnCollections('posts');
|
|
|
|
$this->addMediaConversion('hero') //16:9
|
|
->focalCrop(3840, 2160, 50, 50)
|
|
->withResponsiveImages()
|
|
->optimize()
|
|
->format('webp')
|
|
->performOnCollections('posts');
|
|
|
|
$this->addMediaConversion('half_hero') //16:4.5 panoramic
|
|
->focalCrop(3840, 1080, 50, 50)
|
|
->format('webp')
|
|
->performOnCollections('posts');
|
|
|
|
$this->addMediaConversion('4_3') //4:3
|
|
->focalCrop(3072, 2304, 50, 50)
|
|
->withResponsiveImages()
|
|
->optimize()
|
|
->format('webp')
|
|
->performOnCollections('posts');
|
|
|
|
$this->addMediaConversion('email') // For email newsletters - resizes without cropping
|
|
->width(800)
|
|
->optimize()
|
|
->format('jpg')
|
|
->quality(85)
|
|
->performOnCollections('posts');
|
|
|
|
}
|
|
|
|
public function registerMediaCollection(): void
|
|
{
|
|
$this->addMediaCollection('posts')
|
|
->useDisk('media')
|
|
->singleFile();
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the related meeting of the post
|
|
* One-to-one relation
|
|
*
|
|
* @return void
|
|
*/
|
|
public function meeting()
|
|
{
|
|
return $this->hasOne(Meeting::class);
|
|
}
|
|
|
|
/**
|
|
* Get the count of 'like' reactions for this post
|
|
*
|
|
* @return int
|
|
*/
|
|
public function getLikeCountAttribute()
|
|
{
|
|
// Check if post is registered as reactant before getting reactions
|
|
if (!$this->isRegisteredAsLoveReactant()) {
|
|
return 0;
|
|
}
|
|
|
|
// Get the reactant facade
|
|
$reactantFacade = $this->viaLoveReactant();
|
|
|
|
// Get the reaction counter for 'Like' type
|
|
$reactionCounter = $reactantFacade->getReactionCounterOfType('Like');
|
|
|
|
if (!$reactionCounter) {
|
|
return 0;
|
|
}
|
|
|
|
// Return the total count from all users
|
|
return $reactionCounter->getCount();
|
|
}
|
|
|
|
|
|
}
|