Mailing List Archive

Getting template arguments from a parser function?
Hi,

When you have a parser function called from within a template, you can of
course pass in to it any template parameters, like:

{{#flagicon:{{{Flag image|}}} }}

(This is a silly example, but bear with me.) I would like to instead be
able to call the parser function without the parameter, like this:

{{#flagicon:}}

...and have the parser function directly get the value of the "Flag image"
parameter.

I believe this can be done within Lua: when a Lua module is invoked from a
template, it can get the names and values of the parameters/arguments that
have been passed to that template using (I believe) code that looks like
the following:

frame = mw.getCurrentFrame()
origArgs = frame:getParent().args

I tried to do something similar within a parser function's code, using
various calls like the following, but nothing worked:

$frame = $parser->getPreProcessor()->newFrame()->newChild();
$args = $frame->getArguments();

Can this be done? Ideally, it would be great to get an array of all the
arguments that have been passed to the template - but just being able to
get the value for a specified parameter name would be good enough.

-Yaron

--
WikiWorks · MediaWiki Consulting · http://wikiworks.com
Re: Getting template arguments from a parser function? [ In reply to ]
I think what you have to do is set the SFH_OBJECT_ARGS flag in the third
argument of setFunctionHook.

That will change the function signature of your callback to ($parser,
$frame, $args). Note that $args might no longer be an array of strings but
PPNode (or something) stuff you may have to call $frame->expand() on (i
think. It was something like that).

This new form has a PPFrame object as a second arg. You should be able to
call $frame->getParent() on it which should give you what you need.

--
Brian

On Monday, February 15, 2021, Yaron Koren <yaron57@gmail.com> wrote:

> Hi,
>
> When you have a parser function called from within a template, you can of
> course pass in to it any template parameters, like:
>
> {{#flagicon:{{{Flag image|}}} }}
>
> (This is a silly example, but bear with me.) I would like to instead be
> able to call the parser function without the parameter, like this:
>
> {{#flagicon:}}
>
> ...and have the parser function directly get the value of the "Flag image"
> parameter.
>
> I believe this can be done within Lua: when a Lua module is invoked from a
> template, it can get the names and values of the parameters/arguments that
> have been passed to that template using (I believe) code that looks like
> the following:
>
> frame = mw.getCurrentFrame()
> origArgs = frame:getParent().args
>
> I tried to do something similar within a parser function's code, using
> various calls like the following, but nothing worked:
>
> $frame = $parser->getPreProcessor()->newFrame()->newChild();
> $args = $frame->getArguments();
>
> Can this be done? Ideally, it would be great to get an array of all the
> arguments that have been passed to the template - but just being able to
> get the value for a specified parameter name would be good enough.
>
> -Yaron
>
> --
> WikiWorks · MediaWiki Consulting · http://wikiworks.com
>
Re: Getting template arguments from a parser function? [ In reply to ]
Hi Brian,

Thank you! That... mostly worked. I added SFH_OBJECT_ARGS
to setFunctionHook(),and then the new $frame value passed in was indeed
easy to use - I just had to call $frame->getArgument('ParameterName')" to
get the value for that template parameter.

Unfortunately, now I don't know how to get all of the actual arguments to
the parser function. Before, the call func_get_args() did that. Now,
neither that function, nor just getting the $args argument, seems to get
all the arguments - I think they get arguments that are entirely static,
but an argument like "flag image={{{Flag image|}}}" leads to a strange
structure within $args that doesn't seem to include the actual value. Is
there a fix for that?

-Yaron

On Mon, Feb 15, 2021 at 1:02 PM Brian Wolff <bawolff@gmail.com> wrote:

> I think what you have to do is set the SFH_OBJECT_ARGS flag in the third
> argument of setFunctionHook.
>
> That will change the function signature of your callback to ($parser,
> $frame, $args). Note that $args might no longer be an array of strings but
> PPNode (or something) stuff you may have to call $frame->expand() on (i
> think. It was something like that).
>
> This new form has a PPFrame object as a second arg. You should be able to
> call $frame->getParent() on it which should give you what you need.
>
> --
> Brian
>
> On Monday, February 15, 2021, Yaron Koren <yaron57@gmail.com> wrote:
>
>> Hi,
>>
>> When you have a parser function called from within a template, you can of
>> course pass in to it any template parameters, like:
>>
>> {{#flagicon:{{{Flag image|}}} }}
>>
>> (This is a silly example, but bear with me.) I would like to instead be
>> able to call the parser function without the parameter, like this:
>>
>> {{#flagicon:}}
>>
>> ...and have the parser function directly get the value of the "Flag
>> image" parameter.
>>
>> I believe this can be done within Lua: when a Lua module is invoked from
>> a template, it can get the names and values of the parameters/arguments
>> that have been passed to that template using (I believe) code that looks
>> like the following:
>>
>> frame = mw.getCurrentFrame()
>> origArgs = frame:getParent().args
>>
>> I tried to do something similar within a parser function's code, using
>> various calls like the following, but nothing worked:
>>
>> $frame = $parser->getPreProcessor()->newFrame()->newChild();
>> $args = $frame->getArguments();
>>
>> Can this be done? Ideally, it would be great to get an array of all the
>> arguments that have been passed to the template - but just being able to
>> get the value for a specified parameter name would be good enough.
>>
>> -Yaron
>>
>> --
>> WikiWorks · MediaWiki Consulting · http://wikiworks.com
>>
> _______________________________________________
> MediaWiki-l mailing list
> To unsubscribe, go to:
> https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
>


--
WikiWorks · MediaWiki Consulting · http://wikiworks.com
Re: Getting template arguments from a parser function? [ In reply to ]
You need to call $frame->expand( $argument ) on each argument value to get
the actual value. #if is an example of doing this
https://github.com/wikimedia/mediawiki-extensions-ParserFunctions/blob/master/includes/ParserFunctions.php#L118
.

This structure is to allow dead code elimination. Any argument not expanded
is not processed which has an effect on efficiency. Most of the time that's
not something to worry about, but it makes a big difference for control
structures like #if.


I probably should have said Parser::SFH_OBJECT_ARGS instead of just
SFH_OBJECT_ARGS. I think the non class prefixed constant is deprecated.

--
Brian

On Monday, February 15, 2021, Yaron Koren <yaron@wikiworks.com> wrote:

> Hi Brian,
>
> Thank you! That... mostly worked. I added SFH_OBJECT_ARGS
> to setFunctionHook(),and then the new $frame value passed in was indeed
> easy to use - I just had to call $frame->getArgument('ParameterName')" to
> get the value for that template parameter.
>
> Unfortunately, now I don't know how to get all of the actual arguments to
> the parser function. Before, the call func_get_args() did that. Now,
> neither that function, nor just getting the $args argument, seems to get
> all the arguments - I think they get arguments that are entirely static,
> but an argument like "flag image={{{Flag image|}}}" leads to a strange
> structure within $args that doesn't seem to include the actual value. Is
> there a fix for that?
>
> -Yaron
>
> On Mon, Feb 15, 2021 at 1:02 PM Brian Wolff <bawolff@gmail.com> wrote:
>
>> I think what you have to do is set the SFH_OBJECT_ARGS flag in the third
>> argument of setFunctionHook.
>>
>> That will change the function signature of your callback to ($parser,
>> $frame, $args). Note that $args might no longer be an array of strings but
>> PPNode (or something) stuff you may have to call $frame->expand() on (i
>> think. It was something like that).
>>
>> This new form has a PPFrame object as a second arg. You should be able to
>> call $frame->getParent() on it which should give you what you need.
>>
>> --
>> Brian
>>
>> On Monday, February 15, 2021, Yaron Koren <yaron57@gmail.com> wrote:
>>
>>> Hi,
>>>
>>> When you have a parser function called from within a template, you can
>>> of course pass in to it any template parameters, like:
>>>
>>> {{#flagicon:{{{Flag image|}}} }}
>>>
>>> (This is a silly example, but bear with me.) I would like to instead be
>>> able to call the parser function without the parameter, like this:
>>>
>>> {{#flagicon:}}
>>>
>>> ...and have the parser function directly get the value of the "Flag
>>> image" parameter.
>>>
>>> I believe this can be done within Lua: when a Lua module is invoked from
>>> a template, it can get the names and values of the parameters/arguments
>>> that have been passed to that template using (I believe) code that looks
>>> like the following:
>>>
>>> frame = mw.getCurrentFrame()
>>> origArgs = frame:getParent().args
>>>
>>> I tried to do something similar within a parser function's code, using
>>> various calls like the following, but nothing worked:
>>>
>>> $frame = $parser->getPreProcessor()->newFrame()->newChild();
>>> $args = $frame->getArguments();
>>>
>>> Can this be done? Ideally, it would be great to get an array of all the
>>> arguments that have been passed to the template - but just being able to
>>> get the value for a specified parameter name would be good enough.
>>>
>>> -Yaron
>>>
>>> --
>>> WikiWorks · MediaWiki Consulting · http://wikiworks.com
>>>
>> _______________________________________________
>> MediaWiki-l mailing list
>> To unsubscribe, go to:
>> https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
>>
>
>
> --
> WikiWorks · MediaWiki Consulting · http://wikiworks.com
>
Re: Getting template arguments from a parser function? [ In reply to ]
Thanks, Brian! I tried it out, and that worked great. Somehow I never
thought to check how other extensions do it...

On Mon, Feb 15, 2021 at 9:09 PM Brian Wolff <bawolff@gmail.com> wrote:

> You need to call $frame->expand( $argument ) on each argument value to get
> the actual value. #if is an example of doing this
> https://github.com/wikimedia/mediawiki-extensions-ParserFunctions/blob/master/includes/ParserFunctions.php#L118
> .
>
> This structure is to allow dead code elimination. Any argument not
> expanded is not processed which has an effect on efficiency. Most of the
> time that's not something to worry about, but it makes a big difference for
> control structures like #if.
>
>
> I probably should have said Parser::SFH_OBJECT_ARGS instead of just
> SFH_OBJECT_ARGS. I think the non class prefixed constant is deprecated.
>
> --
> Brian
>
> On Monday, February 15, 2021, Yaron Koren <yaron@wikiworks.com> wrote:
>
>> Hi Brian,
>>
>> Thank you! That... mostly worked. I added SFH_OBJECT_ARGS
>> to setFunctionHook(),and then the new $frame value passed in was indeed
>> easy to use - I just had to call $frame->getArgument('ParameterName')" to
>> get the value for that template parameter.
>>
>> Unfortunately, now I don't know how to get all of the actual arguments to
>> the parser function. Before, the call func_get_args() did that. Now,
>> neither that function, nor just getting the $args argument, seems to get
>> all the arguments - I think they get arguments that are entirely static,
>> but an argument like "flag image={{{Flag image|}}}" leads to a strange
>> structure within $args that doesn't seem to include the actual value. Is
>> there a fix for that?
>>
>> -Yaron
>>
>> On Mon, Feb 15, 2021 at 1:02 PM Brian Wolff <bawolff@gmail.com> wrote:
>>
>>> I think what you have to do is set the SFH_OBJECT_ARGS flag in the
>>> third argument of setFunctionHook.
>>>
>>> That will change the function signature of your callback to ($parser,
>>> $frame, $args). Note that $args might no longer be an array of strings but
>>> PPNode (or something) stuff you may have to call $frame->expand() on (i
>>> think. It was something like that).
>>>
>>> This new form has a PPFrame object as a second arg. You should be able
>>> to call $frame->getParent() on it which should give you what you need.
>>>
>>> --
>>> Brian
>>>
>>> On Monday, February 15, 2021, Yaron Koren <yaron57@gmail.com> wrote:
>>>
>>>> Hi,
>>>>
>>>> When you have a parser function called from within a template, you can
>>>> of course pass in to it any template parameters, like:
>>>>
>>>> {{#flagicon:{{{Flag image|}}} }}
>>>>
>>>> (This is a silly example, but bear with me.) I would like to instead be
>>>> able to call the parser function without the parameter, like this:
>>>>
>>>> {{#flagicon:}}
>>>>
>>>> ...and have the parser function directly get the value of the "Flag
>>>> image" parameter.
>>>>
>>>> I believe this can be done within Lua: when a Lua module is invoked
>>>> from a template, it can get the names and values of the
>>>> parameters/arguments that have been passed to that template using (I
>>>> believe) code that looks like the following:
>>>>
>>>> frame = mw.getCurrentFrame()
>>>> origArgs = frame:getParent().args
>>>>
>>>> I tried to do something similar within a parser function's code, using
>>>> various calls like the following, but nothing worked:
>>>>
>>>> $frame = $parser->getPreProcessor()->newFrame()->newChild();
>>>> $args = $frame->getArguments();
>>>>
>>>> Can this be done? Ideally, it would be great to get an array of all the
>>>> arguments that have been passed to the template - but just being able to
>>>> get the value for a specified parameter name would be good enough.
>>>>
>>>> -Yaron
>>>>
>>>> --
>>>> WikiWorks · MediaWiki Consulting · http://wikiworks.com
>>>>
>>> _______________________________________________
>>> MediaWiki-l mailing list
>>> To unsubscribe, go to:
>>> https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
>>>
>>
>>
>> --
>> WikiWorks · MediaWiki Consulting · http://wikiworks.com
>>
> _______________________________________________
> MediaWiki-l mailing list
> To unsubscribe, go to:
> https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
>


--
WikiWorks · MediaWiki Consulting · http://wikiworks.com