Page MenuHomePhabricator

Transclusion of templates inside PhpTags using require/include?
Closed, ResolvedPublic

Description

The new design changes in Change I1506de77 reminded me of an earlier idea that came to mind. I don't know how simple it might be, and PhpTags is still useful without it, but it would add some flexibility for how it can be used.

If it were made possible to transclude templates inside a PhpTags expression, then things that are done in several PhpTags templates could be put in a separate, common template. "Magic expressions" could then transclude templates for use as magic subexpressions.

PHP allows files to return values. If transclusion support is added in PhpTags, then maybe this could be useful for templates used as "subexpressions". And to pass arguments to a template, maybe include/require could also be extended to take them as extra arguments. For example:

<phptag>
...
$something = include( "Template:Get_something", [ 'foo' => 'bar', 'baz' ] );
...
</phptag>

The idea here is to pass arguments in an array which is used to make $argv for the included template. (I think this may be the simplest way to pass arguments.)

A big design change that would be needed is for PhpTags to be able to store several states, as a stack. The runtime state for the first template would need to be stored while a second state is used for running an included template. (And a third state for a template included in the included template, etc.)

I was reminded of this because the change you're making seems to move out some static things from the runtime. Maybe if this feature is added, a further change would be to make the runtime have non-static data, and then PhpTags can use a stack of runtime instances?

Anyway, this seemed like a neat idea, but I don't know how much work it would be or if it would be worth it. Also, if it is done, maybe there are better approaches than the above.

Event Timeline

JoelKP assigned this task to Pastakhov.
JoelKP raised the priority of this task from to Medium.
JoelKP updated the task description. (Show Details)
JoelKP subscribed.
JoelKP set Security to None.

Yes, it is great idea and I planned to add this feature in future.
Also I planned to add analog of eval and other callback and user-defined functions.

There is not a lot of work, but there is the difficulty of choosing from a variety of possible variants.
Operator "Include" can be used like native and transclusion can be released as:

$something = call_user_func_array( "Template:Get_something", [ 'foo' => 'bar', 'baz' ] );

I think this is the best variant that fits php and wiki.
Other variants:

$something = "Template:Get_something"( [ 'foo' => 'bar', 'baz' ] );

$func = function "Template:Get_something"; 
$something = $func( [ 'foo' => 'bar', 'baz' ] ); // or $func( 'bar', 'baz' ) but it doesn't support named arguments.

$something = call_template( "Template:Get_something", [ 'foo' => 'bar', 'baz' ] );
$something = transclude( "Template:Get_something", [ 'foo' => 'bar', 'baz' ] );
etc...

What do you think about this?

Change 209703 had a related patch set uploaded (by Pastakhov):
Allow transclusion of templates inside PhpTags (v 5.1.0) Hook release 8

https://gerrit.wikimedia.org/r/209703

I've been thinking about it, but not sure what's best. Some thoughts on various options:

If support is later added for defining user functions the same way as in PHP inside phptags blocks (function name( ... ) { ... }), then it's possible for page names to conflict with function names. It may not be a big problem: the user could avoid it for example by naming functions with a leading '_', which is never in a page name.

Using a keyword, like the example $func = function "Template:Get_something"; could also be an option to avoid conflict. Perhaps it would also be good to have for flexibility. When using a string which could be the name of either a page or a user function, another way to avoid conflict is to have both call_user_func_array and an operator like transclude:

  • If a string is given to call_user_func_array, it could first check for a user function definition before trying to use the string as a page name.
  • transclude could always treat a string as a page name.

Maybe this is not relevant right now. And I don't know if you plan to eventually support PHP-style user function definitions.

About passing arguments for transclusions: passing an array seems the simplest way to support named arguments. Another way could be to support strings similar to those used in MediaWiki parser functions, "name=value". Then arrays would become the way to pass "raw" arguments, and strings would become a way to pass arguments filtered like MediaWiki does. (If other types are also supported, they might be unnamed raw arguments.) Maybe this would also be worth supporting, though I think the array option gives the most flexibility and would be the simplest to add. If some alternative is supported, there could also be better ideas for it.

Change 212750 had a related patch set uploaded (by Pastakhov):
add transclude function (v 3.5.0) requere PhpTags >= 5.1.0

https://gerrit.wikimedia.org/r/212750

Change 209703 merged by jenkins-bot:
Allow transclusion of templates inside PhpTags (v 5.1.0) Hook release 8 T99997

https://gerrit.wikimedia.org/r/209703

Change 212750 merged by Pastakhov:
add transclude function (v 3.5.0) requere PhpTags >= 5.1.0

https://gerrit.wikimedia.org/r/212750

@Pastakhov: All related patches in Gerrit have been merged, so I assume this is resolved.
(Please reopen via Add Action...Change Status in the dropdown menu if I am wrong.) Thanks!