Piwik_PostEvent call doesn't change passed reference


(Burton Kent) #1

I’m trying to use the ‘Tracker.getNewVisitObject’ hook to add my own visit object.

The relevant code in core/Tracker.php is this:


  protected function getNewVisitObject()
  {
    $visit = null;
    $visit = Piwik_PostEvent('Tracker.getNewVisitObject', $visit);

    [b]// $visit is ALWAYS null[/b]
    if(is_null($visit))
    {
      $visit = new Piwik_Tracker_Visit( self::$forcedIpString, self::$forcedDateTime );
    }
    elseif(!($visit instanceof Piwik_Tracker_Visit_Interface ))
    {
      throw new Exception("The Visit object set in the plugin must implement Piwik_Tracker_Visit_Interface" );
    }
    return $visit;
  }

It looks like Piwik is relying on pass by reference behavior in call_user_func() that’s doesn’t work as expected. The PHP manual explains this.

Am I right about this or is there some way to actually set $visit?

My plugin code is:


class Piwik_MyPlugin extends Piwik_Plugin
{
  public function getInformation()
  {  
    [i][snipped to reduce size][/i]
  }

  public function getListHooksRegistered()
  {
    return array(
      'Tracker.getNewVisitObject' => 'MyVisit',
    );
  }

  public function MyVisit(&$visit) {
    if (!class_exists('Piwik_MyTrackerVisit')) {
      require_once('MyTrackerVisit.php');
    }
    $visit = new Piwik_MyTrackerVisit();
    return $visit;
  }
}

Thanks.


(vipsoft) #2

Hooks always receive a notification object as a parameter. Try:


 public function MyVisit($notification) {
    if (!class_exists('Piwik_MyTrackerVisit')) {
      require_once('MyTrackerVisit.php');
    }

    $visit =& $notification->getNotificationObject();
    $visit = new Piwik_MyTrackerVisit();
  }


(Burton Kent) #3

Thanks. That almost worked, but I found that the Piwik_MyTrackerVisit was being destructed before it could be returned.

My solution was to create a static var $visit, then assign a reference to the object to it AND assign the reference to $visit. This prevents the destructor from running and everything works beautifully.

This gave me the clue I needed: http://www.php.net/manual/en/language.references.return.php#96860


(vipsoft) #4

Right.

BTW use a Singleton.