Symfony2 Twig custom filter in asset - symfony

I'm nearly new in Symfony2 and I have a little question:
I'm developing an email template, which has txt and html parts (no problem with it)
The only 'problem' I have is with the absolute paths of assets in TWIG.
Inside my email.html.twig file I have something like this:
<img src="{{ asset('images/my-image.png') }}" alt="My image" /> but it writes the route with relative path.
I discovered a little solution to add absolute paths, something like this:
{% set abs = app.request.scheme ~ '://' ~ app.request.host %}
<img src="{{ abs ~ asset('images/my-image.png') }}" alt="My image" />
It works! But I want to improve this solution and also learn to create custom filters (I read the documentation, but I got a bit lost)
I want to create something like this:
<img src="{{ asset('images/my-image.png' | absolute) }}" alt="My image" />
But I don't know how to properly override the assetics extension. Can you help me?
Thanks a lot!!

Well, it is a little hard to copy paste the solution but I can make a short cookbook so you can go step by step and do it yourself:
1) You will have to implement Assetic/Filter/FilterInterface
2) If you look at the FilterInterface class, you will see that you have to to implement two methods: filterLoad and filterDump.
So, you will do something like this:
<?php
namespace You\YourBundle\Assetic\Filter;
use Assetic\Asset\AssetInterface;
use Assetic\Filter\FilterInterface;
class YourAsseticFilter implements FilterInterface
{
public function filterLoad(AssetInterface $asset)
{
// do something
}
public function filterDump(AssetInterface $asset)
{
$content = $asset->getContent();
// do something
$asset->setContent($content);
}
}
And after you to this, you have to something very similar to registering twig extensions in services.yml in YourBundle. Sure, it depens if you use YML, XML... configuration. I use yml so I will type it in yml :)
parameters:
your_bundle.class: You\YourBundle\Assetic\Filter\YourAsseticFilter
services:
your_bundle.assetic.your_assetic_filter:
class: %your_bundle.class%
tags:
- { name: assetic.filter }
- { alias: yourChosenNameForYourNewAsseticFilter }
And then you call it like | yourChosenNameForYourNewAsseticFilter, of course.

Related

Generation logo image in email

I have a problem with link generation when I try to send emails.
In my .env file :
WEB_LOGO="http://test.loc/build/images/logo.png"
In my twig.yml
twig:
globals:
web_logo: '%env(WEB_LOGO)%'
My email template :
<img align="center" alt="" src="{{ web_logo }}" height="30">
The problem is that when I open folder /build/images the logo image is like this :
http://test.loc/build/images/logo.12345.png
But I generate like :
http://test.loc/build/images/logo.png
I can't use the generation like {{ absolute_url(asset('build/images/logo.png')) }} be cause I sendind email using an external service and I'm limited. Help please !
I don't know if there is a better way to do it but I would use the Finder component to get the filename like that:
$finder = new Finder();
$directory = 'http://test.loc/build/images';
$name = 'logo';
$finder->in($directory)->name("/{$name}/")->files();
$logoFile = iterator_to_array($finder, false)[0];
$logoPath = $logoFile->getRealPath();
Then you can pass the $logoPath variable as argument to your twig template.
Of course there will be a problem if you have multiple logo files like 'logo.1.png' and 'logo.29.png' etc.

Use LiipImagineBundle without filters

I'm using LiipImagineBundle in my Symfony2 project and everything is working great. I've defined a thumbnail filter:
<img src="{{ 'bundles/app/images/home/warning.jpg'|imagine_filter('thumb_home') }}" alt="Warning" />
And it works perfectly, but some of my images don't need any filter, so I've tried to remove the filter:
<img src="{{ 'bundles/app/images/home/warning.jpg'|imagine_filter('') }}" alt="Warning" />
<img src="{{ 'bundles/app/images/home/warning.jpg'|imagine_filter() }}" alt="Warning" />
**edited to correct the example as malcolm points out
But it doesn't work, so I need to use Assetic for these images:
{% image '#AppBundle/Resources/public/images/example.jpg' %}
<img src="{{ asset_url }}" alt="Example" />
{% endimage %}
I can't find in the documentation of the bundle any option which allows me to use the Bundle without filters. Is that true? Of course, I can use the LiipImagineBundle way to include images when they need a filter and the Assetic way when they don't, but switching between two different ways of achieving almost the same thing is pretty annoying.
Silly answer to your question - create an original size filter then :). Something like this:
class OriginalSizeFilter implements LoaderInterface
{
public function load(ImageInterface $image, array $options = [])
{
$size = $image->getSize();
$origWidth = $size->getWidth();
$origHeight = $size->getHeight();
$filter = new Thumbnail(new Box($origWidth, $origHeight));
$image = $filter->apply($image);
return $image;
}
}
service:
original_size_filter:
class: ...\OriginalSizeFilter
tags:
- { name: liip_imagine.filter.loader, loader: original_size_filter }
config.yml:
filter_sets:
original:
filters:
original_size_filter: ~
Usage:
<img src="{{ 'bundles/app/images/home/warning.jpg'|imagine_filter('original') }}" alt="Warning" />
But, why not use a asset() function if you don't want any filters to be applied?

How to get the absolute path of a file in a Symfony2 controller?

I want to send an email with an attachement so therefore I need the absolute path to the pdf file.
I tried the flowing code in the controller:
$this->get('templating.helper.assets')->getUrl('MyDoc.pdf', 'doc');
But this returns:
/bundles/MyBundle/doc/MyDoc.pdf?v=1
This is the path without the domain for web access. But I need the real path starting the root of the disk, like example below. How is this possible? Thanks.
/home/MyAccount/public_html/web/src/company/MyBundle/Resources/public/doc/MyDoc.pdf
$this->get('templating.helper.assets') asset helper is about HTTP URI, not directory path.
However, you can easily get the right absolute directory web path like this:
$appPath = $this->container->getParameter('kernel.root_dir');
$webPath = realpath($appPath . '/../web');
$webPath should return something like this:
/home/martins/www/symfony-project/web
A bit of a cheat sheet for anyone else looking for different URL/URI paths for different applications.
Using the Symfony\Component\HttpFoundation\Request component, there are lots of different ways you can call upon this.
Consider this link http://dev.col.com/app_dev.php/my-route?bar=1&foo=bar
$r = $this->getRequest();
$r->getClientIp() 127.0.0.1
$r->getScriptName() /app_dev.php
$r->getPathInfo() /my-route
$r->getBasePath() ''
$r->getBaseUrl() /app_dev.php
$r->getScheme() http
$r->getPort() 80
$r->getHttpHost() dev.col.com
$r->getRequestUri() /app_dev.php/my-route?bar=1&foo=bar
$r->getBaseServerUrl() http://dev.col.com
$r->getUri() http://dev.col.com/app_dev.php/my-route?bar=1&foo=bar
$r->getUriForPath("/other-path") http://dev.col.com/app_dev.php/other-path
$r->getQueryString() bar=1&foo=bar
$r->isSecure() false
$r->getHost() dev.col.com
$r->getMethod() GET
$r->isXmlHttpRequest() false
Or you can do it in Twig as well. For example:
<div>
<a href="{{ job.url }}">
<img src="{{ app.request.scheme ~ '://' ~ app.request.host }}{{ asset(job.webPath) }}" alt="{{ job.company }} logo" />
</a>
</div>
<div>
<a href="{{ job.url }}">
<img src="{{ app.baseServerUrl }}{{ asset(job.webPath) }}"alt="{{ job.company }} logo" />
</a>
</div>
use Symfony\Component\Finder\Finder;
$finder = new Finder();
$finder->files()->in("dir")->name("name.file");
foreach ($finder as $file) {
// Dump the absolute path
var_dump($file->getRealPath());
}
From Docs: http://symfony.com/doc/current/components/finder.html

In TWIG, is possible to get absolute url of a link with twig variables in it?

I have several URLs that look as follows:
{{domainID}}/action/{{userId}}/anotherAction
And the latter URL points to:
http://localhost/viewA/{{domainID}}/action/{{userId}}/anotherAction
However, If I try to load viewA from viewB through an iframe, the link inside viewA instead of pointing to:
http://localhost/viewA/{{domainID}}/action/{{userId}}/anotherAction
it will point to:
http://localhost/viewB/{{domainID}}/action/{{userId}}/anotherAction
and the user will end up in a 404 page if it follows the latter.
My question is:
Is there anyway to get the absolute path of a url built that way in twig?
EDIT
The route definition is:
#Route("/domain/details/{domainId}", name="domain_detailed_view")
I tried to get the absolute path this way:
{{ url({{domainID}}/action/{{userId}}/anotherAction) }}
but I get this error:
A hash key must be a quoted string, a number, a name, or an expression
enclosed in parentheses
The url or path functions take the route name, not the path. You can give it an associative array as an optional second argument if the route requires parameters.
For example:
{{ url('domain_detailed_view', { 'domainId': domainId, 'userId': userId }) }}
http://symfony.com/doc/master/reference/twig_reference.html
I know it's old and answered, but with symfony 3 & twig you can do:
{{ app.request.getSchemeAndHttpHost() }}
/* will match even port :) i.e.
* http://localhost:8000
* http://localhost
* http://example.com
*/
which is extremely helpful :D
You have two ways to do the same thing.
Generally you could use url() or path inside absolute_url function like so absoulute_url(path(...)). Consider the following:
// example 1:
{{ url('domain_detailed_view', { 'domainId': domainId, 'userId': userId }) }}
// example 2:
{{ absolute_url(path('domain_detailed_view', { 'domainId': domainId, 'userId': userId })) }}">
// note - those two do the same thing
Generally since Symfony 2.7 you could use absolute_url() with asserts and relative path also (relative to web/root folder). This is how you could use them to set absolute path to image in bundle and in main web folder:
[app/src/UserBundle/Resources/public/img/image.jpg]
<img src="{{ absolute_url(asset('bundle/user/img/image.jpg')) }}" /> // new way since 2.7 up
<img src="{{ asset('bundle/user/img/image.jpg', absolute: true ) }}" /> // old way below 2.7 removed in symfony 3.0
[web/css/img/some.jpg]
<img src="{{ absolute_url('css/img/some.jpg') }}" />
This is what symfony recommends to use while rendering email view.
http://symfony.com/doc/current/email.html

Symfony 2 - Create link to uploaded assets

How can I link to uploaded assets dynamicaly with Symfony 2 and twig? I have a Controller that uploads files to the folder /web/uploads/entityName/fileName. In the template I'm trying to use the asset(document.path) function to create a link to the images. The problem is that the function returns the a path of /web/fileName. How can I add the missing path parameters (uploads/documents)?
Use the Twig string concatenation operator "~", like this:
asset('uploads/documents'~document.path)
You can send the url to Twig from the controller.
// Controller
$twig_params = array('uploadedURL' => $uploadedURL);
$this->render('VendorBundle:someTemplate.html.twig', $twig_params)
// Twig
<img src="{{ uploadedURL }}" />

Resources