Skip to content

Commit

Permalink
feature #1364 Display an error message when an entity doesn't define …
Browse files Browse the repository at this point in the history
…a __toString() method (javiereguiluz)

This PR was squashed before being merged into the master branch (closes #1364).

Discussion
----------

Display an error message when an entity doesn't define a __toString() method

Sadly, it's common to forget adding the `__toString()` method in entities used as part of Doctrine associations. We now display a useful error message in those cases:

![tostring_error_message](https://cloud.githubusercontent.com/assets/73419/20029565/7340bad4-a34f-11e6-9614-b4fd55c7820a.png)

Commits
-------

08d08c8 Display an error message when an entity doesn't define a __toString() method
  • Loading branch information
javiereguiluz committed Nov 17, 2016
2 parents d377ac8 + 08d08c8 commit 411e095
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 4 deletions.
1 change: 1 addition & 0 deletions Configuration/ConfigManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ private function doProcessConfig($backendConfig)
new ViewConfigPass(),
new TemplateConfigPass($this->container->getParameter('kernel.root_dir').'/Resources/views'),
new DefaultConfigPass(),
new ValidationConfigPass(),
);

foreach ($configPasses as $configPass) {
Expand Down
63 changes: 63 additions & 0 deletions Configuration/ValidationConfigPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

/*
* This file is part of the EasyAdminBundle.
*
* (c) Javier Eguiluz <javier.eguiluz@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace JavierEguiluz\Bundle\EasyAdminBundle\Configuration;

/**
* Performs the last validations on the processed backend configuration before
* executing the application.
*
* @author Javier Eguiluz <javier.eguiluz@gmail.com>
*/
class ValidationConfigPass implements ConfigPassInterface
{
public function process(array $backendConfig)
{
$this->validateToStringMethod($backendConfig);

return $backendConfig;
}

/**
* It checks that the __toString() method is defined in the entity classes
* that need it. This avoids the usual error "Object of class ... could not
* be converted to string".
*
* @param array $backendConfig
*/
private function validateToStringMethod(array $backendConfig)
{
foreach ($backendConfig['entities'] as $entityName => $entityConfig) {
foreach (array('list', 'search', 'show') as $view) {
foreach ($entityConfig[$view]['fields'] as $fieldName => $fieldConfig) {
// Doctrine associations that don't define a custom template must define a __toString() method
$fieldUsesDefaultTemplate = '@EasyAdmin/default/field_association.html.twig' === $fieldConfig['template'];
if ('association' === $fieldConfig['dataType'] && $fieldUsesDefaultTemplate) {
if (!method_exists($fieldConfig['targetEntity'], '__toString')) {
throw new \InvalidArgumentException(sprintf('The "%s" class must define a "__toString()" method because it is used as the "%s" field in the "%s" view of the "%s" entity.', $fieldConfig['targetEntity'], $fieldName, $view, $entityName));
}
}
}
}

foreach (array('edit', 'new') as $view) {
foreach ($entityConfig[$view]['fields'] as $fieldName => $fieldConfig) {
// fields used in autocomplete form types must define a __toString() method
if ('easyadmin_autocomplete' === $fieldConfig['fieldType']) {
if (!method_exists($fieldConfig['targetEntity'], '__toString')) {
throw new \InvalidArgumentException(sprintf('The "%s" class must define a "__toString()" method because it is used as the "%s" autocomplete field in the "%s" view of the "%s" entity.', $fieldConfig['targetEntity'], $fieldName, $view, $entityName));
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# TEST
# the entity classes used in associations must define a __toString() method

# EXCEPTION
expected_exception:
class: InvalidArgumentException
message_string: 'The "AppTestBundle\Entity\UnitTests\Exceptions\CategoryWithoutToString" class must define a "__toString()" method because it is used as the "parent" field in the "list" view of the "Category" entity.'

# CONFIGURATION
easy_admin:
entities:
Category:
class: AppTestBundle\Entity\UnitTests\Exceptions\CategoryWithoutToString
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# TEST
# the entity classes used in autocomplete types must define a __toString() method

# EXCEPTION
expected_exception:
class: InvalidArgumentException
message_string: 'The "AppTestBundle\Entity\UnitTests\Exceptions\CategoryWithoutToString" class must define a "__toString()" method because it is used as the "parent" autocomplete field in the "edit" view of the "Category" entity.'

# CONFIGURATION
easy_admin:
entities:
Category:
class: AppTestBundle\Entity\UnitTests\Exceptions\CategoryWithoutToString
# don't include the 'parent' field in the 'list' and 'show' views to avoid
# exceptions that would prevent to test the exception thrown in the 'form' view
list:
fields: ['id']
show:
fields: ['id']
form:
fields:
- { property: parent, type: easyadmin_autocomplete }
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ public function __construct()
$this->products = new ArrayCollection();
}

/** {@inheritdoc} */
public function __toString()
{
return $this->getName();
Expand Down
5 changes: 5 additions & 0 deletions Tests/Fixtures/AppTestBundle/Entity/FunctionalTests/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ class Image
*/
protected $thumbnail;

public function __toString()
{
return 'Image #'.$this->id();
}

/**
* Set the content of the full size image.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,6 @@ public function getId()
return $this->id;
}

/**
* {@inheritdoc}
*/
public function __toString()
{
return $this->getName();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace AppTestBundle\Entity\UnitTests\Exceptions;

use Doctrine\ORM\Mapping as ORM;

/**
* This entity doesn't contain a __toString() method to force an exception
* in some tests.
*
* @ORM\Entity
*/
class CategoryWithoutToString
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

/**
* @ORM\OneToOne(targetEntity="CategoryWithoutToString")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true)
*/
protected $parent;

public function getId()
{
return $this->id;
}

public function setParent($parent)
{
$this->parent = $parent;
}

public function getParent()
{
return $this->parent;
}
}

0 comments on commit 411e095

Please sign in to comment.