Upgrade custom modules to work with Zend 3

You must test your custom modules on a test system before transferring them to your production system. This avoids any negative impact on the operation of your production system. If you have more than one custom module, the modules should all be tested at the same time on the same test system as this ensures that the modules operate correctly with each other and with P4 Code Review.

If you add or edit a module, P4 Code Review will not use that change until the config cache has been reloaded, this forces P4 Code Review to use the module change. You must be an admin or super user to reload the P4 Code Review config cache. Navigate to the User id dropdown menu, select System Information, click the Cache Info tab, and click the System Information.

P4 Code Review 2019.1 uses the Zend 3 framework, previous P4 Code Review versions used the Zend 2 framework. The move to Zend 3 is part of our commitment to move away from using versions of platforms that have reached End-of-Life (EOL).

If you have any custom P4 Code Review modules that were created for P4 Code Review 2018.3 or earlier you must update them so that they will work in P4 Code Review 2019.1 and later.

The section describes the changes that you must make to your custom modules to enable them to work with P4 Code Review 2019.1 and later, it includes:

Summary of changes for the Zend 3 Framework that impact P4 Code Review

The following Zend 3 changes are important for P4 Code Review custom modules:

  • Custom module file locations have changed to the PSR-4 standard locations shown below. For information on how this affects an existing custom module, see Custom module file locations.
  • config/
          custom.modules.config.php (new file, required)
    module/
          ModuleName/ (required)
                    config/ (required)
                          module.config.php (existing file, required)
                    src/ (php files here, required)
                       Controller/
                                 MyIndexController.php
                       ...
                       other directories (non-php files here, optional)
                       ...  
                    Module.php (existing file, required)
    
  • custom.modules.config.php: this is a new configuration file that tells P4 Code Review which custom modules it should load. This gives you control over which modules P4 Code Review loads and prevents modules from being loaded by mistake. For information about the content of the file, see custom.modules.config.php.
  • Previously P4 Code Review checked the modules directory and used any modules it found there.

  • IndexControllers: Zend has deprecated the use of getServiceLocator() to get services. Your invokables definitions must be changed to factories and the factories that create the IndexControllers must inject services.
  • We recommend you follow the ::class description to avoid errors in string representation. For information on changing from invokables definitions to factories, see IndexControllers.

  • View Helpers Zend has deprecated the use of getServiceLocator() to get services. Your invokables definitions must be changed to factories and the factories that create the view helpers must inject the services.
  • We recommend you follow the ::class description to avoid errors in string representation. For instructions on changing from invokables definitions to factories, see View Helpers.

  • Routes are now defined in Zend\Router not Zend\Mvc\Router.
  • Your routes must be updated, see Routes.

  • Event listeners can now use a declarative model that passes events to the listeners.
  • Your event listeners should be changed to use the new declarative model. For instructions on changing the event listeners, see Event listeners.

    Your existing listeners will continue to work for P4 Code Review 2019.1 if you want to keep using them but we strongly recommend you move your event listeners to use the declarative model.

Upgrade custom modules for P4 Code Review 2019.1 and later

This section describes the changes that you need to make to a custom module to refactor it for the Zend 3 framework.

The new language features in PHP 7.x enable you to use [] as a shortcut for array().

Custom module file locations

The file locations for custom modules has changed to the PSR-4 standard location.

For P4 Code Review 2018.3 and earlier the file locations are

module/
      MyModuleName/
                   config/
                          module.config.php
                   src/
                       MyModuleName/
                                    Controller/
                                               MyIndexController.php
                   Module.php

For P4 Code Review 2019.1 and later the file locations are

Changes:

  • The custom.modules.config.php is a new file and is required, see custom.modules.config.php.
  • The Controller directory has moved up the file structure so that it is now in the module/MyModuleName/src directory.
  • The MyIndexController file has moved up the file structure so that it is now in the module/MyModuleName/src/Controller directory.
  • The MyModuleName directory under the src directory is no longer used.
config/
      custom.modules.config.php
module/
      MyModuleName/
                  config/
                         module.config.php
                  src/
                     Controller/
                               MyIndexController.php
                  Module.php

custom.modules.config.php

The custom.modules.config.php is a new file and is required.

P4 Code Review uses this file to check which custom modules it should load. This gives you control over which modules P4 Code Review loads and prevents modules from being loaded by mistake.

Create the custom.modules.config.php file if it does not already exist. Edit the file so that it contains the following details for each of your modules:

  • namespaces array: enter your custom module names and paths
  • return array : enter your custom module names

For example, if you have three modules called MyModuleName, AnotherModuleName, and NewModuleName the file content would look similar to:

<?php
\Zend\Loader\AutoloaderFactory::factory(
    array(
        'Zend\Loader\StandardAutoloader' => array(
            'namespaces' => array(
                'MyModuleName'       => BASE_PATH . '/module/MyModuleName/src',
                'AnotherModuleName'  => BASE_PATH . '/module/AnotherModuleName/src',
                'NewModuleName'      => BASE_PATH . '/module/NewModuleName/src',
            )
        )
    )
);
return [
    'MyModuleName',
    'AnotherModuleName',
    'NewModuleName',
];

IndexControllers

Zend has deprecated the use of getServiceLocator() to get services. This means that your invokables must be changed to factories and the factory that creates the index controller must inject the services.

We recommend you follow the ::class description to avoid errors in string representation.

For P4 Code Review 2018.3 and earlier the index controllers used invokables

'controllers' => array(
    'invokables' => array( 
        'MyModuleName\Controller\Index' => 'MyModuleName\Controller\IndexController'
    ),
),

For P4 Code Review 2019.1 and later the index controllers must use factories

The IndexController should extend Application\Controller\AbstractIndexController, this means that the IndexControllerFactory can automatically inject the services . In this case you can use the P4 Code Review IndexControllerFactory.

Change: Index controller refactored to use factories.

'controllers' => array(
    'factories' => [
        MyModuleName\Controller\IndexController::class => Application\Controller\IndexControllerFactory::class,
    ],
),

View Helpers

Zend has deprecated the use of getServiceLocator() to get services. This means that your invokables must be changed to factories and the factory that creates the view helper must inject the services.

We recommend you follow the ::class description to avoid errors in string representation.

For P4 Code Review 2018.3 and earlier the view helpers use invokables definitions

'view_helpers' => array(
        'invokables' => array(
            'helper1' => 'MyModuleName\View\Helper\Helper1',
            'helper2' => 'MyModuleName\View\Helper\Helper2',
        ),
    ),

For P4 Code Review 2019.1 and later the view helpers must use factories

In the following example, <YourHelperFactory> should construct the correct helper based on the name and inject services if needed. We recommend using ::class rather than arbitrary strings as this can limit the possibility of errors. The use of classes also makes your factory simpler because reflection can be used to construct the helpers if they all extend a common parent class.

Change: View helpers refactored to use factories.

'view_helpers' => array(
        'factories' => array_fill_keys(
            [
                MyModuleName\View\Helper\Helper1::class,
                MyModuleName\View\Helper\Helper2::class,
            ],
            <YourHelperFactory>::class
        )
    )

Routes

Update your routes in module.config.php to match the new controller definitions.

For P4 Code Review 2018.3 and earlier routes would look similar to

'MyModuleName-message' => array(
                'type' => 'Zend\Mvc\Router\Http\Segment',
                'options' => array(
                    'route'    => '/MyModuleName/message[/]',
                    'defaults' => array(
                        'controller' => 'MyModuleName\Controller\Index',
                        'action'     => 'message'
                    ),
                ),
            ),

For P4 Code Review 2019.1 and later routes must be changed to look similar to

Changes:

  • The route has been changed for 'type'
  • The route has been changed for 'controller'
'MyModuleName-message' => array(
                'type' => 'Zend\Router\Http\Segment',
                'options' => array(
                    'route'    => '/MyModuleName/message[/]',
                    'defaults' => array(
                        'controller' => MyModuleName\Controller\IndexController::class,
                        'action'     => 'message'
                    ),
                ),
            ),

Event listeners

Your existing listeners will continue to work for P4 Code Review 2019.1 if you want to keep using them but we strongly recommend you move your event listeners to use the declarative model.

We strongly recommend that you refactor your event listeners to use the declarative model because it has a number of advantages over the previous method:

  • AbstractEventListener provides common code for listeners to use
  • The declarative model offers better debug options (logging)
  • The declarative model is neater, easier to read, easier to support, and easier to maintain

Your listeners should extend Events\Listener\AbstractEventListener. This means that the ListenerFactory can create them without you having to write your own factory.

Look at the code in the AbstractEventListener.php file in module/events/src/Listener of P4 Code Review 2019.1 and later to see the functions that are available to you.

For P4 Code Review 2018.3 and earlier the event listeners look similar to

namespace MyModuleName;
use Zend\Mvc\MvcEvent;
class Module
{
public function onBootstrap(MvcEvent $event)
{
$application = $event->getApplication();
$services = $application->getServiceManager();
$events = $services->get('queue')->getEventManager();

$events->attach(
'*',
function ($event) {
$mail = $event->getParam('mail');
if (!$mail || !isset($mail['htmlTemplate'], $mail['textTemplate'])) {
return;
}
}
-199
); } }

For P4 Code Review 2019.1 and later when using the declarative structure the event listeners should look similar to

Changes:

  • New listener directory created in the MyModuleName directory, in the following example the directory is called Listener
  • New listener PHP file created in the listener directory, in this example it is called Listener.php
  • Edit the content of your module.config.php to configure your event listeners, this replaces the attach listener event functionality of the onBootstrap method in the original Module.php file.
namespace MyModuleName\Listener;

use Events\Listener\AbstractEventListener;
use Zend\EventManager\Event;

class Listener extends AbstractEventListener
{
    public function handleEmail(Event $event)
    {
        $mail = $event->getParam('mail');
        if (!$mail || !isset($mail['htmlTemplate'], $mail['textTemplate'])) {
            return;			
        }
    }
}

Further reading

P4 Code Review supports the Laminas component versions in the LICENSE.txt file, features and functions in the Laminas documentation that were introduced in later versions of Laminas will not work with P4 Code Review. The LICENSE.txt file is in the readme folder of your P4 Code Review installation.