Skip to content

Commit

Permalink
feature #284 Changed the way we assign entity names and labels (javie…
Browse files Browse the repository at this point in the history
…reguiluz)

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

Discussion
----------

Changed the way we assign entity names and labels

Commits
-------

6222c19 Changed the way we assign entity names and labels
  • Loading branch information
javiereguiluz committed May 8, 2015
2 parents 2c9bd0f + 6222c19 commit 47d9995
Show file tree
Hide file tree
Showing 43 changed files with 230 additions and 675 deletions.
58 changes: 40 additions & 18 deletions DependencyInjection/EasyAdminExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ public function getEntitiesConfiguration(array $entitiesConfiguration)
*
* These are the two simple formats allowed:
*
* # Config format #1: no custom entity label
* # Config format #1: no custom entity name
* easy_admin:
* entities:
* - AppBundle\Entity\User
*
* # Config format #2: simple config with custom entity label
* # Config format #2: simple config with custom entity name
* easy_admin:
* entities:
* User: AppBundle\Entity\User
Expand All @@ -123,7 +123,10 @@ public function getEntitiesConfiguration(array $entitiesConfiguration)
* User:
* class: AppBundle\Entity\User
*
* # Config format #3 can optionally define a custom entity label
* By default the entity name is used as its label (showed in buttons, the
* main menu, etc.). That's why the config format #3 can optionally define
* a custom entity label
*
* easy_admin:
* entities:
* User:
Expand All @@ -138,32 +141,40 @@ private function normalizeEntitiesConfiguration(array $entitiesConfiguration)
{
$normalizedConfiguration = array();

foreach ($entitiesConfiguration as $entityLabel => $entityConfiguration) {
// config formats #1 and #2
foreach ($entitiesConfiguration as $entityName => $entityConfiguration) {
// normalize config formats #1 and #2 to use the 'class' option as config format #3
if (!is_array($entityConfiguration)) {
$entityConfiguration = array('class' => $entityConfiguration);
}

// if config format #3 is used, ensure that it defines the 'class' option
if (!isset($entityConfiguration['class'])) {
throw new \RuntimeException(sprintf('The "%s" entity must define its associated Doctrine entity class using the "class" option.', $entityLabel));
throw new \RuntimeException(sprintf('The "%s" entity must define its associated Doctrine entity class using the "class" option.', $entityName));
}

$entityClassParts = explode('\\', $entityConfiguration['class']);
$entityClassName = end($entityClassParts);
// if config format #1 is used, the entity name is the numeric index
// of the configuration array. In this case, autogenerate the entity
// name using its class name
if (is_integer($entityName)) {
$entityClassParts = explode('\\', $entityConfiguration['class']);
$entityClassName = end($entityClassParts);
$entityName = $this->getUniqueEntityName($entityClassName, array_keys($normalizedConfiguration));
} else {
// if config format #2 and #3 are used, make sure that the entity
// name is valid as a PHP method name (this is required to allow
// extending the backend with a custom controller)
if (!$this->isValidMethodName($entityName)) {
throw new \InvalidArgumentException(sprintf('The name of the "%s" entity contains invalid characters (allowed: letters, numbers, underscores; the first character cannot be a number).', $entityName));
}
}

// if config format #3 defines the 'label' option, use its value.
// otherwise, infer the entity label from its configuration.
// otherwise, use the entity name as its label
if (!isset($entityConfiguration['label'])) {
// config format #1 doesn't define any entity label because configuration is
// just a plain numeric array (the label is the integer key of that array).
// In that case, use the entity class name as its label
$entityConfiguration['label'] = is_integer($entityLabel) ? $entityClassName : $entityLabel;
$entityConfiguration['label'] = $entityName;
}

$entityName = $this->getUniqueEntityName($entityClassName, array_keys($normalizedConfiguration));
$entityConfiguration['name'] = $entityName;

$normalizedConfiguration[$entityName] = $entityConfiguration;
}

Expand Down Expand Up @@ -294,10 +305,10 @@ private function normalizeActionsConfiguration(array $actionsConfiguration, arra
$actionName = $actionConfiguration['name'];

// 'name' value is used as the class method name or the Symfony route name
// check that its value complies with the PHP method name regexp (the leading dash
// check that its value complies with the PHP method name rules (the leading dash
// is exceptionally allowed to support the configuration format of removed actions)
if (!preg_match('/^-?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $actionName, $matchActionName)) {
throw new \InvalidArgumentException(sprintf('The name of the "%s" action contains invalid characters (allowed: letters, numbers, underscores).', $actionName));
if (!$this->isValidMethodName('-' === $actionName[0] ? substr($actionName, 1) : $actionName)) {
throw new \InvalidArgumentException(sprintf('The name of the "%s" action contains invalid characters (allowed: letters, numbers, underscores; the first character cannot be a number).', $actionName));
}

$normalizedConfiguration = array_replace($this->defaultActionConfiguration, $actionConfiguration);
Expand Down Expand Up @@ -536,4 +547,15 @@ private function normalizeFieldsConfiguration(array $fieldsConfiguration, $view,

return $fields;
}

/**
* Checks whether the given string is valid as a PHP method name.
*
* @param string $name
* @return boolean
*/
private function isValidMethodName($name)
{
return preg_match('/^-?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name, $matches);
}
}
33 changes: 30 additions & 3 deletions Tests/DependencyInjection/EasyAdminExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function testNameOptionIsMandatoryForActionConfiguration()

/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage The name of the "invalid-Action~Name!!" action contains invalid characters (allowed: letters, numbers, underscores).
* @expectedExceptionMessage The name of the "invalid-Action~Name!!" action contains invalid characters (allowed: letters, numbers, underscores; the first character cannot be a number).
*/
public function testActionNameCannotContainInvalidCharacters()
{
Expand All @@ -99,7 +99,7 @@ public function testActionNameCannotContainInvalidCharacters()

/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage The name of the "Invalid action name" action contains invalid characters (allowed: letters, numbers, underscores).
* @expectedExceptionMessage The name of the "Invalid action name" action contains invalid characters (allowed: letters, numbers, underscores; the first character cannot be a number).
*/
public function testActionNameCannotContainWhiteSpaces()
{
Expand All @@ -108,13 +108,40 @@ public function testActionNameCannotContainWhiteSpaces()

/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage The name of the "7invalidActionName" action contains invalid characters (allowed: letters, numbers, underscores).
* @expectedExceptionMessage The name of the "7invalidActionName" action contains invalid characters (allowed: letters, numbers, underscores; the first character cannot be a number).
*/
public function testActionNameCannotStartWithANumber()
{
$this->parseConfigurationFile(__DIR__.'/fixtures/exceptions/action_name_cannot_start_with_a_number.yml');
}

/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage The name of the "Invalid-Entity~Name!!" entity contains invalid characters (allowed: letters, numbers, underscores; the first character cannot be a number).
*/
public function testEntityNameCannotContainInvalidCharacters()
{
$this->parseConfigurationFile(__DIR__.'/fixtures/exceptions/entity_name_cannot_contain_invalid_caracters.yml');
}

/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage The name of the "Test Entity" entity contains invalid characters (allowed: letters, numbers, underscores; the first character cannot be a number).
*/
public function testEntityNameCannotContainWhiteSpaces()
{
$this->parseConfigurationFile(__DIR__.'/fixtures/exceptions/entity_name_cannot_contain_white_spaces.yml');
}

/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage The name of the "7TestEntity" entity contains invalid characters (allowed: letters, numbers, underscores; the first character cannot be a number).
*/
public function testEntityNameCannotStartWithANumber()
{
$this->parseConfigurationFile(__DIR__.'/fixtures/exceptions/entity_name_cannot_start_with_a_number.yml');
}

/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage Invalid configuration for path "easy_admin.design.theme": The theme name can only be "default".
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# TEST
# configuration format #1 with two different entities with the same name
# configuration format #1 with three different entities with the same class name

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# TEST
# configuration format #2 with custom entity label that matches entity name
# configuration format #2 with custom entity name that matches its class name

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# TEST
# configuration format #2 with custom entity label that doesn't match entity name
# configuration format #2 with custom entity name that doesn't match its class name

# CONFIGURATION
easy_admin:
entities:
CustomEntityLabel: AppBundle\Entity\TestEntity
CustomEntityName: AppBundle\Entity\TestEntity
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# NOTE: this test is empty because it was related to a feature that is no longer
# used in EasyAdmin

# TEST
# configuration format #2 with custom entity label that doesn't match entity name
# configuration format #2 with custom entity name that doesn't match its class name
# and which contains special YAML characters

# CONFIGURATION
easy_admin:
entities:
'Custom #Entity ~ Label': AppBundle\Entity\TestEntity
easy_admin: ~
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# TEST
# configuration format #2: two different entities with the same label
# configuration format #2: two different entities with the same name
# (the first defined entity wins)

# CONFIGURATION
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# TEST
# configuration format #2: two different entities with the same custom label
# configuration format #2: two different entities with the same custom name
# (the first defined entity wins)

# CONFIGURATION
easy_admin:
entities:
CustomEntityLabel: AppBundle\Entity\TestEntity
CustomEntityLabel: AppBundle\OtherNamespace\Entity\TestEntity
CustomEntityName: AppBundle\Entity\TestEntity
CustomEntityName: AppBundle\OtherNamespace\Entity\TestEntity
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# TEST
# configuration format #3: entity label matches entity name
# configuration format #3: entity name matches its class name

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# TEST
# configuration format #3: entity label doesn't match the entity name
# configuration format #3: entity name doesn't match its class name

# CONFIGURATION
easy_admin:
entities:
CustomEntityLabel:
CustomEntityName:
class: AppBundle\Entity\TestEntity
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# NOTE: this test is empty because it was related to a feature that is no longer
# used in EasyAdmin

# TEST
# configuration format #3 with custom entity label that doesn't match entity name
# configuration format #3 with custom entity name that doesn't match its class name
# and which contains special YAML characters

# CONFIGURATION
easy_admin:
entities:
'Custom #Entity ~ Label':
class: AppBundle\Entity\TestEntity
easy_admin: ~
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# TEST
# configuration format #3 with two different entities using the same default label
# configuration format #3 with two different entities using the same name
# (the first defined entity wins)

# CONFIGURATION
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# TEST
# configuration format #3 with two different entities using the same custom label
# configuration format #3 with two different entities using the same custom name
# (the first defined entity wins)

# CONFIGURATION
easy_admin:
entities:
CustomEntityLabel:
CustomEntityName:
class: AppBundle\Entity\TestEntity
CustomEntityLabel:
CustomEntityName:
class: AppBundle\AnotherNamespace\Entity\TestEntity
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# NOTE: this test is empty because it was related to a feature that is no longer
# used in EasyAdmin

# TEST
# configuration format #3 with two different entities using the same custom label
# configuration format #3 with two different entities using the same custom name
# which contains special YAML characters
# (the first defined entity wins)

# CONFIGURATION
easy_admin:
entities:
'Custom #Entity ~ Label':
class: AppBundle\Entity\TestEntity
'Custom #Entity ~ Label':
class: AppBundle\AnotherNamespace\Entity\TestEntity
easy_admin: ~
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TEST
# configuration format #3 with two different entities with the same name
# but defining a different label
# configuration format #3 with two different entities with the same class name
# but with a different entity name

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TEST
# configuration format #3 expanded, with two different entities using
# different names and labels
# configuration format #3 expanded, with two entities with the same class name
# but using different entity names and labels

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TEST
# configuration format #3 expanded, with two different entities using
# different names and same labels
# different entity names but the same label

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TEST
# configuration format #3 expanded, with two different entities using
# different names and same custom labels
# different entity names but the same custom label

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TEST
# combining configuration formats #2 and #3 using entities with same names
# and the same label
# combining configuration formats #2 and #3 using entities with same class names
# and label but different names

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TEST
# combining configuration formats #2 and #3 using entities with same names
# and labels
# combining configuration formats #2 and #3 using entities with same class names
# but different entity names and labels

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# NOTE: this test is empty because it was related to a feature that is no longer
# used in EasyAdmin

# TEST
# combining configuration formats #2 and #3 using entities with same names
# and labels which include special YAML characters
# combining configuration formats #2 and #3 using entities with same class names
# but different names which include special YAML characters

# CONFIGURATION
easy_admin:
entities:
'Custom #Entity ~ Label': AppBundle\Entity\TestEntity
AnotherTestEntity:
class: AppBundle\AnotherNamespace\Entity\TestEntity
label: 'Another Custom #Entity ~ Label'
easy_admin: ~
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# TEST
# all the original (and custom) entity configuration options are maintained
# any custom entity configuration options are maintained when processing the
# backend configuration (this allows to add custom options for complex backends)

# CONFIGURATION
easy_admin:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ easy_admin:
label_undefined: '@EasyAdmin/default/label_undefined.html.twig'
TestEntity2:
class: AppBundle\AnotherNamespace\Entity\TestEntity
label: TestEntity
label: TestEntity2
name: TestEntity2
edit:
fields: { }
Expand Down Expand Up @@ -230,7 +230,7 @@ easy_admin:
label_undefined: '@EasyAdmin/default/label_undefined.html.twig'
TestEntity3:
class: AnotherBundle\Entity\TestEntity
label: TestEntity
label: TestEntity3
name: TestEntity3
edit:
fields: { }
Expand Down
Loading

0 comments on commit 47d9995

Please sign in to comment.