Initial commit
This commit is contained in:
259
app/Models/Post.php
Normal file
259
app/Models/Post.php
Normal file
@@ -0,0 +1,259 @@
|
||||
<?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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user