Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass a rendering helper to section lambdas #101

Merged
merged 3 commits into from Aug 2, 2012
Merged

Conversation

bobthecow
Copy link
Owner

In addition to the section contents, section lambdas (higher order sections) would receive a lambda helper as a second parameter. This helper consists of a single render method, allowing a template to be rendered using the current context stack.

The returned result from a section lambda is automatically rendered as a mustache template, which is sufficient most of the time. But if you want to do something with the rendered value of that template, it doesn't quite cut it.

For example, this data:

<?php
$data = array(
  'foo' => 'win',
  'embiggen' => function($text) {
    return strtoupper($text);
  },
);

... and this template:

{{#embiggen}}{{ foo }}{{/embiggen}}

... would uppercase the {{ FOO }} template string, rather than the value of foo. This would then be automatically rendered, resulting in an empty string, since there is no FOO value available.

With this change, a mustache lambda helper is passed as the second parameter to the anonymous function, giving you a way to render the section value:

<?php
$data = array(
  'foo' => 'win',
  'embiggen' => function($text, $mustache) {
    return strtoupper($mustache->render($text));
  },
);

... which would render as WIN, exactly like you'd expect.

In other languages (JavaScript, Ruby), this method would be bound to the closure context and just be available inside the anonymous function, but this isn't an option in PHP :)

This change is backwards compatible, as the second value will simply be ignored by any section lambda not referencing it.

@uhunkler
Copy link

Great, I'll try how your solution works.

@uhunkler
Copy link

Your $mustache->render() addition was exactly what I was looking for - the solution to handle dynamic partials.

<?php
$template = '{{#dynamicpartial}}{{partialname}}{{/dynamicpartial}}';
$partials = array( 'fullname' => '{{lastname}}, {{name}}' );
$partialname = 'fullname';

$mustache = new Mustache_Engine( array(
    'partials' => $partials
));

$data = array(
    'name' => "Willy",
    'lastname' => 'Moe',
    'partialname' => $partialname,
    'dynamicpartial' => function( $text, $mustache )
    {
        return '{{>' . $mustache->render( $text ) . '}}';
    }
);

echo $mustache->render( $template, $data );

The template calls the lambda 'dynamicpartial'. The function renders the {{partialname}} to build the string that calls the partial and renders the text.

Please add this functionality to Mustache.php, it's a big help.

@bobthecow
Copy link
Owner Author

You could even register 'dynamicpartial' as a helper so you don't have to add it to the rendering context... Just drop this in after instantiating $mustache and it'll always be available:

<?php

$mustache->addHelper('dynamicpartial', function($text, $mustache) {
    return '{{>' . $mustache->render($text) . '}}';
});

@uhunkler
Copy link

Ah - even better.

And from the merge statement I see that you decided to implement the feature in your Mustache.php dev branch - marvelous.

@bobthecow
Copy link
Owner Author

@uhunkler I haven't quite decided yet. It's open as a pull request so we can discuss before I merge it :)

@fwg
Copy link

fwg commented Aug 1, 2012

Awesome, just the feature I was missing right now.

@uhunkler
Copy link

uhunkler commented Aug 2, 2012

Justin, what do you think needs discussion about this feature?

Do you need more people confirming the usefulness? Or more arguments?

One big argument I see is that in other Mustache implementations like JavaScript and Ruby this functionality is inherent. To be able to implement Mustache as consistent as possible I think this functionality should be possible in your PHP version too.

@bobthecow
Copy link
Owner Author

@uhunkler Merging :)

bobthecow added a commit that referenced this pull request Aug 2, 2012
Pass a rendering helper to section lambdas
@bobthecow bobthecow merged commit 345a0c4 into dev Aug 2, 2012
@bobthecow
Copy link
Owner Author

This has been merged into the dev branch, and will go out in the v2.1.0 release.

@uhunkler
Copy link

uhunkler commented Aug 2, 2012

Marvelous :-)

@vendethiel
Copy link

Just something ... What'll happen if it's an user string and it contains, like "{{ admin }}" ? secury issue, isn't it ?

@bobthecow
Copy link
Owner Author

Yup. It's called mustache injection, and it's definitely possible if you return user values from a lambda. I don't see a good way of preventing it at the engine level though.

@satyago
Copy link

satyago commented Nov 28, 2012

Sorry - haven't realized master is still < 2.1

Second parameter for helpers not passed anymore?

@bobthecow
Copy link
Owner Author

@satyago Sorry about that. v2.1 is waiting on logging (see #116), but logging is waiting on an in-progress PHP-FIG discussion trying to standardize logging.

Unless that discussion stalls or doesn't come to a resolution, v2.1 will happen after a logging standard is adopted. In the interim, you should feel free to use the dev branch of Mustache.

bobthecow added a commit that referenced this pull request Nov 28, 2012
This means you can call `$this->render()` from inside a section lambda closure.

See #101
@satyago
Copy link

satyago commented Nov 28, 2012

Absolutely no problem !
It was my own mistake actually. I thought the master I pulled already was v2.1.
As soon as I realized I pulled the feature/lambda-helper-plus-plus tree ...

Needed this feature quite urgently - seemed the simplest solution for my problem ;)

Thanks for the quick support though !

@bobthecow bobthecow mentioned this pull request Nov 28, 2012
@bobthecow
Copy link
Owner Author

I'd use the dev branch rather than the lambda-helper-plus-plus feature branch. That branch is outdated and will most likely not be merged, as dev already contains the lambda helper.

@satyago
Copy link

satyago commented Nov 28, 2012

Thanks and done :) 🎱

@mdings
Copy link

mdings commented Dec 21, 2012

According to this Mustache can make use of helpers like so to, for instance, convert a title uppercase:

{{title|case.upper}}

I was just curious why this doesn't work for dynamic partials as well that were added through the addHelper method?

{{header|dynamic-partial}}

@bobthecow
Copy link
Owner Author

It should, but only if you're using the dev branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants