Skip to content

Commit

Permalink
Adds readonly compatibility with Doctrine Mongo ODM documents
Browse files Browse the repository at this point in the history
  • Loading branch information
alterphp committed Feb 7, 2019
1 parent 0dbb80b commit 4317919
Show file tree
Hide file tree
Showing 48 changed files with 1,421 additions and 404 deletions.
12 changes: 12 additions & 0 deletions TODO_mongo_odm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Utiliser les functions Twig object

# Menu entries (entry type = document)

# Passer les configPass en mongo_odm
- EmbeddedListViewConfigPass: OK
- ExcludeFieldsConfigPass
- ListFormFiltersConfigPass OK
- ShortFormTypeConfigPass: OK
- ShowViewConfigPass: ?

# Tests !
9 changes: 8 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
"twig/twig": "^2.4"
},
"require-dev": {
"alcaeus/mongo-php-adapter": "^1.1",
"alterphp/easyadmin-mongo-odm-bundle": "dev-master",
"doctrine/doctrine-fixtures-bundle": "^3.0",
"doctrine/mongodb-odm-bundle": "^3.4",
"friendsofphp/php-cs-fixer": "^2.11",
"php-coveralls/php-coveralls": "^2.0",
"phpstan/phpstan": "^0.9.2",
Expand All @@ -49,7 +52,11 @@
"symfony/var-dumper": "^4.1"
},
"config": {
"sort-packages": true
"sort-packages": true,
"platform": {
"ext-mongodb": "1.3.3",
"ext-mongo": "1.6.16"
}
},
"autoload": {
"psr-4": { "AlterPHP\\EasyAdminExtensionBundle\\": "src/" },
Expand Down
3 changes: 1 addition & 2 deletions docker-compose.yml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ services:
volumes:
- ./:/app
entrypoint:
- php
- /app/vendor/phpunit/phpunit/phpunit
- ./vendor/bin/phpunit

php-cs-fixer:
image: ekreative/php-cs-fixer
Expand Down
12 changes: 9 additions & 3 deletions docker/phpunit/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
FROM phpunit/phpunit:latest
FROM php:7.2-cli

RUN apk --no-cache add php7-iconv
RUN apk --no-cache add php7-simplexml
RUN docker-php-ext-install -j$(nproc) mysqli

# Install MONGO
RUN pecl install mongodb \
&& docker-php-ext-enable mongodb

VOLUME ["/app"]
WORKDIR /app
52 changes: 30 additions & 22 deletions src/Configuration/EmbeddedListViewConfigPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use EasyCorp\Bundle\EasyAdminBundle\Configuration\ConfigPassInterface;

/**
* Initializes the configuration for all the views of each entity, which is
* needed when some entity relies on the default configuration for some view.
* Initializes the configuration for all the views of each object of type "%s", which is
* needed when some object of type "%s" relies on the default configuration for some view.
*/
class EmbeddedListViewConfigPass implements ConfigPassInterface
{
Expand All @@ -32,9 +32,13 @@ public function process(array $backendConfig)
*/
private function processOpenNewTabConfig(array $backendConfig)
{
foreach ($backendConfig['entities'] as $entityName => $entityConfig) {
if (!isset($entityConfig['embeddedList']['open_new_tab'])) {
$backendConfig['entities'][$entityName]['embeddedList']['open_new_tab'] = $this->defaultOpenNewTab;
foreach (['entities', 'documents'] as $objectTypeRootKey) {
if (isset($backendConfig[$objectTypeRootKey]) && \is_array($backendConfig[$objectTypeRootKey])) {
foreach ($backendConfig[$objectTypeRootKey] as $objectName => $objectConfig) {
if (!isset($objectConfig['embeddedList']['open_new_tab'])) {
$backendConfig[$objectTypeRootKey][$objectName]['embeddedList']['open_new_tab'] = $this->defaultOpenNewTab;
}
}
}
}

Expand All @@ -48,25 +52,29 @@ private function processOpenNewTabConfig(array $backendConfig)
*/
private function processSortingConfig(array $backendConfig)
{
foreach ($backendConfig['entities'] as $entityName => $entityConfig) {
if (
!isset($entityConfig['embeddedList']['sort'])
&& isset($entityConfig['list']['sort'])
) {
$backendConfig['entities'][$entityName]['embeddedList']['sort'] = $entityConfig['list']['sort'];
} elseif (isset($entityConfig['embeddedList']['sort'])) {
$sortConfig = $entityConfig['embeddedList']['sort'];
if (!\is_string($sortConfig) && !\is_array($sortConfig)) {
throw new \InvalidArgumentException(\sprintf('The "sort" option of the "embeddedList" view of the "%s" entity contains an invalid value (it can only be a string or an array).', $entityName));
}
foreach (['entities', 'documents'] as $objectTypeRootKey) {
if (isset($backendConfig[$objectTypeRootKey]) && \is_array($backendConfig[$objectTypeRootKey])) {
foreach ($backendConfig[$objectTypeRootKey] as $objectName => $objectConfig) {
if (
!isset($objectConfig['embeddedList']['sort'])
&& isset($objectConfig['list']['sort'])
) {
$backendConfig[$objectTypeRootKey][$objectName]['embeddedList']['sort'] = $objectConfig['list']['sort'];
} elseif (isset($objectConfig['embeddedList']['sort'])) {
$sortConfig = $objectConfig['embeddedList']['sort'];
if (!\is_string($sortConfig) && !\is_array($sortConfig)) {
throw new \InvalidArgumentException(\sprintf('The "sort" option of the "embeddedList" view of the "%s" object contains an invalid value (it can only be a string or an array).', $objectName));
}

if (\is_string($sortConfig)) {
$sortConfig = ['field' => $sortConfig, 'direction' => 'DESC'];
} else {
$sortConfig = ['field' => $sortConfig[0], 'direction' => \strtoupper($sortConfig[1])];
}
if (\is_string($sortConfig)) {
$sortConfig = ['field' => $sortConfig, 'direction' => 'DESC'];
} else {
$sortConfig = ['field' => $sortConfig[0], 'direction' => \strtoupper($sortConfig[1])];
}

$backendConfig['entities'][$entityName]['embeddedList']['sort'] = $sortConfig;
$backendConfig[$objectTypeRootKey][$objectName]['embeddedList']['sort'] = $sortConfig;
}
}
}
}

Expand Down
67 changes: 41 additions & 26 deletions src/Configuration/ListFormFiltersConfigPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,34 @@ public function __construct(ManagerRegistry $doctrine)
*/
public function process(array $backendConfig): array
{
if (!isset($backendConfig['entities'])) {
return $backendConfig;
if (isset($backendConfig['entities']) && \is_array($backendConfig['entities'])) {
$this->processObjectListFormFilters('entity', $backendConfig['entities']);
}

foreach ($backendConfig['entities'] as $entityName => $entityConfig) {
if (!isset($entityConfig['list']['form_filters'])) {
if (isset($backendConfig['documents']) && \is_array($backendConfig['documents'])) {
$this->processObjectListFormFilters('document', $backendConfig['documents']);
}

return $backendConfig;
}

private function processObjectListFormFilters(string $objectType, array &$objectConfigs)
{
foreach ($objectConfigs as $objectName => $objectConfig) {
if (!isset($objectConfig['list']['form_filters'])) {
continue;
}

$formFilters = [];

foreach ($entityConfig['list']['form_filters'] as $i => $formFilter) {
foreach ($objectConfig['list']['form_filters'] as $key => $formFilter) {
// Detects invalid config node
if (!\is_string($formFilter) && !\is_array($formFilter)) {
throw new \RuntimeException(
\sprintf(
'The values of the "form_filters" option for the list view of the "%s" entity can only be strings or arrays.',
$entityConfig['class']
'The values of the "form_filters" option for the list view of the "%s" object of type "%s" can only be strings or arrays.',
$objectConfig['class'],
$objectType
)
);
}
Expand All @@ -59,12 +69,17 @@ public function process(array $backendConfig): array
$filterConfig = ['property' => $formFilter];
} else {
if (!\array_key_exists('property', $formFilter)) {
throw new \RuntimeException(
\sprintf(
'One of the values of the "form_filters" option for the "list" view of the "%s" entity does not define the mandatory option "property".',
$entityConfig['class']
)
);
if (\is_string($key)) {
$formFilter['property'] = $key;
} else {
throw new \RuntimeException(
\sprintf(
'One of the values of the "form_filters" option for the "list" view of the "%s" object of type "%s" does not define the mandatory option "property".',
$objectConfig['class'],
$objectType
)
);
}
}

$filterConfig = $formFilter;
Expand All @@ -75,11 +90,13 @@ public function process(array $backendConfig): array
// Auto set label with name value
$filterConfig['label'] = $filterConfig['label'] ?? $filterConfig['name'];

$this->configureFilter(
$entityConfig['class'],
$filterConfig,
$backendConfig['translation_domain'] ?? 'EasyAdminBundle'
);
if ('entity' === $objectType) {
$this->configureEntityFormFilter(
$objectConfig['class'],
$filterConfig,
$backendConfig['translation_domain'] ?? 'EasyAdminBundle'
);
}

// If type is not configured at this steps => not guessable
if (!isset($filterConfig['type'])) {
Expand All @@ -90,13 +107,11 @@ public function process(array $backendConfig): array
}

// set form filters config and form !
$backendConfig['entities'][$entityName]['list']['form_filters'] = $formFilters;
$objectConfigs[$objectName]['list']['form_filters'] = $formFilters;
}

return $backendConfig;
}

private function configureFilter(string $entityClass, array &$filterConfig, string $translationDomain)
private function configureEntityFormFilter(string $entityClass, array &$filterConfig, string $translationDomain)
{
$em = $this->doctrine->getManagerForClass($entityClass);
$entityMetadata = $em->getMetadataFactory()->getMetadataFor($entityClass);
Expand All @@ -110,17 +125,17 @@ private function configureFilter(string $entityClass, array &$filterConfig, stri
}

if ($entityMetadata->hasField($filterConfig['property'])) {
$this->configureFieldFilter(
$this->configureEntityPropertyFilter(
$entityClass, $entityMetadata->getFieldMapping($filterConfig['property']), $filterConfig, $translationDomain
);
} elseif ($entityMetadata->hasAssociation($filterConfig['property'])) {
$this->configureAssociationFilter(
$this->configureEntityAssociationFilter(
$entityClass, $entityMetadata->getAssociationMapping($filterConfig['property']), $filterConfig
);
}
}

private function configureFieldFilter(
private function configureEntityPropertyFilter(
string $entityClass, array $fieldMapping, array &$filterConfig, string $translationDomain
) {
switch ($fieldMapping['type']) {
Expand Down Expand Up @@ -181,7 +196,7 @@ private function configureFieldFilter(
}
}

private function configureAssociationFilter(string $entityClass, array $associationMapping, array &$filterConfig)
private function configureEntityAssociationFilter(string $entityClass, array $associationMapping, array &$filterConfig)
{
// To-One (EasyAdminAutocompleteType)
if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
Expand Down
15 changes: 8 additions & 7 deletions src/Configuration/ShortFormTypeConfigPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,16 @@ public function process(array $backendConfig)

private function replaceShortNameTypes(array $backendConfig)
{
if (
!isset($backendConfig['entities'])
|| !\is_array($backendConfig['entities'])
) {
return $backendConfig;
if (isset($backendConfig['entities']) && \is_array($backendConfig['entities'])) {
foreach ($backendConfig['entities'] as &$entityConfig) {
$entityConfig = $this->replaceShortFormTypesInObjectConfig($entityConfig);
}
}

foreach ($backendConfig['entities'] as &$entity) {
$entity = $this->replaceShortFormTypesInObjectConfig($entity);
if (isset($backendConfig['documents']) && \is_array($backendConfig['documents'])) {
foreach ($backendConfig['documents'] as &$documentConfig) {
$documentConfig = $this->replaceShortFormTypesInObjectConfig($documentConfig);
}
}

return $backendConfig;
Expand Down
78 changes: 55 additions & 23 deletions src/Configuration/ShowViewConfigPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,25 @@ public function process(array $backendConfig)
*/
private function processCustomShowTypes(array $backendConfig)
{
foreach ($backendConfig['entities'] as $entityName => $entityConfig) {
foreach ($entityConfig['show']['fields'] as $fieldName => $fieldMetadata) {
if (\array_key_exists($fieldMetadata['type'], static::$mapTypeToTemplates)) {
$template = $this->isFieldTemplateDefined($fieldMetadata)
? $fieldMetadata['template']
: static::$mapTypeToTemplates[$fieldMetadata['type']];
$entityConfig['show']['fields'][$fieldName]['template'] = $template;

$entityConfig['show']['fields'][$fieldName]['template_options'] = $this->processTemplateOptions(
$fieldMetadata['type'], $fieldMetadata
);
foreach (['entities', 'documents'] as $objectTypeRootKey) {
if (isset($backendConfig[$objectTypeRootKey]) && \is_array($backendConfig[$objectTypeRootKey])) {
foreach ($backendConfig[$objectTypeRootKey] as $objectName => $objectConfig) {
foreach ($objectConfig['show']['fields'] as $fieldName => $fieldMetadata) {
if (\array_key_exists($fieldMetadata['type'], static::$mapTypeToTemplates)) {
$template = $this->isFieldTemplateDefined($fieldMetadata)
? $fieldMetadata['template']
: static::$mapTypeToTemplates[$fieldMetadata['type']];
$objectConfig['show']['fields'][$fieldName]['template'] = $template;

$objectConfig['show']['fields'][$fieldName]['template_options'] = $this->processTemplateOptions(
$fieldMetadata['type'], $fieldMetadata
);
}
}

$backendConfig[$objectTypeRootKey][$objectName] = $objectConfig;
}
}

$backendConfig['entities'][$entityName] = $entityConfig;
}

return $backendConfig;
Expand All @@ -81,19 +85,47 @@ private function processTemplateOptions(string $type, array $fieldMetadata)

switch ($type) {
case 'embedded_list':
$parentEntityFqcn = $templateOptions['parent_entity_fqcn'] ?? $fieldMetadata['sourceEntity'];
$parentEntityProperty = $templateOptions['parent_entity_property'] ?? $fieldMetadata['property'];
$entityFqcn = $this->embeddedListHelper->getEntityFqcnFromParent(
$parentEntityFqcn, $parentEntityProperty
// Deprecations
if (isset($templateOptions['entity_fqcn']) && !isset($templateOptions['object_fqcn'])) {
$templateOptions['object_fqcn'] = $templateOptions['entity_fqcn'];
unset($templateOptions['entity_fqcn']);

\trigger_error(\sprintf('The "entity_fqcn" option for embedded_list is deprecated since version 1.4.0 and it will be removed in 2.0. Use the "object_fqcn" option instead.'), E_USER_DEPRECATED);
}
if (isset($templateOptions['parent_entity_fqcn']) && !isset($templateOptions['parent_object_fqcn'])) {
$templateOptions['parent_object_fqcn'] = $templateOptions['parent_entity_fqcn'];
unset($templateOptions['parent_entity_fqcn']);

\trigger_error(\sprintf('The "parent_entity_fqcn" option for embedded_list is deprecated since version 1.4.0 and it will be removed in 2.0. Use the "parent_object_fqcn" option instead.'), E_USER_DEPRECATED);
}
if (isset($templateOptions['parent_entity_property']) && !isset($templateOptions['parent_object_property'])) {
$templateOptions['parent_object_property'] = $templateOptions['parent_entity_property'];
unset($templateOptions['parent_entity_property']);

\trigger_error(\sprintf('The "parent_entity_property" option for embedded_list is deprecated since version 1.4.0 and it will be removed in 2.0. Use the "parent_object_property" option instead.'), E_USER_DEPRECATED);
}

$parentObjectFqcn = $templateOptions['parent_object_fqcn'] ?? $fieldMetadata['sourceEntity'];
$parentObjectProperty = $templateOptions['parent_object_property'] ?? $fieldMetadata['property'];
$objectFqcn = $this->embeddedListHelper->getEntityFqcnFromParent(
$parentObjectFqcn, $parentObjectProperty
);
if (!isset($templateOptions['entity_fqcn'])) {
$templateOptions['entity_fqcn'] = $entityFqcn;

if (isset($templateOptions['document'])) {
$templateOptions['object_type'] = 'document';
} else {
$templateOptions['object_type'] = 'entity';
}
if (!isset($templateOptions['parent_entity_property'])) {
$templateOptions['parent_entity_property'] = $parentEntityProperty;

if (!isset($templateOptions['entity']) && !isset($templateOptions['document'])) {
$templateOptions['entity'] = $this->embeddedListHelper->guessEntityEntry($objectFqcn);
}

if (!isset($templateOptions['object_fqcn'])) {
$templateOptions['object_fqcn'] = $objectFqcn;
}
if (!isset($templateOptions['entity'])) {
$templateOptions['entity'] = $this->embeddedListHelper->guessEntityEntry($entityFqcn);
if (!isset($templateOptions['parent_object_property'])) {
$templateOptions['parent_object_property'] = $parentObjectProperty;
}
if (!isset($templateOptions['filters'])) {
$templateOptions['filters'] = [];
Expand Down
1 change: 1 addition & 0 deletions src/Controller/EasyAdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ protected function embeddedListAction()
$this->dispatch(EasyAdminEvents::POST_LIST, ['paginator' => $paginator]);

return $this->render('@EasyAdminExtension/default/embedded_list.html.twig', [
'objectType' => 'entity',
'paginator' => $paginator,
'fields' => $fields,
'masterRequest' => $this->get('request_stack')->getMasterRequest(),
Expand Down
Loading

0 comments on commit 4317919

Please sign in to comment.