Skip to content

Commit

Permalink
Sonata 4 compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
BrownSim committed Oct 5, 2023
1 parent fe8bd8a commit 79824c6
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 89 deletions.
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

0 comments on commit 79824c6

Please sign in to comment.