$_GET is empty after defining a rewrite rule - wordpress

Hello Wordpress ninjas,
I am new to wordpress develpoment. I define a rewrite rule (with a tag), similar to what you can find in examples here and here.
$wp_rewrite->add_rewrite_tag('%filterx_location%', '([^&/]+)', 'filterx_location=');
$wp_rewrite->add_rule('property-location/(.+)$','index.php?post_type=property&filterx_location=$matches[1]', 'top');
Now, the problem is, that when the query is completed (the page is shown), the filterx_location paramater is not set. In fact, var_dump($_GET) gives me an array(0) { }.
I have a black out or something, seems like something simple I miss here, just cannot figure it out :-/
Any help is much appreciated!
UPDATE
what is even stranger is that when I generate rewrite rules with:
$wp_rewrite->add_rewrite_tag('%filterx_location%', '([^/]+)', 'filterx_location=');
$permalink_prefix = 'property-location';
$permalink_structure = '%filterx_location%/';
$rewrite_rules = $wp_rewrite->generate_rewrite_rules($permalink_prefix.'/'.$permalink_structure, EP_ALL, true, true, true, true, true);
I see a bunch of generated urls matches and redirects, if I print them. One of them is:
property-location/([^/]+)/page/?([0-9]{1,})/?$ => index.php?filterx_location=$matches[1]&paged=$matches[2]&post_type=property
I add all the generated urls with:
foreach($rewrite_rules as $regex => $redirect) {
if(strpos($redirect, 'attachment=') === false) {
//add the post_type to the rewrite rule
$redirect .= '&post_type=property';
}
//turn all of the $1, $2,... variables in the matching regex into $matches[] form
if(0 < preg_match_all('#\$([0-9])#', $redirect, $matches)) {
for($i = 0; $i < count($matches[0]); $i++) {
$redirect = str_replace($matches[0][$i], '$matches['.$matches[1][$i].']', $redirect);
}
}
//add the rewrite rule to wp_rewrite
$wp_rewrite->add_rule($regex, $redirect, 'top');
}
And If I go to the URL /property-location/madrid/page/2/ then the query_vars correctly do have ["paged"]=> int(2). But the filterx_location is totally ignored!

Ok, I got it working, in a strange turn of events. First I replaced
$wp_rewrite->add_rewrite_tag('%filterx_location%', '([^/]+)', 'filterx_location=');
with:
add_rewrite_tag('%filterx_location%', '([^/]+)', 'filterx_location=');
I noticed those are two different things. I took a look into the wordpress code of add_rewrite_tag:
function add_rewrite_tag($tagname, $regex) {
//validation
if ( strlen($tagname) < 3 || $tagname[0] != '%' || $tagname[strlen($tagname)-1] != '%' )
return;
$qv = trim($tagname, '%');
global $wp_rewrite, $wp;
$wp->add_query_var($qv);
$wp_rewrite->add_rewrite_tag($tagname, $regex, $qv . '=');
}
I thought the "add_query_var" part might be essential.
But it still did not work!
So what I did finally was add another call to add_query_var() after the add_rewrite_tag() call:
add_rewrite_tag('%filterx_location%', '([^/]+)', 'filterx_location=');
$wp->add_query_var('filterx_location');
and only then everything started to work. Initially I assumed that $_GET should be holding my variable, but then even calls to get_query_var('filterx_location') were empty. Now it get the right stuff.

Related

wordpress remove post status count from cms

I want to remove the post status count from WordPress edit.php.
My WordPress CMS have more than 500,000 posts. The publish count is loaded every time you open the page. The following query is fired every time.
This makes my Wordpress CMS loading very slow.
SELECT post_status, COUNT( * ) AS num_posts FROM wp_posts WHERE post_type = 'post' GROUP BY post_status
By tracing the code, I've worked up the only solution that I can see.
The filter bulk_post_updated_messages is ONLY called on the edit.php screen.
The counts are not calculated (in class-wp-posts-list-table.php, get_views method) if the global variable $locked_post_status is not empty.
By gluing these two pieces of information together, I've got a solution that you can use by dropping it into your theme's functions.php file:
// Hook this filter, only called on the `edit.php` screen.
// It's not the "correct" filter, but it's the only one we can leverage
// so we're hijacking it a bit.
add_filter('bulk_post_updated_messages', 'suppress_counts', 10, 2);
// We need to let the function "pass through" the intended filter content, so accept the variable $bulk_messages
function suppress_counts($bulk_messages) {
// If the GET "post_type" is not set, then it's the "posts" type
$post_type = (isset($_GET['post_type'])) ? $_GET['post_type'] : 'post';
// List any post types you would like to KEEP counts for in this array
$exclude_post_types = array('page');
// Global in the variable so we can modify it
global $locked_post_status;
// If the post type is not in the "Exclude" list, then set the $locked variable
if ( ! in_array($post_type, $exclude_post_types)) {
$locked_post_status = TRUE;
}
// Don't forget to return this so the filtered content still displays!
return $bulk_messages;
}
i came up with this solution.
//Disable Article Counter - query runs for about 1-2 seconds
add_filter('admin_init', function () {
foreach (get_post_types() as $type) {
$cache_key = _count_posts_cache_key($type, "readable");
$counts = array_fill_keys(get_post_stati(), 1);
wp_cache_set($cache_key, (object)$counts, 'counts');
}
}, -1);
add_action('admin_head', function () {
$css = '<style>';
$css .= '.subsubsub a .count { display: none; }';
$css .= '</style>';
echo $css;
});
the post counter uses the wp-cache, the idea behind this approach is, to prefill the cache with the "correct" object containing 1's (0 would skip the status from being clickable) - at the earliest moment.
it results in all stati being displayed - with 1's and the query is not run et-all
in addition it returns a css snippet to hide the (1)

Drupal HOOK_views_pre_render not working for simple change of $views->result

well I haven't been able to find the problem with my little custom module for a couple of days, I'm hoping some clever and kind person might spot my issue ;)
So I am creating a simple module that runs on a certain view type, this view contains images, the images have alt tags, I want to amend these alt tags by using the url alias and sticking this on the end of the alt tag..
I have successfully found the data in the $view array and I have looped through all image instances and done as said above, I know it has worked because I have printed them out onto the page.
However it is not updating the view on the actual page, the alt tags remain the same... Please excuse my ignorance here as I am learning PHP and multidimensional keyed arrays are taking some time to sink in.
So what is the variable called for the alt tag, an object? I think that's wrong but anyway.. This variable which is ..
$view->result[0]->_field_data['nid']['entity']->field_image_front_menu['und'][0]['alt']
... is being changed, everything seems fine inside the function and I have tried
return $view
but to no avail.
Here is my code in entirety
<?php
function image_alt_tag_alter_views_pre_render(&$view) {
if ($view->name == "we_print_for_menu") {
$path = arg(0) . "/" . arg(1);
$alias = drupal_get_path_alias($path);
// loops through index in array to change each alt tag
for ($i = 0; $i < count($view->result); ++$i) {
$view->result[$i]->_field_data['nid']['entity']->field_image_front_menu['und'][0]['alt'] = $view->result[$i]->_field_data['nid']['entity']->field_image_front_menu['und'][0]['alt'] . $alias;
}
return $view;
?>
<?php
function image_alt_tag_alter_views_post_execute(&$view) {
global $user;
if ($view->name == "we_print_for_menu") {
path = arg(0) . "/" . arg(1);
$alias = drupal_get_path_alias($path);
dsm($view);
for ($i = 0; $i < count($view->result); ++$i) {
$amended_alt = $view->result[$i]->_field_data['nid']['entity']->field_image_front_menu['und'][0]['alt'] . " " . $alias;
$view->result[$i]->_field_data['nid']['entity']->field_image_front_menu['und'][0]['alt'] = $amended_alt;
}
}
}

Navigating through Wordpress sibling pages using functions.php

I'm trying to find a way to get through sibling pages on my wordpress hosted site. After a bit of searching I found this to put into my functions.php:
function siblings($link) {
global $post;
$siblings = get_pages('child_of='.$post->post_parent.'&parent='.$post->post_parent);
foreach ($siblings as $key=>$sibling){
if ($post->ID == $sibling->ID){
$ID = $key;
}
}
$closest = array('before'=>get_permalink($siblings[$ID-1]->ID),'after'=>get_permalink($siblings[$ID+1]->ID));
if ($link == 'before' || $link == 'after') { echo $closest[$link]; } else { return $closest; } }
It's almost perfect for what I need. The only problems are:
It sorts them alphabetically and I need them sorted by the Order Number
I need it to loop (so the last pages links to the first) and not just end
It automatically says "Previous of Next" and I would like to get rid of that "of"
If anyone has input on any of the three issues, I would greatly appreciate it. I'm doing some tinkering myself but I figured that most of you are probably a lot better at this than I am. That, and I've gotten "500 Server Errors" one too many times.
Thanks
Here is your modified piece of code. It solves your first two requests. The last one is not part of provided code. This code does not generate either of mentined words. It only echoes or returns permalinks.
function siblings($link) {
global $post;
$siblings = get_pages('child_of='.$post->post_parent.'&parent='.$post->post_parent.'&sort_column=menu_order');
foreach ($siblings as $key=>$sibling){
if ($post->ID == $sibling->ID){
$ID = $key;
}
}
if( $ID == 0 ){
$closest = array('before'=>get_permalink($siblings[count($siblings)-1]->ID),'after'=>get_permalink($siblings[$ID+1]->ID));
}elseif( $ID == count($siblings)-1 ){
$closest = array('before'=>get_permalink($siblings[$ID-1]->ID),'after'=>get_permalink($siblings[0]->ID));
}else{
$closest = array('before'=>get_permalink($siblings[$ID-1]->ID),'after'=>get_permalink($siblings[$ID+1]->ID));
}
if ($link == 'before' || $link == 'after') { echo $closest[$link]; } else { return $closest; } }
EDIT: Added &sort_column=menu_order to get_pages arguments to solve first request

Drupal PHP block visibility rules

In a Drupal block's Page Visibility Settings I'd like to prevent a certain block from showing if the second value in the path is a number. This does not seem to be working for me. Cheers.
Show block ONLY when arguments are:
domain.com/video/one (arg 0 is 'video' and arg 1 is present and NOT a number)
Don't show:
domain.com/video
domain.com/video/1
<?php
if (arg(0) == 'video' && is_nan(arg(1)) && empty(arg(2))) {
return TRUE;
}
else {
return FALSE;
}
?>
I'm assuming this is in a hook_block/hook_block_view function? You could try a different approach:
if (preg_match('/^video\/[0-9]+$/', $_GET['q'])) {
// Path has matched, don't show the block. Are you sure you should be returning TRUE here?
return TRUE;
}
else {
// Path has matched, go ahead and show the block
return FALSE;
}
You can simply use the following code:
<?php
$arg1 = arg(1);
$arg2 = arg(2);
// Check arg(1) is not empty, or is_numeric() returns TRUE for NULL.
return (arg(0) == 'video' && !empty($arg1) && !is_numeric($arg1) && empty($arg2));
?>
As KingCrunch already said, is_nan() doesn't return TRUE when its argument is a number.
The code you reported contains another error too: empty() can be used only with variables, as reported in the PHP documentation.
empty() only checks variables as anything else will result in a parse error. In other words, the following will not work: empty(trim($name)).
The code I reported shows the block for paths like "video/video1"; if you want to show the block also for paths such as "video/video1/edit", then the following code should be used.
<?php
$arg1 = arg(1);
return (arg(0) == 'video' && !empty($arg1) && !is_numeric($arg1));
?>
Using arg() doesn't work if the path you are looking for is a path alias. Suppose that "video/video1" is a path alias for "node/10"; in that case arg(0) will return "node," and arg(1) will return "10." The same is true for $_GET['q'] that will be equal to "node/10."
This happens because Drupal, during its bootstrap, initialize $_GET['q'] with the following code:
// Drupal 6.
if (!empty($_GET['q'])) {
$_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/'));
}
else {
$_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
}
// Drupal 7.
if (!empty($_GET['q'])) {
$_GET['q'] = drupal_get_normal_path($_GET['q']);
}
else {
$_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
}
If you what you are checking is a path alias, then you should use the following code:
// Drupal 6.
$arg = explode('/', drupal_get_path_alias($_GET['q']);
return (arg[0] == 'video' && !empty($arg[1]) && !is_numeric(arg[1]) && empty($arg[2]));
// Drupal 7.
$arg = explode('/', drupal_get_path_alias();
return (arg[0] == 'video' && !empty($arg[1]) && !is_numeric(arg[1]) && empty($arg[2]));
Dont know, what your arguments looks like, but I assume you mixed up two kinds of types. is_nan() only works with numbers. If you want to test, if a value is a number,
var_dump(is_numeric(arg(1));
is_nan() tests, if a "numeric" value is a concrete value or "not a number" like "infinite" or the result of "0/0" or such.

How do you determine if apachesolr has returned null results

I am looking to execute some code if apachesolr has returned null results for the search query in a separate module. I am looking to leave the apachesolr module and acquia modules untouched.
I was looking for the same thing and found this comment very helpful:
http://drupal.org/node/877346#comment-3310554
Basically you just overwrite the theme_box function in template.php in your theme and check if the title and content matches the default "no results" template.
What I ended up with:
function mytheme_box($title, $content, $region = 'main') {
if ($title == t('Your search yielded no results') &&
$content == variable_get('apachesolr_search_noresults', apachesolr_search_noresults())) {
if ($_GET['fuzzyhelp']) {
// No results with fuzzy, go to landing page for no results.
drupal_goto('search_no_results');
}
// Rewrite search keys with fuzzy characters.
$keys = array_map('trim', explode(' ', search_get_keys()));
drupal_goto('search/apachesolr_search/'. implode('~ ', $keys). '~', 'fuzzyhelp=1');
}
else if ($_GET['fuzzyhelp']) {
// Tell user search was rewritten with fuzzy notations.
drupal_set_message(t('Your exact search did not match any products and was broadened to include all possible matches.'));
}
return $content;
}

Resources