phpcakephpcakephp-2.0

Cakephp 2.3 beforeFilter and implementedEvents aren't able to co-exist


Using cakephp 2.3.5.

I use beforeFilter in several controllers to allow certain actions without the need to log in. I've used it successfully for quite some time. However, I've noticed that I can't get beforeFilter to fire if the controller also has the implementedEvents() method.

public function beforeFilter() {
        parent::beforeFilter();
        $this->Auth->allow('matchWwiProducts');
}     

public function implementedEvents() {
       return array(
                    'Controller.Product.delete' => 'deleteSku',
                    'Controller.Product.price'  => 'notifySubscribers',
                    'Controller.Product.stock'  => 'notifySubscribers'
       );
}

For the code as displayed above I will be forced to do a login if I call the method www.example.com/products/matchWwiProducts.

When I comment out the implementedEvents() everything works as intended. I've searched around and can't find any references to implementedEvents() creating issues with beforeFilter.

The action matchWwiProducts() is as follows. It works perfectly when I log in. However, I don't want to force a log in for this action to take place.

public function matchWwiProducts() {
     // this is an audit function that matches Products sourced by wwi
     //
     $this->autoRender = false; // no view to be rendered
     // retrieve products sourced from wwi from Table::Product
     $this->Product->contain();
     $wwiProducts = $this->Product->getWwiSkus();                        
     $wwiProductCount = count($wwiProducts);
     // retrieve products sourced from wwi from Table:Wwiproduct
     $this->loadModel('WwiProduct');
     $this->Wwiproduct->contain();
     $wwiSource = $this->Wwiproduct->getSkuList();
     $wwiSourceCount = count($wwiSource);                        
     // identify SKUs in $wwiProducts that are not in $wwiSource
     $invalidSkus = array_diff($wwiProducts, $wwiSource);                        
     // identify SKUs in $wwiSource that are not in $wwiProducts
     $missingSkus = array_diff($wwiSource, $wwiProducts);                        
     $missingSkuDetails = array();
     foreach ($missingSkus as $missingSku) {
             $skuStockStatus = $this->Wwiproduct->getStockStatus($missingSku);
             $missingSkuDetails[$missingSku] = $skuStockStatus;
             }                        
     $email = new CakeEmail();
     $email->config('sourcewwi');
     $email->template('sourcewwiaudit', 'sourcewwi');
     if (count($invalidSkus) > 0 || count($missingSkus) > 0) {
            $email->subject('WWI Source Audit: Invalid or Missing SKUs');
            $email->viewVars(array('invalidSkus' => $invalidSkus,                                                       
                                   'missingSkuDetails' => $missingSkuDetails,
                                   'wwiProductCount' => $wwiProductCount,
                                   'wwiSourceCount' => $wwiSourceCount));
     } else {
             $email->subject('WWI Source Audit: No Exceptions');
             $email->viewVars(array('wwiProductCount' => $wwiProductCount,
                                    'wwiSourceCount' => $wwiSourceCount));
     }
     $email->send();
}

Solution

  • It doesn't fire because you're overloading the implementendEvents() method without making sure you keep the existing events there.

    public function implementedEvents() {
           return array_merge(parent::implementedEvents(), array(
                        'Controller.Product.delete' => 'deleteSku',
                        'Controller.Product.price'  => 'notifySubscribers',
                        'Controller.Product.stock'  => 'notifySubscribers'
           ));
    }
    

    Overloading in php.

    Check most of the base classes, Controller, Table, Behavior, Component, they all fire or listen to events. So be careful when extending certain methods there. Most simple way might to do a search for "EventListenerInterface" in all classes. A class that implements this interface is likely to implement event callbacks.