How to add a custom model accessible for respective channel administrators?¶
Given that you are using Sylius Plus, the licensed edition of Sylius, you may have the Administrators per Channel defined in your application. Thus when you add a new, channel-based entity to it, you will need to enable this entity to be viewed only by the relevant channel admins.
1. Define your custom model, our example will be the Supplier entity¶
In order to prepare a simple Entity follow this guide.
Remember to then add your entity to the admin menu. Adding a new entity to the admin menu
is described in the section How to customize Admin Menu
of this guide.
Having your Supplier entity created, add a channel field with relation to the
Channel
entity:
/**
* @var ChannelInterface
* @ORM\ManyToOne(targetEntity="Sylius\Plus\Entity\ChannelInterface")
* @ORM\JoinColumn(name="channel_id", referencedColumnName="id", nullable=true)
*/
protected $channel;
public function getChannel(): ?ChannelInterface
{
return $this->channel;
}
public function setChannel(?ChannelInterface $channel): void
{
$this->channel = $channel;
}
Assuming that your database was up-to-date before these changes, create a proper migration and use it:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
Next, create a form type for your entity:
<?php
declare(strict_types=1);
namespace App\Form\Type;
use Sylius\Bundle\ChannelBundle\Form\Type\ChannelChoiceType;
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
use Sylius\Plus\ChannelAdmin\Application\Provider\AvailableChannelsForAdminProviderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
final class SupplierType extends AbstractResourceType
{
/** @var AvailableChannelsForAdminProviderInterface */
private $availableChannelsForAdminProvider;
public function __construct(
string $dataClass,
array $validationGroups,
AvailableChannelsForAdminProviderInterface $availableChannelsForAdminProvider
) {
parent::__construct($dataClass, $validationGroups);
$this->availableChannelsForAdminProvider = $availableChannelsForAdminProvider;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, [
'label' => 'Name'
])
->add('channel', ChannelChoiceType::class, [
'choices' => $this->availableChannelsForAdminProvider->getChannels(),
'label' => 'sylius.ui.channel',
])
;
}
public function getBlockPrefix(): string
{
return 'supplier';
}
}
# config/services.yaml
App\Form\Type\SupplierType:
arguments:
- 'App\Entity\Supplier'
- 'sylius'
- '@Sylius\Plus\ChannelAdmin\Application\Provider\AvailableChannelsForAdminProviderInterface'
tags: ['form.type']
The Sylius\Plus\ChannelAdmin\Application\Provider\AvailableChannelsForAdminProviderInterface
service allows getting
a list of proper channels for the currently logged in admin user.
Remember to register App\Form\SupplierType
for resource:
sylius_resource:
resources:
app.supplier:
driver: doctrine/orm
classes:
model: App\Entity\Supplier
+ form: App\Form\Type\SupplierType
2. Restrict access to the entity for the respective channel administrator:¶
Note
More information about using administrator roles (ACL/RBAC) can be found here.
Add supplier to restricted resources:
sylius_plus:
channel_admin:
restricted_resources:
supplier: ~
Create
App\Checker\SupplierResourceChannelChecker
and tag this service with sylius_plus.channel_admin.resource_channel_checker:
Tip
If the created entity implements the Sylius\Component\Channel\Model\ChannelAwareInterface
interface,
everything will work without having to do this step and create SupplierResourceChannelChecker
.
<?php
declare(strict_types=1);
namespace App\Checker;
use App\Entity\Supplier;
use Sylius\Plus\ChannelAdmin\Application\Checker\ResourceChannelCheckerInterface;
use Sylius\Plus\Entity\ChannelInterface;
final class SupplierResourceChannelChecker implements ResourceChannelCheckerInterface
{
public function isFromChannel(object $resource, ChannelInterface $channel): bool
{
if ($resource instanceof Supplier && in_array($resource->getChannel(), [$channel, null], true)) {
return true;
}
return false;
}
}
# config/services.yaml
App\Checker\SupplierResourceChannelChecker:
tags:
- { name: sylius_plus.channel_admin.resource_channel_checker }
After that, access to the resource should work properly with all restrictions.
Next add
RestrictingSupplierListQueryBuilder
:
<?php
declare(strict_types=1);
namespace App\Doctrine\ORM;
use Doctrine\ORM\QueryBuilder;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Plus\ChannelAdmin\Application\Provider\AdminChannelProviderInterface;
final class RestrictingSupplierListQueryBuilder
{
/** @var AdminChannelProviderInterface */
private $adminChannelProvider;
/** @var EntityRepository */
private $supplierRepository;
public function __construct(
AdminChannelProviderInterface $adminChannelProvider,
EntityRepository $supplierRepository
) {
$this->adminChannelProvider = $adminChannelProvider;
$this->supplierRepository = $supplierRepository;
}
public function create(): QueryBuilder
{
$listQueryBuilder = $this->supplierRepository->createQueryBuilder('o');
/** @var ChannelInterface|null $channel */
$channel = $this->adminChannelProvider->getChannel();
if ($channel === null) {
return $listQueryBuilder;
}
return $listQueryBuilder
->andWhere('o.channel = :channel')
->setParameter('channel', $channel)
;
}
}
# config/services.yaml
App\Doctrine\ORM\RestrictingSupplierListQueryBuilder:
public: true
class: App\Doctrine\ORM\RestrictingSupplierListQueryBuilder
arguments: ['@Sylius\Plus\ChannelAdmin\Application\Provider\AdminChannelProviderInterface', '@app.repository.supplier']
Add method to the Suppliers grid:
sylius_grid:
grids:
app_admin_supplier:
driver:
name: doctrine/orm
options:
class: App\Entity\Supplier
+ repository:
+ method: [expr:service('App\\Doctrine\\ORM\\RestrictingSupplierListQueryBuilder'), create]
Well done! That’s it, now you have a Supplier entity, that is accessible within the Sylius Plus Administrators per Channel feature!