How to get template source in php mustache engine - php

I am trying to get a raw template that is already loaded by Mustache_Engine. On creation of the mustache object Filesystem_Loader instance is set up and pointing to the default directory.
$mustache = new Mustache_Engine( array(
'loader' => new Mustache_Loader_FilesystemLoader( 'path-to-templates' )
) );
And later, for rendering the templates I use.
echo $mustache->render( 'template-name', $data );
The same template is used by mustache.js on server side, so i want to also print that template as inline script.
I could load the template from the filesystem manually with file_get_contents, but since that template is already loaded maybe there's a way to retrieve that from Mustache_Engine. Also, to use the file_get_contents i must use full path of the template and that just contradicts with the purpose of Mustache Template Loader.

After digging through the Mustache_Engine source, found the answer. getLoader() will get the current Mustache Template Loader instance, and load() function will load the template ( if is not already loaded ) and return it as string.
echo $mustache->getLoader()->load( 'template-name' );

Related

Drupal 8 custom module add php classes

I have created a custom Drupal 8 module that works as is with a custom block and block form to collect some info.
This is all good.
I also have a twig template that I want to render a twitter feed using a php feed class I bought. I just don't know how it integrate this into the module.
This is the setup for the class: http://austinbrunkhorst.com/demos/twitter-class/#setup
It contains two files:
ultimate.twitter.feed.php
and
tmhOAuth.php
Which is currently a require_once 'tmhOAuth.php'; in the head of ultimate.twitter.feed.php
According to the instruction I should be creating a php file that has this:
$options = array(
'screen_name' => 'FeedTestUser',
'consumer_key' => '...',
'consumer_secret' => '...',
'user_token' => '...',
'user_secret' => '...',
);
$twitter = new Twitter($options);
$twitter->PrintFeed();
Which I'm guessing is also a hurdle as twig files are not php
Any help with this is very much appreciated.
C
I would setup the class as a Service in your module. Your block will then implement that service and do the handling. You don't really want to use require_once() if you can avoid it, rather use Drupal constructs (in part so that if you reorganize things later Drupal will help find the files in their new location).
Place the class in your module's src directory, and add a namespace to the start of the file (assuming there isn't one there already). Then in your block's class file you should be able to add a use statement that references that name space (even better would be to use a dependency injection, but the details on that would get in your way here).
In your block class's build() method you then instantiate the class as described in your question, but instead of just letting the module print HTML, you can want to capture that HTML and place it into your block as markup. If the class allows you to do that without using a buffer, you should (but I didn't see anything in the docs to support that), and then attempt to theme the structured data. If not, you can use PHP's output buffering to capture its attempt to print:
ob_start();
$twitter->PrintFeed();
$content= ob_get_contents();
ob_end_clean();
Then place the generated markup into a render array:
return [
'my_twitter_block' => [
'#markup' => $content,
],
];
Create a custom block and add the result of PrintFeed() to the render array. Just as with any usual custom block. In the render array you can specify a template which should be used (if needed). If you wanna output pure html without any template you could use the '#markup' key.
Small example:
Your block render array:
return array(
'#theme' => 'name_of_your_theme',
'#some_twig_variable' => $twitter->PrintFeed();
);
your your_module.module file (in the root of your module folder):
function your_module_theme() {
return array(
'name_of_your_theme' => array(
'variables' => array(
'some_twig_variable' => some-default-value,
),
),
);
}
your name-of-your-theme.html.twig template (should be under your_module/templates):
{{ some_twig_variable }}
As far as using the class: I see no problem using a require_once for that matter (in your Block php file). Of course it's always better/nicer if you can require the library/package via the make file or composer and then use the autoloader, but if that's not possible just put it e.g. in your drupal root under /libraries/twitter or so and then require it. If you do it like that you have to check that library into your git repository obviously.
have you use ultimate.twitter.feed.php in your TwitterBlock.php file
If not then try adding this line before class block beginns:
require_once 'path/to/twitter_class/ultimate.twitter.feed.php';

pligg add module to story

in pligg adding new modules to the the main pligg template pligg.tpl is quite straight forward, however, i want to add a new module to the story. located in link_summary.tpl. the problem is that when the link summary template is created, a new variable $main_smarty is created with it's own local scope, not available to my modulename_main.php file. when I use the global $main_smarty variable, it refferences the main pligg template smarty object. So i have used to quick and somewhat dirty fix to the main architecture php code, to the link.php file I added a new call back:
$vars = '';
check_actions('add_to_summary', $vars);
and then created a new global variable refferencing the $main_smarty object in the link.php file, which i then used in my modulename_main.php
global $link_smarty;
global $link_variables;
$link_variables = $this;
$link_smarty = $main_smarty;
is there a more native, proper and cleaner way of doing this without tweaking the main architecture pligg code?
Not sure if this would be helpful.
An alternative way would be to write a new module and assign it to that particular page, in your case link_summary.
As you know, each module has an init file, something like your_module_init.php. In your case the init file would be similar to:
<?php
if(defined('mnminclude')){
include_once('your_module_settings.php');
$include_in_pages = array('link_summary');
$do_not_include_in_pages = array();
if( do_we_load_module() ) {
module_add_action('');
include_once(mnmmodules . 'your_module_name/your_module_main.php');
}
}
?>
Cheers,

Import an HTML file from inside a Twig template

I want to import an HTML file from inside a Twig template. The HTML file is located at /var/files/5 (with no extension). And I render the template like this:
$path = $_SERVER['DOCUMENT_ROOT'] . '/../var/files/5';
$content = $this->get('templating')->render('ProConvocationBundle:Default:definitive-view.html.twig', array('path' => $path));
Inside the Twig template I import the HTML file like this:
{% include path %}
but it is not finding the path: Unable to find template "/myDocumentRoot/../app/var/files/5"
I've also tried several relative paths without success. Any idea of how to achieve it?
What causes this exception?
After digging in the Twig code a little, the following seems to cause this exception:
Twig tries to load the file from a known path/namespace, being bundle names (like /var/www/myApplication/src/AcmeBundle/Resources/views) and the app path being myApplication/app/Resources/views). Anyway it doesn't accept absolute paths, since it always tries to add a known path to the beginning of the given file.
<?php
// Twig/Loader/Filesystem.php
class Twig_Loader_Filesystem {
// ...
protected function findTemplate()
{
// ...
foreach ($this->paths[$namespace] as $path) {
if (is_file($path.'/'.$shortname)) {
return $this->cache[$name] = $path.'/'.$shortname;
}
}
throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])));
}
So it basically isn't possible to include a file by an absolue path, like in your example.
How to solve this?
You've got a bunch of possibilities to achieve this behaviour:
Add the path to the template loader
See post by #Adam Elsodaney
Move the file
You could simply move your file from app/var/files to app/Resources/views/var/files and use the path var/files/5 to include the file. This is probably not a suitable solution, since you want to keep those files in place.
Write a Twig Extension
You could write your own extension that provides a function named something like include_absolute() that simply returns file_get_contents($yourPath).
More on Twig extensions: http://symfony.com/doc/current/cookbook/templating/twig_extension.html
Be aware that you would might need to add the |raw filter to the output of the Twig function since a lot of stuff gets escaped everywhere.
In Symfony, you should make everything relative to the Kernel root directory which is the app directory.
$uploadedTemplatesDir = $this->get('kernel')->getRootDir() . '/../var/files';
Then add this to your templating loader
$this->get('twig.loader')->addPath($uploadedTemplatesDir);

CakePHP + TinyButStrong

Anyone tried using TinyButStrong together with CakePHP?
I have no prior knowledge of TinyButStrong but seems to be a good way to generate Word documents from templates. But I am not sure how to integrate this with a CakePHP application.
Thank you for any ideas / suggestions.
Best regards,
Tony.
I presume you mean TinyButStrong with the OpenTBS plug-in which can merge DOCX (and other Ms Office and OpenOffice documents) using templates.
Here is a way to add an export action in a CakePHP Controller which is destined to generate a Docx to be downloaded.
The following code is available for CakePHP version 1.3, it is not tested with version 2.0.
Steps :
1) Add the TBS and OpenTBS classes in the vendor directory, under a subdirectory:
vendors/tbs/tbs_class.php
vendors/tbs/tbs_plugin_opentbs.php
2) Create a CakePHP helper that will simplify the preparation of TBS + OpenTBS:
app/views/helpers/tbs.php
<?php
class TbsHelper extends AppHelper {
function getOpenTbs() {
App::import('Vendor', 'tbs/tbs_class');
App::import('Vendor', 'tbs/tbs_plugin_opentbs');
$tbs = new clsTinyButStrong; // new instance of TBS
$tbs->Plugin(TBS_INSTALL, OPENTBS_PLUGIN); // load OpenTBS plugin
return $tbs;
}
}
3) Now add a new "export" action in the controller that should generate the Docx:
app/controllers/example_controller.php
<?php
class ExamplesController extends AppController {
var $name = 'Examples';
function export() {
// Stop Cake from displaying action's execution time, this can corrupt the exported file
// Re-ativate in order to see bugs
Configure::write('debug',0);
// Make the Tbs helper available in the view
$this->helpers[] = 'Tbs';
// Set available data in the view
$this->set('records', $this->Example->find('all'));
}
}
4) The last thing is to create the corresponding view. Don't forget to place your DOCX template in the same folder as the view.
app/views/examples/export.ctp (below)
app/views/examples/export_template1.docx (to build with Ms Office)
<?php
ob_end_clean(); // Just in case, to be sure
// Get a new instance of TBS with the OpenTBS plug-in
$otbs = $tbs->getOpenTbs();
// Load the DOCX template which is supposed to be placed in the same folder
$otbs->LoadTemplate(dirname(__FILE__).'/export_template1.docx');
// Merge data in the template
$otbs->MergeBlock('r', $records);
// End the merge and export
$file_name = 'export.docx';
$otbs->Show(OPENTBS_DOWNLOAD, $file_name);
exit; // Just in case, to be sure
TinyButStrong gives facilities to merge PHP global variables, but it is recommended to not use such feature within CakePHP. Instead, you should use MergeBlock() and MergeField() with the data set by the Controller for the View.
If you met bugs, don't forget to disable the line
Configure::write('debug', 0);
and this will show you the CakePHP errors. Otherwise CakePHP will hide all errors including PHP errors.
Don't forget that OpenTBS has also a debug mode. See the manual if needed.
You can also make this a lib (to be used anywhere in your application).

How do I load a module specific custom helper from a task in symfony?

I'm rendering a partial from inside a task in symfony 1.4.6...
$this->configuration = $this->createConfiguration(app, env, false);
$this->configuration->loadHelpers(array('Partial'));
$context = sfContext::createInstance($this->configuration);
$html = get_partial(partialName, params);
...Inside the partial there is a reference to a custom helper, which can't be referenced from the default context, so an exception is throw...
Unable to load "fooHelper.php" helper in: SF_ROOT_DIR/apps/frontend/lib/helper, SF_ROOT_DIR/lib/helper, SF_ROOT_DIR/lib/vendor/symfony/lib/helper.
...And attempting to load the custom helper from the task referencing the module name in loadHelpers doesn't seem to fix the issue either...
$this->configuration->loadHelpers(array('Partial'), moduleName);
The helper I am trying to load is specific to the module, I don't really want to move it to one of the default project helper directories listed in the exception above. Any help would be appreciated!
Please have a look at the content of the HelperHelper.php helper file.
use_helper() can be used in a partial, so I guess putting this piece of code on top of the partial would do the job:
$context = sfContext::getInstance();
$context->getConfiguration()->loadHelpers(array('Custom'), 'moduleName');

Categories