Search all posts by an author in Wordpress/Timber - wordpress

I'm trying to display all posts by a given author on the search results page using Timber. I've found that this works if I manually type it in:
/s?&author_name={username}
But I need to create these links dynamically in a loop, and unfortunately Timber's User object doesn't have access to a User's username. Going by ID also doesn't work (/s?&author={author_id}).
What's the solution here?

I would suggest you make a function available in Twig which allows you to pass in the author id and return the author archive link via get_author_posts_url() or access the WP user class.
See documentation on how to achieve this:
https://timber.github.io/docs/guides/functions/#make-functions-available-in-twig
php
add_filter( 'timber/twig', 'add_to_twig_author_link' );
function add_to_twig_author_link( $twig ) {
$twig->addFunction( new Timber\Twig_Function( 'get_author_posts_url', 'get_author_posts_url' ) );
return $twig;
};
twig
{{ get_author_posts_url( author_id ) }}

If you need to access author archive via link, you can do it by Timber\Post object
{% for post in posts %}
{{ post.author.name }}
{% endfor %}
But as I understood, your problem is to pass user login into twig templates. This way you can add to a global context all of your users.
search.php
$ctx = Timber::context();
$ctx['users'] = get_users(); // it will return array of WP_User objects
Timber::render( 'search.twig', $ctx );
search.twig
{% for user in users %}
{{ user.user_login }} // this will show user login
{% endfor %}

Related

Print user role when submitting comments in Drupal 8

In my Drupal site, user profile has username, role and group Taxonomy term. There is a Article content type setup to take comments from users. Every time when a user comments, I would like to show as:
Submitted by: username, role, group
I tried to read the role and category fields through template_preprocess function as below:
function bartik_preprocess_comment(array &$variables) {
if (isset($variables['elements']['#view_mode'])) {
$variables['view_mode'] = $variables['elements']['#view_mode'];
}
else {
$variables['view_mode'] = 'default';
}
dd($variables);
}
But the dump does not show "group" field. Unsure what's missing.Rightnow, only the username is showing up. My comments.html.twig looks as below:
<div class="author-comments">
<p class="comment-submitted">{{ submitted }}</p>
<div{{ content_attributes.addClass('content') }}>
{% if title %}
{{ title_prefix }}
<h3{{ title_attributes }}>{{ title }}</h3>
{{ title_suffix }}
{% endif %}
{{ content }}
</div>
</div>
any help on how to pull out the role and category field and plug into the twig template? Thanks!
Alright, I'm able to figure this out. Below is my answer:
In mytheme.theme file:
/**
* Implements hook_preprocess_HOOK() for comment.html.twig.
*/
function mytheme_preprocess_comment(array &$variables) {
$user = \Drupal::currentUser();
$user_entity = \Drupal::entityTypeManager()
->getStorage('user')
->load($user->id());
$roles = $user->getRoles();
$variables['user_roles'] = $roles ;
}
This variable can be printed on comment.html.twig as: {{ user_roles }} as however needed.

Get custom post type label instead of name - WordPress + Timber

I created 3 custom post types in WordPress : dissertation, subject-imposed, subject-free
In each custom post type the user is allowed to create only ONE post.
I created a menu composed with those three custom post types which allow to switch from post to another from the same user.
But I got a problem. The menu item display the name of the post type and not the label.
I got : DISSERTATION / SUBJECT-IMPOSED / SUBJECT FREE
And I would like the label (labels are in french) : MEMOIRE / SUJET IMPOSE / SUJET LIBRE
How can I get the label instead ? Thank you in advance.
In single.php :
$post_queried = get_queried_object();
$context['post_type_current'] = get_post_type_object(get_post_type($post_queried));
$get_post_current_user = get_posts( array(
'author' => $current_user->ID,
'post_type' => array('dissertation', 'subject-imposed', 'subject-free'),
));
$context['list_posts_current_user'] = $get_post_current_user;
In single.twig :
<ul class="menu-secondary__list">
{% for item in list_posts_current_user %}
{% set active = (post_type_current.name == item.post_type) ? 'active' : '' %}
<li class="menu-secondary__item">{{ item.post_type }}</li>
{% endfor %}
</ul>
Two steps to fix this one, first ...
Convert into an array of Timber\Posts
$get_post_current_user is an array of WP_Posts we need to convert these to Timber\Posts in order to interact with Timber's methods. Many ways to do this, but the easiest ...
{% for item in Post(list_posts_current_user) %}
Access the type method:
Now you can use the Post::type() method in your Twig template and access the labels:
{{ item.type.labels.name }}
The {{ item.type }} property will give you everything from here:
https://developer.wordpress.org/reference/functions/get_post_type_object/

Using doctrine database object in a template

I am new to Symfony and am finally beginning to understand how to query a database using a Doctrine. However, I am lost as far understanding how to use the database object content in a Twig template.
Lets say my database object contains product Id's, names, prices, for 50 different products. After I am done querying the database in the controller, I do the following, to pass the database object into the Twig template:
public function searchAction($word)
{
//query database using the $word slug and prepare database object accordingly
$dataObject; // contains query results
return $this->render('GreatBundle:Default:search.html.twig', array('word' => $word));
}
This is where I am stuck. Now I have a Twig template, I would like to pass the DB object from the controller and then print out the database data in my Twig template.
I appreciate any suggestions as to how I can accomplish this.
Many thanks in advance!
I'll respond with an example (more easier for me to explain)
You want to search something with a slug (the var $word in your example). Let's say you want to find a article with that.
So your controller :
public function searchAction($word)
{
//query database using the $word slug and prepare database object accordingly
// Search the list of articles with the slug "$word" in your model
$articleRepository = $this->getDoctrine()->getRepositoy('GreatBundle:Article');
$dataObject = $articleRepository->findBySlug($word);
// So the result is in $dataObject and to print the result in your twig, your pass the var in your template
return $this->render('GreatBundle:Default:search.html.twig', array('result' => $dataObject));
}
The twig template 'GreatBundle:Default:search.html.twig'
{% for item in result %}
{{ item.title }} : {{ item.content }}
{% endfor %}
Just look the second example in the Symfony2 Book (Sf2 Book - templating), you have to use the function "for" to parse your object (like an array in php !)
Example in your twig template :
{% for item in word %}
{{ item.id }} - {{ item.name }} - {{ item.description }}{# etc... #}<br>
{% else %}
<h2>Aoutch ! No data !</h2>
{% endfor %}
Ah, and it's not the good var in your render method (but it's was for your example !)
public function searchAction($word)
{
//query database using the $word slug and prepare database object accordingly
$dataObject; // contains query results
return $this->render('GreatBundle:Default:search.html.twig', array('word' => $dataObject));
}

How to get params in twig file

how can i use $_GET params in TWIG file like using PHP and alerting with JS.
URI-> ?comment=added...
in TWIG,
if($_GET['comment'] == "added"){
...echo '<script>alert("in TWIG file!");</script>';
}
hope it will help you
{% if app.request.get('comment') == "added" %}
<script>alert("in TWIG file!");</script>
{% endif %}
Depending on what you're really trying to achieve, the "Symfony way" of showing confirmation messages would be to use "Flash Messages":
YourController.php:
public function updateAction()
{
$form = $this->createForm(...);
$form->handleRequest($this->getRequest());
if ($form->isValid()) {
// do some sort of processing
$this->get('session')->getFlashBag()->add(
'notice',
'Your changes were saved!'
);
return $this->redirect($this->generateUrl(...));
}
return $this->render(...);
}
Your TwigTemplate.twig:
{% for flashMessage in app.session.flashbag.get('notice') %}
<div class="flash-notice">
{{ flashMessage }}
</div>
{% endfor %}
This way you have multiple advantages:
Redirecting after action prevents form reloading.
Message cannot be triggered from outside.
Flash messages are only fetched once.
See the official documentation on this topic.
The "correct" solution would be use your controller to provide a function to Twig rather than switching on the querystring. This will be more robust and provide better security:
Controller:
function someAction()
{
$params = array('added' => false);
if( /* form logic post */ )
{
//some logic to define 'added'
$params['added'] = true;
}
$this->render('template_name', $params);
}
view:
{% if added %}
<script>alert('added');</script>
{% endif %}
The reasoning is that this is more secure (I can't trigger the alert by just browsing to the url), it maintains all business logic in the controller and you're also able to handle any errors - e.g. if you browse to foo.php?comment=added and there is an error wherein your comment isn't added, the user will still receive the alert.

How to get the current page name in Silex

I'm wondering how to get the current page name, basically 'just' the last parameter in the route (i.e. /news or /about). I'm doing this because I want to be able to have the current page in the navigation highlighted.
Ideally, I'd like to store the current page name in a global variable so that in Twig I can just compare the current page name against the link and add a class accordingly.
I can't figure out how to add the current page name to a global variable though. I've tried using something like this:
$app['twig']->addGlobal('current_page_name', $app['request']->getRequestUri());
at the top of my app.php file, but an 'outside of request scope' error. But I wouldn't like to have to include this in every route.
What's the best way to do this?
If you put it into an app-level before middleware like this, that'll work:
$app->before(function (Request $request) use ($app) {
$app['twig']->addGlobal('current_page_name', $request->getRequestUri());
});
The "page name" part of your question is unclear, are you looking for the current route's name? You can access that via $request->get("_route") even in the before middleware, as it gets called when routing is already done.
You could also generate navigation list directly in stand alone nav twig template. And then import it in to the main template. Then you would only have to get silex to pass to the view the current page identifier. Simplest way... for example from Silex you would have to pass in the "path" variable to your view. Probably it would more convenient to to fetch nav_list from database and pass it in to twig template as global array variable instead. However this example is the simplest you could get to do what you intend.
nav.twig
{% set nav_list = [
["./", "home"],
["./contact", "contact"],
["./about", "about us"]
{# ... #}
] %}
{% set link_active = path|default("") %}
{% for link in nav_list %}
<li><a href="{{ link[0] }}" class="{% if link[0] == link_active %} activeClass {% endif %}" >{{ link[1] }}</a></li>
{% endfor %}
app.php
//...
$app->match('/about', function (Request $request) use ($app) {
return $app['twig']->render('about.twig', array(
'path' => './'.end(explode('/', $request->getRequestUri()))
));
});
//...

Resources