tags:

views:

40

answers:

2

Hy there. I'm developing plug-in system and I have problems with call_user_func and referenced variables.

I'm calling plug-in handler like this:

    if(PluginFactory::NumberOfPlugins() != 0)
    foreach(PluginFactory::GetPlugins() as $pPlugin)
        call_user_func(get_class($pPlugin) . "::OnHandlePluggablePart", "Core:AfterSceneAssembly", $Document);

Where $Document is my document object where I hold my controls. The idea is that plug-ins can modify control set (add, delete, modify). My plugin class is this:

class SomePlugin extends Plugin
{

    ...

    public static function OnHandlePluggablePart($sPart, &$Document)
    {
        if($sPart == "Core:AfterSceneAssembly")
        {
            $Document->AddControl(new Paragraph("", "Plugin test"));
        }
    }
}

Document object is passed by value (copied) not reference... What to do, what to do :) ?

A: 

Here's a self-contained example that works fine with php5 and uses (most of) your code from the question.

<?php
echo 'phpversion: ', phpversion(), "\n";

$Document = new MyDocument;
if(PluginFactory::NumberOfPlugins() != 0)
  foreach(PluginFactory::GetPlugins() as $pPlugin)
    call_user_func( get_class($pPlugin) . "::OnHandlePluggablePart", "Core:AfterSceneAssembly", $Document);

foreach( $Document->a as $a ) {
  echo '# ', $a, "\n";
}

class MyDocument {
  public $a = array();
  public function AddControl($s) {
    $this->a[] = $s;
  }
}

class PlugA {
  public static function OnHandlePluggablePart($sPart, $Document) {
    $Document->AddControl('PlugA-Control');
  }
}

class PlugB {
  public static function OnHandlePluggablePart($sPart, $Document) {
    $Document->AddControl('PlugB-Control');
  }
}

class PluginFactory {
  static $p = null;
  public static function NumberOfPlugins() {
    self::foo(); return count(self::$p);
  }
  public static function GetPlugins() {
    self::foo(); return self::$p;
  }
  public static function foo() {
    if ( is_null(self::$p) ) {
      self::$p = array(new PlugA, new PlugB);
    }
  }
}

prints

phpversion: 5.3.3
# PlugA-Control
# PlugB-Control
VolkerK
+2  A: 

Try that:

if(PluginFactory::NumberOfPlugins() != 0)
    foreach(PluginFactory::GetPlugins() as $pPlugin) {
        $class = get_class($pPlugin);
        $class::$transport = &$Document;
        call_user_func( $class."::OnHandlePluggablePart", "Core:AfterSceneAssembly");
    }

class Plugin {
    public static $transport;
    ...
}


class SomePlugin extends Plugin {

    ...

    public static function OnHandlePluggablePart($sPart) {
        if($sPart == "Core:AfterSceneAssembly") {
            self::$transport->AddControl(new Paragraph("", "Plugin test"));
        }
    }
}
ITroubs
Jup, that would work. It's workaround for PHP < 5.3.
Stazh