Display something only once in a loop in twig - php

I have some pics that I want to display by months.
But I my code I get the month on top of every pics.
How to avoid this ?
{% for media in medias %}
{% if media.date|date("m") == 10 and media.assetpath is not null %}
<h2>Photos october</h2>
<div class="col-xs-2">
<img class="img-responsive" src="{{ asset(media.assetpath) }}"/>
</div>
{% elseif media.date|date("m") == 11 and media.assetpath is not null %}
<h2>Photos november</h2>
<div class="col-xs-2">
<img class="img-responsive" src="{{ asset(media.assetpath) }}"/>
</div>
{% else %}
<h2>other month</h2>
<div class="col-xs-2">
<img class="img-responsive" src="{{ asset(media.assetpath) }}"/>
</div>
{% endif %}
{% endfor %}

Assuming that medias is an array sorted by date, the problem can be solved using a temporary variable:
{% set last_month = '' %}
{% for media in medias %}
{% set month = media.date('F')|lower %}
{% if last_month and month != last_month %}
<h2>Photos {{ month }}</h2>
{% endif %}
{% set last_month = month %}
<div class="col-xs-2">
<img class="img-responsive" src="{{ asset(media.assetpath) }}"/>
</div>
{% endfor %}
However, I would rather generate a more appropriate structure, e.g.:
$media = [
'November' => [
[ /* media 1 */],
[ /* media 2 */],
// ...
],
// ...
];
With this structure, the template code will look much cleaner:
{% for month, media in medias %}
<h2>Photos {{ month }}</h2>
{% for m in media %}
<div class="col-xs-2">
<img class="img-responsive" src="{{ asset(m.assetpath) }}"/>
</div>
{% endfor %}
{% endfor %}

Related

OctoberCMS | How to get value from dropdown within repeater

How can I get value from the dropdown within the repeater field? Here is what I have setup in the frontend with if statement within For statement. Can anyone assist me with this ?
{% for module in project.project_module %}
<div class="card {{ module.card_orientation }}">
<div class="asset">
{% if module.project_asset['project_image'] %}
{% if module.viewing_style('single_image') %}
<h2>Image</h2><img src="{{ project.business_card | media }}" loading=lazy />
{% endif %}
{% if module.viewing_style('carousel') %}
<div>Carsouel</div>
{% endif %}
{% endif %}
{% if module.project_asset['project_video'] %}
<video controls>
<source src="{{ module.video_url }}"></source>
</video>
{% endif %}
{% if module.project_asset['project_text'] %}
{{ module.project_description }}
{% endif %}
</div>
<div class="label">{{ module.project_module_title }}</div>
</div>
{% endfor %}

Use Twig loop to output WordPress/ACF image gallery in nested structure

I am using the following code to output an image gallery from WordPress and Advanced Custom Fields using the Timber plugin.
{% if story.meta( 'gallery' ) %}
<div class="story__gallery">
<div class="gallery__row">
{% for image in story.meta( 'gallery' ) %}
{% if Image(image).width > Image(image).height %}
{% set dimension = 'gallery__item--horizontal' %}
{% else %}
{% set dimension = 'gallery__item--vertical' %}
{% endif %}
<figure class="gallery__item gallery__item--{{ Image(image).id }} {{ dimension }}">
<img src="{{ Image(image) }}" width="{{ Image(image).width }}" height="{{ Image(image).height }}" alt="{{ Image(image).alt }}" />
</figure>
{% if loop.index is divisible by(3) and not loop.last %}
</div><div class="gallery__row">
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
This version of the code is working, but now I am needing to implement some logic to output the gallery using the following HTML structure.
<div class="story__gallery">
<div class="gallery__row">
<figure class="gallery__item gallery__item--large"></figure>
<div class="gallery__cluster">
<figure class="gallery__item gallery__item--small"></figure>
<figure class="gallery__item gallery__item--small"></figure>
</div>
</div>
</div>
How would I go about working with the loop.index to wrap the two small figures in the gallery__cluster div and have it properly outputted in the gallery__row container?
I would set a variable outside of the loop and increment it by 1 each time, since you need to do different things each increment of the loop. Reset it every 3 loops. It's a lot of if statements, but it gets the job done. Note I have not tested the below since I don't have a component that matches yours to test but I think you can make it work.
{% set rowIndex = 0 %}
{% if story.meta( 'gallery' ) %}
<div class="story__gallery">
{% for image in story.meta( 'gallery' ) %}
{% set rowIndex = rowIndex + 1 %}
{% if rowIndex == 1 %}
<div class="gallery__row">
<figure class="gallery__item gallery__item--large">
<img src="{{ Image(image) }}" width="{{ Image(image).width }}" height="{{ Image(image).height }}" alt="{{ Image(image).alt }}" />
</figure>
{% if loop.last %}
</div>
{% endif %}
{% endif %}
{% if rowIndex == 2 %}
<div class="gallery__cluster">
<figure class="gallery__item gallery__item--small">
<img src="{{ Image(image) }}" width="{{ Image(image).width }}" height="{{ Image(image).height }}" alt="{{ Image(image).alt }}" />
</figure>
{% if loop.last %}
</div>
</div>
{% endif %}
{% endif %}
{% if rowIndex == 3 %}
<figure class="gallery__item gallery__item--small">
<img src="{{ Image(image) }}" width="{{ Image(image).width }}" height="{{ Image(image).height }}" alt="{{ Image(image).alt }}" />
</figure>
</div>
</div>
{% set rowIndex = 0 %}
{% endif %}
{% endfor %}
</div>
{% endif %}

Render a form ONLY ONCE inside a for loop in a twig template

I have a twig template to display audio options (Auto play and Continuos play) as shown in the screen shot:
Click to see the screen shot of the page
The following is the code in my twig file. {{ audio_options_form}} renders the form with the checkboxes.I want to display the check boxes only once if {{ item.audio }} is true. Please let me know what changes should I make:
<div id="textcontent">
{% set field = data|slice(2) %}
{% set field = field|slice(0, -1) %}
<div class="col-md-12">
<div class = "source-box audio">
{% for item in field %}
{% if item.audio %}
{{ audio_options_form }}
{% if data.play.autoplay == 1 %}
<audio autoplay controls src= "{{item.audio}}" id = "audio-play">
Your browser does not support the
<code>audio</code> element.
</audio>
{% elseif data.play.continuousplay == 1 %}
<audio autoplay controls src= "{{item.audio}}" id = "audio-play" onended="continousPlay('{{data.lastlevel}}')">
Your browser does not support the
<code>audio</code> element.
</audio>
{% else %}
<audio controls src= "{{item.audio}}" id = "audio-play">
Your browser does not support the
<code>audio</code> element.
</audio>
{% endif %}
<div id="source-controls">
{# {% if allow_edit == 1 %}
<a class="edit-text" href="{{ path('heritage_text_manager.editsource', {'sourceid': item.uniqueid}, {'query': {'destination': path('heritage_ui.contentpage', {'textid': textid})}}) }}">{{ 'Edit'|t }}</a>
{% endif %} #}
<a class="more use-ajax" data-toggle="modal" data-dialog-type="modal" href="{{ path('heritage_ui.metadata', {'sourceid': item.uniqueid}) }}">{{ 'More'|t }}</a>
</div>
{% endif %}
{% endfor %}
</div>
Either create a 2nd loop with a flag or use the filter filter.
{% set show_audio_form = false %}
{% for item in field %}
{% if item.audio %}
{% set show_audio_form = true %}
{% endif %}
{% endfor %}
{% if show_audio_form %}{{ audio_options_form }}{% endif %}
{% for item in field %}
... display audio ...
{% endfor %}
{% if items|filter(v => v.audio|default)| length %}
{{ audio_options_form }}
{% endif %}
{% for item in items %}
... display audio ...
{% endfor %}
demo

Getting WooCommerce product attributes within Twig/Timber and calling PHP methods

I'm building a WooCommerce site whilst utilising the Twig templating system along with the Timber WordPress plugin and following along with this guide for the tease template.
However, looking at WooCommerce's own default templates/content-product.php they have this at the very top:
// Ensure visibility.
if ( empty( $product ) || ! $product->is_visible() ) {
return;
}
So I'm thinking that we should be doing the same check in the template file? However I am unsure how to check this value in Twig.
I have tried dump(post.is_visible()) but every one returns (bool) false.
I additionally have no idea where showthumb is coming from and couldn't find much information or docs about this particular setting/attribute.
Edit: Here is my controller: (my-theme/woocommerce/archive-product.php)
$context = Timber::get_context();
$context['shop-sidebar'] = Timber::get_widgets( 'shop-sidebar' );
$posts = Timber::get_posts();
$context['products'] = $posts;
if ( is_product_category() ) {
$queried_object = get_queried_object();
$term_id = $queried_object->term_id;
$context['category'] = get_term( $term_id, 'product_cat' );
$context['title'] = single_term_title( '', false );
}
Timber::render( 'views/woo/archive.twig', $context );
Here is my archive.twig file:
{% extends 'archive.twig' %} {# Base Archive File #}
{% block before_article %}
{% do action('woocommerce_before_main_content') %}
{% endblock %}
{% block below_h1 %}
{% do action('woocommerce_archive_description') %}
{% endblock %}
{% block primary_block %}
{% if products|length > 0 %}
<div class="before-products">
{% do action('woocommerce_before_shop_loop') %}
</div>
<div class="products-wrap">
<div class="products row flex">
{% for post in products %}
<div class="product col-sm-6 col-md-4">
{% do action('woocommerce_shop_loop') %}
{% include ["woo/partials/tease-product.twig"] %}
</div>
{% endfor %}
</div>
</div>
<div class="after-products">
{% do action('woocommerce_after_shop_loop') %}
</div>
{% else %}
<div class="no-products">
{% do action('woocommerce_no_products_found') %}
</div>
{% endif %}
{% endblock %}
{% block after_article %}
{% do action('woocommerce_after_main_content') %}
{{ parent() }}
{% endblock %}
Here is my tease-product.twig file:
<article {{ fn('post_class', ['entry'] ) }}>
{{ fn('timber_set_product', post) }}
<div class="media">
<div class="media-figure {% if not post.thumbnail %}placeholder{% endif %}">
<a href="{{ post.link }}">
{% if post.thumbnail %}
<img src="{{ post.thumbnail.src|resize(600)|e('esc_url') }}" class="img-responsive" />
{% else %}
<span class="thumb-placeholder"><i class="icon-camera"></i></span>
{% endif %}
</a>
</div>
<div class="media-content">
{% do action('woocommerce_before_shop_loop_item') %}
{% do action('woocommerce_before_shop_loop_item_title') %}
{% if post.title %}
<h3 class="entry-title">{{ post.title }}</h3>
{% else %}
<h3 class="entry-title">{{ fn('the_title') }}</h3>
{% endif %}
{% do action( 'woocommerce_after_shop_loop_item_title' ) %}
{% do action( 'woocommerce_after_shop_loop_item' ) %}
</div>
</div>
</article>
How can I retrieve the correct value of the is_visible method?
I reckon OP has solved the problem by now. But, for future reference...
You should be able to do {{ post.is_visible }} to output the value.
Similarly, both if statements below work for me.
{% if (product.is_visible) %}
{% if (product.is_visible()) %}
Now, I am fairly new to WooCommerce and Timber, and I don't know much about is_visible, so I apologize if I am wrong here. But, I know I Am able to use WC_Product member functions in twig templates like {{ variable.function_name }}, ie. {{ product.get_title }} or {{ product.get_price }}, so I expect is_visible to be no different.

Make a custom login screen for the HWIOAuth Bundle using bootstrap

{% extends '::base.html.twig' %}
{% block content %}
<div>
{% if is_granted("IS_AUTHENTICATED_REMEMBERED") %}
{{ 'layout.logged_in_as'|trans({'%username%': app.user.username}, 'FOSUserBundle') }} |
<a href="{{ path('fos_user_security_logout') }}">
{{ 'layout.logout'|trans({}, 'FOSUserBundle') }}
</a>
{% else %}
{{ 'layout.login'|trans({}, 'FOSUserBundle') }}
{% endif %}
</div>
{% for type, messages in app.session.flashBag.all %}
{% for message in messages %}
<div class="{{ type }}">
{{ message|trans({}, 'FOSUserBundle') }}
</div>
{% endfor %}
{% endfor %}
<div>
{% block fos_user_content %}
{% endblock fos_user_content %}
</div>
{% endblock %}
for now my screen has an appearance just to appear buttons to login with facebook or gmail, like an example of how to do a more visual screen with the icons login and centralized.
Thank you.
<div class="customBtn"><a href="{{ path('hwi_oauth_service_redirect', {'service': 'facebook'}) }}">
{% image 'bundles/delivveweb/images/Facebook.png' %}
<img src="{{ asset_url }}">
{% endimage %}
</a></div>
<div class="customBtn"><a href="{{ path('hwi_oauth_service_redirect', {'service': 'google'}) }}">
{% image 'bundles/delivveweb/images/Google.png' %}
<img src="{{ asset_url }}">
{% endimage %}
</a></div>
<div class="customBtn"><a href="{{ path('hwi_oauth_service_redirect', {'service': 'linkedin'}) }}">
{% image 'bundles/delivveweb/images/in.png' %}
<img src="{{ asset_url }}">
{% endimage %}
</a></div>
I could do it this way to be a more customizable login menu also did a Provider and a controller to make the treatment of my User if someone needs to send a comment below to edit the answer.

Categories