When is $wp_query initialized and how to override it? - wordpress

I am trying to write a new query function using WP_Query object.
I created a new template file and put the followings:
$query_args = array(
'post_type' => 'page',
'post_parent=41',
);
// The Featured Posts query.
$results = new WP_Query($query_args);
But whatever arguments I use, the query does not change. It looks as if the query is already initialized and creating a new WP_Query does not have any effect on the existing query.
The only wordpress function called before my code is get_header() which does not include any call to WP_Query or query_posts.
I put the following line to find out what the actual sql query is:
echo $GLOBALS['wp_query']->request;
The actual sql query is:
SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND (wp_posts.ID = '14') AND wp_posts.post_type = 'page' ORDER BY wp_posts.post_date DESC
This query does not change when I change my $query_args.
I wonder when the global variable $wp_query is initialized and what should I do to use my own query?

You are creating a new WP_Query object and saving it to $results. That is where the results of your query will be, not in $GLOBALS['wp_query']. Of course it doesn't overwrite $wp_query. They are different things. Try var_dump($results) instead.
You can overwrite $wp_query by creating a new WP_Query object like so: $wp_query = new WP_Query($query_args);. But that isn't efficient. You run two queries when you only need one. The better way to do it is to hook into pre_get_posts. Something like:
function alter_query_so_15250127($qry) {
if ( $qry->is_main_query() && is_page('featured-posts-page') ) {
$qry->set('post_type','page');
$qry->set('post_parent',41);
}
}
add_action('pre_get_posts','alter_query_so_15250127');
The if conditional is very important. You need to use that line to make sure the filter fires only on the page(s) you want it to fire on. Your question does not have enough detail for me to work out the precise conditions.

Have a look at the following diagram as posted in http://codex.wordpress.org/Function_Reference/query_posts

Related

WP All Import Pro: Polylang compatibility

I'm trying to import data from an Excel sheet into WordPress with the Pro version of WP All Import. We are using Polylang for multi language support. I wonder how to manage importing the content into the correct language versions. I discovered that there is a hidden taxonomy "language" which I can manually set to "de" for setting language to German. But how do I link corresponding translations? Any ideas how to solve this, maybe with some custom functions? Thank you in advance!
I have found a better solution.
if ( !function_exists( 'pll_save_post_translations' ) ) {
require_once '/include/api.php'; }
$arr = array();
$result = pll_save_post_translations(['en' => 21398, 'ro'=>21396]);
//where 21398 and 21396 are the post_id and 'en' and 'ro' the nicenames of the languages.
Put this code in your functions.php and run it only once (meaning you refresh the page only once as admin after you put it). Then delete the code from functions.php. It does not actually create errors, just don't risk it, don't run it twice.
Before you do that, you must import the products in both (in my case) languages. Meaning you import them in one language (you select one language from the top admin bar) and then in another session you import them in the other language (you select the other language) and also if you see "Show private taxonomies" in WP All import, put one language code there. One for each session. After the products in both languages have been imported, you run the code above to tell WordPress that "this post_id is the translation of that post_id".
I hope it helps.
Ah, and you get the post_id in a nice table which you can edit in excel by exporting the products with Wordpress Export (it is pre-installed when you install WordPress, I think). You find it in Dashboard in Tools/Export.
And put
$result = pll_save_post_translations(['en' => 56465, 'ro'=>654864]);
as many times as you need
$result = pll_save_post_translations(['en' => 9999, 'ro'=>34654]);
$result = pll_save_post_translations(['en' => 98641, 'ro'=>98651]); .
for each correlation.
You can do it easier in Excel, you have the correlating id's on two separate columns then put this formula on the next row
=concatenate("$result = pll_save_post_translations(['en' =>",CELL A1,"
'ro'=>",CELL B1,"]);")
Apply it downwards. Select the column you have just concatenated. Paste it under the code in functions.php. Save. Refresh. Delete code from functions.php. Refresh. Booyah.
Please note that I'm currently using both Polylang and Wp All Import/Export Pro versions.
Also, this is currently not 'outdated' code. It relies on an undocumented feature, that was suggested directly from the wp all import team. I'm speaking simply of the additional parameter $data passed by the pmxi_saved_post action.
That said, I know polylang devs are currently working on an addon for this specific issue. Anyway, I managed to do it in this way, for now:
1 -> when you export data, there are 2 polylang-related fields: languages and post_translations. Export them too.
2 -> when you import your data, on the wpallimport screen, create 2 more custom fields and save the 2 above. See attachment below. Now you've got the translations data with every post.
3 -> set this filter:
global $language_codes;
$language_codes = array( // sample lang data
'italiano' => 'it'
,'english' => 'en'
,'espanol' => 'es'
,'francais' => 'fr'
,'deutsch' => 'de'
);
add_action('pmxi_saved_post', 'set_imports_lang', 10, 2);
// using undocumented param $data
// action firm is the following (in fact, it passes 3 params): do_action( 'pmxi_saved_post', $pid, $rootNodes[$i], $is_update );
function set_imports_lang($post_id, $data){
global $language_codes;
// 'lingue' is italian, I guess it will be 'languages' in english: it's one of the 2 fields we saved before
pll_set_post_language($post_id, $language_codes[sanitize_title($data->lingue)]);
}
At this point you have just set each post's original language, nothing more. Now we have to link translations each other. We'll do this with a function that we have to run ONLY 1 TIME. It will run simply reloading any wp screen/page.
function set_imports_translations(){
global $wpdb;
global $language_codes;
// substitute 'enews' with your own post type
$list = $wpdb->get_results("
SELECT
m.post_id, m.meta_value pll, group_concat(concat_ws(':', m2.meta_value, m.post_id)) ids
FROM
$wpdb->posts p
INNER JOIN $wpdb->postmeta m ON p.ID = m.post_id
INNER JOIN $wpdb->postmeta m2 ON m.post_id = m2.post_id AND m2.meta_key = '_import_language_name'
WHERE
p.post_type = 'enews' AND m.meta_key = '_import_translations_id'
GROUP BY pll
");
// query results are something like this:
// 10258 pll_57e92254c445f 10258:Italiano,10259:English,10260:Español,10261:Français,10262:Deutsch
// 10263 pll_57e922552b8c6 10263:Italiano,10264:English,10265:Español,10266:Deutsch
// 10267 pll_57e9225587124 10267:Italiano
// extract data from the third column string
foreach($list as $item){
$ids = explode(',',$item->ids);
$list = array();
foreach($ids as $id){
$data = explode(':',$id);
$list[$language_codes[sanitize_title($data[0])]] = intval($data[1]);
}
//set the translations
pll_save_post_translations($list);
}
}
set_imports_translations();
That's all. :) Ah, the attachment mentioned above:

Wordpress - showing last uploaded images, but only from a specific custom post type

I have a Wordpress-powered website with several custom post types, and I'm struggling to find a way to load the latest uploaded images from one of the custom post types only.
In other words, I know how to ask for the most recent 4 images added to the Wordpress media library, but I can't find a way to filter the attachments depending of the post type of their parent page (in this case, show only the images uploaded to 'Image Gallery' posts - not regular posts, not 'Video Gallery' posts, etc).
It feels like a very basic question, but for some reason I can't get this work and I'm really frustrated. Is there any way to get the post type of the post parent in the query? Or I should approach this issue from another angle?
I don't believe it's possible to use WP_Query to filter based on the post type of the parent. The most straightforward way around this is to use SQL and $wpdb->get_results() directly. This will also bypass all built in caching, etc so think about how your implementation will be used.
global $wpdb;
// the SQL statement to only fetch the N last attachments
$sql = <<<SQL
SELECT attachments.*
FROM {$wpdb->posts} attachments
-- join the parent post based on the parent_post value to filter by cpt
JOIN {$wpdb->posts} post
ON post.ID = attachments.post_parent
AND post.post_status = 'publish'
-- pass in the custom post type
AND post.post_type = %s
WHERE
-- only fetch images, double percents for prepare()
attachments.post_mime_type LIKE 'image%%'
ORDER BY attachments.post_date DESC
-- pass in the number to fetch
LIMIT %d
SQL;
$cpt = "your_custom_post_type";
$limit = 4;
$attachments = $wpdb->get_results( $wpdb->prepare( $sql, $cpt, $limit ) );
foreach ( $attachments as $attachment ){
// $attachment will have all the rows from the posts table.
$id = $attachment->ID;
}

Accessing WordPress query var from a function hooked to woocommerce_add_to_cart_validation

I need to perform a check before adding a product to a WooCommerce cart. The check is based on a value stored in a WordPress query var. The problem is I can not access the $WP_Query from a function fired on the *woocommerce_add_to_cart_validation* hook.
The basic idea I'm trying to use for that is expressed in the following code:
add_action('woocommerce_add_to_cart_validation', 'the_function_to_go_with', 1, 5);
function the_function_to_go_with($passed, $product_id, $quantity) {
global $WP_Query;
$product_city = get_query_var('product_city');
$product_cat = get_query_var('product_cat');
*// a set of if clauses for the actual check*
}
If printed out to a file, the $WP_Query returns NULL. So, neither the query vars are returned.
An advice of what I am missing here would be much appreciated.

Wordpress: How to combine keyword search and meta filter in WP_query

I am trying to combine the search by keyword and meta_key and meta_value filter in WP_query. Keyword search and meta filter works good independently, but together are not. How to get it done? Thanks!
Here is my code:
if ( isset($_REQUEST['search']) AND $_REQUEST['search'] )
{
$query_param = array( 's' => urldecode($_REQUEST['search']), 'post_type' => GOODS_POST_TYPE );
$query_param['meta_key'] = 'sku';
$query_param['meta_value'] = urldecode($_REQUEST['search']);
}
$query = new WP_Query($query_param);
Modify your query before the search is run, and use Wordpress' built-in functions to do what you need rather than relying on unfiltered data:
<?php
add_action('pre_get_posts', 'modify_goods_search');
function modify_goods_search($query)
{
if($query->is_search)
{
$query->set('meta_key', 'sku');
$query->set('meta_value', get_search_query());
$query->set('post_type', GOODS_POST_TYPE);
}
}
?>
Remember that this will modify ALL searches. If you want to modify only one particular search, you can modify the conditional to make sure you're on a particular page before modifying the given query.
You might also want to consider using meta_query rather than just meta_key and meta_value.
Information on everything:
Pre Get Posts
Custom Field Parameters in Meta Query
Get Search Query

wordpress plugin creation get_post_meta

I am building my first plugin, and I am using as a reference the following link.
http://www.sitepoint.com/create-a-voting-plugin-for-wordpress/
and I am trying to underestand the following part of the code:
function voteme_addvote()
{
$results = '';
global $wpdb;
$post_ID = $_POST['postid'];
$votemecount = get_post_meta($post_ID, '_votemecount', true) != '' ? get_post_meta($post_ID, '_votemecount', true) : '0';
$votemecountNew = $votemecount + 1;
update_post_meta($post_ID, '_votemecount', $votemecountNew);
$results.='<div class="votescore" >'.$votemecountNew.'</div>';
// Return the String
die($results);
}
I run the code and it works, but I just dont understand the following:
What is "get_post_meta" doing?
Does it create a custom meta field, the same as add_post_meta?, if it doesnt why there is not an add_post_meta?
I checked the DB, and it looks like it is creating a custom meta field... so in that order what is the difference between get_post_meta and add_post_meta?
Thanks very much for helping me understand this.
The first time your code runs, get_post_meta returns '' so $votemecount is set to 0. The following update_post_meta creates the new meta field as documented below. Values that start with _ are not displayed (are hidden meta fields).
The function, update_post_meta(), updates the value of an existing meta key (custom field) for the specified post.
This may be used in place of add_post_meta() function. The first thing this function will do is make sure that $meta_key already exists on $post_id. If it does not, add_post_meta($post_id, $meta_key, $meta_value) is called instead and its result is returned.

Resources