Make post preview empty if excerpt is blank with Timber - timber

I've tackled this issue before in vanilla Wordpress however I can't seem to find a way to keep the post.preview object blank if the excerpt field is empty. Despite searching around no one else seems to find this an issue!
Anyway, I've come up with a work around based on my previous methods to set a variable in my logic files for the twig template to use which is simple enough and someone else may find useful. Just intrigued to see if I'm missing something that would be possible from within Timber.
Here's the solutions I used and it was placed in page.php
$excerpt = '';
if ( ! has_excerpt() ) {
$excerpt = '';
} else {
$excerpt = get_the_excerpt();
}
$context['post_excerpt'] = $excerpt;

post_excerpt is already a property of Timber\Post. If post is in your context, you probably don't need to add another var just for this.
To embrace doing things a more 'Timber-esque` way, access the property off the object, rather than setting another var in the context.
{# page.twig *}
{% if post.page_excerpt %}
{{ post.preview }}
{% endif %}
This also has less reliance on globals (like has_excerpt() or get_excerpt() ) so it becomes easier to reuse this code in other templates or files.

Since PHP 7 this should also work as expected and is a much cleaner solution:
$context['post_excerpt'] = get_the_excerpt() ?? '';
The ?? operator is called the 'Null Coalescing Operator'. You can find more about it in the official PHP docs.
An alternative solution is to use the timber "preview"-method on the post class directly in your twig template:
{{ post.preview }}
You can find more info about this in the official Timber docs.

Related

Wordpress: Individual Styling/Coding for Custom Post Types on Index

I'm really struggling to Google my way out of this issue. I've set-up custom post-types, and I've managed to include those custom types in the index page. But now I really need a way of styling those entries differently to the regular posts. Does anyone know how I can do this? It's not just styling, but also, replacing/adding/removing certain code, as the custom types operate/look differently to regular posts.
Any help would be HUGELY appreciated!
As for the CSS, inside your loop, when you're defining the element that contains your post, try doing something like this
<article class="<?php echo $post->post_type; ?>" ...>
This will give you a class you can hook onto within your CSS file.
You can also use WordPress's built-in post_class function to achieve a similar result
<article <?php post_class($post->post_type); ?>>
That will add the post type to the rest of the default post classes, so you can still style those elements differently.
As for the different code for different post types, one of the answers above me mentioned using an if statement based on the post type:
if ('my_post_type' == $post->post_type)
{
// Code Here
}
I hope this helps you.
Codex Reference for post_class
you can use this code inside the loop:
if ( 'custom_post_type' == get_post_type() ){
//do whatever
}
or if you need to check some post types you can use a switch like:
switch ( get_post_type() ) {
case 'post':
//do whatever;
break;
case 'custom_post_type_1':
//do whatever;
break;
case 'custom_post_type_2':
//do whatever;
break;
}

Get current URL in Twig template?

I looked around for the code to get the current path in a Twig template (and not the full URL), i.e.
I don't want http://www.sitename.com/page, I only need /page.
{{ path(app.request.attributes.get('_route'),
app.request.attributes.get('_route_params')) }}
If you want to read it into a view variable:
{% set currentPath = path(app.request.attributes.get('_route'),
app.request.attributes.get('_route_params')) %}
The app global view variable contains all sorts of useful shortcuts, such as app.session and app.security.token.user, that reference the services you might use in a controller.
Get current url: {{ app.request.uri }} in Symfony 2.3, 3, 4, 5
Get path only: {{ app.request.pathinfo }} (without parameters)
Get request uri: {{ app.request.requesturi }} (with parameters)
In symfony 2.1 you can use this:
{{ path(app.request.attributes.get('_route'),
app.request.attributes.get('_route_params')) }}
In symfony 2.0, one solution is to write a twig extension for this
public function getFunctions()
{
return array(
'my_router_params' => new \Twig_Function_Method($this, 'routerParams'),
);
}
/**
* Emulating the symfony 2.1.x $request->attributes->get('_route_params') feature.
* Code based on PagerfantaBundle's twig extension.
*/
public function routerParams()
{
$router = $this->container->get('router');
$request = $this->container->get('request');
$routeName = $request->attributes->get('_route');
$routeParams = $request->query->all();
foreach ($router->getRouteCollection()->get($routeName)->compile()->getVariables() as $variable) {
$routeParams[$variable] = $request->attributes->get($variable);
}
return $routeParams;
}
And use like this
{{ path(app.request.attributes.get('_route'), my_router_params()|merge({'additional': 'value'}) }}
You won't need all this unless you want to add additional parameters to your links, like in a pager, or you want to change one of the parameters.
You can get the current URL in Twig like this:
{{ app.request.schemeAndHttpHost ~ app.request.requestUri }}
It should be noted that if you have additional query parameters in your URL, which are not part of the configured route, the accepted answer will not include them in the current URL (path).
Why would you want extra parameters?
For example, if you have a list page with records that can be filtered by keyword and the page has pagination, most likely the query variables for "keyword" and "page" will not be in your route. But in your forward and back buttons for paging, you need the full current URL (that contains the keywords so the next page is still filtered). And you need to modify the page variable.
How to Merge In Extra Query Parameters
So you can get the current route, and merge in the extra variables (after modifying one or more of those extra variables). Note that you are merging in your own variables to the app.request.query.all, and then merging that array into the app.request.attributes.get('_route_params'). The path() method requires that you provide all the required parameters of the route, which is why you need to include the _route_params.
{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')|merge(app.request.query.all|merge({'page': 2 }))) }}
That's really ugly, but if you are developing pagination, you will need to modify the page variable on each separate link, so you have to include the whole thing each time. Perhaps others have a better solution.
Using Symfony 5 you can use this:
{{ app.request.uri }}
If you are using Silex 2 you can not access the Request object anymore.
You can access the current request attributes this way.
app.request_stack.currentrequest.attributes.get('_route')
And to generate the full current URL :
path(app.request_stack.currentrequest.attributes.get('_route'), app.request_stack.currentrequest.attributes.get('_route_params'))

Wordpress - How to adding a custom comment_type?

I want to add a custom comment type to some of the comments, but I don't know how to write the custom comment type with the comment form into the comment_type row in the database-table. I've tried it the following way, but it won't work:
<input type="hidden" name="comment_type" value="reader" id="comment_type" />
I've tried many hours and searched the whole web. :-/
Any suggestions?
back again, now on a better keyboard than my phone ;-)
as you can see in the official documentation, comment_type is not an attribute you can set with a value you wish. it describes the system type of the command (either a trackback, pingback or simply, a comment)
considering my comment above, i guess you'd like to differ between your own comments and those of your visitors.
i solved this in my own blog theme by reacting on the author id of the comments.
following a snippet from my comments.php file:
$isCommentFromAuthor = get_the_author_id() == $comment->user_id;
// ...
<div class="<? if($isCommentFromAuthor) : ?>author-content<? else: ?>content<? endif ?>">
this solution checks the author of the current article and compares it with the comments author.
if the comment is from the articles author, another css class is passed to the comment container which will style it differently.
does this help you any further?
If you have <input type="hidden" name="comment_type" value="reader" id="comment_type" /> in comment_form, you only need to hook preprocess_comment
function preprocess_comment_handler( $commentdata ) {
if ( isset( $_POST['comment_type'] ) ) {
$commentdata['comment_type'] = $_POST['comment_type'];
}
return $commentdata;
}
add_filter( 'preprocess_comment', 'preprocess_comment_handler' );

How to insert a block into a node or template in Drupal 7?

In Drupal 6, it was easy to insert a block into a template with the following code:
$block = module_invoke('views', 'block', 'view', 'block_name');
print $block['content'];
However, using the same instructions in Drupal 7 does not seem to work. I have looked around and cannot find the new method.
Does Drupal 7 have a routine that can allow for programmatically inserting a block into a template or node?
D7:
<?php
$block = module_invoke('module_name', 'block_view', 'block_delta');
print render($block['content']);
?>
'module_name' = The machine name of the module (i.e. the module's folder name). This is true for core modules too, so for instance 'search', 'user' and 'comment' would all work here.
'block_delta' = The machine name of the block. You can determine what this is by visiting the block administration page and editing the block. The URL for editing a webform block, for instance, would be something like:
Drupal 7: admin/structure/block/manage/webform/client-block-11/configure
In this example, 'webform' is the module's name, 'client-block-11' is the block's delta.
Custom blocks will have module name of 'block' and a number for a delta, which you can also find by editing the block.
More information: http://drupal.org/node/26502
This appears to be the solution for inserting blocks into templates for Drupal 7, but it seems a bit clunky and I have no idea about impact on performance:
$block = block_load('views', 'block_name');
$output = drupal_render(_block_get_renderable_array(_block_render_blocks(array($block))));
print $output;
If anyone has a better procedure, please do add.
With wrburgess's answer you may get an error if your server is using a newer version of PHP.
Strict warning: Only variables should be passed by reference in include()...
This is what I did to not cause/get rid of the error.
<?php
$blockObject = block_load('views', 'block_name');
$block = _block_get_renderable_array(_block_render_blocks(array($blockObject)));
$output = drupal_render($block);
print $output;
?>
This work for me:
98 is the id of the block
$block =block_load('block',98);
$output = drupal_render(_block_get_renderable_array(_block_render_blocks(array($block))));
print $output;
Just tested this in drupal 7 and it works:
$bloqueServicios = module_invoke('views', 'block_view', 'servicios-blo_home');
print render($bloqueServicios);
Good luck!
The module_invoke() function works. However, I found that rendering a block this way apparently won't use a custom template for that block. This might be OK depending upon your needs.
As commented before in other answers, this works as well and also makes use of custom templates:
$raw_block = block_load('your-module', 'delta');
$rendered_block = drupal_render(_block_get_renderable_array(_block_render_blocks(array($raw_block))));
print $rendered_block;
So, if you have a custom block--your-module--delta.tpl.php template file, it will be used to format the block.
Source: http://api.drupal.org/api/drupal/includes!module.inc/function/module_invoke/7
For some reason render() doesn't work for me, but this does:
<?php
$block = module_invoke('block', 'block_view', '1');
echo $block['content'];
?>
In my search to include a block in a template, i came across this post.
As an addition, if you want to include a custom block (that you added through the block interface) you have to use (instead of block_load(); in drupal 7)
$block = block_get_custom_block($bid);
$content = $block['body'];
Improving wrburgess' answer, you can do it in one line...
<?php print drupal_render(_block_get_renderable_array(_block_render_blocks(array(block_load('module_name', 'block_delta'))))); ?>
So for example, I use block number 6...
<?php print drupal_render(_block_get_renderable_array(_block_render_blocks(array(block_load('block', '6'))))); ?>
This worked for my Drupal 7 ,
URL: admin/structure/block/manage/addthis/addthis_block/configure
NOTE:delta and module name present in the url itself
$addblock = module_invoke('addthis','block_view','addthis_block');
print render($addblock['content']);
More information can be found on
http://technarco.com/drupal/insert-block-node-or-template-drupal-7
$block = module_invoke('menu_block', 'block_view', '6');
echo render ($block['content']);
This works for me for printing menu block.
There's module called insert_block for those which want to insert block "Drupal way" (not to program anything, just enable the module). Here's how to set it up.
NOTE: I know this question is about "programmatically inserting a block into a template or node" but Google sends people here even their are looking for non-programmer solution like me.
Have a look how Drupal does it in _block_render_blocks. The result of that function gets passed to drupal_render.
Recently I faced the same issue and I came across a nice solution which describes the solution in drupal as drupal's way.
You can print regions inside any template, but they aren't available out of the box in the node.tpl.php template. To make them available, you'll create a new variable for use in your node.tpl.php template that'll contain all the region content.
Creating new template variables is done by using a preprocess function. In your theme's template.php file, create a function that looks like this:
function mytheme_preprocess_node(&$variables) {
// Get a list of all the regions for this theme
foreach (system_region_list($GLOBALS['theme']) as $region_key => $region_name) {
// Get the content for each region and add it to the $region variable
if ($blocks = block_get_blocks_by_region($region_key)) {
$variables['region'][$region_key] = $blocks;
}
else {
$variables['region'][$region_key] = array();
}
}
}
Then, in your theme's node.tpl.php template, you can render any region by doing the following:
<?php print render($region['sidebar_first']); ?>
Where sidebar_first is the name of the region you want to render.
Read the complete article here: https://drupal.stackexchange.com/questions/20054/can-regions-be-printed-within-a-node-template
module_invoke Working fine for render block in the template file, but it's not working multilingual sites.

Content elements for wordpress

I'm looking for a plugin (or better yet, not a plugin) for wordpress that lets me generate standard content elements, or includes for posts and pages.
For example, my_content_1 could be:
buy it now for $23!!
Which could then be included in posts and pages using some kind of syntax (or whatever) like:
Welcome to my site, blah blah blah.. check out this product - %my_content_1%
Not looking for anything fancy, anything that does this sort of thing would be awesome.
The point of this being much like a regular php include I could have the same information updated in one place and applied over many pages/posts.
I found something that is pretty much what I'm looking for:
http://wordpress.org/extend/plugins/reusables/
However, other suggestions would be good as I'm not too confident in the quality of the code for that plugin.
Not sure about a plugin, but how about simply creating something yourself? If you created a PHP page and set up variables such as
$content->title = "This is a title"
$content->smallText = "Insert some short paragraph here"
And then just include it in your header? You could store it in your theme directory and then call it like so
<?php $themeFolder = get_bloginfo("template_url"); ?>
<?php include($themeFolder."/content.php") ?>
Would that be suitable?
How about creating a few files and link them in using shortcode?
ie: open your themes/functions.php file add this..
<?php
function wp_my_shortcodes($atts)
{
extract(shortcode_atts(array(
'type' => '', //author, rss, adverts
), $atts));
switch($type) {
case 'author' : $display = wp_display_author_info(); break;
case 'rssview' : $display = wp_display_rss_info(); break;
case 'adverts' : $display = wp_display_adverts(); break;
default : $display = wp_display_author_info(); break;
}
return $display ;
}
add_shortcode('mycontent', wp_my_shortcodes);
function wp_display_author_info()
{
include(TEMPLATEPATH.'/my_author_info.php');
}
function wp_display_rss_info()
{
include(TEMPLATEPATH.'/my_rss_info.php');
}
function wp_display_adverts()
{
include(TEMPLATEPATH.'/my_adverts.php');
}
?>
using shortcodes inside your posts you can then bring in which ever piece of content that you want.. in the example above I've created 3 pages in the template root folder called
my_author_info.php, my_rss_info.php, my_adverts.php all of which speak for themself..
my_author_info.php
this page could use the the_author_meta() to populate a div box with included author info,
my_rss_info.php
include your subscription box to let users subscribe to your blog
my_adverts.php
include 4x 125x125 adverts?
so in the post i could use
[mycontent type='author']
[mycontent type='rssview']
[mycontent type='adverts']
if no argument is added to the shortcode then the default view is shown, in this case..
[mycontent]
would return the authorview as default...
this would then include that file in the content...
just remember to create the included files :)
I found something that is pretty much what I'm looking for:
http://wordpress.org/extend/plugins/reusables/

Resources