Skip to content

Commit

Permalink
Allow entities with primary keys not named 'id'
Browse files Browse the repository at this point in the history
  • Loading branch information
javiereguiluz committed Jan 28, 2015
1 parent 54eb708 commit 4a2d207
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 32 deletions.
35 changes: 19 additions & 16 deletions Configuration/Configurator.php
Expand Up @@ -12,6 +12,7 @@
namespace JavierEguiluz\Bundle\EasyAdminBundle\Configuration;

use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\ClassMetadataInfo;

class Configurator
Expand Down Expand Up @@ -70,13 +71,17 @@ public function getEntityConfiguration($entityName)
$entityClass = $this->backendConfig['entities'][$entityName]['class'];
$entityConfiguration['class'] = $entityClass;

$entityProperties = $this->getEntityPropertiesMetadata($entityClass);
$doctrineEntityMetadata = $this->em->getMetadataFactory()->getMetadataFor($entityClass);

$entityProperties = $this->getEntityPropertiesMetadata($doctrineEntityMetadata);
$entityConfiguration['properties'] = $entityProperties;

$entityConfiguration['primary_key_field_name'] = $doctrineEntityMetadata->getSingleIdentifierFieldName();

$entityConfiguration['list']['fields'] = $this->getFieldsForListAction($this->backendConfig['entities'][$entityName], $entityProperties);
$entityConfiguration['show']['fields'] = $this->getFieldsForShowAction($this->backendConfig['entities'][$entityName], $entityProperties);
$entityConfiguration['edit']['fields'] = $this->getFieldsForFormBasedActions('edit', $this->backendConfig['entities'][$entityName], $entityProperties);
$entityConfiguration['new']['fields'] = $this->getFieldsForFormBasedActions('new', $this->backendConfig['entities'][$entityName], $entityProperties);
$entityConfiguration['edit']['fields'] = $this->getFieldsForFormBasedActions('edit', $this->backendConfig['entities'][$entityName], $entityProperties, $entityConfiguration['primary_key_field_name']);
$entityConfiguration['new']['fields'] = $this->getFieldsForFormBasedActions('new', $this->backendConfig['entities'][$entityName], $entityProperties, $entityConfiguration['primary_key_field_name']);
$entityConfiguration['search']['fields'] = $this->getFieldsForSearchAction($entityProperties);

$this->entitiesConfig[$entityName] = $entityConfiguration;
Expand All @@ -88,18 +93,15 @@ public function getEntityConfiguration($entityName)
* Takes the FQCN of the entity and returns all the metadata of its properties
* introspected via Doctrine.
*
* @param string $entityClass The fully qualified class name of the entity
* @return array The entity properties metadata provided by Doctrine
* @param ClassMetadata $entityMetadata The entity metadata introspected via Doctrine
* @return array The entity properties metadata provided by Doctrine
*/
private function getEntityPropertiesMetadata($entityClass)
private function getEntityPropertiesMetadata(ClassMetadata $entityMetadata)
{
$entityPropertiesMetadata = array();

/** @var ClassMetadata $entityMetadata */
$entityMetadata = $this->em->getMetadataFactory()->getMetadataFor($entityClass);

if ('id' !== $entityMetadata->getSingleIdentifierFieldName()) {
throw new \RuntimeException(sprintf("The '%s' entity isn't valid because it doesn't define a primary key called 'id'.", $entityClass));
if ($entityMetadata->isIdentifierComposite) {
throw new \RuntimeException(sprintf("The '%s' entity isn't valid because it contains a composite primary key.", $entityMetadata->name));
}

// introspect regular entity fields
Expand Down Expand Up @@ -173,11 +175,12 @@ private function getFieldsForShowAction(array $entityConfiguration, array $entit
* Returns the list of fields to show in the forms of this entity for the
* actions which display forms ('edit' and 'new').
*
* @param array $entityConfiguration
* @param array $entityProperties
* @return array The list of fields to show and their metadata
* @param array $entityConfiguration
* @param array $entityProperties
* @param string $primaryKeyFieldName
* @return array The list of fields to show and their metadata
*/
protected function getFieldsForFormBasedActions($action, array $entityConfiguration, array $entityProperties)
protected function getFieldsForFormBasedActions($action, array $entityConfiguration, array $entityProperties, $primaryKeyFieldName)
{
$entityFields = array();

Expand All @@ -190,7 +193,7 @@ protected function getFieldsForFormBasedActions($action, array $entityConfigurat
} else {
$entityFields = $this->createEntityFieldsFromEntityProperties($entityProperties);

$excludedFieldNames = array('id');
$excludedFieldNames = array($primaryKeyFieldName);
$excludedFieldTypes = array('binary', 'blob', 'json_array', 'object');
$entityFields = $this->filterEntityFieldsBasedOnNameAndTypeBlackList($entityFields, $excludedFieldNames, $excludedFieldTypes);
}
Expand Down
12 changes: 7 additions & 5 deletions Controller/AdminController.php
Expand Up @@ -104,11 +104,13 @@ protected function initialize(Request $request)
$this->entity = $this->get('easyadmin.configurator')->getEntityConfiguration($entityName);
}

if (!$request->query->has('sortField')) {
$request->query->set('sortField', 'id');
}
if (!$request->query->has('sortDirection') || !in_array(strtoupper($request->query->get('sortDirection')), array('ASC', 'DESC'))) {
$request->query->set('sortDirection', 'DESC');
if (null !== $entityName) {
if (!$request->query->has('sortField')) {
$request->query->set('sortField', $this->entity['primary_key_field_name']);
}
if (!$request->query->has('sortDirection') || !in_array(strtoupper($request->query->get('sortDirection')), array('ASC', 'DESC'))) {
$request->query->set('sortDirection', 'DESC');
}
}

$this->request = $request;
Expand Down
14 changes: 11 additions & 3 deletions DependencyInjection/EasyAdminExtension.php
Expand Up @@ -100,6 +100,8 @@ protected function getEntitiesConfiguration(array $entitiesConfiguration)
private function normalizeEntityConfiguration(array $simpleConfig)
{
$normalizedConfig = array();

$entityNames = array();
foreach ($simpleConfig as $entityName => $entityClass) {
if (is_integer($entityName)) {
// the simplest configuration format defines no custom entity names,
Expand All @@ -108,7 +110,10 @@ private function normalizeEntityConfiguration(array $simpleConfig)
$entityName = array_pop($entityClassParts);
}

$normalizedConfig[$entityName] = array(
$uniqueEntityName = $this->getUniqueEntityName($entityClass, $entityNames);
$entityNames[] = $uniqueEntityName;

$normalizedConfig[$uniqueEntityName] = array(
'class' => $entityClass,
);
}
Expand All @@ -127,6 +132,7 @@ private function processEntitiesConfiguration(array $entitiesConfiguration)
{
$entities = array();

$entityNames = array();
foreach ($entitiesConfiguration as $entityName => $entityConfiguration) {
// copy the original entity configuration to not loose any of its options
$config = $entityConfiguration;
Expand All @@ -148,7 +154,9 @@ private function processEntitiesConfiguration(array $entitiesConfiguration)
$config[$action]['fields'] = $this->processFieldsConfiguration($config[$action]['fields'], $action, $config['class']);
}

$uniqueEntityName = $this->getUniqueEntityName($config['class'], array_keys($entitiesConfiguration));
$uniqueEntityName = $this->getUniqueEntityName($config['class'], $entityNames);
$entityNames[] = $uniqueEntityName;

$config['name'] = $uniqueEntityName;

$entities[$uniqueEntityName] = $config;
Expand All @@ -175,7 +183,7 @@ private function getUniqueEntityName($entityClass, $entityNames)
$entityClassParts = explode('\\', $entityClass);
$uniqueEntityName = array_pop($entityClassParts);

while (array_key_exists($uniqueEntityName, $entityNames)) {
while (in_array($uniqueEntityName, $entityNames)) {
$uniqueEntityName .= '_';
}

Expand Down
8 changes: 5 additions & 3 deletions README.md
Expand Up @@ -15,9 +15,11 @@ with unprecedented simplicity.

**Requirements**

EasyAdmin is compatible with Symfony 2.3+ applications that use Doctrine ORM
entities to define their model. These entities must include a simple primary
key called `id` and `many-to-many` associations are not supported.
* Symfony 2.3+ applications (Silex not supported).
* Doctrine ORM entities (Doctrine ODM and Propel not supported).
* Entities with simple primary keys (composite keys not supported).
* All kinds of entity associations are supported, except `many-to-many`.
* Entities using inheritance are not supported.

Installation
------------
Expand Down
2 changes: 1 addition & 1 deletion Resources/views/edit.html.twig
Expand Up @@ -25,7 +25,7 @@
{% endblock %}

{% block content_title %}
{{ 'entity.edit' | trans({'%label%': entity.name ~ ' #' ~ item.id}) }}
{{ 'entity.edit' | trans({'%label%': entity.name ~ ' #' ~ attribute(item, entity.primary_key_field_name)}) }}
{% endblock %}

{% block main %}
Expand Down
2 changes: 1 addition & 1 deletion Resources/views/list.html.twig
Expand Up @@ -97,7 +97,7 @@
{% endfor %}
<td class="actions">
{% for action in config['list_actions'] %}
<a href="{{ path('admin', { action: action, entity: entity.name, id: attribute(item, 'id') }) }}">
<a href="{{ path('admin', { action: action, entity: entity.name, id: attribute(item, entity.primary_key_field_name) }) }}">
{{ ('actions.' ~ action)|trans }}
</a>
{% endfor %}
Expand Down
4 changes: 2 additions & 2 deletions Resources/views/show.html.twig
Expand Up @@ -21,7 +21,7 @@
{% endblock %}

{% block content_title %}
{{ entity.name ~ ' #' ~ item.id }}
{{ entity.name ~ ' #' ~ attribute(item, entity.primary_key_field_name) }}
{% endblock %}

{% block main %}
Expand All @@ -47,7 +47,7 @@

<div class="form-group form-actions">
<div class="col-sm-10 col-sm-offset-2">
<a class="btn btn-edit" href="{{ path('admin', { action: 'edit', entity: entity.name, id: attribute(item, 'id') }) }}">
<a class="btn btn-edit" href="{{ path('admin', { action: 'edit', entity: entity.name, id: attribute(item, entity.primary_key_field_name) }) }}">
<i class="fa fa-edit"></i> {{ 'entity.edit' | trans({"%entity%": entity.name}) }}
</a>

Expand Down
2 changes: 1 addition & 1 deletion Twig/EasyAdminTwigExtension.php
Expand Up @@ -92,7 +92,7 @@ public function displayEntityField($entity, $fieldName, array $fieldMetadata)
return new \Twig_Markup(sprintf('<a href="%s">%s</a>', $this->urlGenerator->generate('admin', array('entity' => $associatedEntityClassName, 'action' => 'show', 'id' => $value->getId())), $value), 'UTF-8');
}

return '';
return $value;
}
} catch (\Exception $e) {
return '';
Expand Down

0 comments on commit 4a2d207

Please sign in to comment.