6
votes

I have a working Extbase extension in TYPO3 V6.2, which stores Products. Now I want to learn about using Signal/Slot (Extbase variant of Hooks). I wonder why the example don't work. When I update a product in List module in the TYPO3 Backend, it saves correctly but no message appears.

File typo3conf/ext/myext/ext_localconf.php

$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( 'TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher' );
$signalSlotDispatcher->connect(
    'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Backend',
    'afterUpdateObject',
    'MyVendor\\MyExt\\Service\\Signalservice',    
    'myAfterUpdate',
    FALSE
);

File typo3conf/ext/myext/Service/Signalservice.php

namespace MyVendor\MyExt\Service;

class Signalservice implements \TYPO3\CMS\Core\SingletonInterface {

    /**
     * @param  \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object
     */
    public function myAfterUpdate(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object){

            if ($object instanceof \MyVendor\MyExt\Domain\Model\Products) {

                // check if we come to this point 
                \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump('Successfully hooked - I am a slot.');
                die();

            }   

    }

}


Update 15.06.2015
A hint from Patrick Lobacher remarked, that we cannot use die() in this context. Instead, we should write a logfile. But that don't work for me either. No file was written:

File typo3conf/ext/myext/ext_localconf.php

/** 
 * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher 
 * */
$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager')->get('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
$signalSlotDispatcher->connect(
   'TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Backend',
   'afterUpdateObject',
   function ($payload) {

       $logfile = "fileadmin/test/logfile.txt"; 
       $handle = fopen($logfile, "a+");
       fwrite ($handle, 'Hi. I was written by ext_localconf.php. ' . time());
       fclose ($handle);

   });


Update 29.06.2015
On https://forge.typo3.org/issues/61979 Francois wrote, that "Object Manager may only be used in Extbase Context, not in ext_localconf.php". However, the given answer even don't work for me. But perhaps it helps someone else.

1

1 Answers

3
votes

Currently there is no official documentation, but in the issue you can find unofficial documentation: https://forge.typo3.org/issues/59089

The problem is that you are using Signal Slots of Extbase in list Module. In 6.2 the list Module is not implemented using Extbase. So there are no Slots you can use. Instead you need to follow the old, documented, way using Hooks: https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/Hooks/Concept/Index.html

In your case, the following code should work as an entry point:

ext_localconf.php:

$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][$_EXTKEY]
    = 'Vendor\ExtName\Hook\DataMapHook';

There you configure the class to use as Hook for t3lib_tcemain the old Classname before TYPO3 6.2 handling more then just the data for List View.

Inside of your class you can implement your code as already done by you:

Classes/Hook/DataMapHook.php:

<?php
namespace Vendor\ExtName\Hook;

/**
 * Hook to process updated records.
 *
 * @author Daniel Siepmann <[email protected]>
 */
class DataMapHook
{

    /**
    * Hook to add latitude and longitude to locations.
    *
    * @param string $action The action to perform, e.g. 'update'.
    * @param string $table The table affected by action, e.g. 'fe_users'.
    * @param int $uid The uid of the record affected by action.
    * @param array $modifiedFields The modified fields of the record.
    *
    * @return void
    */
    public function processDatamap_postProcessFieldArray(
        $action, $table, $uid, array &$modifiedFields
    ) {
        if(!$this->executeHook($table, $action)) {
            return;
        }

        // check if we come to this point 
        \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump('Successfully hooked - I am a slot.');
        die();
    }

    /**
    * Check whether to execute hook or not.
    *
    * @param string $table
    * @param string $action
    * @param array $modifiedFields
    *
    * @return bool
    */
    protected function executeHook($table, $action)
    {
        // Do not process if foreign table, unintended action,
        // or fields were changed explicitly.
        if ($table !== 'tx_extname_domain_model_modelname' || $action !== 'update') {
            return false;
        }

        return false;
    }
}

And yes, you CAN use die in this context, for debugging and such. As TYPO3 just will iterate over the configured hooks and call the methods. So nothing fancy here. You get some parameters defined by implementation and can work with them.

In the above example there is one check to only execute the hook if table and action matches. As this code is called for many reasons you make sure to whitelist it, to only execute in environments you know about. For security and performance reasons.