<?php
namespace Whater\Domain\Blog\Model;
use BornFree\TacticianDomainEvent\Recorder\ContainsRecordedEvents;
use BornFree\TacticianDomainEvent\Recorder\EventRecorderCapabilities;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Ramsey\Uuid\Uuid;
use Assert\Assertion;
use Whater\Domain\Blog\Exception\InvalidArticleStatusException;
use Whater\Domain\Blog\Model\Translation\TranslatableInterface;
use Whater\Domain\Blog\Model\Translation\TranslatableTrait;
use Whater\Domain\Blog\Model\Translation\TranslationInterface;
use Whater\Domain\Common\Exception\InvalidUUIDException;
/**
* Class Article
*
* @package Whater\Domain\Blog\Model
*/
class Article implements ContainsRecordedEvents
{
use EventRecorderCapabilities;
public const DEFAULT_LOCALE = 'es';
public const ARTICLE_DRAFT = "AS_DRAFT";
public const ARTICLE_PUBLIC = "AS_PUBLIC";
/**
* @var string
*/
private $uuid;
/**
* @var string
*/
private $status;
/**
* @var Collection
*/
private $categories;
/**
* @var Collection
*/
private $translations;
/**
* @var string
*/
private $headerImageUrl;
/**
* @var \DateTime
*/
private $publishAt;
/**
* @var string
*/
private $defaultLocale;
/**
* @var null|\DateTime
*/
private $createdAt;
/**
* @var null|\DateTime
*/
private $updatedAt;
/**
* @var bool
*/
private $showInBlog;
/**
* @var bool
*/
private $showInWhaterpoints;
/**
* @var Collection
*/
private $linkedWhaterpoints;
/**
* @var bool
*/
private $showInDistributionNetworks;
/**
* @var Collection
*/
private $linkedDistributionNetworks;
public function __construct(
string $articleId = null,
string $title,
string $slug,
string $content,
\DateTime $publishAt = null,
string $status = Article::ARTICLE_DRAFT,
string $locale = Article::DEFAULT_LOCALE,
string $headerImageUrl = null
) {
try {
$this->uuid = Uuid::fromString($articleId ?: Uuid::uuid4())->toString();
} catch (\InvalidArgumentException $e) {
throw new InvalidUUIDException();
}
$this->categories = new ArrayCollection();
switch ($status) {
case Article::ARTICLE_DRAFT:
case Article::ARTICLE_PUBLIC:
$this->status = $status;
break;
default:
throw new InvalidArticleStatusException();
}
$this->defaultLocale = $locale;
$articleTranslation = new ArticleTranslation(
null,
$this,
$locale,
$title,
$slug,
$content
);
$this->translations = new ArrayCollection();
$this->translations->add($articleTranslation);
$this->publishAt = $publishAt;
if (is_null($this->publishAt)) {
$this->publishAt = new \DateTime();
}
$this->headerImageUrl = $headerImageUrl;
$this->showInBlog = true;
$this->showInWhaterpoints = false;
$this->linkedWhaterpoints = new ArrayCollection();
$this->showInDistributionNetworks = false;
$this->linkedDistributionNetworks = new ArrayCollection();
$this->createdAt = new \DateTime();
$this->updatedAt = $this->createdAt();
}
/**
* @return string
*/
public function id(): string
{
return $this->uuid;
}
/**
* @return Collection
*/
public function categories(): Collection
{
return $this->categories;
}
/**
* @param string|null $locale
* @return ArticleTranslation
*/
public function getTranslation(?string $locale = null): ArticleTranslation
{
$articleTranslation = null;
$locale = $locale ?: $this->defaultLocale();
foreach ($this->translations as $translation) {
if ($translation->locale() == $locale) {
$articleTranslation = $translation;
break;
}
}
if (is_null($articleTranslation)) {
$articleTranslation = new ArticleTranslation(
null,
$this,
$locale,
$this->getTranslation(Article::DEFAULT_LOCALE)->title(),
$this->getTranslation(Article::DEFAULT_LOCALE)->slug(),
$this->getTranslation(Article::DEFAULT_LOCALE)->content()
);
$this->translations->add($articleTranslation);
}
return $articleTranslation;
}
/**
* @param string|null $locale
* @return bool
*/
public function hasTranslation(string $locale): bool
{
foreach ($this->translations as $translation) {
if ($translation->locale() == $locale) {
return true;
}
}
return false;
}
public function updateArticle(
string $status,
string $headerImageUrl = null,
\DateTime $publishAt = null
) {
if ($this->status != $status) {
switch ($status) {
case Article::ARTICLE_DRAFT:
case Article::ARTICLE_PUBLIC:
$this->status = $status;
$this->updatedAt = new \DateTime();
break;
default:
throw new InvalidArticleStatusException();
}
}
if (!is_null($publishAt)) {
$this->publishAt = $publishAt;
$this->updatedAt = new \DateTime();
}
if (!is_null($headerImageUrl)) {
$this->headerImageUrl = $headerImageUrl;
$this->updatedAt = new \DateTime();
}
return $this;
}
public function updateTranslation(
string $locale,
string $title,
string $slug,
string $content,
\DateTime $publishAt = null,
array $metaKeywords = [],
string $metaDescription = null
) {
$articleTranslation = $this->getTranslation($locale);
if (is_null($articleTranslation)) {
$articleTranslation = new ArticleTranslation(
null,
$this,
$locale,
$title,
$slug,
$content,
$metaKeywords,
$metaDescription
);
$this->translations->add($articleTranslation);
} else {
$articleTranslation->updateArticleTranslation(
$title,
$slug,
$content,
$metaKeywords,
$metaDescription
);
}
if (!is_null($publishAt)) {
$this->publishAt = $publishAt;
}
$this->updatedAt = new \DateTime();
return $this;
}
public function updateShowIn(
bool $showInBlog,
bool $showInWhaterpoints,
bool $showInDistributionNetworks
) {
$this->showInBlog = $showInBlog;
$this->showInWhaterpoints = $showInWhaterpoints;
$this->showInDistributionNetworks = $showInDistributionNetworks;
}
/**
* @return string
*/
public function status(): string
{
return $this->status;
}
/**
* @return string
*/
public function headerImageUrl(): ?string
{
return $this->headerImageUrl;
}
/**
* @return string
*/
public function defaultLocale(): string
{
return $this->defaultLocale;
}
/**
* @return string
*/
public function slug(string $locale = null): string
{
return $this->getTranslation($locale)->slug();
}
/**
* @return string
*/
public function title(string $locale = null): string
{
return $this->getTranslation($locale)->title();
}
/**
* @return string
*/
public function content(string $locale = null): string
{
return $this->getTranslation($locale)->content();
}
/**
* @return array
*/
public function metaKeywords(string $locale = null): array
{
return $this->getTranslation($locale)->metaKeywords();
}
/**
* @return string
*/
public function metaDescription(string $locale = null): ?string
{
return $this->getTranslation()->metaDescription();
}
/**
* @return \DateTime
*/
public function publishAt(): \DateTime
{
return $this->publishAt;
}
/**
* @return bool
*/
public function showInBlog(): bool
{
return $this->showInBlog;
}
/**
* @return bool
*/
public function showInWhaterpoints(): bool
{
return $this->showInWhaterpoints;
}
/**
* @return bool
*/
public function showInDistributionNetworks(): bool
{
return $this->showInDistributionNetworks;
}
/**
* @return Collection
*/
public function linkedWhaterpoints(): Collection
{
return $this->linkedWhaterpoints;
}
/**
* @return Collection
*/
public function linkedDistributionNetworks(): Collection
{
return $this->linkedDistributionNetworks;
}
/**
* @return \DateTime
*/
public function createdAt(): \DateTime
{
return $this->createdAt;
}
/**
* @return \DateTime
*/
public function updatedAt(): \DateTime
{
return $this->updatedAt;
}
}