Include content of CSS file in twig - css

Let's say I use Webpack, and builded a Css file properly at "build/theme/mail.css".
I wants to include the CONTENT of this File into my twig.
{% include "https://mysite.io/build/theme/mail.css" %} doesn't work saying it can't find the file ( but it exist).
I don't want that because im using an inliner, and absolutly need the #CONTENT in my twig.

Tried the File get Content, didn't works. Found a solution:
twig:
paths:
'%kernel.project_dir%/public': public
Add a twig path to public directory
and then use :
{% apply inline_css(source(theme_asset('#public/build/theme/email.css'))) %}
and add a webpackconfig to build the scss file into public/build
Thanks you all.

You could create custom twig extension and use file_get_contents.
Extension:
<?php
namespace App\Twig;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class GetPublicFileContentExtension extends AbstractExtension
{
/** #var string */
private $publicPath;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->publicPath = $parameterBag->get('kernel.project_dir') . '/public/';
}
public function getFunctions(): array
{
return [
new TwigFunction('get_public_file_content', [$this, 'getPublicFileContent']),
];
}
public function getPublicFileContent(string $filepath)
{
return file_get_contents($this->publicPath . $filepath);
}
}
Twig:
{{ get_public_file_content('build/theme/mail.css') }}

Related

Substring Count in Twig

I am looking to use substr_count in Twig, does anything exist already? I want to perform something like this;
<?php
$text = 'This is a test';
echo strlen($text); // 14
echo substr_count($text, 'is'); // 2
I can do an extension but it seems this might be something built in already that I have missed.
How about this?
{%set count = text|split('is')|length-1 %}
This doesn't exist in the list of Twig functions or filters.
You'll have to write your own custom function/filter or try a package (note; I've never used this package so can't comment on it, but was on the first page of Google results).
I went for an extension
namespace AppBundle\Twig;
class SubStrCountExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('substr_count', array($this, 'substr_count')),
);
}
public function getName()
{
return 'substr_count_extension';
}
public function substr_count($str, $char)
{
return substr_count($str, $char);
}
}
And in services.yml
app.twig_extension.substr_count_extension:
class: AppBundle\Twig\SubStrCountExtension
tags:
- { name: twig.extension }
I use solution in Symfony 3.2.8 but in the description does not say this block of code should is inside : services
If you does not make show this error:
There is no extension able to load the configuration for .....
This code should is inside services this is correct:
services:
app.twig_extension.substr_count_extension:
class: AppBundle\Twig\SubStrCountExtension
tags:
- { name: twig.extension }
Finally, the correct use in twig is:
tu placa es: {{substr_count(datos.picoyplaca,4)}}
Regards

Why symfony can't find template it rendered in other function

I have a function in my controller like this:
<?php
namespace GradeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use GradeBundle\Entity\User;
use GradeBundle\Entity\SchoolClass;
class MainController extends Controller
{
/**
* #Route("/", name="index_page")
*/
public function index()
{
return $this->render('GradeBundle:Default:index.html.twig');
}
It renders the twig template correctly. However when I use other function:
/**
* #Route("/adminNew", name="add_admin")
*/
public function addAdmin()
{
$session = new Session();
if($session->get('loggedIn') == null)
return $this->redirect($this->generateUrl('index_page'));
else
return $this->render('GradeBundle:Add:newAdmin.html.twig');
}
I have the following error:
Unable to find template "GradeBundle:Default:index.twig.html".
Does anybody have any idea what might be wrong?
It's a typo somewhere you call template:
GradeBundle:Default:index.twig.html
But you have only GradeBundle:Default:index.html.twig template.
Note the difference: html.twig twig.html
I suspect that you extend it in GradeBundle:Add:newAdmin.html.twig by:
{% extends 'GradeBundle:Default:index.twig.html' %}
but should be:
{% extends 'GradeBundle:Default:index.html.twig' %}
Have you made sure to use the correct namespace for the Controller you're using? And are you including the correct files? Also I'm not sure I understand the question correctly - are you saying if you add another function with a different twig file render, the first one no longer renders? Could I see your class names and the namespaces / use statements?
Usually in these instances, it's that the templates are in the wrong place or the correct file is not included in order to find it.
Michael

Split function not working in Twig

what i Need :
Split the string.
i Need first Character from the String.
if the string certain character limit i like to show only first name not by(...).
ex: ankit mishra pandit aggarwaal.
- so i just want only ankit.
- if its is ankit mishra its ok.
* otherwise show Full Name.
Here is the twig code:
{%if item.metadata.name |length < 20 %}
{% set foo = item.metadata.name|split(',') %}
{{ foo[0] }}
{%else%}{{WordLimit(item.metadata.name,20,10)}} ..
{%endif%}
output im getting :
Deepak Singh.
i have refer Source: Twig Split filter http://twig.sensiolabs.org/doc/filters/split.html.
where i have done wrong.
I think the best solution is to write a twig extension.
See http://symfony.com/doc/current/cookbook/templating/twig_extension.html
class AcmeExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('first_word', array($this, 'first_word')),
);
}
public function first_word($word)
{
$words = explode(' ', $word);
$first_word = $words[0];
...
return $first_word;
}
public function getName()
{
return 'acme_extension';
}
}
And if your twig file :
{{item.metadata.name | first_word }}

How to use Assetic with CacheBustingWorker and twig

As i can see Assetic made some progress on CacheBusting:
https://github.com/kriswallsmith/assetic#cache-busting
But i dont really understand how i should use this.
Can this be used from within twig:
{% stylesheets 'bundles/mybundle/css/fonts.css'
'bundles/mybundle/css/style.css'
'bundles/mybundle/css/screen.css'
filter='cssrewrite'
%}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
{% endstylesheets %}
And with the usual assetic:dump command?
Where would i have to hook the CacheBustingWorker in?
Cache buster is now part of symfony/AsseticBundle (Version >= 2.5.0).
Change AsseticBundle version in composer.json like that:
"symfony/assetic-bundle": "2.5.0",
And activate cache busting for assets in your config.yml file like that
assetic:
workers:
cache_busting: ~
My JS files are now looking like that:
web/bundles/js/projectname-876f9ee.js
See https://github.com/symfony/AsseticBundle/pull/119#issuecomment-28877145
I have been recently looking how to do the same.
The solution I came up with was to override Symfony's AssetFactory with my own class and add the CacheBustingWorker in its constructor. Basically you create a file like the following:
<?php
namespace YourSite\YourBundle\Factory;
use Symfony\Bundle\AsseticBundle\Factory\AssetFactory as BaseAssetFactory;
use Assetic\Factory\Worker\CacheBustingWorker;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class AssetFactory extends BaseAssetFactory
{
public function __construct(KernelInterface $kernel, ContainerInterface $container, ParameterBagInterface $parameterBag, $baseDir, $debug = false)
{
parent::__construct($kernel, $container, $parameterBag, $baseDir, $debug);
// Add CacheBustingWorker
$this->addWorker(new CacheBustingWorker(CacheBustingWorker::STRATEGY_CONTENT));
}
}
and then change the assetic.asset_factory.class parameter to point to this new class in your config. In my case I added the following to config.yml:
parameters:
assetic.asset_factory.class: YourSite\YourBundle\Factory\AssetFactory
With the current implementation of assetic, I needed to update your code to the following to get this to work. Also note if you are using xdebug, you must up the max nesting level - xdebug.max_nesting_level = 200 to more than 100.
<?php
namespace YourSite\YourBundle\Factory;
use Symfony\Bundle\AsseticBundle\Factory\AssetFactory as BaseAssetFactory;
use Assetic\Factory\LazyAssetManager;
use Assetic\Factory\Worker\CacheBustingWorker;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class AssetFactory extends BaseAssetFactory
{
public function __construct(KernelInterface $kernel, ContainerInterface $container, ParameterBagInterface $parameterBag, $baseDir, $debug = false)
{
parent::__construct($kernel, $container, $parameterBag, $baseDir, $debug);
// Add CacheBustingWorker
$this->addWorker(new CacheBustingWorker(new LazyAssetManager(new BaseAssetFactory($kernel, $container, $parameterBag, $baseDir, $debug))));
}
}
Hope this helps someone
As the assetic code changed again, there is no need of Stategy on LazyAssetManager on the master branch.
Do not forget to change your composer.json file:
{
"kriswallsmith/assetic": "dev-master#dev",
"symfony/assetic-bundle": "dev-master#dev"
}
You now just need this:
namespace YourSite\YourBundle\Factory;
use Symfony\Bundle\AsseticBundle\Factory\AssetFactory as BaseAssetFactory;
use Assetic\Factory\Worker\CacheBustingWorker;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class AssetFactory extends BaseAssetFactory
{
public function __construct(
KernelInterface $kernel,
ContainerInterface $container,
ParameterBagInterface $parameterBag,
$baseDir,
$debug = false
) {
parent::__construct($kernel, $container, $parameterBag, $baseDir, $debug);
// Add CacheBustingWorker
$this->addWorker(new CacheBustingWorker());
}
}
Do not forget to php app/console cache:clear -e prod before dumping assets one time to avoid standard filenames to be generated.
assetic:
workers:
cache_busting: ~
Is the answer.

transfer data in symfony2

I have created two functions in controller of Symfony as follow:
first is newAction
public function newAction()
{
return $this->render('AcmeTaskBundle:Default:index.html.twig');
}
then subAction
public function subAction()
{
echo "hello";
}
I want to use some data from index.html.twig into subAction function.
How I can do that?
All you need is to use
$content = $this->renderView('AcmeTaskBundle:Default:index.html.twig')
This will render contents of template in variable
http://symfony.com/doc/current/book/controller.html#rendering-templates
EDIT according to comment
If you need to render only part of template - then you should refactor your templates.
Exclude that part of code from your index.html.twig into separate template file and include it in index.html.twig:
...
{% include 'AcmeTaskBundle:Default:subpage.html.twig' %}
...
And then in your subAction() call:
$content = $this->renderView('AcmeTaskBundle:Default:subpage.html.twig')

Resources