Select posts that have a specific term using withSelect in Gutenberg block - wordpress

I'm trying to select posts -- or more specifically, a custom post type -- that belong to a specific term, and display them in my Gutenberg block's edit screen. I'm wanting to recreate what would be tax_query with WP_Query, but in Javascript.
I'm able to select posts, but I'm unsure what parameters to use with getEntityRecords to select by term (or if it is even possible). The documentation is still a little vague at this point.
Here's where I'm at. This successfully selects all posts of the 'rmenu' type:
const items = select("core").getEntityRecords(
"postType",
"rmenu"
);
Does anyone know if getEntityRecords is the right way to handle this?
Thanks.

The third parameter to getEntityRecords is a query object. You can pass any query argument accepted by Wordpress API such as categories or tags. Selecting by category term would look like this:
const items = select("core").getEntityRecords(
"postType",
"rmenu",
{ categories: [ 13 ] }
}

Although Capi's answer is correct, it wasn't clear for me that this would also work for custom taxonomies. It turns out wp.data will add your custom taxonomies automatically as properties to the post object. For example, a post could look like this:
{
title: "hello world",
content: "this is a post",
id: 123,
type: 'my-custom-posttype'
my-custom-tax: [5, 8, 24],
...
}
So, in order to get all the posts of the type my-custom-posttype that have a term with ID 4 or 8 of the taxonomy my-custom-tax, you would run this query:
wp.data.select( 'core' ).getEntityRecords( 'postType', 'my-custom-posttype', { 'my-custom-tax':[4,8] })
Important! If you test this in your browser, you need to run it twice. The first time it will return an empty array, because it only invokes the promise.

Related

Query string in URL makes main query misbehave and pagination not to work in Wordpress

I have archive page of movies in which I am presenting all movies paginated. On side bar I have genres(taxonomy) for movies. When user clicks on one I want results on the page to be filtered according to which genre he clicked.
My way of thinking made me do this using query string in URL. So when user click on genre it requests same URL (archive for movies) but adds ?genre=SOMETHING. Then in pre_get_posts hook I have this if statement to modify main query:
if(
!is_admin() &&
$query->is_main_query() &&
is_post_type_archive('movie') &&
get_query_var('genre')
)
Then after that I have code like this to filter movies by genre user clicked on :
$taxonomyQuery = [
[
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => get_query_var('genre'),
],
];
$query->set('tax_query', $taxonomyQuery);
Sidebar link are constructed like this :
<a href="<?php echo esc_url(add_query_arg('genre', $genre->slug)) ?>">
<?php echo $genre->name; ?>
</a>
Taxonomy is created with name genre so that name is automatically added to query_vars.
When I open archive page of movies /movies/ I get paginated results and everything works fine. But once I click on genre I get this path /movies/?genre=comedy.
pre_get_posts activates and filters movies according to the genre selected but pagination doesnt work. Even if I set $query->set('posts_per_page', 1); I still get more than one result returned from query. Problem only occurs when query string ?genre=SOMETHING gets added to URL and I cannot figure out why.
NOTE: I am relatively new to wordpress development and I do not actually know if this is the right way to do this kind of thing.
Any help is appreciated!
So after some testing with different things I got to this conclusion.
When I registered taxonomy with register_taxonomy I did not place 'query_var' property as I thought it is adding query string value like when you use :
add_filter('query_vars', 'demo_query_vars');
function demo_query_vars($queryVars) {
$queryVars[] = 'genre';
return $queryVars;
}
These two thing are not the same. First one enables you to load taxonomy using query_var. From the docs :
Sets the query var key for this taxonomy. Default `$taxonomy` key. If false, a taxonomy cannot be loaded at `?{query_var}={term_slug}`. If a string, the query `?{query_var}={term_slug}` will be valid.
Second one enables custom query_var and query string to be used, which is what i needed.
FIX: Just disable query_bar 'query_var' => false'
Then add code I posted above to allow query variable to be processed (add_filter function) and you will be able to use your query_var.
NOTE: This problem was caused for me because I my taxonomy is called genre therfore query_var in register_taxonomy function is automatically set to this value. And I also wanted to use the same name for my own custom query_var which made conflicts.
If your taxonomy name is different from your query_var (the query string you wich to use, example if I used ?g=SOMETHING instead of ?genre=SOMETHING) YOU WILL NOT run into this problem since there will be no conflicts between these two variables..
Another possible solution would be to make your custom query_var different than one specified in register_taxonomy if you are using query_var defined in register_taxonomy function. They just need to be different so there are no conflicts.
I am just at the beginning so this potentially could not be right but it for sure has something to do with these 2 variable names being the same.

stop wordpress search showing a custom post type

I have one custom post type I use for some text blocks on a page built using uncode theme. I need these blocks to be public so they display on the page but I want to stop them appearing in search results.
The search.php isn't like a normal wordpress search file, it is the uncode-theme file and doesn't have normal queries in I don't think so I'm thinking I need a function maybe?
Can anyone please advise how to achieve this?
The CPT is 'staticcontent'
Thanks!
The answer here depends on whether you're creating the CPT via your own code, or if another plugin is creating the CPT. See this link for a great explanation of both approaches:
http://www.webtipblog.com/exclude-custom-post-type-search-wordpress/
The basic gist is this:
If you're creating your own CPT, you can add an argument to the register_post_type() call of 'exclude_from_search' => true
If another plugin / theme is creating the CPT, you need to set this exclude_from_search variable later on, as part of a filter to the CPT, as such:
// functions.php
add_action( 'init', 'update_my_custom_type', 99 );
function update_my_custom_type() {
global $wp_post_types;
if ( post_type_exists( 'staticcontent' ) ) {
// exclude from search results
$wp_post_types['staticcontent']->exclude_from_search = true;
}
}
I don think accepted answer is correct. exclude_from_search prevents all $query = new WP_Query from returning results.
The core says:
...retrieves any type except revisions and types with
'exclude_from_search' set to TRUE)
This is a common problem and mixup with the front end search results page v.s. search posts in the database.
Presenting content using custom queries on front end, needs exclude_from_search = false or use another approach and get the content by id directly.
You need to filter the search front end mechanism instead. This is a true Exclude Post Types From Search, without manually re-build "known" types:
function entex_fn_remove_post_type_from_search_results($query){
/* check is front end main loop content */
if(is_admin() || !$query->is_main_query()) return;
/* check is search result query */
if($query->is_search()){
$post_type_to_remove = 'staticcontent';
/* get all searchable post types */
$searchable_post_types = get_post_types(array('exclude_from_search' => false));
/* make sure you got the proper results, and that your post type is in the results */
if(is_array($searchable_post_types) && in_array($post_type_to_remove, $searchable_post_types)){
/* remove the post type from the array */
unset( $searchable_post_types[ $post_type_to_remove ] );
/* set the query to the remaining searchable post types */
$query->set('post_type', $searchable_post_types);
}
}
}
add_action('pre_get_posts', 'entex_fn_remove_post_type_from_search_results');
And remark $post_type_to_remove = 'staticcontent'; can be changed to fit any other post type.
Please make a comment if Im missing something here, I cant find another way to prevent post type scenarios like this, showing content by query but hide from search/ direct access to front end users.
First of all, the answer by Jonas Lundman is correct and should be the accepted answer.
The exclude_from_search parameter does work incorrectly - it excludes the post type from other queries as well.
There is a ticket on WP issue tracking system, but they have closed it as wontfix because they cannot fix this without breaking the backwards compatibility. See this ticket and this one for more details.
I've added additional checks to the solution proposed by Jonas Lundman, because:
in real setups there can be other plugins trying to modify the search query, so simply replacing the post_type may cause unexpected results.
I think it's more flexible to use an array of post types to exclude.
add_action('pre_get_posts', 'remove_my_cpt_from_search_results');
function remove_my_cpt_from_search_results($query) {
if (is_admin() || !$query->is_main_query() || !$query->is_search()) {
return $query;
}
// can exclude multiple post types, for ex. array('staticcontent', 'cpt2', 'cpt3')
$post_types_to_exclude = array('staticcontent');
if ($query->get('post_type')) {
$query_post_types = $query->get('post_type');
if (is_string($query_post_types)) {
$query_post_types = explode(',', $query_post_types);
}
} else {
$query_post_types = get_post_types(array('exclude_from_search' => false));
}
if (sizeof(array_intersect($query_post_types, $post_types_to_exclude))) {
$query->set('post_type', array_diff($query_post_types, $post_types_to_exclude));
}
return $query;
}

Displaying field collections loop in Content Type TPL file for drupal 7

I have a content type "about" created in Drupal 7. I have a field collection named "field_usf_projects" which is set to unlimited and contains 2 fields, "usf_title" and "usf_description". Now I want to run a for loop which retrieves the field_usf_projects and then displays 2 fields namely ("usf_title" and "usf_description") inside a ul - li structure.
I have gone through many links but cannot find a working solution. Please help me with this.
Thanks in advance.
Here is my solution, on hook_node_view you can use the entity wrapper to get the fields
function mymodule_node_view($node, $view_mode, $langcode) {
// Check if the node is type 'about'.
if ($node->type != 'about') {
return;
}
// Get the contents of the node using entity wrapper.
$node_wrapper = entity_metadata_wrapper('node', $node);
// Get the contents of the field collection.
$values = $node_wrapper->field_usf_projects;
// Loop field_usf_projects.
foreach ($values as $item) {
// Print the values of the fields.
var_dump($item->usf_title->value());
var_dump($item->usf_description->value());
}
}
Instead of dumping, you can add the markup for your
A nicer thing to do would be use the hook_preprocess_node to add the markup straight into the $variables, and print them via template.
https://api.drupal.org/api/drupal/modules!node!node.module/function/template_preprocess_node/7
I can tell you how I'm handling this, event it's a bit dirty and I'm risking to be crucified, but it works for me. If you are inside node template you have $node object. Print it with print_r or similar way and just follow the structure of output to get to your data. It will probably be something like:
$node->field_usf_title['und']...
If you don't have that $node object find node id and load the node with
$node = node_load($nid);
first.
I was finally fed up with Field collection. I cannot get any data. I have used Multifield which is way too much better than Field collection. Please see it at https://www.drupal.org/project/multifield
Let me know what is better multi field or Field Collection.
Thanks!

How can I add custom meta fields in categories?

Does anyone have any idea how to add custom meta fields while making categories and fetch them in the loop in WordPress? I was wondering how to do that without hacking the WordPress core, but if I do – it won't become a hindrance to update WordPress in the future.
A plugin I have found that comes close is Wp-Category-Meta, but it doesn't have the ability to add checkboxes as fields in Edit Categories.
This will be very useful as users can make certain categories "featured", and then the code can use that meta value in the loop to style "featured" categories differently.
The problem:
Wordpress does not have a structure nor method to store "meta" values for taxonomies.
UPDATE 2017: WP 4.4+ has "term meta"!
For working with term metas use these:
update_term_meta()
get_term_meta()
delete_term_meta()
add_term_meta()
The Actions below are still valid though! :)
Additional reading: 4.4 Taxonomy Roundup
Solution for WP version <= 4.3.x and COMMON actions
Actions:
create_category and edit_category for category edit
category_add_form_fields and category_edit_form for category form fields
There are more actions than I've presented, but they seem to be deprecated (according to developer.wordpress.org).
The reason I chose the actions that I chose:
- They work on WordPress 4.4.2
- Due to lack of documentation I assumed these are the new ones replacing the deprecated ones...
Functions:
get_option( $option, $default );
update_option( $option, $new_value, $autoload );
update_option has two great abilities:
a) It craetes the option when such option does not exist yet
Unless you need to specify the optional arguments of add_option(),
update_option() is a useful catch-all for both adding and updating
options.
b) $new_value can be an integer, string, array, or object.
You may ask, why to use array/object? ...well, because each option = 1 database row => you probably want to store your category options in one row :)
The CODE
function my_category_form_fields($tag_object){
//output/display extra form fields, e.g. by echo ...
//ADD EXTRA SPECIFIC FIELD TO LATER CHECK IF IT'S CATEGORY SAVE/EDIT!
//(see note at 'edit_category' action...)
if( !empty($tag_object['term_id']) ){
//edit category form specific
//...load existing options with get_option( $option, $default );
} else {
//create category form specific
}
}
function my_category_save(){
//CHECK FOR YOUR EXTRA SPECIFIC FIELD TO CHECK IF IT'S CATEGORY SAVE/EDIT
//(see note at 'edit_category' action...)
//SECURITY CHECK
if( empty($_POST['EXTRA_SPECIFIC_FIELD']) || ! current_user_can('manage_categories') )
return null;
//save your form values using update_option()
//Recommendation:
//Add "category_" prefix and $category_id to your option name!
}
add_action( 'create_category', 'my_category_save', 10, 1 );
//Runs when a category is updated/edited,
//INCLUDING when a post or blogroll link is added/deleted or its categories are updated
//(which causes the count for the category to update)
add_action( 'edit_category', 'my_category_save', 10, 1 );
add_action( 'category_add_form_fields', 'my_category_form_fields', 10, 1 );
add_action( 'category_edit_form', 'my_category_form_fields', 10, 1 );
Create or Edit?
You might wonder whether you are creating or saving a category - this not documented yet (as far as I know), but from testing:
Edit save => $tag_object is object and contains some properties, most notably:
term_id
taxonomy
filter
Create save => $tag_object is just a regular string "category" - I guess this might change in the future...
General taxonomy
There are also actions like these for taxonomies in general - check these actions.
Jaz,
It looks like the plugin you mention in your original question has been updated to include a checkbox field (included in v1.2.3)
I think the Category SEO Meta Tags plugin will help you.
There is an updated and refactured version of this plugin to be found here:
https://wordpress.org/plugins/custom-taxonomy-category-and-term-fields/
Also added a WYSIWYG editor fieldtype.

Setting a drupal view to a random page number

I have views 2 installed and I have created a view that is displayed in the front page.
The view displays some page links ( 1 | 2 | 3 | 4 | ... etc). I want to know if it's possible to make the view start at a random page instead of always starting at page 1.
Note: I don't want to randomize the display I really just want to randomize the page it loads.
Thanks
Possible Solution:
In the views_pre_execute hook I used this:
$view->query->pager->set_current_page([random value]);
I am not sure I can determine the number of total pages in the pager at this time but I am going to keep investigating (The $view object given in the hook has tons of properties with arrays and other objects which makes this complicated)
I do not know how to do this from the Views UI, but you should be able to achieve this using one of the views module hooks, in this case probably hook_views_pre_execute. Unfortunately, the documentation for these is practically non existing, so you'd need to implement the hook in a custom module and inspect the passed in view object via the debugger (or print, var_dump, etc. statements).
You should look for $view->pager['current_page'], which you can set to a random page. Unfortunately, if I read the code correctly, the count query that determines the possible number of pages is not yet run at this point, so you'll either have to use a 'best guess', or come up with a different way to determine the proper range to select from...
NOTE: This is in no way meant as an 'authoritative' answer - just a pointer where I'd start looking, since nobody else has answered this so far. I might well be missing a more obvious/easy solution :/
Another option would be to randomize the entries in your views. So your page would always be page 1 but it achieves your objective of seeing something different every time come on your site.
In your sort criteria (in the Global Group) add
Global: Random -- Randomize the display order.
(Inspired by suggestion at http://mydrupal.com/random_node_or_front_page_in_drupal_like_stumbleupon )
I have just created a custom pager that goes automatically to last page and I think it is related to what your are trying to do :
In project.info :
files[] = plugins/views_plugin_pager_last.inc
In project.module :
function cvoxm_views_plugins(){
return array(
'pager' => array(
'last' => array(
'title' => t('Paged output, full pager and last by default'),
'short title' => t('Full & Last'),
'help' => t('Paged output, full Drupal style and last by default'),
'handler' => 'views_plugin_pager_last',
'help topic' => 'pager-last',
'uses options' => TRUE,
),
)
);
}
And the content of plugins/views_plugin_pager_last.inc is :
class views_plugin_pager_last extends views_plugin_pager_full {
function pre_execute(&$query) {
if(!isset($_GET['page'])){ // TODO: Should use pager_id
// Go to last page
$this->set_current_page($this->get_total_items() / $this->get_items_per_page() - 1 );
$this->query(); // Rebuild query
$this->update_page_info(); // Update info
}
}
}

Resources