Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental article admin with article content dimension entity #554

Merged
merged 2 commits into from
Mar 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Article/Domain/Model/Article.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@
namespace Sulu\Bundle\ArticleBundle\Article\Domain\Model;

use Ramsey\Uuid\Uuid;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityTrait;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface;
use Sulu\Component\Persistence\Model\AuditableTrait;

/**
* @experimental
*/
class Article implements ArticleInterface
{
use ContentRichEntityTrait;
use AuditableTrait;

/**
* @var string
*/
private $id;
protected $id;

public function __construct(
?string $id = null
Expand All @@ -36,4 +39,12 @@ public function getId(): string
{
return $this->id;
}

/**
* @return ArticleDimensionContentInterface
*/
public function createDimensionContent(): DimensionContentInterface
{
return new ArticleDimensionContent($this);
}
}
101 changes: 101 additions & 0 deletions Article/Domain/Model/ArticleDimensionContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

declare(strict_types=1);

/*
* This file is part of Sulu.
*
* (c) Sulu GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ArticleBundle\Article\Domain\Model;

use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentTrait;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\ExcerptTrait;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\RoutableTrait;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\SeoTrait;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\TemplateTrait;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\WorkflowTrait;

/**
* @experimental
*/
class ArticleDimensionContent implements ArticleDimensionContentInterface
{
use DimensionContentTrait;
use ExcerptTrait;
use RoutableTrait;
use SeoTrait;
use TemplateTrait {
getTemplateData as parentGetTemplateData;
setTemplateData as parentSetTemplateData;
}
use WorkflowTrait;

/**
* @var int
*/
protected $id;

/**
* @var ArticleInterface
*/
protected $article;

/**
* @var string|null
*/
protected $title;

public function __construct(ArticleInterface $article)
{
$this->article = $article;
}

/**
* @return ArticleInterface
*/
public function getResource(): ContentRichEntityInterface
{
return $this->article;
}

public function getTitle(): ?string
{
return $this->title;
}

public function setTitle(?string $title): void
{
$this->title = $title;
}

public function getTemplateData(): array
{
$data = $this->parentGetTemplateData();
$data['title'] = $this->getTitle();

return $data;
}

public function setTemplateData(array $templateData): void
{
$this->setTitle($templateData['title']);
unset($templateData['title']);
$this->parentSetTemplateData($templateData);
}

public static function getTemplateType(): string
{
return ArticleInterface::TEMPLATE_TYPE;
}

public static function getResourceKey(): string
{
return ArticleInterface::RESOURCE_KEY;
}
}
29 changes: 29 additions & 0 deletions Article/Domain/Model/ArticleDimensionContentInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/*
* This file is part of Sulu.
*
* (c) Sulu GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ArticleBundle\Article\Domain\Model;

use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\ExcerptInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\RoutableInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\SeoInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\TemplateInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\WorkflowInterface;

/**
* @experimental
*/
interface ArticleDimensionContentInterface extends DimensionContentInterface, ExcerptInterface, SeoInterface, TemplateInterface, RoutableInterface, WorkflowInterface
{
public function getTitle(): ?string;

public function setTitle(?string $title);
}
3 changes: 2 additions & 1 deletion Article/Domain/Model/ArticleInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@

namespace Sulu\Bundle\ArticleBundle\Article\Domain\Model;

use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityInterface;
use Sulu\Component\Persistence\Model\AuditableInterface;

/**
* @experimental
*/
interface ArticleInterface extends AuditableInterface
interface ArticleInterface extends AuditableInterface, ContentRichEntityInterface
{
public const TEMPLATE_TYPE = 'article';
public const RESOURCE_KEY = 'article';
Expand Down
166 changes: 166 additions & 0 deletions Article/Infrastructure/Sulu/Admin/ArticleAdmin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<?php

/*
* This file is part of Sulu.
*
* (c) Sulu GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ArticleBundle\Article\Infrastructure\Sulu\Admin;

use Sulu\Bundle\AdminBundle\Admin\Admin;
use Sulu\Bundle\AdminBundle\Admin\Navigation\NavigationItem;
use Sulu\Bundle\AdminBundle\Admin\Navigation\NavigationItemCollection;
use Sulu\Bundle\AdminBundle\Admin\View\ToolbarAction;
use Sulu\Bundle\AdminBundle\Admin\View\ViewBuilderFactoryInterface;
use Sulu\Bundle\AdminBundle\Admin\View\ViewCollection;
use Sulu\Bundle\ArticleBundle\Article\Domain\Model\ArticleInterface;
use Sulu\Bundle\ContentBundle\Content\Infrastructure\Sulu\Admin\ContentViewBuilderFactoryInterface;
use Sulu\Component\Localization\Manager\LocalizationManagerInterface;
use Sulu\Component\Security\Authorization\PermissionTypes;
use Sulu\Component\Security\Authorization\SecurityCheckerInterface;

/**
* @internal This class is internal and should not be extended or overwritten.
* You can create a separate admin class in your project and get the
* respective object from the collection to extend a navigation item or a view
*
* @experimental
*/
class ArticleAdmin extends Admin
{
const SECURITY_CONTEXT = 'sulu.article.articles';

const LIST_VIEW = 'sulu_article.article.list';

const ADD_TABS_VIEW = 'sulu_article.article.add_tabs';

const EDIT_TABS_VIEW = 'sulu_article.article.edit_tabs';

/**
* @var ViewBuilderFactoryInterface
*/
private $viewBuilderFactory;

/**
* @var ContentViewBuilderFactoryInterface
*/
private $contentViewBuilderFactory;

/**
* @var SecurityCheckerInterface
*/
private $securityChecker;

/**
* @var LocalizationManagerInterface
*/
private $localizationManager;

public function __construct(
ViewBuilderFactoryInterface $viewBuilderFactory,
ContentViewBuilderFactoryInterface $contentViewBuilderFactory,
SecurityCheckerInterface $securityChecker,
LocalizationManagerInterface $localizationManager
) {
$this->viewBuilderFactory = $viewBuilderFactory;
$this->contentViewBuilderFactory = $contentViewBuilderFactory;
$this->securityChecker = $securityChecker;
$this->localizationManager = $localizationManager;
}

public function configureNavigationItems(NavigationItemCollection $navigationItemCollection): void
{
if ($this->securityChecker->hasPermission(static::SECURITY_CONTEXT, PermissionTypes::EDIT)) {
$navigationItem = new NavigationItem('sulu_article.articles');
$navigationItem->setPosition(20);
$navigationItem->setIcon('su-newspaper');
$navigationItem->setView(static::LIST_VIEW);

$navigationItemCollection->add($navigationItem);
}
}

public function configureViews(ViewCollection $viewCollection): void
{
$bundlePrefix = 'sulu_article.';
$locales = $this->localizationManager->getLocales();
$resourceKey = ArticleInterface::RESOURCE_KEY;

$listToolbarActions = [];

if ($this->securityChecker->hasPermission(static::SECURITY_CONTEXT, PermissionTypes::ADD)) {
$listToolbarActions[] = new ToolbarAction('sulu_admin.add');
}

if ($this->securityChecker->hasPermission(static::SECURITY_CONTEXT, PermissionTypes::DELETE)) {
$listToolbarActions[] = new ToolbarAction('sulu_admin.delete');
}

if ($this->securityChecker->hasPermission(static::SECURITY_CONTEXT, PermissionTypes::VIEW)) {
$listToolbarActions[] = new ToolbarAction('sulu_admin.export');
}

if ($this->securityChecker->hasPermission(static::SECURITY_CONTEXT, PermissionTypes::EDIT)) {
$viewCollection->add(
$this->viewBuilderFactory->createListViewBuilder(static::LIST_VIEW, '/' . $resourceKey . '/:locale')
->setResourceKey($resourceKey)
->setListKey($resourceKey)
->setTitle($bundlePrefix . $resourceKey)
->addListAdapters(['table'])
->addLocales($locales)
->setDefaultLocale($locales[0])
->setAddView(static::ADD_TABS_VIEW)
->setEditView(static::EDIT_TABS_VIEW)
->addToolbarActions($listToolbarActions)
);
$viewCollection->add(
$this->viewBuilderFactory->createResourceTabViewBuilder(static::ADD_TABS_VIEW, '/' . $resourceKey . '/:locale/add')
->setResourceKey($resourceKey)
->addLocales($locales)
->setBackView(static::LIST_VIEW)
);
$viewCollection->add(
$this->viewBuilderFactory->createResourceTabViewBuilder(static::EDIT_TABS_VIEW, '/' . $resourceKey . '/:locale/:id')
->setResourceKey($resourceKey)
->addLocales($locales)
->setBackView(static::LIST_VIEW)
->setTitleProperty('name')
);

$viewBuilders = $this->contentViewBuilderFactory->createViews(
ArticleInterface::class,
static::EDIT_TABS_VIEW,
static::ADD_TABS_VIEW,
static::SECURITY_CONTEXT
);

foreach ($viewBuilders as $viewBuilder) {
$viewCollection->add($viewBuilder);
}
}
}

/**
* @return mixed[]
*/
public function getSecurityContexts()
{
return [
'Sulu' => [
'Global' => [
static::SECURITY_CONTEXT => [
PermissionTypes::VIEW,
PermissionTypes::ADD,
PermissionTypes::EDIT,
PermissionTypes::DELETE,
PermissionTypes::LIVE,
],
],
],
];
}
}
7 changes: 7 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Sulu\Bundle\ArticleBundle\DependencyInjection;

use Sulu\Bundle\ArticleBundle\Article\Domain\Model\Article;
use Sulu\Bundle\ArticleBundle\Article\Domain\Model\ArticleDimensionContent;
use Sulu\Bundle\ArticleBundle\Document\ArticlePageViewObject;
use Sulu\Bundle\ArticleBundle\Document\ArticleViewDocument;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
Expand Down Expand Up @@ -51,6 +52,12 @@ public function getConfigTreeBuilder()
->scalarNode('model')->defaultValue(Article::class)->end()
->end()
->end()
->arrayNode('article_content')
->addDefaultsIfNotSet()
->children()
->scalarNode('model')->defaultValue(ArticleDimensionContent::class)->end()
->end()
->end()
->end()
->end()
->end()
Expand Down
2 changes: 2 additions & 0 deletions DependencyInjection/SuluArticleExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ public function load(array $configs, ContainerBuilder $container)
private function loadExperimentalStorage(array $config, ContainerBuilder $container, Loader\XmlFileLoader $loader): void
{
$this->configurePersistence($config['article']['objects'], $container);

$loader->load('experimental.xml');
}

/**
Expand Down
6 changes: 6 additions & 0 deletions Resources/config/doctrine/Article/Article.orm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@
<id name="id" type="string" column="id">
<generator strategy="NONE"/>
</id>

<one-to-many field="dimensionContents" target-entity="Sulu\Bundle\ArticleBundle\Article\Domain\Model\ArticleDimensionContentInterface" mapped-by="article">
<cascade>
<cascade-persist/>
</cascade>
</one-to-many>
</mapped-superclass>
</doctrine-mapping>
Loading