From 458cd19acb234e0ac0c217e3d2e14895ec692d0b Mon Sep 17 00:00:00 2001 From: Ambroise Maupate Date: Mon, 16 Dec 2024 17:34:15 +0100 Subject: [PATCH 1/4] chore: Use `HostRegexp` and `PathRegexp` for Traefik v3 compatibility --- .env | 12 +++++++----- compose.yml | 14 +++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.env b/.env index d4b3c9c7..eb900d89 100644 --- a/.env +++ b/.env @@ -43,11 +43,13 @@ SMTP_MAILER_PORT=1125 # # 127.0.0.1 roadiz-core-app.test roadiz-core-app.local varnish.roadiz-core-app.test varnish.roadiz-core-app.local pma.roadiz-core-app.test pma.roadiz-core-app.local solr.roadiz-core-app.test solr.roadiz-core-app.local mail.roadiz-core-app.test mail.roadiz-core-app.local # -HOSTNAME=`roadiz-core-app.test`,`roadiz-core-app.local` -HOSTNAME_VARNISH=`varnish.roadiz-core-app.test`,`varnish.roadiz-core-app.local` -HOSTNAME_PMA=`pma.roadiz-core-app.test`,`pma.roadiz-core-app.local` -HOSTNAME_SOLR=`solr.roadiz-core-app.test`,`solr.roadiz-core-app.local` -HOSTNAME_MAILER=`mail.roadiz-core-app.test`,`mail.roadiz-core-app.local` +HOSTNAME=`^roadiz\-core\-app\.(test|local)$` +HOSTNAME_VARNISH=`^varnish\.roadiz\-core\-app\.(test|local)$` +HOSTNAME_PMA=`^pma\.roadiz\-core\-app\.(test|local)$` +HOSTNAME_SOLR=`^solr\.roadiz\-core\-app\.(test|local)$` +HOSTNAME_MAILER=`^(mail|mailer)\.roadiz\-core\-app\.(test|local)$` +PATH_PREFIX=`(?i)^/(rz\-admin|files|assets|themes|bundles|api|_wdt|_profiler|css/main\-color\.css|custom\-form|css/login/image)` + DEFAULT_GATEWAY=172.58.0.0 ###> rezozero/intervention-request-bundle ### diff --git a/compose.yml b/compose.yml index c70b5029..a7527187 100644 --- a/compose.yml +++ b/compose.yml @@ -49,7 +49,7 @@ services: - "traefik.http.services.${APP_NAMESPACE}_pma.loadbalancer.passhostheader=true" # Listen HTTP - "traefik.http.routers.${APP_NAMESPACE}_pma.entrypoints=http" - - "traefik.http.routers.${APP_NAMESPACE}_pma.rule=Host(${HOSTNAME_PMA})" + - "traefik.http.routers.${APP_NAMESPACE}_pma.rule=HostRegexp(${HOSTNAME_PMA})" - "traefik.http.routers.${APP_NAMESPACE}_pma.service=${APP_NAMESPACE}_pma" solr: @@ -74,7 +74,7 @@ services: - "traefik.http.services.${APP_NAMESPACE}_solr.loadbalancer.passhostheader=true" # Listen HTTP - "traefik.http.routers.${APP_NAMESPACE}_solr.entrypoints=http" - - "traefik.http.routers.${APP_NAMESPACE}_solr.rule=Host(${HOSTNAME_SOLR})" + - "traefik.http.routers.${APP_NAMESPACE}_solr.rule=HostRegexp(${HOSTNAME_SOLR})" - "traefik.http.routers.${APP_NAMESPACE}_solr.service=${APP_NAMESPACE}_solr" redis: @@ -144,11 +144,11 @@ services: - "traefik.http.services.${APP_NAMESPACE}.loadbalancer.passhostheader=true" # Listen HTTP - "traefik.http.routers.${APP_NAMESPACE}.entrypoints=http" - - "traefik.http.routers.${APP_NAMESPACE}.rule=Host(${HOSTNAME})" + - "traefik.http.routers.${APP_NAMESPACE}.rule=HostRegexp(${HOSTNAME}) && PathRegexp(${PATH_PREFIX})" - "traefik.http.routers.${APP_NAMESPACE}.service=${APP_NAMESPACE}" # Listen HTTPS - "traefik.http.routers.${APP_NAMESPACE}_secure.entrypoints=https" - - "traefik.http.routers.${APP_NAMESPACE}_secure.rule=Host(${HOSTNAME})" + - "traefik.http.routers.${APP_NAMESPACE}_secure.rule=HostRegexp(${HOSTNAME}) && PathRegexp(${PATH_PREFIX})" - "traefik.http.routers.${APP_NAMESPACE}_secure.tls=true" - "traefik.http.routers.${APP_NAMESPACE}_secure.service=${APP_NAMESPACE}" @@ -167,11 +167,11 @@ services: - "traefik.http.services.${APP_NAMESPACE}_varnish.loadbalancer.passhostheader=true" # Listen HTTP - "traefik.http.routers.${APP_NAMESPACE}_varnish.entrypoints=http" - - "traefik.http.routers.${APP_NAMESPACE}_varnish.rule=Host(${HOSTNAME_VARNISH})" + - "traefik.http.routers.${APP_NAMESPACE}_varnish.rule=HostRegexp(${HOSTNAME_VARNISH}) && PathRegexp(${PATH_PREFIX})" - "traefik.http.routers.${APP_NAMESPACE}_varnish.service=${APP_NAMESPACE}_varnish" # Listen HTTPS - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.entrypoints=https" - - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.rule=Host(${HOSTNAME_VARNISH})" + - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.rule=HostRegexp(${HOSTNAME_VARNISH}) && PathRegexp(${PATH_PREFIX})" - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.tls=true" - "traefik.http.routers.${APP_NAMESPACE}_varnish_secure.service=${APP_NAMESPACE}_varnish" @@ -188,7 +188,7 @@ services: - "traefik.http.services.${APP_NAMESPACE}_mailer.loadbalancer.passhostheader=true" # Listen HTTP - "traefik.http.routers.${APP_NAMESPACE}_mailer.entrypoints=http" - - "traefik.http.routers.${APP_NAMESPACE}_mailer.rule=Host(${HOSTNAME_MAILER})" + - "traefik.http.routers.${APP_NAMESPACE}_mailer.rule=HostRegexp(${HOSTNAME_MAILER})" - "traefik.http.routers.${APP_NAMESPACE}_mailer.service=${APP_NAMESPACE}_mailer" networks: From 39448bdc690aa6c46775c58e5da803fb06364d0b Mon Sep 17 00:00:00 2001 From: Ambroise Maupate Date: Thu, 19 Dec 2024 10:26:55 +0100 Subject: [PATCH 2/4] feat: Added new NodeTypeField.php `normalizationContext` to alter normalization groups per field basis (#29) We can optimize API responses by configuring serialization context per NodeType field. This will avoid heavy WebResponse resources. --- ...ponse object.bru => Get a WebResponse.bru} | 11 +++-- composer.json | 1 + config/api_resources/web_response.yml | 2 + config/services.yaml | 7 ++++ lib/DocGenerator/composer.json | 3 +- lib/Documents/composer.json | 1 + lib/DtsGenerator/composer.json | 3 +- lib/EntityGenerator/composer.json | 1 + .../src/Field/AbstractFieldGenerator.php | 25 +++++++++++ .../src/Field/CustomFormsFieldGenerator.php | 18 ++++++++ .../Mocks/GeneratedNodesSources/NSMock.php | 6 +++ .../NSMock.php | 6 +++ lib/Jwt/composer.json | 3 +- lib/Markdown/composer.json | 3 +- lib/Models/composer.json | 1 + lib/OpenId/composer.json | 3 +- lib/Random/composer.json | 3 +- lib/RoadizCompatBundle/composer.json | 1 + lib/RoadizCoreBundle/composer.json | 1 + .../migrations/Version20241218095458.php | 29 +++++++++++++ .../src/Entity/NodeTypeField.php | 37 +++++++++++++++++ lib/RoadizFontBundle/composer.json | 1 + lib/RoadizRozierBundle/composer.json | 1 + lib/RoadizTwoFactorBundle/composer.json | 1 + lib/RoadizUserBundle/composer.json | 1 + lib/Rozier/composer.json | 1 + .../AjaxControllers/AjaxSearchController.php | 4 +- .../Forms/NodeTypeFieldSerializationType.php | 41 +++++++++++++------ .../Resources/translations/messages.en.xlf | 17 ++++++++ .../Resources/translations/messages.fr.xlf | 17 ++++++++ .../src/Resources/translations/messages.xlf | 3 ++ .../views/node-type-fields/editBase.html.twig | 3 +- src/GeneratedEntity/NSMenuLink.php | 11 +++-- src/GeneratedEntity/NSPage.php | 25 ++++++----- src/Resources/node-types/MenuLink.json | 12 +++++- src/Resources/node-types/Page.json | 13 +++++- 36 files changed, 270 insertions(+), 46 deletions(-) rename bruno/Roadiz development app/WebResponse/{Get a Page by its path wrapped in a WebResponse object.bru => Get a WebResponse.bru} (75%) create mode 100644 lib/RoadizCoreBundle/migrations/Version20241218095458.php diff --git a/bruno/Roadiz development app/WebResponse/Get a Page by its path wrapped in a WebResponse object.bru b/bruno/Roadiz development app/WebResponse/Get a WebResponse.bru similarity index 75% rename from bruno/Roadiz development app/WebResponse/Get a Page by its path wrapped in a WebResponse object.bru rename to bruno/Roadiz development app/WebResponse/Get a WebResponse.bru index ea0b7def..b61fe186 100644 --- a/bruno/Roadiz development app/WebResponse/Get a Page by its path wrapped in a WebResponse object.bru +++ b/bruno/Roadiz development app/WebResponse/Get a WebResponse.bru @@ -1,5 +1,5 @@ meta { - name: Get a Page by its path wrapped in a WebResponse object + name: Get a WebResponse type: http seq: 1 } @@ -12,19 +12,18 @@ get { params:query { path: / - ~path: /articles/article-with-attributes + ~properties[item][]: nodeReferences + ~properties[item][]: title ~properties[]: item - ~properties[item]: title + ~path: /articles/article-with-attributes ~properties[]: blocks - ~properties[item]: url + ~properties[item][]: url ~path: /contact ~_preview: 1 ~path: /fr/articles/article-with-attributes - ~testsd: sd ~path: /fr/articles ~properties[item][]: nodeReferences ~path: /data:image/svg-xml - ~_locale: zh } auth:bearer { diff --git a/composer.json b/composer.json index cfe7c53a..df441787 100644 --- a/composer.json +++ b/composer.json @@ -143,6 +143,7 @@ "league/flysystem-aws-s3-v3": "^3.10", "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpstan/phpstan-doctrine": "^1.3", "phpstan/phpstan-symfony": "^1.1.8", "phpunit/phpunit": "^9.5", diff --git a/config/api_resources/web_response.yml b/config/api_resources/web_response.yml index a7d7a121..d0879cb2 100644 --- a/config/api_resources/web_response.yml +++ b/config/api_resources/web_response.yml @@ -1,5 +1,7 @@ resources: RZ\Roadiz\CoreBundle\Api\Model\WebResponse: + filters: + - app.property_filter graphQlOperations: { } operations: article_get_by_path: diff --git a/config/services.yaml b/config/services.yaml index df9af835..9a4a607c 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -32,3 +32,10 @@ services: app.serializer.normalizer.menu_link_path.json: class: 'App\Serializer\Normalizer\MenuLinkPathNormalizer' decorates: 'api_platform.serializer.normalizer.item' + + app.property_filter: + parent: 'api_platform.serializer.property_filter' + tags: [ 'api_platform.filter' ] + autowire: false + autoconfigure: false + public: false diff --git a/lib/DocGenerator/composer.json b/lib/DocGenerator/composer.json index 1785675b..55ac3952 100644 --- a/lib/DocGenerator/composer.json +++ b/lib/DocGenerator/composer.json @@ -23,7 +23,8 @@ } }, "require-dev": { - "phpstan/phpstan": "^1.5.3" + "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2" }, "extra": { "branch-alias": { diff --git a/lib/Documents/composer.json b/lib/Documents/composer.json index 98c44c85..02257dcb 100644 --- a/lib/Documents/composer.json +++ b/lib/Documents/composer.json @@ -46,6 +46,7 @@ "doctrine/doctrine-bundle": "^2.8.1", "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpstan/phpstan-doctrine": "^1.3", "phpunit/phpunit": "^9.5" }, diff --git a/lib/DtsGenerator/composer.json b/lib/DtsGenerator/composer.json index 9a48cacc..f2f226ad 100644 --- a/lib/DtsGenerator/composer.json +++ b/lib/DtsGenerator/composer.json @@ -7,7 +7,8 @@ "symfony/http-foundation": "6.4.*" }, "require-dev": { - "phpstan/phpstan": "^1.5.3" + "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2" }, "license": "MIT", "authors": [ diff --git a/lib/EntityGenerator/composer.json b/lib/EntityGenerator/composer.json index 3c3aba4d..304bdae3 100644 --- a/lib/EntityGenerator/composer.json +++ b/lib/EntityGenerator/composer.json @@ -36,6 +36,7 @@ }, "require-dev": { "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpunit/phpunit": "^9.5", "api-platform/core": "~3.3.11" }, diff --git a/lib/EntityGenerator/src/Field/AbstractFieldGenerator.php b/lib/EntityGenerator/src/Field/AbstractFieldGenerator.php index c27d46bc..04f42eeb 100644 --- a/lib/EntityGenerator/src/Field/AbstractFieldGenerator.php +++ b/lib/EntityGenerator/src/Field/AbstractFieldGenerator.php @@ -93,6 +93,21 @@ protected function getFieldDefaultValueDeclaration(): Literal|string|null return null; } + /** + * @return array|null + */ + protected function getNormalizationContext(): ?array + { + if (\method_exists($this->field, 'getNormalizationContext')) { + $normalizationContext = $this->field->getNormalizationContext(); + if (\is_array($normalizationContext) && !empty($normalizationContext['groups'])) { + return $normalizationContext; + } + } + + return null; + } + protected function addFieldAttributes(Property $property, PhpNamespace $namespace, bool $exclude = false): self { if ($exclude) { @@ -134,6 +149,16 @@ protected function addFieldAttributes(Property $property, PhpNamespace $namespac $this->getSerializationMaxDepth(), ]); } + + /* + * Enable different serialization context for this field. + */ + if (null !== $this->getNormalizationContext()) { + $property->addAttribute('Symfony\Component\Serializer\Attribute\Context', [ + 'normalizationContext' => $this->getNormalizationContext(), + 'groups' => $this->getSerializationGroups(), + ]); + } } if ( diff --git a/lib/EntityGenerator/src/Field/CustomFormsFieldGenerator.php b/lib/EntityGenerator/src/Field/CustomFormsFieldGenerator.php index 31e2977f..8e31f013 100644 --- a/lib/EntityGenerator/src/Field/CustomFormsFieldGenerator.php +++ b/lib/EntityGenerator/src/Field/CustomFormsFieldGenerator.php @@ -23,6 +23,24 @@ protected function addSerializationAttributes(Property|Method $property): self return $this; } + protected function addFieldAnnotation(Property $property): AbstractFieldGenerator + { + parent::addFieldAnnotation($property); + + $property->addComment(''); + $property->addComment('@var '.$this->options['custom_form_class'].'[]|null'); + + return $this; + } + + protected function getNormalizationContext(): array + { + return [ + 'groups' => ['nodes_sources', 'urls'], + ...(parent::getNormalizationContext() ?? []), + ]; + } + protected function getDefaultSerializationGroups(): array { $groups = parent::getDefaultSerializationGroups(); diff --git a/lib/EntityGenerator/tests/Mocks/GeneratedNodesSources/NSMock.php b/lib/EntityGenerator/tests/Mocks/GeneratedNodesSources/NSMock.php index f8517574..c66a0af5 100644 --- a/lib/EntityGenerator/tests/Mocks/GeneratedNodesSources/NSMock.php +++ b/lib/EntityGenerator/tests/Mocks/GeneratedNodesSources/NSMock.php @@ -309,12 +309,18 @@ class NSMock extends NodesSources /** * Custom forms field. * (Virtual field, this var is a buffer) + * + * @var \mock\Entity\CustomForm[]|null */ #[JMS\Exclude] #[Serializer\SerializedName(serializedName: 'theForms')] #[Serializer\Groups(['nodes_sources', 'nodes_sources_default', 'nodes_sources_custom_forms'])] #[ApiProperty(description: 'Custom forms field')] #[Serializer\MaxDepth(2)] + #[Serializer\Context( + normalizationContext: ['groups' => ['nodes_sources', 'urls']], + groups: ['nodes_sources', 'nodes_sources_default', 'nodes_sources_custom_forms'], + )] private ?array $theForms = null; /** diff --git a/lib/EntityGenerator/tests/Mocks/GeneratedNodesSourcesWithRepository/NSMock.php b/lib/EntityGenerator/tests/Mocks/GeneratedNodesSourcesWithRepository/NSMock.php index 94dbfba4..ba7e1311 100644 --- a/lib/EntityGenerator/tests/Mocks/GeneratedNodesSourcesWithRepository/NSMock.php +++ b/lib/EntityGenerator/tests/Mocks/GeneratedNodesSourcesWithRepository/NSMock.php @@ -309,12 +309,18 @@ class NSMock extends NodesSources /** * Custom forms field. * (Virtual field, this var is a buffer) + * + * @var \mock\Entity\CustomForm[]|null */ #[JMS\Exclude] #[Serializer\SerializedName(serializedName: 'theForms')] #[Serializer\Groups(['nodes_sources', 'nodes_sources_default', 'nodes_sources_custom_forms'])] #[ApiProperty(description: 'Custom forms field')] #[Serializer\MaxDepth(2)] + #[Serializer\Context( + normalizationContext: ['groups' => ['nodes_sources', 'urls']], + groups: ['nodes_sources', 'nodes_sources_default', 'nodes_sources_custom_forms'], + )] private ?array $theForms = null; /** diff --git a/lib/Jwt/composer.json b/lib/Jwt/composer.json index e07b7747..e962b96e 100644 --- a/lib/Jwt/composer.json +++ b/lib/Jwt/composer.json @@ -17,7 +17,8 @@ "symfony/http-client": "6.4.*" }, "require-dev": { - "phpstan/phpstan": "^1.5.3" + "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2" }, "autoload": { "psr-4": { diff --git a/lib/Markdown/composer.json b/lib/Markdown/composer.json index 3ee2ef78..67136924 100644 --- a/lib/Markdown/composer.json +++ b/lib/Markdown/composer.json @@ -10,7 +10,8 @@ "twig/twig": "^3.16" }, "require-dev": { - "phpstan/phpstan": "^1.5.3" + "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2" }, "license": "MIT", "authors": [ diff --git a/lib/Models/composer.json b/lib/Models/composer.json index d894f5df..4f2abf9f 100644 --- a/lib/Models/composer.json +++ b/lib/Models/composer.json @@ -32,6 +32,7 @@ "doctrine/doctrine-bundle": "^2.8.1", "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpunit/phpunit": "^9.5" }, "autoload": { diff --git a/lib/OpenId/composer.json b/lib/OpenId/composer.json index 5f359f02..2cb824f5 100644 --- a/lib/OpenId/composer.json +++ b/lib/OpenId/composer.json @@ -30,7 +30,8 @@ "symfony/security-http": "6.4.*" }, "require-dev": { - "phpstan/phpstan": "^1.5.3" + "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2" }, "autoload": { "psr-4": { diff --git a/lib/Random/composer.json b/lib/Random/composer.json index 5778d104..3b9d1eb5 100644 --- a/lib/Random/composer.json +++ b/lib/Random/composer.json @@ -17,7 +17,8 @@ "ext-openssl": "*" }, "require-dev": { - "phpstan/phpstan": "^1.5.3" + "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2" }, "autoload": { "psr-4": { diff --git a/lib/RoadizCompatBundle/composer.json b/lib/RoadizCompatBundle/composer.json index 26862ef9..2c5f6a93 100644 --- a/lib/RoadizCompatBundle/composer.json +++ b/lib/RoadizCompatBundle/composer.json @@ -26,6 +26,7 @@ "require-dev": { "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpstan/phpstan-doctrine": "^1.3", "phpstan/phpstan-symfony": "^1.1.8", "roadiz/doc-generator": "2.4.*", diff --git a/lib/RoadizCoreBundle/composer.json b/lib/RoadizCoreBundle/composer.json index 9df8748e..a36ebf36 100644 --- a/lib/RoadizCoreBundle/composer.json +++ b/lib/RoadizCoreBundle/composer.json @@ -100,6 +100,7 @@ "require-dev": { "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpstan/phpstan-doctrine": "^1.3", "phpunit/phpunit": "^9.5", "symfony/browser-kit": "6.4.*", diff --git a/lib/RoadizCoreBundle/migrations/Version20241218095458.php b/lib/RoadizCoreBundle/migrations/Version20241218095458.php new file mode 100644 index 00000000..df19d4f8 --- /dev/null +++ b/lib/RoadizCoreBundle/migrations/Version20241218095458.php @@ -0,0 +1,29 @@ +addSql('ALTER TABLE node_type_fields ADD normalization_context JSON DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE node_type_fields DROP normalization_context'); + } +} diff --git a/lib/RoadizCoreBundle/src/Entity/NodeTypeField.php b/lib/RoadizCoreBundle/src/Entity/NodeTypeField.php index ec3b331f..397e9bbb 100644 --- a/lib/RoadizCoreBundle/src/Entity/NodeTypeField.php +++ b/lib/RoadizCoreBundle/src/Entity/NodeTypeField.php @@ -98,6 +98,14 @@ class NodeTypeField extends AbstractField implements NodeTypeFieldInterface, Ser ] private ?array $serializationGroups = null; + #[ + Serializer\Groups(['node_type']), + SymfonySerializer\Groups(['node_type']), + Serializer\Type('array'), + ORM\Column(name: 'normalization_context', type: 'json', nullable: true) + ] + private ?array $normalizationContext = null; + #[ Serializer\Groups(['node_type']), SymfonySerializer\Groups(['node_type']), @@ -330,4 +338,33 @@ public function setExcludedFromSerialization(bool $excludedFromSerialization): N return $this; } + + public function getNormalizationContext(): ?array + { + return $this->normalizationContext; + } + + public function setNormalizationContext(?array $normalizationContext): NodeTypeField + { + $this->normalizationContext = $normalizationContext; + + return $this; + } + + #[SymfonySerializer\Ignore] + public function getNormalizationContextGroups(): ?array + { + return $this->normalizationContext['groups'] ?? []; + } + + #[SymfonySerializer\Ignore] + public function setNormalizationContextGroups(?array $normalizationContextGroups): NodeTypeField + { + if (null === $normalizationContextGroups) { + $this->normalizationContext = null; + } + $this->normalizationContext['groups'] = $normalizationContextGroups; + + return $this; + } } diff --git a/lib/RoadizFontBundle/composer.json b/lib/RoadizFontBundle/composer.json index f151878d..519857e6 100644 --- a/lib/RoadizFontBundle/composer.json +++ b/lib/RoadizFontBundle/composer.json @@ -51,6 +51,7 @@ "require-dev": { "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpstan/phpstan-doctrine": "^1.3", "phpunit/phpunit": "^9.5", "roadiz/compat-bundle": "2.4.*", diff --git a/lib/RoadizRozierBundle/composer.json b/lib/RoadizRozierBundle/composer.json index 2072e328..71dea22f 100644 --- a/lib/RoadizRozierBundle/composer.json +++ b/lib/RoadizRozierBundle/composer.json @@ -29,6 +29,7 @@ "require-dev": { "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpstan/phpstan-doctrine": "^1.3", "phpstan/phpstan-symfony": "^1.1.8" }, diff --git a/lib/RoadizTwoFactorBundle/composer.json b/lib/RoadizTwoFactorBundle/composer.json index e81464da..f39da26e 100644 --- a/lib/RoadizTwoFactorBundle/composer.json +++ b/lib/RoadizTwoFactorBundle/composer.json @@ -36,6 +36,7 @@ "require-dev": { "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpstan/phpstan-doctrine": "^1.3", "phpunit/phpunit": "^9.5", "roadiz/doc-generator": "2.4.*", diff --git a/lib/RoadizUserBundle/composer.json b/lib/RoadizUserBundle/composer.json index 5b9a3adc..1a792d70 100644 --- a/lib/RoadizUserBundle/composer.json +++ b/lib/RoadizUserBundle/composer.json @@ -31,6 +31,7 @@ "require-dev": { "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpstan/phpstan-doctrine": "^1.3", "roadiz/doc-generator": "2.4.*", "roadiz/entity-generator": "2.4.*", diff --git a/lib/Rozier/composer.json b/lib/Rozier/composer.json index 2cd451f3..f4397740 100644 --- a/lib/Rozier/composer.json +++ b/lib/Rozier/composer.json @@ -66,6 +66,7 @@ "require-dev": { "php-coveralls/php-coveralls": "^2.4", "phpstan/phpstan": "^1.5.3", + "phpstan/phpdoc-parser": "<2", "phpstan/phpstan-doctrine": "^1.3", "roadiz/entity-generator": "2.4.*", "roadiz/jwt": "2.4.*", diff --git a/lib/Rozier/src/AjaxControllers/AjaxSearchController.php b/lib/Rozier/src/AjaxControllers/AjaxSearchController.php index 69695faa..40bbd25c 100644 --- a/lib/Rozier/src/AjaxControllers/AjaxSearchController.php +++ b/lib/Rozier/src/AjaxControllers/AjaxSearchController.php @@ -65,12 +65,12 @@ public function searchAction(Request $request): Response foreach ($nodesSources as $source) { $uniqueKey = null; if ($source instanceof NodesSources) { - $uniqueKey = 'n_' . $source->getNode()->getId(); + $uniqueKey = 'n_'.$source->getNode()->getId(); if (!$this->security->isGranted(NodeVoter::READ, $source)) { continue; } } elseif ($source instanceof PersistableInterface) { - $uniqueKey = 'p_' . $source->getId(); + $uniqueKey = 'p_'.$source->getId(); } if (key_exists($uniqueKey, $data)) { continue; diff --git a/lib/Rozier/src/Forms/NodeTypeFieldSerializationType.php b/lib/Rozier/src/Forms/NodeTypeFieldSerializationType.php index c151f0c3..91d56689 100644 --- a/lib/Rozier/src/Forms/NodeTypeFieldSerializationType.php +++ b/lib/Rozier/src/Forms/NodeTypeFieldSerializationType.php @@ -24,6 +24,34 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'help' => 'exclude_this_field_from_api_serialization', 'required' => false, ]) + ->add('serializationGroups', CollectionType::class, [ + 'label' => 'nodeTypeField.serializationGroups', + 'help' => 'nodeTypeField.serializationGroups.help', + 'required' => false, + 'allow_add' => true, + 'allow_delete' => true, + 'attr' => [ + 'class' => 'rz-collection-form-type', + ], + 'entry_options' => [ + 'label' => false, + ], + 'entry_type' => TextType::class, + ]) + ->add('normalizationContextGroups', CollectionType::class, [ + 'label' => 'nodeTypeField.normalizationContextGroups', + 'help' => 'nodeTypeField.normalizationContextGroups.help', + 'required' => false, + 'allow_add' => true, + 'allow_delete' => true, + 'attr' => [ + 'class' => 'rz-collection-form-type', + ], + 'entry_options' => [ + 'label' => false, + ], + 'entry_type' => TextType::class, + ]) ->add('serializationMaxDepth', IntegerType::class, [ 'label' => 'nodeTypeField.serializationMaxDepth', 'required' => false, @@ -43,19 +71,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'attr' => [ 'placeholder' => 'enter_symfony_expression_language_with_object_as_var_name', ], - ]) - ->add('serializationGroups', CollectionType::class, [ - 'label' => 'nodeTypeField.serializationGroups', - 'required' => false, - 'allow_add' => true, - 'allow_delete' => true, - 'attr' => [ - 'class' => 'rz-collection-form-type', - ], - 'entry_options' => [ - 'label' => false, - ], - 'entry_type' => TextType::class, ]); } diff --git a/lib/Rozier/src/Resources/translations/messages.en.xlf b/lib/Rozier/src/Resources/translations/messages.en.xlf index b760da51..063c1fe5 100644 --- a/lib/Rozier/src/Resources/translations/messages.en.xlf +++ b/lib/Rozier/src/Resources/translations/messages.en.xlf @@ -402,6 +402,23 @@ nodeTypeField.defaultValues Advanced field configuration + + nodeTypeField.normalizationContextGroups + Custom serialization context (groups) + + + nodeTypeField.normalizationContextGroups.help + Changes the serialization context for the contents of this field. + + + nodeTypeField.serializationGroups.help + + Select the [serialization groups](https://docs.roadiz.io/en/latest/developer/api/serialization.html#serialization-groups) for which this field will be serialized. + By default, this field will be serialized for the *nodes_sources* and *nodes_sources_default* groups. + If the field is part of a Field Group, it will use the *nodes_sources_{group name}* group instead of *nodes_sources_default*. + which will hide the field from an API collection operation. + + enter_values_comma_separated Enter each values separated with commas. diff --git a/lib/Rozier/src/Resources/translations/messages.fr.xlf b/lib/Rozier/src/Resources/translations/messages.fr.xlf index c2580a96..4573c23b 100644 --- a/lib/Rozier/src/Resources/translations/messages.fr.xlf +++ b/lib/Rozier/src/Resources/translations/messages.fr.xlf @@ -402,6 +402,23 @@ nodeTypeField.defaultValues Configuration avancée + + nodeTypeField.normalizationContextGroups + Contexte personalisé de sérialisation (groupes) + + + nodeTypeField.normalizationContextGroups.help + Permet de modifier le contexte de sérialisation pour le contenu de ce champ. + + + nodeTypeField.serializationGroups.help + + Permet de choisir des [groupes de sérialisation](https://docs.roadiz.io/en/latest/developer/api/serialization.html#serialization-groups) pour lesquels ce champ sera sérialisé. + Par défaut, ce champ sera sérialisé pour les groupes *nodes_sources* et *nodes_sources_default*. + Si le champ fait partie d'un Groupe de champ, il utilisera le groupe *nodes_sources_{nom du groupe}* à la place de *nodes_sources_default* + ce qui cachera le champ depuis une opération API de type Collection. + + enter_values_comma_separated Entrez les valeurs séparées par des virgules… diff --git a/lib/Rozier/src/Resources/translations/messages.xlf b/lib/Rozier/src/Resources/translations/messages.xlf index 6d3fae26..f6b4d2cd 100644 --- a/lib/Rozier/src/Resources/translations/messages.xlf +++ b/lib/Rozier/src/Resources/translations/messages.xlf @@ -102,6 +102,9 @@ defaultValues customFormField.defaultValues nodeTypeField.defaultValues + nodeTypeField.normalizationContextGroups + nodeTypeField.normalizationContextGroups.help + nodeTypeField.serializationGroups.help enter_values_comma_separated node.%name%.translated node_source.%node_source%.updated.%translation% diff --git a/lib/Rozier/src/Resources/views/node-type-fields/editBase.html.twig b/lib/Rozier/src/Resources/views/node-type-fields/editBase.html.twig index 23ab3380..f5b05242 100644 --- a/lib/Rozier/src/Resources/views/node-type-fields/editBase.html.twig +++ b/lib/Rozier/src/Resources/views/node-type-fields/editBase.html.twig @@ -5,7 +5,8 @@ {% block content %}
-

{{ "edit.nodeTypeField.%name%"|trans({'%name%': field.getName})|u.truncate(25, '[…]', true) }}

+

{{ nodeType.name }}

+

{{ "edit.nodeTypeField.%name%"|trans({'%name%': field.getName})|u.truncate(25, '[…]', true) }}

diff --git a/src/GeneratedEntity/NSMenuLink.php b/src/GeneratedEntity/NSMenuLink.php index 83809bbf..8b54cf70 100644 --- a/src/GeneratedEntity/NSMenuLink.php +++ b/src/GeneratedEntity/NSMenuLink.php @@ -48,14 +48,13 @@ class NSMenuLink extends NodesSources * linkInternalReferenceSources NodesSources direct field buffer. * @var \RZ\Roadiz\CoreBundle\Entity\NodesSources[]|null * Référence au nœud (Page ou Bloc de page). - * Default values: - * Page, Article, ArticleContainer, Offer */ #[JMS\Exclude] #[Serializer\SerializedName(serializedName: 'linkInternalReference')] - #[Serializer\Groups(['nodes_sources', 'nodes_sources_default', 'nodes_sources_nodes'])] + #[Serializer\Groups(['urls'])] #[ApiProperty(description: 'Référence au nœud (Page ou Bloc de page)')] - #[Serializer\MaxDepth(2)] + #[Serializer\MaxDepth(1)] + #[Serializer\Context(normalizationContext: ['groups' => ['urls', 'nodes_sources_base']], groups: ['urls'])] private ?array $linkInternalReferenceSources = null; /** @@ -91,8 +90,8 @@ public function setLinkExternalUrl(?string $linkExternalUrl): static /** * @return \RZ\Roadiz\CoreBundle\Entity\NodesSources[] */ - #[JMS\Groups(['nodes_sources', 'nodes_sources_default', 'nodes_sources_nodes'])] - #[JMS\MaxDepth(2)] + #[JMS\Groups(['urls'])] + #[JMS\MaxDepth(1)] #[JMS\VirtualProperty] #[JMS\SerializedName('linkInternalReference')] #[JMS\Type('array')] diff --git a/src/GeneratedEntity/NSPage.php b/src/GeneratedEntity/NSPage.php index 7a515b1e..5ec50d1c 100644 --- a/src/GeneratedEntity/NSPage.php +++ b/src/GeneratedEntity/NSPage.php @@ -125,16 +125,15 @@ class NSPage extends NodesSources /** * nodeReferencesSources NodesSources direct field buffer. - * @var \App\GeneratedEntity\NSPage[]|null + * @var \RZ\Roadiz\CoreBundle\Entity\NodesSources[]|null * References. - * Default values: - * Page */ #[JMS\Exclude] #[Serializer\SerializedName(serializedName: 'nodeReferences')] - #[Serializer\Groups(['nodes_sources', 'nodes_sources_default', 'nodes_sources_nodes'])] + #[Serializer\Groups(['page_get_by_path'])] #[ApiProperty(description: 'References')] - #[Serializer\MaxDepth(2)] + #[Serializer\MaxDepth(1)] + #[Serializer\Context(normalizationContext: ['groups' => ['page_get_by_path', 'urls', 'nodes_sources_base']], groups: ['page_get_by_path'])] private ?array $nodeReferencesSources = null; /** @@ -174,12 +173,18 @@ class NSPage extends NodesSources /** * Custom form. * (Virtual field, this var is a buffer) + * + * @var \RZ\Roadiz\CoreBundle\Entity\CustomForm[]|null */ #[JMS\Exclude] #[Serializer\SerializedName(serializedName: 'customForm')] #[Serializer\Groups(['nodes_sources', 'nodes_sources_default', 'nodes_sources_custom_forms'])] #[ApiProperty(description: 'Custom form')] #[Serializer\MaxDepth(2)] + #[Serializer\Context( + normalizationContext: ['groups' => ['nodes_sources', 'urls']], + groups: ['nodes_sources', 'nodes_sources_default', 'nodes_sources_custom_forms'], + )] private ?array $customForm = null; /** @@ -597,10 +602,10 @@ public function addPictures(\RZ\Roadiz\CoreBundle\Entity\Document $document): st } /** - * @return \App\GeneratedEntity\NSPage[] + * @return \RZ\Roadiz\CoreBundle\Entity\NodesSources[] */ - #[JMS\Groups(['nodes_sources', 'nodes_sources_default', 'nodes_sources_nodes'])] - #[JMS\MaxDepth(2)] + #[JMS\Groups(['page_get_by_path'])] + #[JMS\MaxDepth(1)] #[JMS\VirtualProperty] #[JMS\SerializedName('nodeReferences')] #[JMS\Type('array')] @@ -609,7 +614,7 @@ public function getNodeReferencesSources(): array if (null === $this->nodeReferencesSources) { if (null !== $this->objectManager) { $this->nodeReferencesSources = $this->objectManager - ->getRepository(\App\GeneratedEntity\NSPage::class) + ->getRepository(\RZ\Roadiz\CoreBundle\Entity\NodesSources::class) ->findByNodesSourcesAndFieldNameAndTranslation( $this, 'node_references' @@ -622,7 +627,7 @@ public function getNodeReferencesSources(): array } /** - * @param \App\GeneratedEntity\NSPage[]|null $nodeReferencesSources + * @param \RZ\Roadiz\CoreBundle\Entity\NodesSources[]|null $nodeReferencesSources * @return $this */ public function setNodeReferencesSources(?array $nodeReferencesSources): static diff --git a/src/Resources/node-types/MenuLink.json b/src/Resources/node-types/MenuLink.json index ef8e0f67..a8dd6568 100644 --- a/src/Resources/node-types/MenuLink.json +++ b/src/Resources/node-types/MenuLink.json @@ -5,6 +5,7 @@ "visible": false, "publishable": false, "attributable": true, + "sorting_attributes_by_weight": false, "reachable": false, "hiding_nodes": false, "hiding_non_reachable_nodes": false, @@ -25,11 +26,20 @@ "position": 2.0, "name": "link_internal_reference", "label": "R\u00e9f\u00e9rence au n\u0153ud (Page ou Bloc de page)", - "default_values": "Page, Article, ArticleContainer, Offer", "type": 13, "expanded": false, "universal": true, "exclude_from_search": false, + "serialization_groups": [ + "urls" + ], + "normalization_context": { + "groups": [ + "urls", + "nodes_sources_base" + ] + }, + "serialization_max_depth": 1, "excluded_from_serialization": false, "indexed": false, "visible": true diff --git a/src/Resources/node-types/Page.json b/src/Resources/node-types/Page.json index 6789da6a..8a0cd200 100644 --- a/src/Resources/node-types/Page.json +++ b/src/Resources/node-types/Page.json @@ -6,6 +6,7 @@ "visible": true, "publishable": true, "attributable": true, + "sorting_attributes_by_weight": false, "reachable": true, "hiding_nodes": false, "hiding_non_reachable_nodes": true, @@ -120,11 +121,21 @@ "position": 9.0, "name": "node_references", "label": "References", - "default_values": "Page", "type": 13, "expanded": false, "universal": false, "exclude_from_search": false, + "serialization_groups": [ + "page_get_by_path" + ], + "normalization_context": { + "groups": [ + "page_get_by_path", + "urls", + "nodes_sources_base" + ] + }, + "serialization_max_depth": 1, "excluded_from_serialization": false, "indexed": false, "visible": true From b661641a33a51dc9a1e56f29e7e39328356dcfce Mon Sep 17 00:00:00 2001 From: Ambroise Maupate Date: Thu, 19 Dec 2024 12:38:15 +0100 Subject: [PATCH 3/4] fix: Keep only fully translated languages --- lib/Rozier/src/RozierApp.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/Rozier/src/RozierApp.php b/lib/Rozier/src/RozierApp.php index 32a9f3f4..6faaca7c 100644 --- a/lib/Rozier/src/RozierApp.php +++ b/lib/Rozier/src/RozierApp.php @@ -35,16 +35,8 @@ class RozierApp extends AppController public const DEFAULT_ITEM_PER_PAGE = 50; public static array $backendLanguages = [ - 'Arabic' => 'ar', 'English' => 'en', - 'Español' => 'es', 'Français' => 'fr', - 'Indonesian' => 'id', - 'Italiano' => 'it', - 'Türkçe' => 'tr', - 'Русский язык' => 'ru', - 'српска ћирилица' => 'sr', - '中文' => 'zh', ]; public static function getSubscribedServices(): array From 1195db9bbc70c7fb4beb96206313b3c8e90f823e Mon Sep 17 00:00:00 2001 From: Ambroise Maupate Date: Thu, 19 Dec 2024 12:50:36 +0100 Subject: [PATCH 4/4] chore: Bumped --- CHANGELOG.md | 10 ++++++++++ lib/RoadizCoreBundle/config/services.yaml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee92fae4..dd76e976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to Roadiz will be documented in this file. +## [2.4.3](https://github.com/roadiz/core-bundle-dev-app/compare/v2.4.2...v2.4.3) - 2024-12-19 + +### Bug Fixes + +- Keep only fully translated languages - ([b661641](https://github.com/roadiz/core-bundle-dev-app/commit/b661641a33a51dc9a1e56f29e7e39328356dcfce)) + +### Features + +- Added new NodeTypeField.php `normalizationContext` to alter normalization groups per field basis ([#29](https://github.com/roadiz/core-bundle-dev-app/issues/29)) - ([39448bd](https://github.com/roadiz/core-bundle-dev-app/commit/39448bdc690aa6c46775c58e5da803fb06364d0b)) + ## [2.4.2](https://github.com/roadiz/core-bundle-dev-app/compare/v2.4.1...v2.4.2) - 2024-12-11 ### Bug Fixes diff --git a/lib/RoadizCoreBundle/config/services.yaml b/lib/RoadizCoreBundle/config/services.yaml index caf50de2..99f25d14 100644 --- a/lib/RoadizCoreBundle/config/services.yaml +++ b/lib/RoadizCoreBundle/config/services.yaml @@ -1,6 +1,6 @@ --- parameters: - roadiz_core.cms_version: '2.4.2' + roadiz_core.cms_version: '2.4.3' roadiz_core.cms_version_prefix: 'main' env(APP_NAMESPACE): "roadiz" env(APP_VERSION): "0.1.0"