Navigating through Wordpress sibling pages using functions.php - wordpress

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

Related

WordPress prevent delete taxonomy

I would like to prevent that some categories are accidentally deleted. For this I use a meta entry for the category to be protected.
I use the following code for this:
// edit: wrong hook! ** add_action( 'delete_term_taxonomy', 'taxonomy_delete_protection', 10, 1 );
add_action( 'pre_delete_term', 'taxonomy_delete_protection', 10, 1 );
function taxonomy_delete_protection ( $term_id )
{
if (get_term_meta ($term_id, 'delete-protect', true) === true)
{
wp_die('Cannot delete this category');
}
}
Unfortunately, instead of my error message, only "Something went wrong" is displayed. Why?
Edit: The `delete_term_taxonomy` is the wrong hook for my code, because it deleted the meta before i can check the meta entry. `pre_delete_term` does fire before anything happens with the category.
The "Why" is because of the following JavaScript that ships with WordPress:
$.post(ajaxurl, data, function(r){
if ( '1' == r ) {
$('#ajax-response').empty();
tr.fadeOut('normal', function(){ tr.remove(); });
/**
* Removes the term from the parent box and the tag cloud.
*
* `data.match(/tag_ID=(\d+)/)[1]` matches the term ID from the data variable.
* This term ID is then used to select the relevant HTML elements:
* The parent box and the tag cloud.
*/
$('select#parent option[value="' + data.match(/tag_ID=(\d+)/)[1] + '"]').remove();
$('a.tag-link-' + data.match(/tag_ID=(\d+)/)[1]).remove();
} else if ( '-1' == r ) {
$('#ajax-response').empty().append('<div class="error"><p>' + wp.i18n.__( 'Sorry, you are not allowed to do that.' ) + '</p></div>');
tr.children().css('backgroundColor', '');
} else {
$('#ajax-response').empty().append('<div class="error"><p>' + wp.i18n.__( 'Something went wrong.' ) + '</p></div>');
tr.children().css('backgroundColor', '');
}
});
The expected response to this POST request is:
'1' if the term was deleted
'-1' if your user doesn't have permission to delete the term.
For all other cases, "Something went wrong" is displayed.
You are terminating the script early with wp_die, yielding an unexpected response, which comes under "other cases".
There isn't a way to provide a custom error message in the notice box here without writing some JavaScript of your own.
This is my current solution, not perfect but it works.
The "Something went wrong" message show up if you delete the taxonomy with the row action. So i unset the "delete" action so it couldn't be triggered this way.
add_filter ('category_row_actions', 'unset_taxonomy_row_actions', 10, 2);
function unset_taxonomy_row_actions ($actions, $term)
{
$delete_protected = get_term_meta ($term->term_id, 'delete-protect', true);
if ($delete_protected)
{
unset ($actions['delete']);
}
return $actions;
}
Then i hide the "Delete" Link in the taxonomy edit form with css. It's still could be triggered if you inspect the site and it's link, but there is no hook to remove this action otherwise.
add_action( 'category_edit_form', 'remove_delete_edit_term_form', 10, 2 );
function remove_delete_edit_term_form ($term, $taxonomy)
{
$delete_protected = get_term_meta ($term->term_id, 'delete-protect', true);
if ($delete_protected)
{
// insert css
echo '<style type="text/css">#delete-link {display: none !important;}</style>';
}
}
Finally the check before deleting the taxonomy. This should catch all other ways, like the bulk action "delete". I didn't found another way yet to stop the script from deleting the taxonomy.
add_action ('pre_delete_term', 'taxonomy_delete_protection', 10, 1 );
function taxonomy_delete_protection ( $term_id )
{
$delete_protected = get_term_meta ($term_id, 'delete-protect', true);
if ($delete_protected)
{
$term = get_term ($term_id);
$error = new WP_Error ();
$error->add (1, '<h2>Delete Protection Active!</h2>You cannot delete "' . $term->name . '"!');
wp_die ($error);
}
}
This solution provides a way to disable all categories from being deleted by a non Admin. This is for anyone like myself who's been searching.
function disable_delete_cat() {
global $wp_taxonomies;
if(!current_user_can('administrator')){
$wp_taxonomies[ 'category' ]->cap->delete_terms = 'do_not_allow';
}
}
add_action('init','disable_delete_cat');
The easiest solution (that will automatically take care of all different places where you can possibly delete the category/term) and in my opinion the most flexible one is using the user_has_cap hook:
function maybeDoNotAllowDeletion($allcaps, $caps, array $args, $user)
{
if ($args[0] !== 'delete_term') return $allcaps;
// you can skip protection for any user here
// let's say that for the default admin with id === 1
if ($args[1] === 1) return $allcaps;
$termId = $args[2];
$term = get_term($termId);
// you can skip protection for all taxonomies except
// some special one - let's say it is called 'sections'
if ($term->taxonomy !== 'sections') return $allcaps;
// you can protect only selected set of terms from
// the 'sections' taxonomy here
$protectedTermIds = [23, 122, 3234];
if (in_array($termId, $protectedTermIds )) {
$allcaps['delete_categories'] = false;
// if you have some custom caps set
$allcaps['delete_sections'] = false;
}
return $allcaps;
}
add_filter('user_has_cap', 'maybeDoNotAllowDeletion', 10, 4);

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;
}
}
}

$_GET is empty after defining a rewrite rule

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.

Reading node field values in drupal7 programmatically

I am looking for the best way to get a field value from a node id.
My actually code works however I guess there is an easier way.
$node = node_load( 1 );
$lang = $node->language;
$field = 'body';
$value = '';
if ( isset($node->{$field}[$lang]) && isset($node->{$field}[$lang][0]) )
{
$value = $node->{$field}[$lang][0]['value'];
}
echo $value;
Is there any build in drupal function that takes care of this?
Not all of it, but you should be able to simplify it a bit with http://api.drupal.org/api/drupal/modules--field--field.module/function/field_get_items/7.
You still need to check if $items[0] exists and get the 'value' of that.
Thanks #Berdir. I agree field_get_items is a better way. Here is a code example:
<?php
$body = field_get_items('node',$node, 'body');
print $body[0]['value'];
?>

Wordpress creating plugin for most viewed posts problem?

I just want to create plugin that will when visitor(user,visitor,...) visit some post,remember what post,and to increment counter of that post,I wrote this code,but sometimes,counter is incremented,even post isn't viewed,or post with other Id is added to a table.Can someone help me with this,please.I know that there are plugins for this that I'm trying to do,but still want to write this plugin.
function IncrementPostCount($the_content) {
global $post;
global $wpdb;
if(($post->post_status == 'publish') && (int)$post->ID) {
if(is_single()) { // just for single post - not for page
$postID = (int)$post->ID;
$postTitle = urlencode($post->post_title);
$postLink = urlencode(get_permalink($post->ID));
$oneRow = $wpdb->get_row("SELECT * FROM wp_postovi WHERE postAjDi='$postID'");
if(empty ($oneRow)) {
$postCounter = 1;
$data_array = array(
'readnTimes' => $postCounter,
'linkPost'=>$postLink,
'TitlePost'=>$postTitle,
'postAjDi'=>$postID);
$wpdb->insert('wp_najcitaniji_postovi', $data_array);
}
else {
$postCounter = intval($oneRow->readnTimes) + 1;
$data_array = array('readnTimes' => $postCounter);
$where_array = array('postAjDi'=>intval($oneRow->postAjDi));
$wpdb->update('wp_postovi',$data_array,$where_array);
}
return $the_content;
}
return $the_content;
}
}
add_filter('the_content','IncrementPostCount');
Sorry on my bad english,tnx in advance.
Here's how to do that with the postmeta table.
function IncrementPostCount(){
if(is_single()){
global $wp_query;
$count = get_post_meta( $wp_query->post->ID, 'readnTimes', true );
$count = empty($count) ? 1 : $count + 1;
add_post_meta($wp_query->post->ID, 'readnTimes', $count, true) or update_post_meta($wp_query->post->ID, 'readnTimes', $count);
}
}
add_action( 'template_redirect', 'IncrementPostCount' );
Also, it's better to hook it in earlier. That way, the count is only incremented once per page load (the_content can be fired multiple times per page, even on a single page. template_redirect only fires once per request). Also, if you store the data at template_redirect, you can use the updated view count in the template, giving your visitors an even more accurate view count.
And you don't need to worry about database tables, custom SQL, or any of that.

Resources