Which method will have higher priority? - wordpress

There are two approaches for limiting revisions in WordPress; WP_POST_REVISIONS and wp_revisions_to_keep(). Which will have higher priority ? I could not understand even after reading codex.

WP_POST_REVISIONS is constant, not a function. if you have set WP_POST_REVISIONS like this: define( 'WP_POST_REVISIONS', 3 ); then you'll get 3 when you'll call the function wp_revisions_to_keep (provided that there is no filter who is modifying the value). If WP_POST_REVISIONS is not set then it will store every revision and you'll get -1 when you'll call wp_revisions_to_keep. This is the source code of wp_revisions_to_keep.
/**
* Determine how many revisions to retain for a given post.
* By default, an infinite number of revisions are stored if a post type supports revisions.
*
* #since 3.6.0
*
* #uses post_type_supports()
* #uses apply_filters() Calls 'wp_revisions_to_keep' hook on the number of revisions.
*
* #param object $post The post object.
* #return int The number of revisions to keep.
*/
function wp_revisions_to_keep( $post ) {
$num = WP_POST_REVISIONS;
if ( true === $num )
$num = -1;
else
$num = intval( $num );
if ( ! post_type_supports( $post->post_type, 'revisions' ) )
$num = 0;
return (int) apply_filters( 'wp_revisions_to_keep', $num, $post );
}
From this, it is clear that function wp_revisions_to_keep() uses WP_POST_REVISIONS inside it. However, to be 100% sure that your suggested number of revisions work then you should hook a function to wp_revisions_to_keep. Something like this:-
add_filter('wp_revisions_to_keep', 'custom_revisions_number', 10, 2);
function custom_revisions_number($num, $post) {
$num = 5; // <---- change this accordingly.
return $num;
}
Highest priority is of the hook that will execute last.

Related

"woocommerce_can_reduce_order_stock" filter is not working on backend

I have a custom order status called 'quote', and I have added the following code to try and prevent stock levels being decremented for orders with this status.
function bw_do_not_reduce_quote_stock( $reduce_stock, $order ) {
if ( $order->has_status( 'quote' ) ) {
$reduce_stock = false;
}
return $reduce_stock;
}
add_filter( 'woocommerce_can_reduce_order_stock', 'bw_do_not_reduce_quote_stock', 10, 2 );
This works for orders placed on the front-end website. But if the admin adds or edits an order on the backend, the stock is decremented.
Is there an alternative hook for the backend? Or am I missing something else?
In addition to your current code, add the woocommerce_prevent_adjust_line_item_product_stock filter hook
/**
* Prevent adjust line item
*
* #param $prevent
* #param $item
* #param $quantity
*/
function filter_woocommerce_prevent_adjust_line_item_product_stock ( $prevent, $item, $quantity ) {
// Get order
$order = $item->get_order();
if ( $order->has_status( 'quote' ) ) {
$prevent = true;
}
return $prevent;
}
add_filter( 'woocommerce_prevent_adjust_line_item_product_stock', 'filter_woocommerce_prevent_adjust_line_item_product_stock', 10, 3 );

Override Items Per Page in WP Admin for Post Type

I'm trying to override the number of Items Per Page that a user sets in Screen Options for a specific post type (WP Admin only, not the front end). In this case and for a specific post type, I'd like it to list all posts (regardless of user-set limit) when you click on the post type in WP Admin (edit.php).
I've searched and tried several filter and action hooks but nothing has worked. I'm confident that it is possible.
WordPress 4.9.7
PHP 7.1.17
Multisite
Thank you,
Daniel
EDIT: I forgot to mention - I'm trying to do this from a plugin.
WordPress tries to derive this from the wp_usermeta table if it exists, otherwise it just defaults to 20. You can filter the metavalue and provide a different default - the key may change if on a multisite so you should check the usermeta table if need be.
/**
* Override pagination settings
*
* #param Integer $meta_value
* #param Integer $user_id
* #param String $meta_key
*
* #return Integer $meta_value
*/
function so51343268( $meta_value, $user_id, $meta_key ) {
/**
* The specific meta key is a combination of the post type and keywords.
* For 'post' it would be: `edit_post_per_page`
* For 'category' it would be: `edit_category_per_page`
*/
if( false !== strpos( $meta_key, '_per_page' ) ) {
/* Object Type Slug => Pagination Override */
$unpaginated_types = array(
'post' => 999,
'category' => 4,
);
/* Remove prefix and postfix to get the object type */
$type = rtrim( ltrim( $meta_key, 'edit_' ), '_per_page' );
if( isset( $unpaginated_types[ $type ] ) ) {
$meta_value = $unpaginated_types[ $type ];
}
}
return $meta_value;
}
add_filter( 'get_user_metadata', 'so51343268', 10, 3 );

Any change in post update inlcuding metadata?

Having code below (given in a class)
class X
{
public function __construct()
{
add_action( 'post_updated', array( $this, 'datachangecheck' ), 10, 3 );
}
function datachangecheck( $post_id, $post_after, $post_before )
{
if ( $post_before->post_title != $post_after->post_title )
{
//do whatever
}
return;
}
}
Above works fine when checking if a title has been changed, but is there any away way of managing the same thing when having metadata related to it?
I only want to know if any data has changed (I don't need any returned values). I can't manage to find any hook where I can see like meta_post_before and meta_post_after or similar. Can someone point me into right direction? Thank you!
This was kind of tricky, so I guess someone else might have the same issue so I share some code here and hopefully someone has any help from it :-) I have the most important part in the code below:
public function __construct()
{
add_action( 'post_updated', array( $this, 'datachangecheck' ), 10, 3 );
}
/*
* datachangecheck
*
* This function is called upon hook post_updated.
* The function checks if data for updated post has been changed,
* and saves a file when data has been changed
*
* #param string $post_id id of post affected
* #param WP_Post $post_after WP_Post after post has been updated
* #param WP_Post $post_before WP_Post before post has been updated
* #return N/A
*
*/
function datachangecheck( $post_id, $post_after, $post_before )
{
//Cast postobjects into arrays, so comparision is possible with builtin-php functions
$spf = (array)$post_before;
$spa = (array)$post_after;
//These would differ every update. so remove them for possible comparision
unset ( $spf['post_modified']);
unset ( $spf['post_modified_gmt']);
unset ( $spa['post_modified']);
unset ( $spa['post_modified_gmt']);
//Check if any difference between arrays (if empty no difference)
//If not empty, save file that tells plugin that data has been changed
$ard = array_diff ( $spf, $spa);
if ( !empty ( $ard ) )
{
$this->datahaschanged_save();
}
else
{
//No change of post native data, check if any metapost data has been changed
//Remove edit_last and edit_lock because they could differ without data being changed
$this->metadata_before = get_post_meta( $post_id );
unset ( $this->metadata_before['_edit_last']);
unset ( $this->metadata_before['_edit_lock']);
add_action('updated_post_meta', array( $this, 'checkmetadata_after'), 10, 2);
}
return;
}
/*
* checkmetadata_after
*
* This function is called upon hook updated_post_meta when data has been update, but no change in native post data
* has been made and saves a file when data has been changed
*
* #param string $post_id id of post affected
* #param WP_Post $post_after WP_Post after post has been updated
* #param WP_Post $post_before WP_Post before post has been updated
* #return N/A
*
*/
function checkmetadata_after( $meta_id, $post_id )
{
//Because updated_post_meta is used, now we can grab the actual updated values
//Remove edit_last and edit_lock because they could differ without data being changed
$this->metadata_after = get_post_meta( $post_id );
unset ( $this->metadata_after['_edit_last']);
unset ( $this->metadata_after['_edit_lock']);
//Make one-level index arrays of metadata
//so array_diff works correctly down below
$arr_mdb = $this->onelevel_array( $this->metadata_before );
$arr_mda = $this->onelevel_array( $this->metadata_after );
//Compare array with metapost values before and after
//If not empty, save file that tells plugin that data has been changed
$ard_metadata = array_diff ( $arr_mdb, $arr_mda );
if (!empty ( $ard_metadata))
{
$this->datahaschanged_save();
}
return;
}

How to create multiple content blocks in wordpress?

thanks in advance for explaining the idea of creating multiple content blocks in Wordpress post editor in the admin panel. I tried searching for similar thread before asking and couldn't find any answer.
What I need is to create an additional content field along with the default one. What functions do I need to implement please? I found a plugin "Multiple Content Blocks" in wordpress plugin library but I believe this simple task will require fewer codes. I hope I have explained well what I need. Thanks again!
Oldish question, but since it was the first hit on my google search I'll add my method - there are a few major issues with the accepted answer, primarily:
using a meta box, when the documentation clearly states that it is not safe for wp_editor().
using sanitize_text_field() to sanitize html (which removes all html!)
This file can be dropped into your theme folder or at the bottom of your functions.php, and all posts and pages will get an additional editor.
If using a separate file just remember to include it from your functions.php:
include __DIR__ . '/my_extra_content.php';
Obviously you should do a search for "my_" and replace with something meaningful - "extra_content" may also be a tad too generic, so come up with something more exotic.
<?php
//Use a class to avoid conflicts
class my_extra_content {
/**
* Called on instantiation, this is where we hook functions
*/
function __construct() {
/* Using add_meta_box seems like the correct way to do this, but since
* we're inserting a TinyMCE editor we cannot (should not) - from codex:
* ---
* Once instantiated, the WYSIWYG editor cannot be moved around in the
* DOM. What this means in practical terms, is that you cannot put it in
* meta-boxes that can be dragged and placed elsewhere on the page.
* Instead use 'edit_page_form' (for pages) or 'edit_form_advanced'
* (for other post types).
*/
add_action( 'edit_page_form', array($this, 'my_extra_content_custom_box') );
add_action( 'edit_form_advanced', array($this, 'my_extra_content_custom_box') );
/* This one saves the content */
add_action( 'save_post', array($this, 'save_postdata' ));
}
/**
* This actually outputs the tinyMCE box
*/
function my_extra_content_custom_box( $post ) {
/* Always use a nonce */
wp_nonce_field( 'my_extra_content_custom_box', 'my_extra_content_custom_box_nonce' );
/* Get the content */
$content = self::get_content($post);
/* Insert the editor */
wp_editor( $content, "my_extra_content");
}
/**
* Saves the content
*/
function save_postdata( $post_id ) {
/* Check that nonce was sent */
if ( ! isset( $_POST['my_extra_content_custom_box_nonce'] ) ) {
return $post_id;
}
/* Check that nonce is valid */
if ( ! wp_verify_nonce( $_POST['my_extra_content_custom_box_nonce'], 'my_extra_content_custom_box' ) ) {
return $post_id;
}
/* Don't try to do anything on autosave (custom fields aren't included) */
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
/* Check permissions */
if ( 'page' === get_post_type( $post_id ) ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}
/* Sanitize content - we don't use sanitize_text_field() as it strips all
* HTML, which is clearly not wanted with a wysiwyg - wp_kses_post()
* should do what we want */
$sane_content = wp_kses_post( $_POST['my_extra_content'] );
/* Save content - notice the underscore in the meta name - it hides the
* field from the "normal" custom field editor */
update_post_meta( $post_id, '_my_extra_content_content', $sane_content );
}
/**
* Static function makes it easy to get the value wherever you need it.
* - for example:
* $my_extra_content = my_extra_content::get_content()
*/
static function get_content($post_or_post_id = null) {
/* First find the post id */
$post_id = false;
if ($post_or_post_id === null) {
/* If nothing was passed, try to get it from global post object */
global $post;
$post_or_post_id = $post->ID;
}
if (is_a($post_or_post_id, 'WP_Post')) {
/* If a post object was passed, or we're using the global $post */
$post_id = $post_or_post_id->ID;
} elseif (is_numeric($post_or_post_id)) {
/* If a number (hopefully a post id) was passed */
$post_id = intval($post_or_post_id);
}
/* Try to get the value */
$value = get_post_meta($post_id, '_my_extra_content_content', true );
/* If we didn't get a valid string return an empty one */
if (!is_string($value)) {
return '';
}
return $value;
}
/**
* Static function to very easily output the content in a template
* - for example:
* my_extra_content::echo_content()
*/
static function echo_content( $post_or_post_id = null ) {
$output = self::get_content($post_or_post_id);
/* do_shortcode makes sure we support shortcodes (if that is wanted) */
// $output = do_shortcode($output);
/* the_content filter will apply all normal filters (including
* do_shortcode) to the content (not required!) */
$output = apply_filters( 'the_content', $output);
/* print it */
echo $output;
}
}
/* Instantiate the class - because of the static functions used to fetch the
* content we won't need to ever use this variable, we just need __construct()
* to be called, so our hooks are added */
$extra_content_throwaway_var = new my_extra_content();
First of all adding content editors to Wordpress edit pages is a lot harder than it sounds, so if you are not familiar with the save/update cycle and metaboxes then I would recommend using a plugin. I like "Advanced Custom Fields" but I'm sure "Multiple Content Blocks" is good too.
In any case I have outlined a general Custom Meta Box solution here. So here we go:
The wp_editor() function is what we use to create an editor instance. http://codex.wordpress.org/Function_Reference/wp_editor
However, I would call this within a meta box.
http://codex.wordpress.org/add_meta_box
Here is some sample code that creates a meta box with a content editor in it.
This plugin stores the value of the content editor in a custom field called _hurtigtech_extra_content that gets saved when the post/page is updated update.
You can drop this plugin into the plugins folder /wp-content/plugins/ and play with it there. Feel free to leave comments if you need help with this, I know it is a lot of code so again the plugins might be best, but this is also a good baseline if you feel confident.
<?php
/**
* Plugin Name: Extra Metabox Content Editor
*/
/**
* Adds a box to the main column on the Post and Page edit screens.
*/
function hurtigtech_add_custom_box() {
$screens = array( 'post', 'page' );
foreach ( $screens as $screen ) {
add_meta_box(
'hrutigtech_extra_content_section',
__( 'My Post Extra Content', 'hurtigtech_translations' ),
'hurtigtech_inner_custom_box',
$screen
);
}
}
add_action( 'add_meta_boxes', 'hurtigtech_add_custom_box' );
/**
* Prints the box content.
*
* #param WP_Post $post The object for the current post/page.
*/
function hurtigtech_inner_custom_box( $post ) {
// Add an nonce field so we can check for it later.
wp_nonce_field( 'hurtigtech_inner_custom_box', 'hurtigtech_inner_custom_box_nonce' );
/*
* Use get_post_meta() to retrieve an existing value
* from the database and use the value for the form.
*/
$value = get_post_meta( $post->ID, '_hurtigtech_extra_content', true );
echo '<br />';
wp_editor( $value, "hurtigtech_extra_content_editor");
}
/**
* When the post is saved, saves our custom data.
*
* #param int $post_id The ID of the post being saved.
*/
function hurtigtech_save_postdata( $post_id ) {
/*
* We need to verify this came from the our screen and with proper authorization,
* because save_post can be triggered at other times.
*/
// Check if our nonce is set.
if ( ! isset( $_POST['hurtigtech_inner_custom_box_nonce'] ) )
return $post_id;
$nonce = $_POST['hurtigtech_inner_custom_box_nonce'];
// Verify that the nonce is valid.
if ( ! wp_verify_nonce( $nonce, 'hurtigtech_inner_custom_box' ) )
return $post_id;
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return $post_id;
// Check the user's permissions.
if ( 'page' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_page', $post_id ) )
return $post_id;
} else {
if ( ! current_user_can( 'edit_post', $post_id ) )
return $post_id;
}
/* OK, its safe for us to save the data now. */
// Sanitize user input.
$mydata = sanitize_text_field( $_POST['hurtigtech_extra_content_editor'] );
// Update the meta field in the database.
update_post_meta( $post_id, '_hurtigtech_extra_content', $mydata );
}
add_action( 'save_post', 'hurtigtech_save_postdata' );
NOTE: There is a style issue with the content box background. This needs to be added to an editor-style.css file to fix it.
.hurtigtech_extra_content_editor {
background: #fff;
}

get_page_by_title in Wordpress. How to use to fetch posts?

Recently, Wordpress added in the Trac that you can fetch posts by title using:
get_page_by_title
Instead of querying the database straight up. If I wanted to get post titled "my farm", how would I change the parameters so it is searching for a post (or a post type?):
$page_title='Joey in the forest';
'character' is a post type. But don't know how to work this. I assume the default return is the id, which would be $post->ID. Not sure what would be the equivalent if I use a post type.
Thanks for anyone's help on this
I wrote a function (linked in the bug report) which does exactly that:
/**
* Retrieves a post/page/custom-type/taxonomy ID by its title.
*
* Returns only the first result. If you search for a post title
* that you have used more than once, restrict the type.
* Or don’t use this function. :)
* Simple usage:
* $page_start_id = id_by_title('Start');
*
* To get the ID of a taxonomy (category, tag, custom) set $tax
* to the name of this taxonomy.
* Example:
* $cat_css_id = id_by_title('CSS', 0, 'category');
*
* The result is cached internally to save db queries.
*
* #param string $title
* #param string $type Restrict the post type.
* #param string|bool $tax Taxonomy to search for.
* #return int ID or -1 on failure
*/
function id_by_title($title, $type = 'any', $tax = FALSE)
{
static $cache = array ();
$title = mysql_real_escape_string( trim($title, '"\'') );
// Unique index for the cache.
$index = "$title-$type-" . ( $tax ? $tax : 0 );
if ( isset ( $cache[$index] ) )
{
return $cache[$index];
}
if ( $tax )
{
$taxonomy = get_term_by('name', $title, $tax);
$cache[$index] = $taxonomy ? $taxonomy->term_id : -1;
return $cache[$index];
}
$type_sql = 'any' == $type
? ''
: "AND post_type = '"
. mysql_real_escape_string($type) . "'";
global $wpdb;
$query = "SELECT ID FROM $wpdb->posts
WHERE (
post_status = 'publish'
AND post_title = '$title'
$type_sql
)
LIMIT 1";
$result = $wpdb->get_results($query);
$cache[$index] = empty ( $result ) ? -1 : (int) $result[0]->ID;
return $cache[$index];
}
Since I hit upon this page, others might as well.
get_page_by_title() also handles Posts and custom post types.
Please be aware that it gets the first post/page item in the database even if the post is trashed.
Sample:
$post = get_page_by_title('sample-post','post');
echo $post->ID

Resources