<?php
namespace NetzpBlog6\Helper;
use NetzpBlog6\Core\Content\Blog\BlogEntity;
use Shopware\Core\Content\ProductStream\Service\ProductStreamBuilderInterface;
use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Grouping\FieldGrouping;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class BlogHelper
{
private $container;
private $productStreamBuilder;
private $productRepository;
public function __construct(ContainerInterface $container,
ProductStreamBuilderInterface $productStreamBuilder,
EntityRepositoryInterface $productRepository)
{
$this->container = $container;
$this->productStreamBuilder = $productStreamBuilder;
$this->productRepository = $productRepository;
}
public function getPublicBlogPosts(SalesChannelContext $salesChannelContext, Context $context, $limit = null, $offset = null,
$rssCategoryOnly = false)
{
$repo = $this->container->get('s_plugin_netzp_blog.repository');
$criteria = new Criteria();
$this->addBlogDateFilterAndSorting($criteria, true);
$criteria->addAssociation('category');
$criteria->addAssociation('tags');
$criteria->addAssociation('items');
$criteria->addAssociation('blogmedia');
$criteria->addFilter(new EqualsFilter('noindex', false));
$criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsFilter('categoryid', '00000000000000000000000000000000'),
new EqualsFilter('category.onlyloggedin', false),
]));
$criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsFilter('category.saleschannelid', null),
new EqualsFilter('category.saleschannelid', '00000000000000000000000000000000'),
new EqualsFilter('category.saleschannelid', $salesChannelContext->getSalesChannel()->getId()),
]));
if($rssCategoryOnly) {
$criteria->addFilter(new EqualsFilter('category.includeinrss', true));
}
$criteria->addSorting(new FieldSorting('items.number', FieldSorting::ASCENDING));
$criteria->addSorting(new FieldSorting('blogmedia.number', FieldSorting::ASCENDING));
if($limit) {
$criteria->setLimit($limit);
}
if($offset) {
$criteria->setOffset($offset);
}
$posts = $repo->search($criteria, $context)->getEntities();
return $posts;
}
public function isPluginActive($pluginName, Context $context)
{
$pluginRepo = $this->container->get('plugin.repository');
$pluginCriteria = new Criteria();
$pluginCriteria->addFilter(new EqualsFilter('name', $pluginName));
$plugin = $pluginRepo->search($pluginCriteria, $context)->getEntities()->first();
return $plugin && $plugin->getActive();
}
public function getBlogPosts(Criteria $criteria, SalesChannelContext $salesChannelContext,
?string $categoryId, ?string $authorId, ?array $tags, ?string $sortOrder)
{
$repo = $this->container->get('s_plugin_netzp_blog.repository');
$criteria->addAssociation('netzp_blog.translations');
$criteria->addAssociation('category');
$criteria->addAssociation('categories');
$criteria->addAssociation('tags');
$this->addBlogDateFilterAndSorting($criteria, false); // without sorting
$this->addRestrictionsFilter($criteria, $salesChannelContext);
if($categoryId && $categoryId != '00000000000000000000000000000000') {
$criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsFilter('categoryid', $categoryId),
new EqualsAnyFilter('categories.id', [$categoryId]),
]));
}
if($authorId && $authorId != '00000000000000000000000000000000') {
$criteria->addFilter(
new EqualsFilter('authorid', $authorId)
);
}
if($tags != null && is_array($tags) && count($tags) > 0) {
$criteria->addFilter(new EqualsAnyFilter('tags.id', $tags));
}
$criteria->addSorting(new FieldSorting('sticky', FieldSorting::DESCENDING));
$criteria->addSorting(new FieldSorting(
'postdate', $sortOrder == 'asc' ? FieldSorting::ASCENDING : FieldSorting::DESCENDING)
);
$criteria->addSorting(new FieldSorting('title', FieldSorting::ASCENDING));
$results = $repo->search($criteria, $salesChannelContext->getContext());
return $results;
}
public function getBlogPost($postId, SalesChannelContext $salesChannelContext, Context $context)
{
if( ! Uuid::isValid($postId)) {
throw new NotFoundHttpException('No valid UUID');
}
$repo = $this->container->get('s_plugin_netzp_blog.repository');
$criteria = new Criteria();
$criteria->addAssociation('products.event');
$criteria->addAssociation('category');
$criteria->addAssociation('categories');
$criteria->addAssociation('tags');
$criteria->addAssociation('items');
$criteria->getAssociation('items')->addSorting(new FieldSorting('number', FieldSorting::ASCENDING));
$criteria->addAssociation('blogmedia');
$criteria->getAssociation('blogmedia')->addSorting(new FieldSorting('number', FieldSorting::ASCENDING));
$criteria->addAssociation('blogmedia.media');
$criteria->addFilter(new EqualsFilter('id', $postId));
$this->addRestrictionsFilter($criteria, $salesChannelContext);
$this->addBlogDateFilterAndSorting($criteria);
$post = $repo->search($criteria, $context)->getEntities()->first();
if( ! $post) {
throw new NotFoundHttpException('Blog post not found');
}
$assignedProducts = [];
$tmpProducts = [];
if($post->getIsProductStream() && $post->getProductStreamId() != null) {
try {
$tmpProducts = $this->collectByProductStream($context, $post);
}
catch(\Exception $ex) {
//
}
}
else {
$tmpProducts = $post->getProducts();
}
foreach ($tmpProducts as $product) {
array_push($assignedProducts, $product->getId());
}
if(count($assignedProducts) > 0) {
$productRepository = $this->container->get('sales_channel.product.repository');
$criteria2 = new Criteria($assignedProducts);
$criteria2->addAssociation('cover');
$criteria2->addAssociation('event');
$products = $productRepository->search($criteria2, $salesChannelContext)->getEntities();
$post->setProducts($products);
}
return $post;
}
public function addRestrictionsFilter(Criteria $criteria, SalesChannelContext $salesChannelContext)
{
$userLoggedIn = $salesChannelContext->getCustomer() != null;
$userCustomerGroupId = $salesChannelContext->getCurrentCustomerGroup()->getId();
$criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsFilter('category.saleschannelid', null),
new EqualsFilter('category.saleschannelid', '00000000000000000000000000000000'),
new EqualsFilter('category.saleschannelid', $salesChannelContext->getSalesChannel()->getId()),
]));
$criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsFilter('categoryid', '00000000000000000000000000000000'),
new EqualsFilter('category.onlyloggedin', false),
new MultiFilter(MultiFilter::CONNECTION_AND, [
new EqualsFilter('category.onlyloggedin', true),
new EqualsFilter('category.onlyloggedin', $userLoggedIn)
])
]));
$criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsFilter('category.customergroupid', null),
new EqualsFilter('category.customergroupid', '00000000000000000000000000000000'),
new MultiFilter(MultiFilter::CONNECTION_AND, [
new NotFilter(NotFilter::CONNECTION_AND, [
new EqualsFilter('category.customergroupid', '00000000000000000000000000000000')
]),
new EqualsFilter('category.customergroupid', $userCustomerGroupId),
])
]));
}
public function addBlogDateFilterAndSorting(Criteria $criteria, bool $addSorting = false)
{
$now = (new \DateTime())->format('Y-m-d');
$criteria->addFilter(
new MultiFilter(
MultiFilter::CONNECTION_OR, [
new RangeFilter('showfrom', ['lte' => $now]),
new EqualsFilter('showfrom', null)
]
)
);
$criteria->addFilter(
new MultiFilter(
MultiFilter::CONNECTION_OR, [
new RangeFilter('showuntil', ['gte' => $now]),
new EqualsFilter('showuntil', null)
]
)
);
if($addSorting) {
$criteria->addSorting(new FieldSorting('sticky', FieldSorting::DESCENDING));
$criteria->addSorting(new FieldSorting('postdate', 'desc'));
$criteria->addSorting(new FieldSorting('title', FieldSorting::ASCENDING));
}
}
private function collectByProductStream(Context $context, BlogEntity $blogPost): EntityCollection
{
if (!$blogPost->getIsProductStream() || $blogPost->getProductStreamId() == null) {
return new EntityCollection();
}
$filters = $this->productStreamBuilder->buildFilters($blogPost->getProductStreamId(), $context);
$criteria = new Criteria();
$criteria->addAssociation('options.group');
$criteria->addFilter(...$filters);
// Ensure storefront presentation settings of product variants, see ProductSliderCmsElementResolver
$criteria->addGroupField(new FieldGrouping('displayGroup'));
$criteria->addFilter(
new NotFilter(
NotFilter::CONNECTION_AND,
[new EqualsFilter('displayGroup', null)]
)
);
$criteria->addSorting(new FieldSorting('name', FieldSorting::ASCENDING));
return $this->productRepository->search($criteria, $context)->getEntities();
}
}