How to get image metadata from ACF gallery images? - timber

I wanted to display image metadata of images from a gallery added with Advanced Custom Fields, is that possible?
So far, I've tried this (and a few other things too which didn't work either):
front-page.php
<?php
/**
The front page template file
*/
$context = Timber::get_context();
$post = Timber::query_post();
$context['post'] = $post;
Timber::render( 'home.twig', $context );
home.twig
{% extends "base.twig" %}
{% block content %}
{% for image in post.get_field('gallery') %}
{{ post.wp_get_attachment_metadata(TimberImage(image).id) [image_metadata][aperture] }}
{% endfor %}
{% endblock content %}
Thanks for your answer, I hope you can help me! :)

the meta data that you want should be available when converting to a TimberImage object so....
{% for image in TimberImage(post.get_field('gallery')) %}
{{ image|print_r }}
{% endfor %}
The print_r filter will output all the values on the object. That said, if you specifically want the array that WP normally the "fix" for your code would likely be...
{% for image in post.get_field('gallery') %}
{{ function('wp_get_attachment_metadata', TimberImage(image).id). image_meta.aperture }}
{% endfor %}
I say "likely" because the above is untested — give it a shot and let me know!

Related

Issue with Post Object Timber/Twig WordPress

I have an ACF field, It's a Repeater, and inside the Repeater is a Post Object.
Controller
/* Template Name: Strategic Partners */
use Timber\Timber;
use Timber\PostQuery;
use Flynt\Utils\Options;
use const Flynt\Archives\POST_TYPES;
$context = Timber::get_context();
$context['slider'] = get_field('slider');
$context['featured'] = get_field('featured');
if (isset($_GET['contentOnly'])) {
$context['contentOnly'] = true;
}
Timber::render('templates/StrategicPartners/index.twig', $context);
Here's the snippet from the View
{% for partner in Post(featured) %}
{{ partner.link }}
{% endfor %}
I'm var_dumping the context, and it's getting the Timber Post... but {{ partner.title }} does not grab the Post Title, it's blank.
{{ partner.link }} comes out with the direct link.
Output
http://***/strategic-partners/
http://***/strategic-partners/
What am I doing wrong here? I'm using {{ Post() }}} within a seperate repeater, within for foreach itself and that works on another page, but it does not work here either, so I tried Post() included in the foreach and it still is not working.
No one answered this for me. I answered it myself.
There isn't much documentation on this within the formal Timber documentation so I hope this helps somebody.
Do not call Post with your foreach
Do this for a Post Object within a Repeater (ACF)
{% for item in seq %}
{{ Post(item.post_object_name).field }}
{% endfor %}
seq is your ACF Field
post_object_name is the Post Object within the field.
field is the field within the Post Object type.
Hope this helps someone.
For more Context:
Controller
<?php
/* Template Name: Strategic Partners */
use Timber\Timber;
use Timber\PostQuery;
use Flynt\Utils\Options;
use const Flynt\Archives\POST_TYPES;
$context = Timber::get_context();
$context['slider'] = get_field('slider');
$context['featured_sps'] = get_field('featured_strategic_partners');
$context['rebate'] = get_field('rebate_information');
if (isset($_GET['contentOnly'])) {
$context['contentOnly'] = true;
}
Timber::render('templates/StrategicPartners/index.twig', $context);
Twig View
{% for partner in featured_sps %}
{{ Post(partner.featured).title }}
{% endfor %}
Images are more complex
{% for partner in featured_sps %}
<div class="slide">
<a href="{{ Post(partner.featured).link }}">
<img src="{{ Image(Post(partner.featured).logo).src }}" alt="{{ Post(partner.featured.title) }} Logo">
</a>
</div>
{% endfor %}

Add posts with timber twig into an include

On a single page, I need to add an include, on the bottom of the page, that add 3 projects.
I have a content type called projects I made with ACF.
single-project.twig
I have a "single-project.twig" page that display the content of a post (which is also a project). At the bottom of this page, I need to add a block like this:
{% block related %}
{% include 'inc-related.twig' %}
{% endblock %}
inc-related.twig
Into "inc-related.twig", I have this:
{% for post in related_posts %}
{% if post.thumbnail %}
<a href="{{post.link}}" class="l-basicgrid-work work">
<article>
<figure>
<img data-src="{{post.get_thumbnail.src('medium_large')|resize(800, 533)}}" alt="{{post.title}}" class="lazy">
</figure>
<figcaption>
<h2>{{ post.title }}</h2>
</figcaption>
</article>
</a>
{% endif %}
{% endfor %}
related.php
I also create a "related.php" page, that integrate the following rendering:
$context = Timber::get_context();
$context['related_posts'] = Timber::get_posts('post_type=project&posts_per_page=3');
Timber::render('inc-related.twig', $context);
Questions
I have 2 questions:
The project are not displaying into the single page. What I have done
wrong?
Can I select 3 project except the one who is displayed on the
single page?
Thank you
you have include twig template but not send data to him. Your related.php is not include automatically. You should write $context['related_posts'] = Timber::get_posts('post_type=project&posts_per_page=3'); in your single-project.twig. And do not use post name in inc-related.twig. May be conflict with current post object.
To single-project.php add $context['related_posts'] = Timber::get_posts('post_type=project&posts_per_page=3');
This is what I did.
single-project.php
I have created a single-project.php page. It contains the following script:
$context = Timber::get_context();
$args = array(
// Get post type project
'post_type' => 'project',
// Get 3 posts
'posts_per_page' => 3,
// Order random
'orderby' => 'rand',
);
$context['related_posts'] = Timber::get_posts( $args );
Timber::render('single-project.twig', $context);
single-project.twig
On my single-project.twig, I have the code that get the result of the php page. Actually, that code is included into an "inc-related.twig" page. And it works!
{% for post in related_posts %}
{% if post.thumbnail %}
<a href="{{post.link}}" class="l-basicgrid-work work">
<article>
<figure>
<img data-src="{{post.get_thumbnail.src('medium_large')|resize(800, 533)}}" alt="{{post.title}}" class="lazy">
</figure>
<figcaption>
<h2>{{ post.title }}</h2>
</figcaption>
</article>
</a>
{% endif %}
{% endfor %}
But on the same page (single-project.twig), I also have data that display content from Advanced Custom Field.
{% if post.project_images %}
{% for item in post.get_field('project_images') %}
<figure class="{{item.project_media_css}}">
<img data-src="{{TimberImage(item.project_media).src}}" alt="{{item.alt_media}}" class="lazy">
</figure>
{% endfor %}
{% endif %}
The problem now is that the ACF field don't return anything.
How should I modify single-project.php to get content from "related_project" and ACF field?
The ACF context is passed to the single page template via Timber $context, using the get_posts function.
single-project.php
$context['related_posts'] = Timber::get_posts('post_type=project&posts_per_page=3');
Twig sends along the active context by default, so this template is fine as-is.
{% block related %}
{% include 'inc-related.twig' %}
{% endblock %}
Finally, the posts in $context['related_posts'] can be looped over. However, within the for loop, refer to each post by anything other than post, such as rel_post. This avoids conflict with the regular post object.
{% for rel_post in related_posts %}
{% if rel_post.thumbnail %}
...
{% endif %}
{% endfor %}

Timber Wordpress child menu

I am looking for a way to display all child pages of the current page, similar to the wp_page_list function, but in Timber (Twig).
I know I can either add to the context via a query, or simply wrap the worpdress function in a timber function.
Either method I am struggling with and would appreciate some syntax guidance.
Many thanks.
Not sure how ideal this is, but it does the trick
{% for item in menu.get_items %}
{% if item.get_children and post.link == item.url %}
<ul class="jumbo-menu {{ post.slug | replace({'-data':''})}}">
{% for child in item.get_children %}
<li>{{child.title}}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
Are you trying to display child pages without using a WordPress menu? So without the get_items method? The children of a given page are available via the post object, irrespective of any menu functions.
{% for child in post.children %}
<li>{{ child.title }}</li>
{% endfor %}
This assumes $context['post'] = new TimberPost(); in your controller.

symfony2: Applying theme to individual field for collection type

Just applying a theme to form field is easy e.g.:
{% form_theme form _self %}
{% block _product_name_widget %}
{{ block('field_widget') }}
{% endblock %}
but what if the form field is of collection type? E.g.: product['models'][1][comment,
I have no ideas how to customize it. (This may be the first kind question here)
UPDATE: anwser here: Symfony2: collection form field type with data-prototype
As of Symfony 2.1 (it may work as well for 2.0 but not sure) to apply theme for collection you do this way:
Lets say we have a collection of products (we have multiple Product entities)
Controller:
$repository = $this->getDoctrine()->getRepository('ExampleBundle:Product');
$products = $repository->findAll();
$productCollection = new Products;
foreach ($products as $product) {
$productCollection->getProducts()->add($product);
}
$collection = $this->createForm(new ProductsType, $productCollection);
return $this->render('ExampleBundle:Default:index.html.twig', array(
'collection' => $collection->createView()
));
Your theme can look like this:
{% block _productsType_products_entry_name_row %}
<div class="yourDivName">{{ block('form_widget') }}</div>
{% endblock %}
{% block _productsType_products_entry_description_row %}
<div class="yourDivDescription">{{ block('form_widget') }}</div>
{% endblock %}
The trick is with "entry" where twig will do the job for you to apply above changes to each row and for each field you specify
Hope that helps!
You can do with override collection_widget block:
{% block collection_widget %}
{% spaceless %}
{% if prototype is defined %}
{% set attr = attr|merge({'data-prototype': form_row(prototype) }) %}
{% endif %}
{{ block('form_widget') }}
{% endspaceless %}
{% endblock collection_widget %}
If you want how to customize form collection type try to look at this Product Bundle
You can override the collection_widget theme for a single field by referencing the widget like this as well.
For example, if "categories" is a "collection" widget on a ProductType form, you can do this.
{% block _product_categories_widget %}
{% for child in form %}
{{- form_row(child) -}}
<hr>
{% endfor %}
{% endblock %}

Overwriting a field of AdmingeneratorGeneratorBundle

I am trying to overwrite a field of the AdmingeneratorGeneratorBundle and want to append a link to a certain field. That works quite well following the documentation:
{% extends_admingenerated "MyMainBundle:PageEdit:index.html.twig" %}
{% block form_status %}
{{ parent() }}
Preview
{% endblock %}
What I would need to do now, is to get the real id of my page instead of the static 8, but i could not figure out, what the object is called inside the twig template. Any ideas?
Update:
In my case, as I only need the ID of my page, I can use app.request.attributes.get('pk') to get it in twig. Would be interesting how to get other values tough.
Just use
{% extends_admingenerated "MyMainBundle:PageEdit:index.html.twig" %}
{% block form_status %}
{{ parent() }}
Preview
{% endblock %}
Cedric
The Documentation has been updated.
Thats ho it works:
{% extends_admingenerated "NamespaceYourBundle:List:index.html.twig" %}
{% block list_td_column_title %}
<span style="font-weight:bold">{{ Movie.title }}</span>
{% endblock %}

Resources