|  |  |  | <?php
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace common\modules\blog\entities;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use common\modules\blog\entities\queries\BlogPostQuery;
 | 
					
						
							|  |  |  | use core\behaviors\MetaBehavior;
 | 
					
						
							|  |  |  | use core\behaviors\RevisionBehavior;
 | 
					
						
							|  |  |  | 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 int $type
 | 
					
						
							|  |  |  |  * @property int $revision_at
 | 
					
						
							|  |  |  |  * @property int $revision_id
 | 
					
						
							|  |  |  |  *
 | 
					
						
							|  |  |  |  * @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 TYPE_PUBLIC = 0;
 | 
					
						
							|  |  |  | 	const TYPE_REVISION = 1;
 | 
					
						
							|  |  |  | 	const TYPE_PREVIEW = 2;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const FILE_ORIGINAL_PATH = '@staticRoot/origin/posts';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	public $meta;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	public static function create($categoryId, $title, $slug, $description, $content, $published_at, $video, $type = 0, 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;
 | 
					
						
							|  |  |  | 		$post->type = $type;
 | 
					
						
							|  |  |  | 		$post->revision_at = time();
 | 
					
						
							|  |  |  | 		return $post;
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	public function setImage(UploadedFile $image): void
 | 
					
						
							|  |  |  | 	{
 | 
					
						
							|  |  |  | 		$this->image = $image;
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	public function edit($categoryId, $title, $slug, $description, $content, $published_at, $video, $type = 0, 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;
 | 
					
						
							|  |  |  | 		$this->type = $type;
 | 
					
						
							|  |  |  | 		$this->revision_at = time();
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @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'),
 | 
					
						
							|  |  |  |             'type' => Yii::t('blog', 'Type'),
 | 
					
						
							|  |  |  |             'revision_at' => Yii::t('blog', 'Revision At'),
 | 
					
						
							|  |  |  |             '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::class, ['post_id' => 'id']);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function getBlogTagAssignments(): ActiveQuery
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         return $this->hasMany(BlogTagAssignment::class, ['post_id' => 'id']);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function getTags(): ActiveQuery
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         return $this->hasMany(BlogTag::class, ['id' => 'tag_id'])->viaTable('blog_tag_assignments', ['post_id' => 'id']);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function getCategory(): ActiveQuery
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         return $this->hasOne(BlogCategory::class, ['id' => 'category_id']);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ######################################
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	public function behaviors(): array
 | 
					
						
							|  |  |  | 	{
 | 
					
						
							|  |  |  | 		return [
 | 
					
						
							|  |  |  | 			TimestampBehavior::class,
 | 
					
						
							|  |  |  | 			MetaBehavior::class,
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				'class' => SaveRelationsBehavior::class,
 | 
					
						
							|  |  |  | 				'relations' => ['blogTagAssignments', 'blogComments'],
 | 
					
						
							|  |  |  | 			],
 | 
					
						
							|  |  |  | 			[
 | 
					
						
							|  |  |  | 				// todo Image Sizes to settings or theme settings
 | 
					
						
							|  |  |  | 				'class' => ImageUploadBehavior::class,
 | 
					
						
							|  |  |  | 				'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, 'resizeUp' => true],
 | 
					
						
							|  |  |  | 					'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);
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 |