Updating modules to work with OXID 7

This section will give some ideas how to adapt an existing module to work with OXID 7. Of course you can just take your module, make it installable in OXID 7 and then adapt it step by step until the module works as intended.

Mind you, we are talking about updating an existing product ready module, so we can assume that the starting point is a module that is compatible to latest OXID eShop 6.5. You can make your update life easier by preparing the module in OXID 6.5 to make the final switch to OXID 7 easier.

Please first read the whole section here and then decide which way to start.

Steps to make the module fit

The following changes can be applied in 6.5 as well as 7 but as stated above, we recommend to stay in OXID 6.5 for now. Use the highest supported PHP version for the OXID 6.5 installation.

  • Before you start, add tests. The higher the test coverage, the less issues you will have. After each step of refactoring make your tests pass again. In case your module is not yet covered with tests at all: start by adding acceptance (codeception) tests. As many as you need to fully test the module’s ‘visible’ functionality. Add unit and integration tests when refactoring code. Codeception tests will serve to verify refactoring did not break the module. When the module code is then sufficiently covered by unit and integration tests, you can start to remove excess acceptance tests as those are way slower than units/integrations.

  • Does the module use OnActivate/OnDeactivate methods to update the database schema? Please extract this part into a migration and run the migration command after composer install or composer update. All migrations are tracked in the database and executed only once, so it’s safe to use them.

    Please keep in mind: once a migration is applied, it won’t run again. So, never change a migration after it’s been released unless there’s a critical issue. In that case, create a new migration to fix the problem for those who already applied the original one. If your module needs further database changes, add new migrations instead of modifying the old ones.

  • Refactor module entry points into controllers. In OXID eShop up to latest version 6, as module code is duplicated into source/modules folder, it is possible to directly invoke a script residing in this directory.

    https://myoxideshop.com/modules/moduledir/moduleendpoint.php
    

    Please change this into a shop controller, which then can be invoked like

    https://myoxideshop.com/index.php?cl=moduleendpoint
    

    See Module Controllers for details.

  • From OXID eShop 7.0 on, only metadata version 2.0 is supported. This means: the module must have namespaces. Namespace should point to the code in the vendor directory. Move module sourcecode into src folder and adapt namespace pointer. This is not strictly necessary, but we recommend a clean structure.

    Example:
    "autoload": {
       "psr-4": {
           "OxidEsales\\ModuleTemplate\\": "src/",
           "OxidEsales\\ModuleTemplate\\Tests\\": "tests/"
       }
     },
    
  • Update the module settings handling. Older shops were not very strictly distinguishing where a config variable originated from (shop, theme, module), it was usually accessed via

    \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('someConfigParam')
    

    There’s an interface in Shop 6.5

    \OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\Bridge\ModuleSettingBridgeInterface
    

    We recommend to implement a ModuleSettingsService in the module and retrieve/save settings only through it. You’ll find an example in our module template for OXID 6.5 module template for OXID 6.5

    We did improve this part for OXID 7 (as module template gets regular best practices updates) but the service itself did not change, neither do places where settings get actually used need a change as the module’s logic only need to access the shop settings logic in one central place in this example.

  • Clean up the module’s source code. In case of module grown from the early OXID 6 versions have a tendency to have a lot of their business logic built into what we call ‘chain extended’ classes.

    We recommend disentangling the module’s business logic from places where it’s hooked into the shop. This is a recommendation not a must, but it will help to make your code easier to maintain in the long run.

    The idea is to build your module logic as far separated from the shop as possible and only in an infrastructure layer access the shop core. This is not so easy in case you extend shop models or controllers, but still you should evaluate the possibility of encapsulating your logic in small and easily testable services and have the extended classes use those services.

    Get some ideas from what we started doing with Dependency Injection. Even in case you need to chain extend a shop class in order to hook into an existing method and change that method’s logic, put your new code in a service, call logic from that service, and then call the parent method.

    Please refer to our module template for detailed examples. Add interfaces and implement them. Learn about S.O.L.I.D principles.

  • Do not access module assets (css, js, images) directly in templates like you would the old-fashioned module endpoint, rather make use of OxidEsalesEshopCoreViewConfig::getModuleUrl()

    $oViewConf->getModuleUrl('mymodule','relative/path/to/some.css')
    
  • Whichever of the above points you changed: make your tests pass again. Regarding acceptance tests, rewrite them to use codeception, make as much use as possible of OXID’s codeception-modules and codeception-page-objects.

Concerning templates

The template engine for OXID eShop 6.5 is Smarty, the official Template Engine from OXID eShop 7.0 on is the Twig Engine with APEX theme.

We recommend you switch to the Twig Engine but in the first step, the best approach in case you are not yet fully familiar with twig might be to first make the module work with smarty engine. You should have smarty templates for the 6.5 version so you we can go from there.

Steps to take on OXID 7

Install OXID eShop 7 with Smarty engine, and add your module. Installation of smarty engine is described in Switching to the legacy Smarty template engine.

  • Ensure that the module in question can be installed via composer in OXID eShop 7.0. Dependencies listed in the module’s composer.json need to fit OXID eShop 7.0 system requirements like PHP version, Symfony components etc. Please make sure that the packages your module depends on are listed in that module’s composer.json, even if some other component in the metapackage already requires that component too.

  • Also from OXID eShop 7.0 on, as already mentioned above, only metadata version 2.0 is supported. The module code is no longer duplicated into source/modules, so the ‘extra’ section part in composer.json specifying the target directory can be removed now. See example below, it can just be removed from metadata.php now.

    "extra": {
          "oxideshop": {
              "target-directory": "oe/moduletemplate",
              "blacklist-filter": [
                  "source/**/*",
                  "vendor/**/*"
              ]
          }
      },
    

    Once the module is installed, the next step is to make it activatable. See Steps to make the module fit for nesessary preparation steps.

  • In OXID 7, module settings are no longer stored in the oxconfig table (they are fetched by a service from yaml files (cache first, files second) and are written into yaml files). Use the dedicated service to handle module settings.

    The interface we recommended to use in Steps to make the module fit

    OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\Bridge\ModuleSettingBridgeInterface
    

    is still around in OXID 7 but it’s deprecated. Please update to use the newest interface

    OxidEsales\EshopCommunity\Internal\Framework\Module\Facade\ModuleSettingServiceInterface
    
  • The module already comes with migrations? Beware, the migrations need a little update, see Adjust module migrations.

  • Move assets into the assets directory.

    As module code is no longer duplicated to modules directory, you will no longer have direct access there anymore. Assets folder is automatically linked to out directory during module installation. Please access them in templates via oViewCon::getModuleUrl() method as stated earlier.

  • Check for usages of deprecated, removed, or changed shop classes in your module and update those places. See Adjust removed functionality for more information. Try out the mentioned rector and update tools, it’s a big help.

  • Run your unit and integration tests, they should point out the most urgent problems. Fix those places.

  • Try activating the module via console command, and fix reported issues.

  • Smarty templates are registered in the module’s metadata.php, you need to adapt the paths to be relative to the module’s root directory and add the module’s template namespace. See examples below for comparison.

    //OXID 6.5 metadata.php example for Smarty module templates
    'templates'   => [
        'greetingtemplate.tpl' => 'oe/moduletemplate/views/templates/greetingtemplate.tpl',
    ],
     'blocks'      => [
        [
            'template' => 'page/shop/start.tpl',
            'block' => 'start_welcome_text',
            'file' => 'views/blocks/oemt_start_welcome_text.tpl'
        ]
    ],
    
    //OXID 6.5 usage of module own template
    class GreetingController extends FrontendController
    {
        ...
        protected $_sThisTemplate = 'greetingtemplate.tpl';
    

    Comparision for OXID eShop 7.0

     //OXID 7.0 example for Smarty module templates
    'templates'   => [
         '@oe_moduletemplate/templates/greetingtemplate.tpl' => 'views/smarty/templates/greetingtemplate.tpl'
     ],
     'blocks'      => [
         [
             'template' => 'page/shop/start.tpl',
             'block' => 'start_welcome_text',
             'file' => 'views/smarty/blocks/oemt_start_welcome_text.tpl'
         ]
     ],
    
    //OXID 7.0 usage of module own template
    class GreetingController extends FrontendController
    {
       ...
        protected $_sThisTemplate = '@oe_moduletemplate/templates/greetingtemplate';
    

    Check the shop frontend/admin backend to verify whether your module is working as expected. Run your aceptance tests. OXID’s Testing Library is deprecated but still usable for version 7.0.

Converting templates from smarty to twig

The prerequisite - you should have a theme that supports the twig template engine. Use APEX in case you want to stick to the standard or convert your own theme to twig otherwise.

  • Have a look at how twig template inheritance is working in OXID 7 Twig Template Engine. The templates are no longer registered in metadata.php, but now they need to follow the twig theme structure in case of extending theme templates.

  • Use OXID’s Smarty to Twig Converter to convert the module’s templates from smarty to twig. Read the converter repo’s README.md, it contains information about differences between OXID’s smarty and twig templates.