Skip to content

Commit

Permalink
Add case studies
Browse files Browse the repository at this point in the history
  • Loading branch information
maximehuran committed Aug 22, 2024
1 parent 162b225 commit 038ef75
Show file tree
Hide file tree
Showing 34 changed files with 559 additions and 141 deletions.
29 changes: 29 additions & 0 deletions src/Entity/Article.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use InvalidArgumentException;
use Sylius\Component\Channel\Model\ChannelInterface;
use Sylius\Component\Resource\Model\TimestampableTrait;
use Sylius\Component\Resource\Model\ToggleableTrait;
Expand All @@ -36,6 +37,8 @@ class Article implements ArticleInterface

protected ?string $image = null;

protected ?string $thumbnailImage = null;

/** @var bool */
protected $enabled = true;

Expand All @@ -50,6 +53,8 @@ class Article implements ArticleInterface
/** @var Collection<array-key, AuthorInterface> */
protected Collection $authors;

protected string $type = ArticleInterface::BLOG_TYPE;

protected string $state = ArticleInterface::STATE_DRAFT;

public function __construct()
Expand Down Expand Up @@ -85,6 +90,16 @@ public function setImage(?string $image): void
$this->image = $image;
}

public function getThumbnailImage(): ?string
{
return $this->thumbnailImage;
}

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

public function getSlug(): ?string
{
return $this->getTranslation()->getSlug();
Expand Down Expand Up @@ -165,6 +180,20 @@ public function removeChannel(ChannelInterface $channel): void
}
}

public function getType(): string
{
return $this->type;
}

public function setType(string $type): void
{
if (!\in_array($type, ArticleInterface::TYPES, true)) {
throw new InvalidArgumentException(sprintf('Invalid type "%s". Available types are: %s', $type, implode(', ', ArticleInterface::TYPES)));
}

$this->type = $type;
}

public function getState(): string
{
return $this->state;
Expand Down
17 changes: 17 additions & 0 deletions src/Entity/ArticleInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ interface ArticleInterface extends ChannelsAwareInterface, ResourceInterface, Sl

public const STATE_PUBLISHED = 'published';

public const BLOG_TYPE = 'blog';

public const CASE_STUDY_TYPE = 'case_study';

public const TYPES = [
self::BLOG_TYPE,
self::CASE_STUDY_TYPE,
];

public function getTitle(): ?string;

public function setTitle(?string $title): void;
Expand All @@ -42,6 +51,10 @@ public function getImage(): ?string;

public function setImage(?string $image): void;

public function getThumbnailImage(): ?string;

public function setThumbnailImage(?string $thumbnailImage): void;

public function getContent(): ?string;

public function setContent(string $content): void;
Expand All @@ -57,6 +70,10 @@ public function hasTag(TagInterface $tag): bool;
*/
public function getTags(): Collection;

public function getType(): string;

public function setType(string $type): void;

public function getState(): string;

public function setState(string $state): void;
Expand Down
7 changes: 6 additions & 1 deletion src/EventListener/AdminMenuListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ public function __invoke(MenuBuilderEvent $event): void
->setLabelAttribute('icon', 'grid layout')
;

$blogMenu->addChild('monsieurbiz-blog-articles', ['route' => 'monsieurbiz_blog_admin_article_index'])
$blogMenu->addChild('monsieurbiz-blog-articles-blog', ['route' => 'monsieurbiz_blog_admin_article_index'])
->setLabel('monsieurbiz_blog.ui.articles')
->setLabelAttribute('icon', 'newspaper')
;

$blogMenu->addChild('monsieurbiz-blog-articles-case-study', ['route' => 'monsieurbiz_blog_admin_case_study_index'])
->setLabel('monsieurbiz_blog.ui.case_studies')
->setLabelAttribute('icon', 'crosshairs')
;

$blogMenu->addChild('monsieurbiz-blog-authors', ['route' => 'monsieurbiz_blog_admin_author_index'])
->setLabel('monsieurbiz_blog.ui.authors')
->setLabelAttribute('icon', 'user')
Expand Down
52 changes: 52 additions & 0 deletions src/EventListener/ArticleListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/*
* This file is part of Monsieur Biz's Blog plugin for Sylius.
* (c) Monsieur Biz <sylius@monsieurbiz.com>
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace MonsieurBiz\SyliusBlogPlugin\EventListener;

use MonsieurBiz\SyliusBlogPlugin\Entity\ArticleInterface;
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

#[AsEventListener(event: 'monsieurbiz_blog.article.initialize_update', method: 'initializeUpdateArticle')]
#[AsEventListener(event: 'monsieurbiz_blog.case_study.initialize_update', method: 'initializeUpdateCaseStudy')]
class ArticleListener
{
public function initializeUpdateArticle(ResourceControllerEvent $event): void
{
$article = $event->getSubject();

if (!$article instanceof ArticleInterface) {
return;
}

if (ArticleInterface::BLOG_TYPE === $article->getType()) {
return;
}

throw new NotFoundHttpException('The article has not been found');
}

public function initializeUpdateCaseStudy(ResourceControllerEvent $event): void
{
$article = $event->getSubject();

if (!$article instanceof ArticleInterface) {
return;
}

if (ArticleInterface::CASE_STUDY_TYPE === $article->getType()) {
return;
}

throw new NotFoundHttpException('The article has not been found');
}
}
46 changes: 46 additions & 0 deletions src/Factory/ArticleFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/*
* This file is part of Monsieur Biz's Blog plugin for Sylius.
* (c) Monsieur Biz <sylius@monsieurbiz.com>
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace MonsieurBiz\SyliusBlogPlugin\Factory;

use MonsieurBiz\SyliusBlogPlugin\Entity\ArticleInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;

/**
* @implements ArticleFactoryInterface<ArticleInterface>
*/
#[AsDecorator(decorates: 'monsieurbiz_blog.factory.article')]
final class ArticleFactory implements ArticleFactoryInterface
{
/**
* @param FactoryInterface<ArticleInterface> $originalArticleFactory
*/
public function __construct(
#[AutowireDecorated]
private readonly FactoryInterface $originalArticleFactory
) {
}

public function createNew(): ArticleInterface
{
return $this->originalArticleFactory->createNew();
}

public function createNewWithType(string $type): ArticleInterface
{
$article = $this->createNew();
$article->setType($type);

return $article;
}
}
25 changes: 25 additions & 0 deletions src/Factory/ArticleFactoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/*
* This file is part of Monsieur Biz's Blog plugin for Sylius.
* (c) Monsieur Biz <sylius@monsieurbiz.com>
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace MonsieurBiz\SyliusBlogPlugin\Factory;

use MonsieurBiz\SyliusBlogPlugin\Entity\ArticleInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;

/**
* @template T of ArticleInterface
*
* @extends FactoryInterface<T>
*/
interface ArticleFactoryInterface extends FactoryInterface
{
public function createNewWithType(string $type): ArticleInterface;
}
2 changes: 2 additions & 0 deletions src/Fixture/ArticleFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ protected function configureResourceNode(ArrayNodeDefinition $resourceNode): voi
$resourceNode
->children()
->booleanNode('enabled')->defaultTrue()->end()
->scalarNode('type')->cannotBeEmpty()->end()
->scalarNode('image')->defaultNull()->end()
->scalarNode('thumbnailImage')->defaultNull()->end()
->arrayNode('tags')
->scalarPrototype()->end()
->end()
Expand Down
10 changes: 10 additions & 0 deletions src/Fixture/Factory/ArticleFixtureFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public function create(array $options = []): ArticleInterface
/** @var ArticleInterface $article */
$article = $this->articleFactory->createNew();
$article->setEnabled($options['enabled']);
$article->setType($options['type']);
foreach ($options['tags'] as $tag) {
$article->addTag($tag);
}
Expand Down Expand Up @@ -121,12 +122,21 @@ protected function configureOptions(OptionsResolver $resolver): void
return $this->faker->boolean(80);
})

->setDefault('type', ArticleInterface::BLOG_TYPE)
->setAllowedTypes('type', ['string'])

->setDefault('image', $this->lazyImageDefault(80))
->setAllowedTypes('image', ['string', 'null'])
->setNormalizer('image', function (Options $options, $previousValue): ?string {
return $this->getImagePath($previousValue);
})

->setDefault('thumbnailImage', $this->lazyImageDefault(10))
->setAllowedTypes('thumbnailImage', ['string', 'null'])
->setNormalizer('thumbnailImage', function (Options $options, $previousValue): ?string {
return $this->getImagePath($previousValue);
})

->setDefault('tags', LazyOption::randomOnes($this->tagRepository, 2))
->setAllowedTypes('tags', ['array'])
->setNormalizer('tags', function (Options $options, $previousValue): array {
Expand Down
5 changes: 5 additions & 0 deletions src/Form/Type/ArticleType.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'label' => 'monsieurbiz_blog.form.article.image',
'required' => false,
])
->add('thumbnailImage', ImageType::class, [
'label' => 'monsieurbiz_blog.form.article.thumbnail_image',
'help' => 'monsieurbiz_blog.form.article.thumbnail_image_help',
'required' => false,
])
->add('translations', ResourceTranslationsType::class, [
'entry_type' => ArticleTranslationType::class,
])
Expand Down
38 changes: 38 additions & 0 deletions src/Migrations/Version20240822185838.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/*
* This file is part of Monsieur Biz's Blog plugin for Sylius.
* (c) Monsieur Biz <sylius@monsieurbiz.com>
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace MonsieurBiz\SyliusBlogPlugin\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240822185838 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE monsieurbiz_blog_article ADD thumbnailImage VARCHAR(255) DEFAULT NULL, ADD type VARCHAR(255) NOT NULL');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE monsieurbiz_blog_article DROP thumbnailImage, DROP type');
}
}
Loading

0 comments on commit 038ef75

Please sign in to comment.