Skip to content

Commit

Permalink
Add AdminInterface::createNewInstance method
Browse files Browse the repository at this point in the history
Instead of overriding ModelManagerInterface::getModelInstance to
custom construct their objects, now the user can do it from the
related Admin class.

The Instantiator class will be use in 4.0 and its code is copied
from the persistence bundles.
  • Loading branch information
franmomu committed Feb 21, 2021
1 parent e4a72b8 commit aaefc55
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 10 deletions.
7 changes: 7 additions & 0 deletions UPGRADE-3.x.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
UPGRADE 3.x
===========

UPGRADE FROM 3.xx to 3.xx
=========================

### Deprecated `Sonata\AdminBundle\Model\ModelManagerInterface::getModelInstance()` method.

Use `Sonata\AdminBundle\Admin\AdminInterface::createNewInstance()` method instead.

UPGRADE FROM 3.88 to 3.89
=========================

Expand Down
15 changes: 14 additions & 1 deletion src/Admin/AbstractAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
use Sonata\AdminBundle\Security\Handler\AclSecurityHandlerInterface;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\AdminBundle\Templating\MutableTemplateRegistryInterface;
// NEXT_MAJOR: Uncomment next line.
// use Sonata\AdminBundle\Util\Instantiator;
use Sonata\Form\Validator\Constraints\InlineConstraint;
use Sonata\Form\Validator\ErrorElement;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
Expand Down Expand Up @@ -1247,7 +1249,7 @@ public function getTemplate($name)
*/
public function getNewInstance()
{
$object = $this->getModelManager()->getModelInstance($this->getClass());
$object = $this->createNewInstance();

$this->appendParentObject($object);
$this->alterNewInstance($object);
Expand Down Expand Up @@ -2887,6 +2889,17 @@ final public function hasTemplateRegistry(): bool
return null !== $this->templateRegistry;
}

/**
* @phpstan-return T
*/
public function createNewInstance(): object
{
// NEXT_MAJOR: Uncomment next line and remove the other one.
// return Instantiator::instantiate($this->getClass());
/* @phpstan-ignore-next-line */
return $this->getModelManager()->getModelInstance($this->getClass(), 'sonata_deprecation_mute');
}

/**
* @phpstan-param T $object
*/
Expand Down
7 changes: 7 additions & 0 deletions src/Admin/AdminInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
* @method string|null getParentAssociationMapping()
* @method void reorderFormGroup(string $group, array $keys)
* @method void defineFormBuilder(FormBuilderInterface $formBuilder)
* @method object createNewInstance()
*
* @phpstan-template T of object
* @phpstan-extends AccessRegistryInterface<T>
Expand Down Expand Up @@ -789,6 +790,12 @@ public function getListMode();
// * the getFormBuilder is only call by the main admin class.
// */
// public function defineFormBuilder(FormBuilderInterface $formBuilder): void;

// NEXT_MAJOR: uncomment this method in 4.0
// /**
// * @phpstan-return T
// */
// public function createNewInstance(): object;
}

class_exists(\Sonata\Form\Validator\ErrorElement::class);
2 changes: 2 additions & 0 deletions src/Model/ModelManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ public function getUrlSafeIdentifier($model);
/**
* Create a new instance of the model of the specified class.
*
* @deprecated since sonata-project/admin-bundle 3.x. To be removed in 4.0. Use AdminInterface::createNewInstance instead.
*
* @param string $class
*
* @return object
Expand Down
41 changes: 41 additions & 0 deletions src/Util/Instantiator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?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\AdminBundle\Util;

/**
* @internal
*/
final class Instantiator
{
/**
* @template T of object
* @phpstan-param class-string<T> $class
* @phpstan-return T
*/
public static function instantiate(string $class): object
{
$r = new \ReflectionClass($class);
if ($r->isAbstract()) {
throw new \RuntimeException(sprintf('Cannot initialize abstract class: %s', $class));
}

$constructor = $r->getConstructor();

if (null !== $constructor && (!$constructor->isPublic() || $constructor->getNumberOfRequiredParameters() > 0)) {
return $r->newInstanceWithoutConstructor();
}

return new $class();
}
}
16 changes: 8 additions & 8 deletions tests/Admin/AdminTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1627,13 +1627,13 @@ public function testGetNewInstanceForChildAdminWithCollectionParentValue(): void
$formBuilder = $this->createStub(FormBuilderInterface::class);
$formBuilder->method('getForm')->willReturn(null);

$postCategory = new PostCategory();
$postCategoryAdmin = new PostCategoryAdmin('admin.post_category', PostCategory::class, 'MyBundle\MyController');

// NEXT_MAJOR: Remove next three lines related to model manager.
$modelManager = $this->createStub(ModelManagerInterface::class);
$modelManager->method('getModelInstance')->willReturn($postCategory);

$postCategoryAdmin = new PostCategoryAdmin('admin.post_category', PostCategoryAdmin::class, 'MyBundle\MyController');
$modelManager->method('getModelInstance')->willReturn(new PostCategory());
$postCategoryAdmin->setModelManager($modelManager);

$postCategoryAdmin->setParent($postAdmin);

$request = $this->createStub(Request::class);
Expand Down Expand Up @@ -1662,13 +1662,13 @@ public function testGetNewInstanceForEmbededAdminWithParentValue(): void
$parentField->method('getParentAssociationMappings')->willReturn([]);
$parentField->method('getAssociationMapping')->willReturn(['fieldName' => 'tag', 'mappedBy' => 'post']);

$tag = new Tag();
$tagAdmin = new TagAdmin('admin.tag', Tag::class, 'MyBundle\MyController');

// NEXT_MAJOR: Remove next three lines related to model manager.
$modelManager = $this->createStub(ModelManagerInterface::class);
$modelManager->method('getModelInstance')->willReturn($tag);

$tagAdmin = new TagAdmin('admin.tag', Tag::class, 'MyBundle\MyController');
$modelManager->method('getModelInstance')->willReturn(new Tag());
$tagAdmin->setModelManager($modelManager);

$tagAdmin->setParentFieldDescription($parentField);

$request = $this->createStub(Request::class);
Expand Down
2 changes: 1 addition & 1 deletion tests/App/Admin/FooAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

class FooAdmin extends AbstractAdmin
{
public function getNewInstance()
public function createNewInstance(): object
{
return new Foo('test_id', 'foo_name');
}
Expand Down
6 changes: 6 additions & 0 deletions tests/App/Admin/TranslatedAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\AdminBundle\Tests\App\Model\Translated;
use Symfony\Component\Form\Extension\Core\Type\TextType;

final class TranslatedAdmin extends AbstractAdmin
{
public function createNewInstance(): object
{
return new Translated();
}

protected function configureListFields(ListMapper $list): void
{
$list->add('name_list', FieldDescriptionInterface::TYPE_STRING);
Expand Down
3 changes: 3 additions & 0 deletions tests/App/Model/ModelManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ public function getUrlSafeIdentifier($model)
return $model->getId();
}

/**
* NEXT_MAJOR: Remove this method.
*/
public function getModelInstance($class)
{
switch ($class) {
Expand Down

0 comments on commit aaefc55

Please sign in to comment.