Here's basically what I want to accomplish:
{exp:plugin1:method arg="{exp:plugin2:method}"}
I’ve tried a number of different approaches.
Approach 1:
{exp:plugin1:method arg="{exp:plugin2:method}"}
Result: Plugin1->method
’s arg
parameter value is the string, {exp:plugin2:method}
, and it’s never parsed.
Approach 2:
My understanding of the parsing order suggests that this might have different results, but apparently it does not.
{preload_replace:replaced="{exp:plugin2:method}"}
{exp:plugin1:method arg="{replaced}"}
Result: The arg
parameter has the same value as approach 1.
Approach 3:
First I define a snippet (snip
), whose content is:
{exp:plugin2:method}
Then in the template:
{exp:plugin1:method arg="{snip}"}
Result: Same as approaches 1 and 2.
Approach 4:
Noting that plugins are processed in th开发者_如何学Goe order they appear, I have even tested simply placing an instance of {exp:plugin2:method}
before the {exp:plugin1:method}
call. My thinking is that I could wrap this first call in a regex replacement plugin in order to suppress output, but that it would trigger Plugin2’s parsing first.
{exp:plugin2:method}
{exp:plugin1:method arg="{exp:plugin2:method}"}
Result: Plugin1->method
’s arg
parameter value is the temporary hash placeholder for Plugin2->method
’s output (MD5 I believe) that the Template class reserves until later.
Interesting approach. However, this can be achieved more simply like this:
{exp:plugin1:method arg="{exp:plugin2:method}" parse="inward"}
I have a workaround, but I'll wait a while to see if a better solution comes up before I accept my own answer. The workaround is to wrap plugin1
with plugin2
and replace template tags referring to its methods within the tagdata
. Note that this requires a parse="inward"
parameter on the plugin2
call.
In the template:
{exp:plugin2 parse="inward"}
{exp:plugin1:method arg="{someplugin2method}"}
{/exp:plugin2}
In the plugin class:
static $public_methods;
function __construct() {
// Actual construction code omitted...
if(($tagdata = $this->EE->TMPL->tagdata) !== false && trim($tagdata) !== '') {
if(!isset(self::$public_methods)) {
self::$public_methods = array();
$methods = get_class_methods($this);
foreach($methods as $method) {
if($method == get_class($this) || $method == '__construct') {
continue;
}
$reflection = new ReflectionMethod(get_class($this), $method);
if($reflection->isPublic()) {
self::$public_methods[] = $method;
}
}
self::$public_methods = implode('|', self::$public_methods);
}
$tagdata = preg_replace_callback('/\{(' . self::$public_methods . ')\}/',
array($this, 'tagdata_callback'), $tagdata);
$this->return_data = $tagdata;
}
}
private function tagdata_callback($matches) {
$method = $matches[1];
return $this->$method();
}
Caveats:
- This can make for messier templates.
- Maintaining a list of public methods apparently requires
Reflection
which is not available in PHP 4. You can, of course, maintain a list of expected methods manually.
精彩评论