How to execute scripts after installing TYPO3 extensions

Extensions are a great way to add features to the TYPO3 CMS and there are extension for virtually everything! Simply download them from the TYPO3 extension repository and install them via the Extension Manager in the TYPO3 back-end. So far so good …

Often, the remaining tasks of configuring the extension, adding new pages with the plug-ins from the extension or importing required data into the database becomes much more cumbersome. Why can’t life be not as easy as in other CMS? Just click and everything works?

Yes, we can!

The infrastructure for performing additional tasks after installing extensions is part of TYPO3 since some time. At least since TYPO3 6.2 it works flawlessly, before your way may vary. The trick is to utilize the signal/slot mechanism to connect to the Extension Management service and listen for signals emitted after an extension was installed.

In the Aimeos TYPO3 web shop extension we’ve added the following code to the ext_localconf.php:

  1. if (TYPO3_MODE === 'BE') {
  2.     $class = 'TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher';
  3.     $dispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($class);
  4.     $dispatcher->connect(
  5.         'TYPO3\\CMS\\Extensionmanager\\Service\\ExtensionManagementService',
  6.         'hasInstalledExtensions',
  7.         'Aimeos\\Aimeos\\Setup',
  8.         'executeOnSignal'
  9.     );
  10. }

The first line ensures that we are connecting only to the Extension Management service if we are in the back-end. If you leave this line out, your script would connect at every front-end request too, which would only slow down response times. The next two lines instantiates the signal/slot dispatcher class and the makeInstance() method of the GeneralUtility class does a good job.

Don’t use the PHP “new” operator for creating the class instance! This would create one instance each time the code is executed instead of sharing a common instance during the request.

The remaining lines connect your method executeOnSignal() of your namespaced class Aimeos\Aimeos\Setup to the Extension Management service whose class name is handed over as first parameter. Here we are listening to the hasInstalledExtensions signal, that is emitted by the service after an extension has been installed. The key of the installed extension will be passed as first parameter to our method.

There’s another signal that is emitted by the Extension Management service named willInstallExtensions. By listening to this signal, your script can be informed about which extensions are going to be installed next. An array of extension keys is given in this case.

Do what you need

At last, you need to create a class that contains the code to be executed after an extension is installed. The Aimeos TYPO3 extension contains a Setup class in the Classes/ directory of the extension with a method named executeOnSignal() to care about this. The basic code of this class is:

  1. <?php
  2.  
  3. namespace Aimeos\Aimeos;
  4.  
  5. class Setup
  6. {
  7.     public function executeOnSignal( $extname = null )
  8.     {
  9.         if( $extname !== 'aimeos' ) {
  10.             return;
  11.         }
  12.  
  13.         // your code
  14.     }
  15. }

The namespace declaration is important but must be adapted to your extension. The first namespace part is the vendor name, e.g. the name of your company. The second part is the extension key with the first letter uppercased. If your extension key contains an underscore, then the underscore is removed and the next character transformed to uppercase as well, e.g. the boostrap_package uses BootstrapPackage as the second namespace part.

You are free to use any valid class and method name in your extension. Only make sure that the third and fourth parameter of the connect() method call are named appropriately. Also, ensure that your class and method are neither abstract nor static so an instance can be created. Like said above, the key name of the extension that has been installed is given as first parameter to your method. For compatibility reasons, you should make that parameter optional by assigning a default value of null.

Use the given extension key name to filter for your one! The Extension Management service will inform your script about every extension that is installed, not only your own one. Otherwise, you would execute your script code for every installed extension and this may slow down the installation process depending on how much your code does.

What’s next?

Pretty simple, isn’t it? Now it’s time to pimp your TYPO3 extension to remove as much burden as possible from the user! In a second article we will go into more detail how this can save your users day when your extension imports pages and depending TypoScript configuration.

A special thanks goes to Benjamin Kott for his bootstrap_package because it was the first that provided a working example that the signal/slot infrastructure can be used for these kind of use cases.