Render a Twig expression over an HTML string - php

This could sound a bit weird, but this is a special situation:
I have an HTML string in $content, and I want to render a stylesheet block in the head tag of this content. This is what I have:
$response = new Response();
$response->setContent($content);
$response->headers->set('Content-Type', 'text/html');
// returns the HTTP headers followed by the content
return $response;
and I want to add:
{% stylesheets output='compiled/css/*.css' 'css/all.less' %}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
Any idea of how could achieve it?
Edit:
As #CarlMarkham suggested, I tried:
$loader = new \Twig_Loader_Array(array(
'index.html' => $content."{% stylesheets output='compiled/css/*.css' 'css/all.less' %}
<link rel='stylesheet' href='{{ asset_url }}' />
{% endstylesheets %}",
));
$twig = new \Twig_Environment($loader);
return $twig->render('index.html');
but I got this error:
Unknown tag name "stylesheets" in index.html
Also tried this:
$loader = new \Twig_Loader_Array(array(
'index.html' => $content.'<link rel="stylesheet" href="{{ asset("compiled/css/*.css") }}">'
));
$twig = new \Twig_Environment($loader);
return $twig->render('index.html');
but I got:
The function "asset" does not exist in index.html

Take a look at Assetic. You should be able to build the html from within php (first code block click on the php tag). That example is for JS but it is the same concept for CSS. Now you have the string you can add it to the content.

Related

Translator component with twig trans

I am trying to have my twig templates translated using the Symfony Translator Component and .mo files. I used the i18n extention before but wanted a more reliable approach since locale handling for translations on Windows is a nightmare.
These class functions prepare the translation and template:
/**
* Constructor.
*
* #param string $template_dir
* #param string $locale
* #param string $locale_path
*/
public function __construct($template_dir, $locale, $locale_path)
{
$loader = new Twig_Loader_Filesystem($template_dir);
$this->parser = new TemplateNameParser();
$this->template = new \Twig_Environment($loader);
$this->translator = new Translator($locale);
$this->translator->addLoader('mo', new \Symfony\Component\Translation\Loader\MoFileLoader());
$this->translator->addResource('mo', $locale_path, $locale);
$this->template->addExtension(new TranslationExtension($this->translator));
}
/**
* Render template.
*/
public function render($name,$parameters=[]) {
return $this->template->loadTemplate($name,$parameters)->render();
}
Then i have this template:
<h1>{% trans 'Hello World!' %}</h1>
which throws this error:
Uncaught Twig_Error_Syntax: Unexpected token. Twig was looking for the
"with", "from", or "into" keyword.
Which i get because i am not adding the Twig_Extensions_Extension_I18n extension to twig environment. If i do that, the texts in trans functions are not translated because i am not using the filter as i should. For it to work i need to use the trans filter like so: {{ 'Some text'|trans }}.
Is there a way to make translation work with {% trans 'Some text' %} instead of {{ 'Some text'|trans }}? For example, can i add a custom trans function somewhere in the chain?
Note: I know that {% trans %}Some text{% endtrans %} works, but all my templates already use this syntax {% trans 'Some text' %}, and i would like to prevent having to rewrite everything.
The problem seems to stem from incompatible twig and symfony translator versions. But i am not sure tbh.
In my case, i solved the problem long-term by writing a simple script to replace the incorrect syntax with the correct one in each template file.
foreach (glob("your_template_path/*/*/*.twig") as $filename) {
$content = file_get_contents($filename);
$content = preg_replace_callback('/{% trans "[\s\S]+?" %}/',function($matches) {
$text = str_replace(['{% trans','%}','"'],'',$matches[0]);
return '{% trans %}'.trim($text).'{% endtrans %}';
},$content);
$content = preg_replace_callback('/{% trans \'[\s\S]+?\' %}/',function($matches) {
$text = str_replace(['{% trans','%}',"'"],'',$matches[0]);
return '{% trans %}'.trim($text).'{% endtrans %}';
},$content);
file_put_contents($filename,$content);
}
Maybe that helps someone.
Try this
"{% trans %}Hello World{% endtrans %}!"

Slimphp - Twig dynamic include

I need to include template dynamically in twig template. So the template will included the page that defined in routes.php
I try to concatenate string and variable like this code bellow, but still not working.
routes.php:
$app->get('/home', function ($request, $response, $args) {
$data['page'] = "home";
return $this->view->render($response, 'Home/layout.html', $data);
});
Home/layout.html:
{% include 'Home/_header.html' %}
{% include 'Home/_topbar.html' %}
{% include 'Home/_sidebar.html' %}
{% include 'Home/' ~ data.page ~ '.html' %}
{% include 'Home/_footer.html' %}
Error message:
Unable to find template "Home/.html" (looked into: ../App/Templates) in "Home/layout.html" at line 4.
I found my own solution, but it's not the one i want. So I edited routes.php and layout.html like this:
routes.php:
$app->get('/home', function ($request, $response, $args) {
$data['page'] = "{% include 'Home/home.html' %}";
return $this->view->render($response, 'Home/layout.html', $data);
});
Home/layout.html:
{% include 'Home/_header.html' %}
{% include 'Home/_topbar.html' %}
{% include 'Home/_sidebar.html' %}
{% include template_from_string(page) %}
{% include 'Home/_footer.html' %}
What I want is to send variable that contain name of the template file from routes.php, not the template syntax instead.
You are accessing the wrong variable. You are passing the following to twig,
$data['page'] = "home";
return $this->view->render($response, 'Home/layout.html', $data);
Which means to access the variable page inside twig you would just need to call page and not data.page as the array data is not even passed towards to your template
Which means your template should look like the following
{% include 'Home/_header.html' %}
{% include 'Home/_topbar.html' %}
{% include 'Home/_sidebar.html' %}
{% include 'Home/' ~ page ~ '.html' %}
{% include 'Home/_footer.html' %}
You could actually tell this by yourself when looking at the error message
Unable to find template "Home/.html"
As there is nothing in between Home/ and .html, this mean the variable data.page doesn't exist. I recommend to enable debug mode when developing then u would get an error you are trying to access an undefined variable

including css in Twig

I am pretty new to the template engine itself. I am wondering how I could include my css stylesheet using twig as it doesn't render the styles everytime I render it.
index.html including the css stylesheet.
<link href="style.css" rel="stylesheet" type="text/css">
<link href="icomoon/style.css" rel="stylesheet">
index.html showing the data (the data is shown correctly, just the css stylesheet, isn't rendering (or the design is not shown).
{% if sv_query.connect and sv_data.password == 0 %}
<center><img src="images/status/server-online.png"/><br/>Server is online!</center>
<center>Players: <font color=green><b>{{ sv_data.players }}</b></center>
{% elseif sv_data.password == 1 %}
<center><img src="images/status/server-warning.png"></br>The server is passworded (under construction).</center>
{% else %}
<center><img src="images/status/server-offline.png"></br>The server is offline, try again later!</center>
{% endif %}
A basic example of how I render the data. Index.php (twig)
require 'Twig/vendor/autoload.php';
$loader = new Twig_Loader_Filesystem('views');
$twig = new Twig_Environment($loader);
$ip = "127.0.0.1";
$port = "7777";
require("views/samp/samp_query.php");
$query = new SampQuery($ip, $port);
$info = $query->GetInfo();
echo $twig->render('index.html', array (
'sv_query' => $query,
'sv_data' => $info)
);
$query->close();
PS I am not using any plugins or templates engines other than twig as what I am doing right now is pretty basic, I just need to get the stylesheet to function properly, or to be included properly.
Thanks, Patrick!

How to programmatically set twig block content?

Is it possible to set the value of a twig template block from PHP code? I'm migrating from a different template engine and I need a bridge to set the value of blocks without using a twig template.
I've just got plain text that I was hoping to assign before I render the template.
If you want to include PHP files inside blocks, I suggest you to create an extension.
Sample
index.php
<?php
require(__DIR__ . '/../vendor/autoload.php');
$loader = new Twig_Loader_Filesystem('./');
$twig = new Twig_Environment($loader, array());
$function = new Twig_SimpleFunction('get_php_contents', function($file, $context) {
ob_start();
include($file); // $context is available in your php file
return ob_get_clean();
}, array('is_safe' => array('html')));
$twig->addFunction($function);
echo $twig->render('test.twig', array('name' => 'Alain'));
test.twig
{% extends 'base.twig' %}
{% block content %}
{{ get_php_contents('contents.php', _context) }}
{% endblock %}
base.twig
<html>
<div>I'm a base layout</div>
{% block content %}{% endblock %}
</html>
contents.php
<?php
echo '<div style="color:red">';
echo "Hello {$context['name']}, it is now: ";
echo date("Y-m-d H:i:s");
echo '</div>';
Result
<html>
<div>I'm a base layout</div>
<div style="color:red">Hello Alain, it is now: 2014-10-28 19:23:23</div>
</html>

How to append style sheet with close element using zend?

I am using zend. When i use below code,
<?= $this->headLink()
->appendStylesheet(BASE_URL . 'css/css.css');
?>
This outputs like below with out close element.
<link href="/ecomos3/css/css.css" media="screen" rel="stylesheet" type="text/css" >
so this one fails in w3 validation and getting "end tag for "link" omitted, but OMITTAG NO was specified"
i want the link tag should be
<link href="/ecomos3/css/css.css" media="screen" rel="stylesheet" type="text/css" />
How can i do it in zend ? Kindly advice on this.
You need to specify the docType using the doctype helper
You can do it in your bootstrap if you wish:-
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initDoctype()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$view->doctype('XHTML1_STRICT');
}
}
Or add this line to your config.ini file:-
resources.view.doctype = "XHTML1_STRICT"

Categories