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 compatibility sonata 4 #38

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
46 changes: 14 additions & 32 deletions Admin/ContentAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,23 @@
use Sherlockode\AdvancedContentBundle\Model\ContentInterface;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\FormBuilderInterface;

class ContentAdmin extends AbstractAdmin
{
protected $baseRouteName = 'admin_afb_content';

public function getFormTheme()
protected function configure(): void
{
return array_merge(
$this->setFormTheme(array_merge(
parent::getFormTheme(),
['@SherlockodeAdvancedContent/Form/content.html.twig']
);
));
}

public function configureFormFields(FormMapper $form)
public function configureFormFields(FormMapper $form): void
{
$form->tab('content.form.tabs.label')
->with('content.form.tabs.general', [
Expand All @@ -42,31 +43,7 @@ public function configureFormFields(FormMapper $form)
->end(); // init the groups data for this admin class
}

/**
* Create ContentType form
*
* @return FormBuilderInterface
*
* @throws \Exception
*/
private function getCustomFormBuilder()
{
return $this->getFormContractor()
->getFormFactory()
->createNamedBuilder($this->getUniqid(), ContentType::class, null, $this->formOptions);
}

public function getFormBuilder()
{
$this->formOptions['data_class'] = $this->getClass();

$formBuilder = $this->getCustomFormBuilder();
$this->defineFormBuilder($formBuilder);

return $formBuilder;
}

public function configureListFields(ListMapper $list)
public function configureListFields(ListMapper $list): void
{
$list
->add('id', null, ['label' => 'content.id'])
Expand All @@ -80,9 +57,14 @@ public function configureListFields(ListMapper $list)
;
}

public function createQuery($context = 'list')
/**
* @param ProxyQueryInterface $query
*
* @return ProxyQueryInterface
*/
public function configureQuery(ProxyQueryInterface $query): ProxyQueryInterface
{
$query = parent::createQuery();
$query = parent::configureQuery($query);
$query->getQueryBuilder()
->where('o.page IS NULL');

Expand All @@ -94,7 +76,7 @@ public function createQuery($context = 'list')
*
* @return string
*/
public function toString($object)
public function toString($object): string
{
if ($object instanceof ContentInterface && $object->getName()) {
return $object->getName();
Expand Down
2 changes: 1 addition & 1 deletion Admin/Extension/PageExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class PageExtension extends AbstractAdminExtension
private $configurationManager;


public function configureFormFields(FormMapper $formMapper)
public function configureFormFields(FormMapper $formMapper): void
{
if ($formMapper->has('pageType')) {
$formMapper->tab('page.form.tabs.label')
Expand Down
219 changes: 219 additions & 0 deletions Admin/FormContractor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
<?php

namespace Sherlockode\SonataAdvancedContentBundle\Admin;

use Sonata\AdminBundle\Builder\FormContractorInterface;
use Sonata\AdminBundle\FieldDescription\FieldDescriptionInterface;
use Sonata\AdminBundle\Form\Type\AdminType;
use Sonata\AdminBundle\Form\Type\ModelAutocompleteType;
use Sonata\AdminBundle\Form\Type\ModelHiddenType;
use Sonata\AdminBundle\Form\Type\ModelListType;
use Sonata\AdminBundle\Form\Type\ModelReferenceType;
use Sonata\AdminBundle\Form\Type\ModelType;
use Sonata\Form\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormRegistryInterface;

class FormContractor implements FormContractorInterface
{
/**
* @var FormFactoryInterface
*/
protected $formFactory;

/**
* @var FormRegistryInterface
*/
protected $formRegistry;

/**
* @var string
*/
protected $formType;

/**
* @param FormFactoryInterface $formFactory
* @param FormRegistryInterface $formRegistry
*/
public function __construct(FormFactoryInterface $formFactory, FormRegistryInterface $formRegistry)
{
$this->formFactory = $formFactory;
$this->formRegistry = $formRegistry;
}

/**
* @param FieldDescriptionInterface $fieldDescription
*
* @return void
*/
public function fixFieldDescription(FieldDescriptionInterface $fieldDescription): void
{
$fieldDescription->setOption('edit', $fieldDescription->getOption('edit', 'standard'));

if ($fieldDescription->describesAssociation() || null !== $fieldDescription->getOption('admin_code')) {
$fieldDescription->getAdmin()->attachAdminClass($fieldDescription);
}
}

/**
* @param string $name
* @param array $formOptions
*
* @return FormBuilderInterface
*/
public function getFormBuilder(string $name, array $formOptions = []): FormBuilderInterface
{
return $this->formFactory->createNamedBuilder($name, $this->formType, null, $formOptions);
}

/**
* @param string $formType
*
* @return $this
*/
public function setFormType(string $formType): self
{
$this->formType = $formType;

return $this;
}

/**
* @param string|null $type
* @param FieldDescriptionInterface $fieldDescription
* @param array $formOptions
*
* @return array|mixed[]
*/
final public function getDefaultOptions(
?string $type,
FieldDescriptionInterface $fieldDescription,
array $formOptions = []
): array {
$options = [];
$options['sonata_field_description'] = $fieldDescription;

if ($this->isAnyInstanceOf($type, [
ModelType::class,
ModelListType::class,
ModelHiddenType::class,
ModelAutocompleteType::class,
ModelReferenceType::class,
])) {
$options['class'] = $fieldDescription->getTargetModel();
$options['model_manager'] = $fieldDescription->getAdmin()->getModelManager();

if ($this->isAnyInstanceOf($type, [ModelAutocompleteType::class])) {
if (!$fieldDescription->hasAssociationAdmin()) {
throw new \InvalidArgumentException(sprintf(
'The current field `%s` is not linked to an admin.'
.' Please create one for the target model: `%s`.',
$fieldDescription->getName(),
$fieldDescription->getTargetModel() ?? ''
));
}
}
} elseif ($this->isAnyInstanceOf($type, [AdminType::class])) {
if (!$fieldDescription->hasAssociationAdmin()) {
throw new \InvalidArgumentException(sprintf(
'The current field `%s` is not linked to an admin.'
.' Please create one for the target model: `%s`.',
$fieldDescription->getName(),
$fieldDescription->getTargetModel() ?? ''
));
}

if (!$fieldDescription->describesSingleValuedAssociation()) {
throw new \InvalidArgumentException(sprintf(
'You are trying to add `%s` field `%s` which is not a One-To-One or Many-To-One association.'
.' You SHOULD use `%s` instead.',
AdminType::class,
$fieldDescription->getName(),
CollectionType::class
));
}

// set sensitive default value to have a component working fine out of the box
$options['btn_add'] = false;
$options['delete'] = false;

$options['data_class'] = $fieldDescription->getAssociationAdmin()->getClass();
$options['empty_data'] = static fn (): object => $fieldDescription->getAssociationAdmin()->getNewInstance();
$fieldDescription->setOption('edit', $fieldDescription->getOption('edit', 'admin'));
} elseif ($this->isAnyInstanceOf($type, [
CollectionType::class,
])) {
if (!$fieldDescription->hasAssociationAdmin()) {
throw new \InvalidArgumentException(sprintf(
'The current field `%s` is not linked to an admin.'
.' Please create one for the target model: `%s`.',
$fieldDescription->getName(),
$fieldDescription->getTargetModel() ?? ''
));
}

$options['type'] = AdminType::class;
$options['modifiable'] = true;
$options['type_options'] = $this->getDefaultAdminTypeOptions($fieldDescription, $formOptions);
}

return $options;
}

/**
* @param string|null $type
* @param array $classes
*
* @return bool
*/
private function isAnyInstanceOf(?string $type, array $classes): bool
{
if (null === $type) {
return false;
}

foreach ($classes as $class) {
if (is_a($type, $class, true)) {
return true;
}
}

// handle form type inheritance and check all parent types
$resolvedType = $this->formRegistry->getType($type);
$parentType = $resolvedType->getParent();
if (null !== $parentType) {
$parentType = \get_class($parentType->getInnerType());

// all types have "Symfony\Component\Form\Extension\Core\Type\FormType" as parent
// so we ignore it here for performance reasons
if (FormType::class !== $parentType) {
return $this->isAnyInstanceOf($parentType, $classes);
}
}

return false;
}

/**
* @param FieldDescriptionInterface $fieldDescription
* @param array $formOptions
*
* @return array
*/
private function getDefaultAdminTypeOptions(FieldDescriptionInterface $fieldDescription, array $formOptions): array
{
$typeOptions = [
'sonata_field_description' => $fieldDescription,
'data_class' => $fieldDescription->getAssociationAdmin()->getClass(),
'empty_data' => static fn (): object => $fieldDescription->getAssociationAdmin()->getNewInstance(),
];

if (isset($formOptions['by_reference'])) {
$typeOptions['collection_by_reference'] = $formOptions['by_reference'];
}

return $typeOptions;
}
}
39 changes: 8 additions & 31 deletions Admin/PageAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ class PageAdmin extends AbstractAdmin
*/
private $localeProvider;

public function getFormTheme()
protected function configure(): void
{
return array_merge(
$this->setFormTheme(array_merge(
parent::getFormTheme(),
['@SherlockodeAdvancedContent/Form/content.html.twig']
);
));
}

public function configureFormFields(FormMapper $form)
public function configureFormFields(FormMapper $form): void
{
$form->tab('page.form.tabs.label')
->with('page.form.tabs.general')->end(); // init the groups data for this admin class
Expand Down Expand Up @@ -69,37 +69,14 @@ public function configureFormFields(FormMapper $form)
$form->end();
}

public function getFormBuilder()
{
$this->formOptions['data_class'] = $this->getClass();

$formBuilder = $this->getCustomFormBuilder();
$this->defineFormBuilder($formBuilder);

return $formBuilder;
}

/**
* Create PageType form
*
* @return FormBuilderInterface
*
* @throws \Exception
*/
private function getCustomFormBuilder()
{
return $this->getFormContractor()
->getFormFactory()
->createNamedBuilder($this->getUniqid(), PageType::class, null, $this->formOptions);
}

public function configureListFields(ListMapper $list)
public function configureListFields(ListMapper $list): void
{
$list
->add('pageIdentifier', null, ['label' => 'page.form.page_identifier'])
->add('title', null, [
'label' => 'page.form.title',
'template' => '@SherlockodeSonataAdvancedContent/Page/title.html.twig'
'template' => '@SherlockodeSonataAdvancedContent/Page/title.html.twig',
'virtual_field' => true,
])
->add('status', null, [
'label' => 'page.form.status',
Expand All @@ -119,7 +96,7 @@ public function configureListFields(ListMapper $list)
*
* @return string
*/
public function toString($object)
public function toString($object): string
{
if ($object instanceof PageInterface && $object->getPageIdentifier()) {
return $object->getPageIdentifier();
Expand Down
Loading