Skip to content

Commit

Permalink
Implement FieldDescriptionFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
franmomu authored and jordisala1991 committed Mar 22, 2021
1 parent 244f358 commit cc89819
Show file tree
Hide file tree
Showing 22 changed files with 1,017 additions and 29 deletions.
23 changes: 22 additions & 1 deletion UPGRADE-3.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,30 @@ UPGRADE FROM 3.x to 3.x

Deprecated `modelReverseTransform()` method, use `reverseTransform()` instead.

### Sonata\DoctrineMongoDBAdminBundle\Builder\ListBuilder

Deprecated `buildActionFieldDescription()` method without replacement.

### Sonata\DoctrineMongoDBAdminBundle\Guesser\TypeGuesser

Deprecated `guessType()` method, you should use `guess()` method instead.

### Sonata\DoctrineMongoDBAdminBundle\Guesser\FilterTypeGuesser

Deprecated `guessType()` method, you should use `guess()` method instead.

### Sonata\DoctrineMongoDBAdminBundle\Guesser\AbstractTypeGuesser

This class has been deprecated without replacement.

### Sonata\DoctrineMongoDBAdminBundle\Model\ModelManager

Deprecated `getParentMetadataForProperty()` method.
Deprecated `getNewFieldDescriptionInstance()` method, you SHOULD use `FieldDescriptionFactory::create()` instead.

### Sonata\DoctrineMongoDBAdminBundle\Filter\Filter

Deprecate passing an instance of `Sonata\AdminBundle\Datagrid\ProxyQueryInterface`
Deprecated passing an instance of `Sonata\AdminBundle\Datagrid\ProxyQueryInterface`
which is not an instance of `Sonata\DoctrineMongoDBAdminBundle\Datagrid\ProxyQueryInterface` as
argument 1 to the `Sonata\DoctrineMongoDBAdminBundle\Filter\Filter::filter()` method.

Expand Down
2 changes: 2 additions & 0 deletions src/Admin/FieldDescription.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public function setAssociationMapping($associationMapping)

$this->associationMapping = $associationMapping;

// NEXT_MAJOR: Remove next line.
$this->type = $this->type ?: $associationMapping['type'];
$this->mappingType = $this->mappingType ?: $associationMapping['type'];
$this->fieldName = $associationMapping['fieldName'];
Expand Down Expand Up @@ -77,6 +78,7 @@ public function setFieldMapping($fieldMapping)

$this->fieldMapping = $fieldMapping;

// NEXT_MAJOR: Remove next line.
$this->type = $this->type ?: $fieldMapping['type'];
$this->mappingType = $this->mappingType ?: $fieldMapping['type'];
$this->fieldName = $this->fieldName ?: $fieldMapping['fieldName'];
Expand Down
29 changes: 22 additions & 7 deletions src/Builder/DatagridBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
use Sonata\AdminBundle\Builder\DatagridBuilderInterface;
use Sonata\AdminBundle\Datagrid\Datagrid;
use Sonata\AdminBundle\Datagrid\DatagridInterface;
use Sonata\AdminBundle\FieldDescription\TypeGuesserInterface;
use Sonata\AdminBundle\Filter\FilterFactoryInterface;
use Sonata\AdminBundle\Guesser\TypeGuesserInterface;
use Sonata\AdminBundle\Guesser\TypeGuesserInterface as DeprecatedTypeGuesserInterface;
use Sonata\DoctrineMongoDBAdminBundle\Datagrid\Pager;
use Sonata\DoctrineMongoDBAdminBundle\Model\ModelManager;
use Symfony\Component\Form\Extension\Core\Type\FormType;
Expand All @@ -42,7 +43,9 @@ class DatagridBuilder implements DatagridBuilderInterface
protected $formFactory;

/**
* @var TypeGuesserInterface
* NEXT_MAJOR: Remove DeprecatedTypeGuesserInterface type.
*
* @var DeprecatedTypeGuesserInterface|TypeGuesserInterface
*/
protected $guesser;

Expand All @@ -54,9 +57,12 @@ class DatagridBuilder implements DatagridBuilderInterface
protected $csrfTokenEnabled;

/**
* @param bool $csrfTokenEnabled
* NEXT_MAJOR: Remove DeprecatedTypeGuesserInterface type and add TypeGuesserInterface to the constructor.
*
* @param DeprecatedTypeGuesserInterface|TypeGuesserInterface $guesser
* @param bool $csrfTokenEnabled
*/
public function __construct(FormFactoryInterface $formFactory, FilterFactoryInterface $filterFactory, TypeGuesserInterface $guesser, $csrfTokenEnabled = true)
public function __construct(FormFactoryInterface $formFactory, FilterFactoryInterface $filterFactory, $guesser, $csrfTokenEnabled = true)
{
$this->formFactory = $formFactory;
$this->filterFactory = $filterFactory;
Expand All @@ -69,7 +75,7 @@ public function __construct(FormFactoryInterface $formFactory, FilterFactoryInte
*/
public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription)
{
// set default values
// NEXT_MAJOR: Remove this call.
$fieldDescription->setAdmin($admin);

// NEXT_MAJOR: Remove the following 2 lines.
Expand All @@ -78,7 +84,7 @@ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInter

// NEXT_MAJOR: Remove this block.
if ($modelManager->hasMetadata($admin->getClass(), 'sonata_deprecation_mute')) {
[$metadata, $lastPropertyName, $parentAssociationMappings] = $modelManager->getParentMetadataForProperty($admin->getClass(), $fieldDescription->getName());
[$metadata, $lastPropertyName, $parentAssociationMappings] = $modelManager->getParentMetadataForProperty($admin->getClass(), $fieldDescription->getName(), 'sonata_deprecation_mute');

// set the default field mapping
if (isset($metadata->fieldMappings[$lastPropertyName])) {
Expand Down Expand Up @@ -127,7 +133,16 @@ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInter
public function addFilter(DatagridInterface $datagrid, $type, FieldDescriptionInterface $fieldDescription, AdminInterface $admin)
{
if (null === $type) {
$guessType = $this->guesser->guessType($admin->getClass(), $fieldDescription->getName(), $admin->getModelManager());
// NEXT_MAJOR: Remove the condition and keep the if part.
if ($this->guesser instanceof TypeGuesserInterface) {
$guessType = $this->guesser->guess($fieldDescription);
} else {
$guessType = $this->guesser->guessType(
$admin->getClass(),
$fieldDescription->getName(),
$admin->getModelManager()
);
}

$type = $guessType->getType();

Expand Down
2 changes: 2 additions & 0 deletions src/Builder/FormContractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInter
}
}

// NEXT_MAJOR: Remove this block.
if (!$fieldDescription->getType()) {
throw new \RuntimeException(sprintf(
'Please define a type for field `%s` in `%s`',
Expand All @@ -82,6 +83,7 @@ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInter
));
}

// NEXT_MAJOR: Remove this call.
$fieldDescription->setAdmin($admin);
$fieldDescription->setOption('edit', $fieldDescription->getOption('edit', 'standard'));

Expand Down
43 changes: 38 additions & 5 deletions src/Builder/ListBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,34 @@
use Sonata\AdminBundle\Admin\FieldDescriptionCollection;
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
use Sonata\AdminBundle\Builder\ListBuilderInterface;
use Sonata\AdminBundle\Guesser\TypeGuesserInterface;
use Sonata\AdminBundle\FieldDescription\TypeGuesserInterface;
use Sonata\AdminBundle\Guesser\TypeGuesserInterface as DeprecatedTypeGuesserInterface;
use Sonata\DoctrineMongoDBAdminBundle\Model\ModelManager;

/**
* @final since sonata-project/doctrine-mongodb-admin-bundle 3.5.
*/
class ListBuilder implements ListBuilderInterface
{
/**
* NEXT_MAJOR: Remove DeprecatedTypeGuesserInterface type.
*
* @var DeprecatedTypeGuesserInterface|TypeGuesserInterface
*/
protected $guesser;

/**
* @var string[]
*/
protected $templates = [];

public function __construct(TypeGuesserInterface $guesser, array $templates = [])
/**
* NEXT_MAJOR: Remove DeprecatedTypeGuesserInterface type and add TypeGuesserInterface to the constructor.
*
* @param DeprecatedTypeGuesserInterface|TypeGuesserInterface $guesser
* @param string[] $templates
*/
public function __construct($guesser, array $templates = [])
{
$this->guesser = $guesser;
$this->templates = $templates;
Expand All @@ -47,7 +62,16 @@ public function getBaseList(array $options = [])
public function buildField($type, FieldDescriptionInterface $fieldDescription, AdminInterface $admin)
{
if (null === $type) {
$guessType = $this->guesser->guessType($admin->getClass(), $fieldDescription->getName(), $admin->getModelManager());
// NEXT_MAJOR: Remove the condition and keep the if part.
if ($this->guesser instanceof TypeGuesserInterface) {
$guessType = $this->guesser->guess($fieldDescription);
} else {
$guessType = $this->guesser->guessType(
$admin->getClass(),
$fieldDescription->getName(),
$admin->getModelManager()
);
}
$fieldDescription->setType($guessType->getType());
} else {
$fieldDescription->setType($type);
Expand All @@ -73,9 +97,10 @@ public function addField(FieldDescriptionCollection $list, $type, FieldDescripti
public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription)
{
if ('_action' === $fieldDescription->getName() || 'actions' === $fieldDescription->getType()) {
$this->buildActionFieldDescription($fieldDescription);
$this->buildActionFieldDescription($fieldDescription, 'sonata_deprecation_mute');
}

// NEXT_MAJOR: Remove this call.
$fieldDescription->setAdmin($admin);

// NEXT_MAJOR: Remove the following 2 lines.
Expand All @@ -84,7 +109,7 @@ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInter

// NEXT_MAJOR: Remove this block.
if ($modelManager->hasMetadata($admin->getClass(), 'sonata_deprecation_mute')) {
[$metadata, $lastPropertyName, $parentAssociationMappings] = $modelManager->getParentMetadataForProperty($admin->getClass(), $fieldDescription->getName());
[$metadata, $lastPropertyName, $parentAssociationMappings] = $modelManager->getParentMetadataForProperty($admin->getClass(), $fieldDescription->getName(), 'sonata_deprecation_mute');
$fieldDescription->setParentAssociationMappings($parentAssociationMappings);

// set the default field mapping
Expand Down Expand Up @@ -154,6 +179,14 @@ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInter
*/
public function buildActionFieldDescription(FieldDescriptionInterface $fieldDescription)
{
if ('sonata_deprecation_mute' !== (\func_get_args()[1] ?? null)) {
@trigger_error(sprintf(
'The "%s()" method is deprecated since sonata-project/doctrine-mongodb-admin-bundle 3.x and'
.' will be removed in version 4.0.',
__METHOD__
), \E_USER_DEPRECATED);
}

if (null === $fieldDescription->getTemplate()) {
$fieldDescription->setTemplate('@SonataAdmin/CRUD/list__action.html.twig');
}
Expand Down
33 changes: 29 additions & 4 deletions src/Builder/ShowBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,34 @@
use Sonata\AdminBundle\Admin\FieldDescriptionCollection;
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
use Sonata\AdminBundle\Builder\ShowBuilderInterface;
use Sonata\AdminBundle\Guesser\TypeGuesserInterface;
use Sonata\AdminBundle\FieldDescription\TypeGuesserInterface;
use Sonata\AdminBundle\Guesser\TypeGuesserInterface as DeprecatedTypeGuesserInterface;
use Sonata\DoctrineMongoDBAdminBundle\Model\ModelManager;

/**
* @final since sonata-project/doctrine-mongodb-admin-bundle 3.5.
*/
class ShowBuilder implements ShowBuilderInterface
{
/**
* NEXT_MAJOR: Remove DeprecatedTypeGuesserInterface type.
*
* @var DeprecatedTypeGuesserInterface|TypeGuesserInterface
*/
protected $guesser;

/**
* @var string[]
*/
protected $templates;

public function __construct(TypeGuesserInterface $guesser, array $templates)
/**
* NEXT_MAJOR: Remove DeprecatedTypeGuesserInterface type and add TypeGuesserInterface to the constructor.
*
* @param DeprecatedTypeGuesserInterface|TypeGuesserInterface $guesser
* @param string[] $templates
*/
public function __construct($guesser, array $templates)
{
$this->guesser = $guesser;
$this->templates = $templates;
Expand All @@ -47,7 +62,16 @@ public function getBaseList(array $options = [])
public function addField(FieldDescriptionCollection $list, $type, FieldDescriptionInterface $fieldDescription, AdminInterface $admin)
{
if (null === $type) {
$guessType = $this->guesser->guessType($admin->getClass(), $fieldDescription->getName(), $admin->getModelManager());
// NEXT_MAJOR: Remove the condition and keep the if part.
if ($this->guesser instanceof TypeGuesserInterface) {
$guessType = $this->guesser->guess($fieldDescription);
} else {
$guessType = $this->guesser->guessType(
$admin->getClass(),
$fieldDescription->getName(),
$admin->getModelManager()
);
}
$fieldDescription->setType($guessType->getType());
} else {
$fieldDescription->setType($type);
Expand All @@ -64,6 +88,7 @@ public function addField(FieldDescriptionCollection $list, $type, FieldDescripti
*/
public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription)
{
// NEXT_MAJOR: Remove this call.
$fieldDescription->setAdmin($admin);

// NEXT_MAJOR: Remove the following 2 lines.
Expand All @@ -72,7 +97,7 @@ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInter

// NEXT_MAJOR: Remove this block.
if ($modelManager->hasMetadata($admin->getClass(), 'sonata_deprecation_mute')) {
[$metadata, $lastPropertyName, $parentAssociationMappings] = $modelManager->getParentMetadataForProperty($admin->getClass(), $fieldDescription->getName());
[$metadata, $lastPropertyName, $parentAssociationMappings] = $modelManager->getParentMetadataForProperty($admin->getClass(), $fieldDescription->getName(), 'sonata_deprecation_mute');
$fieldDescription->setParentAssociationMappings($parentAssociationMappings);

// set the default field mapping
Expand Down
96 changes: 96 additions & 0 deletions src/FieldDescription/FieldDescriptionFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\DoctrineMongoDBAdminBundle\FieldDescription;

use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
use Doctrine\Persistence\ManagerRegistry;
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
use Sonata\AdminBundle\FieldDescription\FieldDescriptionFactoryInterface;
use Sonata\DoctrineMongoDBAdminBundle\Admin\FieldDescription;

final class FieldDescriptionFactory implements FieldDescriptionFactoryInterface
{
/**
* @var ManagerRegistry
*/
private $registry;

public function __construct(ManagerRegistry $registry)
{
$this->registry = $registry;
}

public function create(string $class, string $name, array $options = []): FieldDescriptionInterface
{
if (!isset($options['route']['name'])) {
$options['route']['name'] = 'edit';
}

if (!isset($options['route']['parameters'])) {
$options['route']['parameters'] = [];
}

[$metadata, $propertyName, $parentAssociationMappings] = $this->getParentMetadataForProperty($class, $name);

return new FieldDescription(
$name,
$options,
$metadata->fieldMappings[$propertyName] ?? [],
$metadata->associationMappings[$propertyName] ?? [],
$parentAssociationMappings,
$propertyName
);
}

private function getParentMetadataForProperty(string $baseClass, string $propertyFullName): array
{
$nameElements = explode('.', $propertyFullName);
$lastPropertyName = array_pop($nameElements);
$class = $baseClass;
$parentAssociationMappings = [];

foreach ($nameElements as $nameElement) {
$metadata = $this->getMetadata($class);
$parentAssociationMappings[] = $metadata->associationMappings[$nameElement];
$class = $metadata->getAssociationTargetClass($nameElement);
}

return [$this->getMetadata($class), $lastPropertyName, $parentAssociationMappings];
}

/**
* @param class-string $class
*/
private function getMetadata(string $class): ClassMetadata
{
return $this->getDocumentManager($class)->getClassMetadata($class);
}

/**
* @param class-string $class
*
* @throw \RuntimeException
*/
private function getDocumentManager(string $class): DocumentManager
{
$dm = $this->registry->getManagerForClass($class);

if (!$dm instanceof DocumentManager) {
throw new \RuntimeException(sprintf('No document manager defined for class %s', $class));
}

return $dm;
}
}
Loading

0 comments on commit cc89819

Please sign in to comment.