|
|
|
<?php
|
|
|
|
|
|
|
|
namespace common\modules\blog\entities;
|
|
|
|
|
|
|
|
use common\modules\blog\entities\queries\BlogPostQuery;
|
|
|
|
use core\behaviors\MetaBehavior;
|
|
|
|
use core\entities\Meta;
|
|
|
|
use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior;
|
|
|
|
use yii\behaviors\TimestampBehavior;
|
|
|
|
use yii\db\ActiveQuery;
|
|
|
|
use yii\db\ActiveRecord;
|
|
|
|
use yii\web\UploadedFile;
|
|
|
|
use yiidreamteam\upload\ImageUploadBehavior;
|
|
|
|
use Yii;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is the model class for table "posts".
|
|
|
|
*
|
|
|
|
* @property int $id
|
|
|
|
* @property int $category_id
|
|
|
|
* @property int $published_at
|
|
|
|
* @property int $created_at
|
|
|
|
* @property int $updated_at
|
|
|
|
* @property string $title
|
|
|
|
* @property string $description
|
|
|
|
* @property string $content
|
|
|
|
* @property string $image
|
|
|
|
* @property string $video
|
|
|
|
* @property int $status
|
|
|
|
* @property string $meta_json
|
|
|
|
* @property int $comments_count
|
|
|
|
* @property int $views
|
|
|
|
* @property string $slug
|
|
|
|
*
|
|
|
|
* @property BlogComment[] $blogComments
|
|
|
|
* @property BlogTagAssignment[] $blogTagAssignments
|
|
|
|
* @property BlogTag[] $tags
|
|
|
|
* @property BlogCategory $category
|
|
|
|
*
|
|
|
|
* @mixin ImageUploadBehavior
|
|
|
|
*/
|
|
|
|
class BlogPost extends ActiveRecord
|
|
|
|
{
|
|
|
|
const STATUS_DRAFT = 0;
|
|
|
|
const STATUS_ACTIVE = 1;
|
|
|
|
|
|
|
|
const FILE_ORIGINAL_PATH = '@staticRoot/origin/posts';
|
|
|
|
|
|
|
|
public $meta;
|
|
|
|
|
|
|
|
public static function create($categoryId, $title, $slug, $description, $content, $published_at, $video, Meta $meta): self
|
|
|
|
{
|
|
|
|
$post = new static();
|
|
|
|
$post->category_id = $categoryId;
|
|
|
|
$post->title = $title;
|
|
|
|
$post->slug = $slug;
|
|
|
|
$post->description = $description;
|
|
|
|
$post->content = $content;
|
|
|
|
$post->meta = $meta;
|
|
|
|
$post->status = self::STATUS_DRAFT;
|
|
|
|
$post->created_at = time();
|
|
|
|
$post->comments_count = 0;
|
|
|
|
$post->published_at = $published_at;
|
|
|
|
$post->video = $video;
|
|
|
|
return $post;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setImage(UploadedFile $image): void
|
|
|
|
{
|
|
|
|
$this->image = $image;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function edit($categoryId, $title, $slug, $description, $content, $published_at, $video, Meta $meta): void
|
|
|
|
{
|
|
|
|
$this->category_id = $categoryId;
|
|
|
|
$this->title = $title;
|
|
|
|
$this->slug = $slug;
|
|
|
|
$this->description = $description;
|
|
|
|
$this->content = $content;
|
|
|
|
$this->meta = $meta;
|
|
|
|
$this->published_at = $published_at;
|
|
|
|
$this->video = $video;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
public static function tableName()
|
|
|
|
{
|
|
|
|
return 'blog_posts';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
public function attributeLabels()
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
'id' => Yii::t('blog', 'ID'),
|
|
|
|
'category_id' => Yii::t('blog', 'Category'),
|
|
|
|
'published_at' => Yii::t('blog', 'Published At'),
|
|
|
|
'created_at' => Yii::t('blog', 'Created At'),
|
|
|
|
'updated_at' => Yii::t('blog', 'Updated At'),
|
|
|
|
'title' => Yii::t('blog', 'Title'),
|
|
|
|
'description' => Yii::t('blog', 'Description'),
|
|
|
|
'content' => Yii::t('blog', 'Content'),
|
|
|
|
'image' => Yii::t('blog', 'Image'),
|
|
|
|
'video' => Yii::t('blog', 'Video'),
|
|
|
|
'status' => Yii::t('blog', 'Status'),
|
|
|
|
'meta_json' => Yii::t('blog', 'Meta Json'),
|
|
|
|
'comments_count' => Yii::t('blog', 'Comments Count'),
|
|
|
|
'views' => Yii::t('blog', 'Views'),
|
|
|
|
'slug' => Yii::t('blog', 'Slug'),
|
|
|
|
'meta.title' => Yii::t('blog', 'Meta Title'),
|
|
|
|
'meta.description' => Yii::t('blog', 'Meta Description'),
|
|
|
|
'meta.keywords' => Yii::t('blog', 'Meta Keywords'),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function activate(): void
|
|
|
|
{
|
|
|
|
if ($this->isActive()) {
|
|
|
|
throw new \DomainException('Post is already active.');
|
|
|
|
}
|
|
|
|
$this->status = self::STATUS_ACTIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function draft(): void
|
|
|
|
{
|
|
|
|
if ($this->isDraft()) {
|
|
|
|
throw new \DomainException('Post is already draft.');
|
|
|
|
}
|
|
|
|
$this->status = self::STATUS_DRAFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function isActive(): bool
|
|
|
|
{
|
|
|
|
return $this->status == self::STATUS_ACTIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function isDraft(): bool
|
|
|
|
{
|
|
|
|
return $this->status == self::STATUS_DRAFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getSeoTitle(): string
|
|
|
|
{
|
|
|
|
return $this->meta->title ?: $this->title;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tags
|
|
|
|
|
|
|
|
public function assignTag($id): void
|
|
|
|
{
|
|
|
|
$assignments = $this->blogTagAssignments;
|
|
|
|
foreach ($assignments as $assignment) {
|
|
|
|
if ($assignment->isForTag($id)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$assignments[] = BlogTagAssignment::create($id);
|
|
|
|
$this->blogTagAssignments = $assignments;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function revokeTag($id): void
|
|
|
|
{
|
|
|
|
$assignments = $this->blogTagAssignments;
|
|
|
|
foreach ($assignments as $i => $assignment) {
|
|
|
|
if ($assignment->isForTag($id)) {
|
|
|
|
unset($assignments[$i]);
|
|
|
|
$this->blogTagAssignments = $assignments;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new \DomainException('Assignment is not found.');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function revokeTags(): void
|
|
|
|
{
|
|
|
|
$this->blogTagAssignments = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comments
|
|
|
|
|
|
|
|
public function addComment($userId, $parentId, $text): BlogComment
|
|
|
|
{
|
|
|
|
$parent = $parentId ? $this->getComment($parentId) : null;
|
|
|
|
if ($parent && !$parent->isActive()) {
|
|
|
|
throw new \DomainException('Cannot add comment to inactive parent.');
|
|
|
|
}
|
|
|
|
$comments = $this->blogComments;
|
|
|
|
$comments[] = $comment = BlogComment::create($userId, $parent ? $parent->id : null, $text);
|
|
|
|
$this->updateComments($comments);
|
|
|
|
return $comment;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function editComment($id, $parentId, $text): void
|
|
|
|
{
|
|
|
|
$parent = $parentId ? $this->getComment($parentId) : null;
|
|
|
|
$comments = $this->blogComments;
|
|
|
|
foreach ($comments as $comment) {
|
|
|
|
if ($comment->isIdEqualTo($id)) {
|
|
|
|
$comment->edit($parent ? $parent->id : null, $text);
|
|
|
|
$this->updateComments($comments);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new \DomainException('Comment is not found.');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function activateComment($id): void
|
|
|
|
{
|
|
|
|
$comments = $this->blogComments;
|
|
|
|
foreach ($comments as $comment) {
|
|
|
|
if ($comment->isIdEqualTo($id)) {
|
|
|
|
$comment->activate();
|
|
|
|
$this->updateComments($comments);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new \DomainException('Comment is not found.');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function removeComment($id): void
|
|
|
|
{
|
|
|
|
$comments = $this->blogComments;
|
|
|
|
foreach ($comments as $i => $comment) {
|
|
|
|
if ($comment->isIdEqualTo($id)) {
|
|
|
|
if ($this->hasChildren($comment->id)) {
|
|
|
|
$comment->draft();
|
|
|
|
} else {
|
|
|
|
unset($comments[$i]);
|
|
|
|
}
|
|
|
|
$this->updateComments($comments);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new \DomainException('Comment is not found.');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getComment($id): BlogComment
|
|
|
|
{
|
|
|
|
foreach ($this->blogComments as $comment) {
|
|
|
|
if ($comment->isIdEqualTo($id)) {
|
|
|
|
return $comment;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new \DomainException('Comment is not found.');
|
|
|
|
}
|
|
|
|
|
|
|
|
private function hasChildren($id): bool
|
|
|
|
{
|
|
|
|
foreach ($this->blogComments as $comment) {
|
|
|
|
if ($comment->isChildOf($id)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function updateComments(array $comments): void
|
|
|
|
{
|
|
|
|
$this->blogComments = $comments;
|
|
|
|
$this->comments_count = count(array_filter($comments, function (BlogComment $comment) {
|
|
|
|
return $comment->isActive();
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
######################################
|
|
|
|
|
|
|
|
public function getBlogComments(): ActiveQuery
|
|
|
|
{
|
|
|
|
return $this->hasMany(BlogComment::className(), ['post_id' => 'id']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getBlogTagAssignments(): ActiveQuery
|
|
|
|
{
|
|
|
|
return $this->hasMany(BlogTagAssignment::className(), ['post_id' => 'id']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getTags(): ActiveQuery
|
|
|
|
{
|
|
|
|
return $this->hasMany(BlogTag::className(), ['id' => 'tag_id'])->viaTable('blog_tag_assignments', ['post_id' => 'id']);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCategory(): ActiveQuery
|
|
|
|
{
|
|
|
|
return $this->hasOne(BlogCategory::className(), ['id' => 'category_id']);
|
|
|
|
}
|
|
|
|
|
|
|
|
######################################
|
|
|
|
|
|
|
|
public function behaviors(): array
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
TimestampBehavior::className(),
|
|
|
|
MetaBehavior::className(),
|
|
|
|
[
|
|
|
|
'class' => SaveRelationsBehavior::className(),
|
|
|
|
'relations' => ['blogTagAssignments', 'blogComments'],
|
|
|
|
],
|
|
|
|
[
|
|
|
|
// todo Image Sizes to settings or theme settings
|
|
|
|
'class' => ImageUploadBehavior::className(),
|
|
|
|
'attribute' => 'image',
|
|
|
|
'createThumbsOnRequest' => true,
|
|
|
|
//'filePath' => $this::FILE_ORIGINAL_PATH . '/[[id]].[[extension]]',
|
|
|
|
'filePath' => '@staticRoot/origin/posts/[[id]].[[extension]]',
|
|
|
|
'fileUrl' => '@static/origin/posts/[[id]].[[extension]]',
|
|
|
|
'thumbPath' => '@staticRoot/cache/posts/[[profile]]_[[id]].[[extension]]',
|
|
|
|
'thumbUrl' => '@static/cache/posts/[[profile]]_[[id]].[[extension]]',
|
|
|
|
'thumbs' => [
|
|
|
|
'blog_list' => ['width' => 750, 'height' => 300],
|
|
|
|
'blog_post' => ['width' => 900, 'height' => 300],
|
|
|
|
|
|
|
|
'admin' => ['width' => 60, 'height' => 60],
|
|
|
|
'thumb' => ['width' => 150, 'height' => 150],
|
|
|
|
'list' => ['width' => 200, 'height' => 200],
|
|
|
|
'home_slider' => ['width' => 369, 'height' => 343],
|
|
|
|
'94_94' => ['width' => 94, 'height' => 94],
|
|
|
|
'368_287' => ['width' => 368, 'height' => 287],
|
|
|
|
'370_325' => ['width' => 370, 'height' => 325],
|
|
|
|
'683_407' => ['width' => 683, 'height' => 407],
|
|
|
|
'thumb_gallery_view' => ['width' => 300, 'height' => 170],
|
|
|
|
//'widget_list' => ['width' => 228, 'height' => 228],
|
|
|
|
//'origin' => ['processor' => [new WaterMarker(1024, 768, '@frontend/web/image/logo.png'), 'process']],
|
|
|
|
'origin' => ['width' => 1024, 'height' => 768],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function transactions(): array
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
self::SCENARIO_DEFAULT => self::OP_ALL,
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function find(): BlogPostQuery
|
|
|
|
{
|
|
|
|
return new BlogPostQuery(static::class);
|
|
|
|
}
|
|
|
|
}
|