myparcelnl / prestashop

PrestaShop module to integrate with MyParcel NL and BE
https://developer.myparcel.nl/nl/documentatie/11.prestashop.html
10 stars 5 forks source link

[BETA]: (beta-2) Configuration page empty after upgrade/Can't save the API key #242

Closed mariuszsienkiewicz closed 4 months ago

mariuszsienkiewicz commented 4 months ago

Version check

PrestaShop version

8.1.5

PHP version

8.1

What went wrong?

We are currently migrating one of my clients from PrestaShop 1.7 to PrestaShop 8.1.5. Unfortunately, beta-2 isn't working; we are using PHP 8.1.

We tried to upgrade the module via standard way of uploading the zip file in the backoffice but in the result we got an empty module configuration page - no errors in the devtools, it said that admin was rendered sucessfully. In the error.log file I have seen this error:

The class 'MyParcelNL\PrestaShop\Entity\MyparcelnlCartDeliveryOptions' was not found in the chain configured namespaces PrestaShopBundle\Entity, PrestaShop\Module\ProductComment\Entity, PrestaShop\Module\PsAccounts\Entity, MyParcelNL\PrestaShop\Entity\Concern

Whole log can be found below (log ID: 1).

Out of curiosity I've cleaned everything related to the previous version of the plugin (emptied all tables and all configuration related to myparcel module), now configuration page shows at lesat the API key form but it doesn't work because of the similar issue as described above, now it can't find the MyParcelNL\PrestaShop\Entity\MyparcelnlCarrierMapping and this error is now reported even via devtools (log ID: 2).

It seems there's an issue with class autoloading and the compiled container in the module and PDK.

Reproduction steps

Described above.

Relevant log output

Log 1:

*ERROR*     v8.1.5  2024/04/18 - 09:32:47: [PDK]: The class 'MyParcelNL\PrestaShop\Entity\MyparcelnlCartDeliveryOptions' was not found in the chain configured namespaces PrestaShopBundle\Entity, PrestaShop\Module\ProductComment\Entity, PrestaShop\Module\PsAccounts\Entity, MyParcelNL\PrestaShop\Entity\Concern
{
    "trace": [
        {
            "file": "\/psroot\/vendor\/doctrine\/persistence\/src\/Persistence\/Mapping\/Driver\/MappingDriverChain.php",
            "line": 89,
            "function": "classNotFoundInNamespaces",
            "class": "Doctrine\\Persistence\\Mapping\\MappingException",
            "type": "::"
        },
        {
            "file": "\/psroot\/vendor\/doctrine\/orm\/lib\/Doctrine\/ORM\/Mapping\/ClassMetadataFactory.php",
            "line": 133,
            "function": "loadMetadataForClass",
            "class": "Doctrine\\Persistence\\Mapping\\Driver\\MappingDriverChain",
            "type": "->"
        },
        {
            "file": "\/psroot\/vendor\/doctrine\/persistence\/src\/Persistence\/Mapping\/AbstractClassMetadataFactory.php",
            "line": 343,
            "function": "doLoadMetadata",
            "class": "Doctrine\\ORM\\Mapping\\ClassMetadataFactory",
            "type": "->"
        },
        {
            "file": "\/psroot\/vendor\/doctrine\/persistence\/src\/Persistence\/Mapping\/AbstractClassMetadataFactory.php",
            "line": 207,
            "function": "loadMetadata",
            "class": "Doctrine\\Persistence\\Mapping\\AbstractClassMetadataFactory",
            "type": "->"
        },
        {
            "file": "\/psroot\/vendor\/doctrine\/orm\/lib\/Doctrine\/ORM\/EntityManager.php",
            "line": 313,
            "function": "getMetadataFor",
            "class": "Doctrine\\Persistence\\Mapping\\AbstractClassMetadataFactory",
            "type": "->"
        },
        {
            "file": "\/psroot\/vendor\/doctrine\/doctrine-bundle\/Repository\/ContainerRepositoryFactory.php",
            "line": 40,
            "function": "getClassMetadata",
            "class": "Doctrine\\ORM\\EntityManager",
            "type": "->"
        },
        {
            "file": "\/psroot\/vendor\/doctrine\/orm\/lib\/Doctrine\/ORM\/EntityManager.php",
            "line": 816,
            "function": "getRepository",
            "class": "Doctrine\\Bundle\\DoctrineBundle\\Repository\\ContainerRepositoryFactory",
            "type": "->"
        },
        {
            "file": "\/psroot\/var\/cache\/prod\/Container7ItU0TU\/EntityManager_9a5be93.php",
            "line": 153,
            "function": "getRepository",
            "class": "Doctrine\\ORM\\EntityManager",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/src\/Repository\/AbstractPsObjectRepository.php",
            "line": 35,
            "function": "getRepository",
            "class": "EntityManager_9a5be93",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ObjectCreator.php",
            "line": 112,
            "function": "__construct",
            "class": "MyParcelNL\\PrestaShop\\Repository\\AbstractPsObjectRepository",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ObjectCreator.php",
            "line": 62,
            "function": "createInstance",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ObjectCreator",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ResolverDispatcher.php",
            "line": 63,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ObjectCreator",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 321,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ResolverDispatcher",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 116,
            "function": "resolveDefinition",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Reference.php",
            "line": 45,
            "function": "get",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ResolverDispatcher.php",
            "line": 60,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Reference",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ParameterResolver.php",
            "line": 62,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ResolverDispatcher",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ObjectCreator.php",
            "line": 111,
            "function": "resolveParameters",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ParameterResolver",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ObjectCreator.php",
            "line": 62,
            "function": "createInstance",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ObjectCreator",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ResolverDispatcher.php",
            "line": 63,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ObjectCreator",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 321,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ResolverDispatcher",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 116,
            "function": "resolveDefinition",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Reference.php",
            "line": 45,
            "function": "get",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ResolverDispatcher.php",
            "line": 60,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Reference",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 321,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ResolverDispatcher",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 116,
            "function": "resolveDefinition",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Reference.php",
            "line": 45,
            "function": "get",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ResolverDispatcher.php",
            "line": 60,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Reference",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ParameterResolver.php",
            "line": 62,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ResolverDispatcher",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ObjectCreator.php",
            "line": 111,
            "function": "resolveParameters",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ParameterResolver",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ObjectCreator.php",
            "line": 62,
            "function": "createInstance",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ObjectCreator",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ResolverDispatcher.php",
            "line": 63,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ObjectCreator",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 321,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ResolverDispatcher",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 116,
            "function": "resolveDefinition",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Reference.php",
            "line": 45,
            "function": "get",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ResolverDispatcher.php",
            "line": 60,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Reference",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 321,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ResolverDispatcher",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 116,
            "function": "resolveDefinition",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Reference.php",
            "line": 45,
            "function": "get",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ResolverDispatcher.php",
            "line": 60,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Reference",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ParameterResolver.php",
            "line": 62,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ResolverDispatcher",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ObjectCreator.php",
            "line": 111,
            "function": "resolveParameters",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ParameterResolver",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ObjectCreator.php",
            "line": 62,
            "function": "createInstance",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ObjectCreator",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Definition\/Resolver\/ResolverDispatcher.php",
            "line": 63,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ObjectCreator",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 321,
            "function": "resolve",
            "class": "_MyParcelNL\\DI\\Definition\\Resolver\\ResolverDispatcher",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/php-di\/php-di\/src\/Container.php",
            "line": 116,
            "function": "resolveDefinition",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Base\/Pdk.php",
            "line": 61,
            "function": "get",
            "class": "_MyParcelNL\\DI\\Container",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Base\/Facade.php",
            "line": 26,
            "function": "get",
            "class": "MyParcelNL\\Pdk\\Base\\Pdk",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Context\/Model\/PluginSettingsViewContext.php",
            "line": 40,
            "function": "__callStatic",
            "class": "MyParcelNL\\Pdk\\Base\\Facade",
            "type": "::"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Context\/Service\/ContextService.php",
            "line": 77,
            "function": "__construct",
            "class": "MyParcelNL\\Pdk\\Context\\Model\\PluginSettingsViewContext",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Context\/Service\/ContextService.php",
            "line": 131,
            "function": "createPluginSettingsViewContext",
            "class": "MyParcelNL\\Pdk\\Context\\Service\\ContextService",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Context\/Service\/ContextService.php",
            "line": 44,
            "function": "resolveContext",
            "class": "MyParcelNL\\Pdk\\Context\\Service\\ContextService",
            "type": "->"
        },
        {
            "function": "MyParcelNL\\Pdk\\Context\\Service\\{closure}",
            "class": "MyParcelNL\\Pdk\\Context\\Service\\ContextService",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Context\/Service\/ContextService.php",
            "line": 46,
            "function": "array_reduce"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Frontend\/Service\/FrontendRenderService.php",
            "line": 214,
            "function": "createContexts",
            "class": "MyParcelNL\\Pdk\\Context\\Service\\ContextService",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Frontend\/Service\/FrontendRenderService.php",
            "line": 201,
            "function": "renderTemplate",
            "class": "MyParcelNL\\Pdk\\Frontend\\Service\\FrontendRenderService",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Frontend\/Service\/FrontendRenderService.php",
            "line": 148,
            "function": "renderComponent",
            "class": "MyParcelNL\\Pdk\\Frontend\\Service\\FrontendRenderService",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/vendor\/myparcelnl\/pdk\/src\/Base\/Facade.php",
            "line": 26,
            "function": "renderPluginSettings",
            "class": "MyParcelNL\\Pdk\\Frontend\\Service\\FrontendRenderService",
            "type": "->"
        },
        {
            "file": "\/psroot\/modules\/myparcelnl\/src\/Controller\/SettingsController.php",
            "line": 18,
            "function": "__callStatic",
            "class": "MyParcelNL\\Pdk\\Base\\Facade",
            "type": "::"
        },
        {
            "file": "\/psroot\/vendor\/symfony\/symfony\/src\/Symfony\/Component\/HttpKernel\/HttpKernel.php",
            "line": 169,
            "function": "index",
            "class": "MyParcelNL\\PrestaShop\\Controller\\SettingsController",
            "type": "->"
        },
        {
            "file": "\/psroot\/vendor\/symfony\/symfony\/src\/Symfony\/Component\/HttpKernel\/HttpKernel.php",
            "line": 81,
            "function": "handleRaw",
            "class": "Symfony\\Component\\HttpKernel\\HttpKernel",
            "type": "->"
        },
        {
            "file": "\/psroot\/vendor\/symfony\/symfony\/src\/Symfony\/Component\/HttpKernel\/Kernel.php",
            "line": 201,
            "function": "handle",
            "class": "Symfony\\Component\\HttpKernel\\HttpKernel",
            "type": "->"
        },
        {
            "file": "\/psroot\/admin-dev\/index.php",
            "line": 84,
            "function": "handle",
            "class": "Symfony\\Component\\HttpKernel\\Kernel",
            "type": "->"
        }
    ],
    "template": "<div\n  data-pdk-context=\"__CONTEXT__\"\n  id=\"__ID__\"><\/div>\n<script id=\"__ID__-script\">\n(() => {\n  var e = '__EVENT_PONG__';\n  var listener = function(event) {\n    event.detail.render('__COMPONENT__', '#__ID__');\n    document.getElementById('__ID__-script').remove();\n    document.removeEventListener(e, listener);\n  };\n\n  document.addEventListener(e, listener);\n  document.dispatchEvent(new Event('__EVENT_PING__'));\n})();\n<\/script>\n",
    "contexts": [
        "pluginSettingsView"
    ],
    "templateParameters": {
        "__ID__": "pdk-plugin-settings-837138776",
        "__COMPONENT__": "PluginSettings",
        "__EVENT_PING__": "myparcel_pdk_ping",
        "__EVENT_PONG__": "myparcel_pdk_pong"
    },
    "contextArguments": []
}

Log 2:

accountUpdateERROR handler ApiException: The class 'MyParcelNL\PrestaShop\Entity\MyparcelnlCarrierMapping' was not found in the chain configured namespaces PrestaShopBundle\Entity, PrestaShop\Module\ProductComment\Entity, PrestaShop\Module\PsAccounts\Entity, MyParcelNL\PrestaShop\Entity\Concern
at Sg.doRequest (https://domain.example/modules/myparcelnl/views/js/backend/admin/dist/index.iife.js:21:55600)
at async Object.Ce [as mutationFn] (https://domain.example/modules/myparcelnl/views/js/backend/admin/dist/index.iife.js:21:56772)

Additional context

No response

RedFuseCap commented 4 months ago

Same issue here. In my case on PrestaShop version 8.1.4 and PHP version 8.1. After installing the module, the configuration page of the module is completely empty.

When I cleared the cache and removed all MyParcel related rows in ps_configuration, the configuration page of the module gives the option to enter the API-key. After pasting the correct API key and clicking "Save", I get an error about an invalid API key. Symphony Profiler shows an 400 error at that point for the following path: /modules/myparcelnl/pdk?action=updateAccount When refreshing the configuration page of the module, it is completely empty again.

Looking in the database within the ps_configuration table after these actions, new rows related to MyParcel are generated again. The "myparcelnl_data_account" config item in this table, shows specific data from MyParcel backend, meaning the API key did work.

RedFuseCap commented 4 months ago

@mariuszsienkiewicz Thanks for the detailed reaction.

Looking at the error logfile in the /var/log/myparcelnl folder, I get similar output as your log 1 output. It starts with the following line:

ERROR v8.1.4 2024/04/22 - 21:58:43: [PDK]: The class 'MyParcelNL\PrestaShop\Entity\MyparcelnlCartDeliveryOptions' was not found in the chain configured namespaces PrestaShopBundle\Entity, PrestaShop\Module\ProductComment\Entity, MyParcelNL\PrestaShop\Entity\Concern

I use English as default language. In addition, we offer Dutch language. As far as I can see, the nl.json should be used in case of Dutch language and looks fine.

mariuszsienkiewicz commented 4 months ago

@RedFuseCap I've encountered so many issues with this module that I've started mixing up their symptoms! 😄 I completely forgot that I had mentioned clearing the configuration and the API key form appearing and that's why I thought that your issue is a little bit different haha. I've deleted my previous comment. Sorry for any confusion!

mariuszsienkiewicz commented 4 months ago

@EdieLemoine I did the hard work to find the reason for this issue (which is probably the same as #235) - and as you can probably see, it's not that "rare". It just won't work on some servers, and that's why I think it should be fixed.

Detailed explanation of the issue

The gray page is caused by the problem that Doctrine can't find the proper namespace. As you have seen in the description of this issue, it looks in those namespaces PrestaShopBundle\Entity, PrestaShop\Module\ProductComment\Entity, PrestaShop\Module\PsAccounts\Entity, and MyParcelNL\PrestaShop\Entity\Concern.

The reason why MyParcelNL\PrestaShop\Entity\Concern is in the chain but MyParcelNL\PrestaShop\Entity is not, is because the PrestaShop compiler does not explicitly support defining subnamespaces at all in the <module>/src/Entity directory:

https://github.com/PrestaShop/PrestaShop/blob/1f3b8d0760470700b792887ebe4d9cc0d4f82625/src/PrestaShopBundle/DependencyInjection/Compiler/ModulesDoctrineCompilerPass.php#L121-L133

It just finds the namespace of the first file (that is provided by Finder - this class will be important later) that has the "namespace" text in it.

So here is a catch - Finder uses the RecursiveDirectoryIterator which uses internally (as far as I know) the opendir function. The latter one has no guarantee how the files will be returned - and it will differ on different servers (kernels) etc. (php version doesn't matter).

For example, on one of the servers that I use, the Finder used above returns files in this order:

<ps_root>/modules/myparcelnl/src/Entity/Concern/HasJsonData.php
<ps_root>/modules/myparcelnl/src/Entity/Concern/HasCreatedTimestamps.php
<ps_root>/modules/myparcelnl/src/Entity/Concern/HasTimestamps.php
<ps_root>/modules/myparcelnl/src/Entity/Contract/EntityWithCreatedTimestampsInterface.php
<ps_root>/modules/myparcelnl/src/Entity/Contract/EntityWithTimestampsInterface.php
<ps_root>/modules/myparcelnl/src/Entity/Contract/EntityInterface.php
<ps_root>/modules/myparcelnl/src/Entity/MyparcelnlOrderData.php
<ps_root>/modules/myparcelnl/src/Entity/MyparcelnlAudit.php
...

But on the other server (where the module works), it returns:

<ps_root>/modules/myparcelnl/src/Entity/MyparcelnlOrderShipment.php
<ps_root>/modules/myparcelnl/src/Entity/MyparcelnlProductSettings.php
<ps_root>/modules/myparcelnl/src/Entity/MyparcelnlCarrierMapping.php
<ps_root>/modules/myparcelnl/src/Entity/MyparcelnlOrderData.php
<ps_root>/modules/myparcelnl/src/Entity/Contract/EntityWithTimestampsInterface.php
<ps_root>/modules/myparcelnl/src/Entity/Contract/EntityWithCreatedTimestampsInterface.php
<ps_root>/modules/myparcelnl/src/Entity/Contract/EntityInterface.php
<ps_root>/modules/myparcelnl/src/Entity/AbstractEntity.php
...

So on the server where it's not working, Finder finds the MyParcelNL\PrestaShop\Entity\Concern first and treats it like a namespace that should be put in the Doctrine namespace chain instead of MyParcelNL\PrestaShop\Entity.

That's why it does not work for me and other people. Clearing cache changes nothing because it doesn't affect how the internal files are being returned to the function.

Fix suggestions

For now, I see only two fixes here to make the module more compatible:


@RedFuseCap could you please check if this issue is similar to yours? Below you can find the code that will display the order of files that are being loaded via PrestaShop Compiler. Just create a new php file in the root folder of PrestaShop and run it via a web browser:

<?php

require_once 'vendor/autoload.php';

use Symfony\Component\Finder\Finder;

$dir = __DIR__ . '/modules/myparcelnl';

// finder
$finder = new Finder();
$finder->files()->in($dir . '/src/Entity')->name('*.php');
echo "<pre>";
foreach ($finder as $phpFile) {
    echo sprintf("file/dir: %s%s", $phpFile, PHP_EOL);
}
echo "</pre>";

// direct use of recursiveIteratorIterator
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir . '/src/Entity'));
echo "<pre>";
/** @var \SplFileObject $spl $ */
foreach ($it as $spl) {
    echo sprintf("file/dir: %s%s", $spl->getFilename(), PHP_EOL);
}
echo "</pre>";

// direct use of opendir
echo "<pre>";
if ($directoryHandler = opendir($dir . '/src/Entity')) {
    while (($file = readdir($directoryHandler)) !== false) {
        echo sprintf("file/dir: %s%s", $file, PHP_EOL);
    }
    closedir($dh);
}
echo "</pre>";
RedFuseCap commented 4 months ago

This is the output on my server:


<ps_root>/modules/myparcelnl/src/Entity/Concern/HasJsonData.php
<ps_root>/modules/myparcelnl/src/Entity/Concern/HasTimestamps.php
<ps_root>/modules/myparcelnl/src/Entity/Concern/HasCreatedTimestamps.php
<ps_root>/modules/myparcelnl/src/Entity/AbstractEntity.php
<ps_root>/modules/myparcelnl/src/Entity/Contract/EntityInterface.php
<ps_root>/modules/myparcelnl/src/Entity/Contract/EntityWithTimestampsInterface.php
<ps_root>/modules/myparcelnl/src/Entity/Contract/EntityWithCreatedTimestampsInterface.php
<ps_root>/modules/myparcelnl/src/Entity/MyparcelnlCartDeliveryOptions.php
<ps_root>/modules/myparcelnl/src/Entity/MyparcelnlProductSettings.php
...
mariuszsienkiewicz commented 4 months ago

Thank you @RedFuseCap! This confirms that the file order is indeed different and is related to the environment. We are now waiting for the devs input.

EdieLemoine commented 4 months ago

Hi @mariuszsienkiewicz and @RedFuseCap,

Thank you for figuring out what this is caused by! This happens a lot on our test environments as well and for us is actually solved by clearing the cache, but we've (incorrectly) assumed it's not a problem for customers. It used to regularly happen on the previous version of the module as well, but customers did not report it happening, so we figured it must be the same thing.

Again thanks @mariuszsienkiewicz for the hard work! 😄 I'll shortly make a pull request (unless you want to get credit for contributing) that moves the classes to the same directory, I hope that finally resolves this issue.

myparcel-bot[bot] commented 4 months ago

:tada: This issue has been resolved in version 4.0.0-beta.3 :tada:

The release is available on GitHub release

Your semantic-release bot :package::rocket: