How do you create a basic Wordpress admin pointer? - wordpress

I have been looking around for quite awhile now and all I have found are tutorials from 3-4 years ago that explain how to do a pointer tour. All I want to do is add a pointer that pops up when someone activates my plugin so that I can notify them of a new menu option where they will go to view my plugin settings. Any help would be greatly appreciated!

Pointers in WP need 3 components:
1: wp-pointer css file
2: wp-pointer JS file
3: A JavaScript snippet
To 1 and 2
include them simply with:
wp_enqueue_style( 'wp-pointer' );
and
wp_enqueue_script( 'wp-pointer' );
The JS code:
<script type="text/javascript">
(function($){
var options = {"content":"<h3>Personal Data and Privacy<\/h3><h4>Personal Data Export and Erasure<\/h4><p>New <strong>Tools<\/strong> have been added to help you with personal data export and erasure requests.<\/p><h4>Privacy Policy<\/h4><p>Create or select your site’s privacy policy page under <strong>Settings > Privacy<\/strong> to keep your users informed and aware.<\/p>","position":{"edge":"left","align":"bottom"},"pointerClass":"wp-pointer arrow-bottom","pointerWidth":420}, setup;
if ( ! options )
return;
options = $.extend( options, {
close: function() {
$.post( ajaxurl, {
pointer: 'wp500_isrc_pointer',
action: 'dismiss-wp-pointer'
});
}
});
setup = function() {
$('#menu-settings').first().pointer( options ).pointer('open');
};
if ( options.position && options.position.defer_loading )
$(window).bind( 'load.wp-pointers', setup );
else
$(document).ready( setup );
})( jQuery );
</script>
Of Course you need to wrap all them in a php file to check the user capabilities and check the dismiss from the users meta.
I have copied the WP pointer class in wp-admin/includes/class-wp-internal-pointers and made a custom one from it.
Here the complete code which i can call it with an action hook like:
add_action( 'admin_enqueue_scripts', array( 'isrc_Internal_Pointers', 'enqueue_scripts') );
add_action( 'user_register',array( 'isrc_Internal_Pointers', 'dismiss_pointers_for_new_users' ) );
The Full PHP file (include it in your code and call the 2 actions):
<?php
/**
* Administration API: WP_Internal_Pointers class
*
* #package WordPress
* #subpackage Administration
* #since 4.4.0
*/
/**
* Core class used to implement an internal admin pointers API.
*
* #since 3.3.0
*/
final class isrc_Internal_Pointers {
/**
* Initializes the new feature pointers.
*
* #since 3.3.0
*
* All pointers can be disabled using the following:
* remove_action( 'admin_enqueue_scripts', array( 'WP_Internal_Pointers', 'enqueue_scripts' ) );
*
* Individual pointers (e.g. wp390_widgets) can be disabled using the following:
* remove_action( 'admin_print_footer_scripts', array( 'WP_Internal_Pointers', 'pointer_wp390_widgets' ) );
*
* #static
*
* #param string $hook_suffix The current admin page.
*/
public static function enqueue_scripts( $hook_suffix ) {
/*
* Register feature pointers
*
* Format:
* array(
* hook_suffix => pointer callback
* )
*
* Example:
* array(
* 'themes.php' => 'wp390_widgets'
* )
*/
$registered_pointers = array(
'index.php' => 'wp500_isrc_pointer',
);
// Check if screen related pointer is registered
if ( empty( $registered_pointers[ $hook_suffix ] ) )
return;
$pointers = (array) $registered_pointers[ $hook_suffix ];
/*
* Specify required capabilities for feature pointers
*
* Format:
* array(
* pointer callback => Array of required capabilities
* )
*
* Example:
* array(
* 'wp390_widgets' => array( 'edit_theme_options' )
* )
*/
$caps_required = array(
'wp500_isrc_pointer' => array(
'install_plugins'
),
);
// Get dismissed pointers
$dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );
$got_pointers = false;
foreach ( array_diff( $pointers, $dismissed ) as $pointer ) {
if ( isset( $caps_required[ $pointer ] ) ) {
foreach ( $caps_required[ $pointer ] as $cap ) {
if ( ! current_user_can( $cap ) )
continue 2;
}
}
// Bind pointer print function
add_action( 'admin_print_footer_scripts', array( 'isrc_Internal_Pointers', 'pointer_'.$pointer ) );
$got_pointers = true;
}
if ( ! $got_pointers )
return;
// Add pointers script and style to queue
wp_enqueue_style( 'wp-pointer' );
wp_enqueue_script( 'wp-pointer' );
}
/**
* Print the pointer JavaScript data.
*
* #since 3.3.0
*
* #static
*
* #param string $pointer_id The pointer ID.
* #param string $selector The HTML elements, on which the pointer should be attached.
* #param array $args Arguments to be passed to the pointer JS (see wp-pointer.js).
*/
private static function print_js( $pointer_id, $selector, $args ) {
if ( empty( $pointer_id ) || empty( $selector ) || empty( $args ) || empty( $args['content'] ) )
return;
?>
<script type="text/javascript">
(function($){
var options = <?php echo wp_json_encode( $args ); ?>, setup;
if ( ! options )
return;
options = $.extend( options, {
close: function() {
$.post( ajaxurl, {
pointer: '<?php echo $pointer_id; ?>',
action: 'dismiss-wp-pointer'
});
}
});
setup = function() {
$('<?php echo $selector; ?>').first().pointer( options ).pointer('open');
};
if ( options.position && options.position.defer_loading )
$(window).bind( 'load.wp-pointers', setup );
else
$(document).ready( setup );
})( jQuery );
</script>
<?php
}
/**
* Display a pointer for wp500_isrc_pointer
*
* #since 4.9.6
*/
public static function pointer_wp500_isrc_pointer() {
$content = '<h3>' . __( 'Personal Data and Privacy' ) . '</h3>';
$content .= '<h4>' . __( 'Personal Data Export and Erasure' ) . '</h4>';
$content .= '<p>' . __( 'New <strong>Tools</strong> have been added to help you with personal data export and erasure requests.' ) . '</p>';
$content .= '<h4>' . __( 'Privacy Policy' ) . '</h4>';
$content .= '<p>' . __( 'Create or select your site’s privacy policy page under <strong>Settings > Privacy</strong> to keep your users informed and aware.' ) . '</p>';
if ( is_rtl() ) {
$position = array(
'edge' => 'right',
'align' => 'bottom',
);
} else {
$position = array(
'edge' => 'left',
'align' => 'bottom',
);
}
$js_args = array(
'content' => $content,
'position' => $position,
'pointerClass' => 'wp-pointer arrow-bottom',
'pointerWidth' => 420,
);
self::print_js( 'wp500_isrc_pointer', '#menu-settings', $js_args );
}
/**
* Prevents new users from seeing existing 'new feature' pointers.
*
* #since 3.3.0
*
* #static
*
* #param int $user_id User ID.
*/
public static function dismiss_pointers_for_new_users( $user_id ) {
add_user_meta( $user_id, 'dismissed_wp_pointers', 'wp500_isrc_pointer' );
}
}

What you are looking for is WordPress Activation / Deactivation Hooks. For example:
register_activation_hook( __FILE__, 'pluginprefix_function_to_run' );
And on pluginprefix_function_to_run, display a nice message to let users know that you've added a menu using admin_notices:
function my_admin_notice() {
?>
<div class="updated">
<p><?php _e( 'Your message goes here!', 'my-text-domain' ); ?></p>
</div>
<?php
}
function pluginprefix_function_to_run() {
add_action( 'admin_notices', 'my_admin_notice' );
}

Related

Keep encoded link after order is completed in wordpress

Hey guys is there a way to keep encoded link after order is completed in wordpress?
It looks good in cart and checkout:
link
But not so good in order review and admin order review
link
I use encodeURIComponent to encode every url param:
My example link that i generate
EDIT
Product creation page: https://isodos.lt/produktas/pinigine/ If you want to see order review page you can add it to the cart and test buy it with random name etc.
Btw, i took php code from somewhere, not my code, im not good with php, especially in wordpress
//small example
const graviravimasFinished = document.querySelector("#iconic-engraving-finished");
if(tf1text === "nerNieko" || tf1text === ""){
tf1TxtFinal = "";
}else{
let txt1TxtEncoded = encodeURIComponent(tf1text);
tf1TxtFinal = `&tf1inner=${txt1TxtEncoded}`;
}
tf1TxtFinal = `${tf1TxtFinal}${tf1TopFinal}${tf1LeftFinal}${tf1SizeFinal}${tf1FontFinal}`;
tf2TxtFinal = `${tf2TxtFinal}${tf2TopFinal}${tf2LeftFinal}${tf2SizeFinal}${tf2FontFinal}`;
tf3TxtFinal = `${tf3TxtFinal}${tf3TopFinal}${tf3LeftFinal}${tf3SizeFinal}${tf3FontFinal}`;
graviravimasFinished.value = `Stilius`;
<?php
function iconic_output_engraving_field() {
global $product;
if ( $product->get_id() !== 5296 ) {
return;
}
?>
<!-- Graviravimo tekstas -->
<div style="padding-bottom: 10px" class="iconic-engraving-field">
<!-- Info -->
<input style="display: none;" type="text" id="iconic-engraving-finished" name="iconic-engraving-finished">
</div>
<?php
}
add_action( 'woocommerce_before_add_to_cart_button', 'iconic_output_engraving_field', 10 );
/**
* Add engraving text to cart item.
*
* #param array $cart_item_data
* #param int $product_id
* #param int $variation_id
*
* #return array
*/
function iconic_add_engraving_text_to_cart_item( $cart_item_data, $product_id, $variation_id ) {
$engraving_text = filter_input( INPUT_POST, 'iconic-engraving-finished' );
if ( empty( $engraving_text ) ) {
return $cart_item_data;
}
$cart_item_data['iconic-engraving-finished'] = $engraving_text;
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'iconic_add_engraving_text_to_cart_item', 10, 3 );
/**
* Display engraving text in the cart.
*
* #param array $item_data
* #param array $cart_item
*
* #return array
*/
function iconic_display_engraving_text_cart( $item_data, $cart_item ) {
if ( empty( $cart_item['iconic-engraving-finished'] ) ) {
return $item_data;
}
$item_data[] = array(
'key' => __( 'Graviravimas', 'iconic-finished' ),
'value' => $cart_item['iconic-engraving-finished'] ,
'display' => '',
);
return $item_data;
}
add_filter( 'woocommerce_get_item_data', 'iconic_display_engraving_text_cart', 10, 2 );
/**
* Add engraving text to order.
*
* #param WC_Order_Item_Product $item
* #param string $cart_item_key
* #param array $values
* #param WC_Order $order
*/
function iconic_add_engraving_text_to_order_items( $item, $cart_item_key, $values, $order ) {
if ( empty( $values['iconic-engraving-finished'] ) ) {
return;
}
$item->add_meta_data( __( 'Graviravimas', 'iconic-finished' ), $values['iconic-engraving-finished'] );
}
add_action( 'woocommerce_checkout_create_order_line_item', 'iconic_add_engraving_text_to_order_items', 10, 4 );

Blank output value from Wordress custom admin settings field

I've added the example cod shown below. This works like a charm. But I am unable to output the saved values on my page.
Using:
get_option( 'title' )
appears to have no value, despite the new admin section properly saving a value for it.
I've also tried get_option( 'title','does not work' ) and confirmed that 'title' is empty, as it's outputting default value of 'does not work'
Here is the code I've added to the function file. All appears fine in admin and saves values as expected. (this is example #2 here: https://codex.wordpress.org/Creating_Options_Pages)
class MySettingsPage
{
/**
* Holds the values to be used in the fields callbacks
*/
private $options;
/**
* Start up
*/
public function __construct()
{
add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
add_action( 'admin_init', array( $this, 'page_init' ) );
}
/**
* Add options page
*/
public function add_plugin_page()
{
// This page will be under "Settings"
add_options_page(
'Settings Admin',
'My Settings',
'manage_options',
'my-setting-admin',
array( $this, 'create_admin_page' )
);
}
/**
* Options page callback
*/
public function create_admin_page()
{
// Set class property
$this->options = get_option( 'my_option_name' );
?>
<div class="wrap">
<h1>My Settings</h1>
<form method="post" action="options.php">
<?php
// This prints out all hidden setting fields
settings_fields( 'my_option_group' );
do_settings_sections( 'my-setting-admin' );
submit_button();
?>
</form>
</div>
<?php
}
/**
* Register and add settings
*/
public function page_init()
{
register_setting(
'my_option_group', // Option group
'my_option_name', // Option name
array( $this, 'sanitize' ) // Sanitize
);
add_settings_section(
'setting_section_id', // ID
'My Custom Settings', // Title
array( $this, 'print_section_info' ), // Callback
'my-setting-admin' // Page
);
add_settings_field(
'id_number', // ID
'ID Number', // Title
array( $this, 'id_number_callback' ), // Callback
'my-setting-admin', // Page
'setting_section_id' // Section
);
add_settings_field(
'title',
'Title',
array( $this, 'title_callback' ),
'my-setting-admin',
'setting_section_id'
);
}
/**
* Sanitize each setting field as needed
*
* #param array $input Contains all settings fields as array keys
*/
public function sanitize( $input )
{
$new_input = array();
if( isset( $input['id_number'] ) )
$new_input['id_number'] = absint( $input['id_number'] );
if( isset( $input['title'] ) )
$new_input['title'] = sanitize_text_field( $input['title'] );
return $new_input;
}
/**
* Print the Section text
*/
public function print_section_info()
{
print 'Enter your settings below:';
}
/**
* Get the settings option array and print one of its values
*/
public function id_number_callback()
{
printf(
'<input type="text" id="id_number" name="my_option_name[id_number]" value="%s" />',
isset( $this->options['id_number'] ) ? esc_attr( $this->options['id_number']) : ''
);
}
/**
* Get the settings option array and print one of its values
*/
public function title_callback()
{
printf(
'<input type="text" id="title" name="my_option_name[title]" value="%s" />',
isset( $this->options['title'] ) ? esc_attr( $this->options['title']) : ''
);
}
}
if( is_admin() )
$my_settings_page = new MySettingsPage();
Your options are saved under a single key my_option_name, so you would access the individual options like:
$my_options = get_option( 'my_option_name' );
echo $my_options['title'];
echo $my_options['id_number'];

Creating breadcrumbs without plugin WordPress

How can i create breadcrumb home->page->post name when we click on main menu any page, open the list of post that time breadcrumb create home ->page name its ok but now when we click on any post that time breadcrumb create home->post category name->post name is is that when we click on post category name on breadcrumb layout shown different we want to its goes on page link, not category link. so we need to when we open any post we need to create the breadcrumb like this home->page name->post name so when we click on page name open the post list page, not category page.
WordPress doesn't provide builtin breadcrumbs functionality. Thus you'll have to either use a plugin or else code it yourself (or copy from the reference below).
As a matter of fact, the plugin or custom code, if providing similar functionality, make not much of a difference. Thus use the one which is more convenient for you.
If you would like to add a custom code, here are few resources which I could look up on search:
https://www.techpulsetoday.com/wordpress-breadcrumbs-without-plugin/
https://www.thewebtaylor.com/articles/wordpress-creating-breadcrumbs-without-a-plugin
https://www.codexworld.com/wordpress-how-to-display-breadcrumb-without-plugin/
https://gist.github.com/tinotriste/5387124
You can look into them and modify them as you wish!
I hope it helps!
I can't understand how an answer with only pasted links can get to that many upvote. The regular WordPress breadcrumb approach is painfully unoptimized, most of the one out there do not suit custom themes. I decided to built a URL based breadcrumb which is, from my point of view, far more efficient and adaptable. I wanted something generic, SEO friendly, without any default styling. It needed also to properly handle posts and pages title.
Version
Requires at least WordPress:
5.0.0
Requires at least PHP:
7.0.0
Tested up to WordPress:
6.0.2
The latest version is available on my GitHub as an unofficial WordPress plugin.
<?php
/**
* Checks if a string ends with a given substring.
* Backward compatibility for PHP < 8.0.0.
*
* #since 1.2.0
* #param String $haystack The string to search in.
* #param String $needle The substring to search for in the haystack.
* #return Boolean
*/
if ( ! function_exists( 'backward_compatibility_str_ends_with' ) ) {
function backward_compatibility_str_ends_with( $haystack, $needle ) {
$length = strlen( $needle );
if ( ! $length ) {
return true;
};
return substr( $haystack, -$length ) === $needle;
};
};
/**
* Determine if a string contains a given substring.
* Backward compatibility for PHP < 8.0.0.
*
* #since 1.2.0
* #param String $haystack The string to search in.
* #param String $needle The substring to search for in the haystack.
* #return Boolean
*/
if ( ! function_exists( 'backward_compatibility_str_contains' ) ) {
function backward_compatibility_str_contains( $haystack, $needle ) {
if ( strpos( $haystack, $needle ) !== false ) {
return true;
};
};
};
/**
* Retrieve the crumbs.
*
* #since 1.0.0
* #return Array Crumbs array.
*/
if ( ! function_exists( 'get_the_crumbs' ) ) {
function get_the_crumbs() {
/**
* $_SERVER["REQUEST_SCHEME"] seems to be UNRELIABLE.
*
* Article "Is $_SERVER['REQUEST_SCHEME'] reliable?".
* #see https://stackoverflow.com/a/18008178/3645650
*
* $_SERVER['REQUEST_SCHEME'] is a native variable of Apache web server since its version 2.4.
* Naturally, if a variable is not set by the server, PHP will not include it in its global array $_SERVER.
*
* An alternative to $_SERVER['REQUEST_SCHEME'] is $_SERVER['HTTPS'] which set to a non-empty value if the script was queried through the HTTPS protocol.
*
* Article "How to find out if you're using HTTPS without $_SERVER['HTTPS']".
* #see https://stackoverflow.com/a/16076965/3645650
*/
if ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) {
$server_scheme = 'https';
} elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || ! empty( $_SERVER['HTTP_X_FORWARDED_SSL'] ) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on' ) {
$server_scheme = 'https';
} else {
$server_scheme = 'http';
};
/**
* $_SERVER["REQUEST_URI"] seems to be RELIABLE.
* $_SERVER['REQUEST_URI'] will not be empty in WordPress, because it is filled in wp_fix_server_vars() (file wp-includes/load.php).
*
* Article "Is it safe to use $_SERVER['REQUEST_URI']?".
* #see https://wordpress.stackexchange.com/a/110541/190376
*/
$server_uri = $_SERVER['REQUEST_URI'];
/**
* $_SERVER["HTTP_HOST"] seems to be RELIABLE.
*
* Article "How reliable is HTTP_HOST?".
* #see https://stackoverflow.com/a/4096246/3645650
*/
$server_host = $_SERVER["HTTP_HOST"];
if ( backward_compatibility_str_contains( $server_uri, '?' ) ) {
$server_uri = substr( $server_uri, 0, strpos( $server_uri, '?' ) );
};
if ( backward_compatibility_str_ends_with( $server_uri, '/' ) ) {
$server_uri = explode( '/', substr( $server_uri, 1, -1 ) );
} else {
$server_uri = explode( '/', substr( $server_uri, 1 ) );
};
$crumbs = array();
foreach ( $server_uri as $crumb ) {
$slug = esc_html( urldecode( $crumb ) );
$url = esc_url( $server_scheme . '://' . $server_host . '/' . substr( implode( '/', $server_uri ), 0, strpos( implode( '/', $server_uri ), $crumb ) ) . $crumb. '/' );
array_push( $crumbs,
array(
'slug' => $slug,
'url' => $url,
)
);
};
/**
* WordPress, by default, doesn't generate a taxonomy index, meaning https://.../taxonomy will redirect to a 404.
* Any request needs to be made against a term. eg: https://.../taxonomy/term will redirect to taxonomy.php.
* Therefore we need to remove the taxonomy slug from the crumbs array to avoid displaying a link to a 404.
*
* We round up all taxonomies through get_taxonomies().
* #see https://developer.wordpress.org/reference/functions/get_taxonomies/
*
* Through array_filter we filter-out any matching crumbs.
* #see https://www.php.net/manual/en/function.array-filter.php
*/
$banned_slugs = array();
$taxonomies = get_taxonomies(
array(
'public' => true,
),
'objects'
);
foreach ( $taxonomies as $taxonomy ) {
array_push( $banned_slugs, $taxonomy->name );
if ( isset( $taxonomy->rewrite['slug'] ) ) {
array_push( $banned_slugs, $taxonomy->rewrite['slug'] );
};
};
$banned_crumbs = array();
foreach ( $banned_slugs as $banned_slug ) {
$slug = esc_html( $banned_slug );
$url = esc_url( $server_scheme . '://' . $server_host . '/' . substr( implode( '/', $server_uri ), 0, strpos( implode( '/', $server_uri ), $banned_slug ) ) . $banned_slug. '/' );
array_push( $banned_crumbs,
array(
'slug' => $slug,
'url' => $url,
)
);
};
$crumbs = array_filter( $crumbs, function( $crumb ) use ( $banned_slugs ) {
if ( ! in_array( $crumb['slug'], $banned_slugs ) && ! in_array( $crumb['url'], $banned_slugs ) ) {
return ! in_array( $crumb['slug'], $banned_slugs );
};
} );
return $crumbs;
};
};
/**
* Display the bread, a formatted crumbs list.
*
* #since 1.0.0
* #param Array $ingredients The bread arguments.
* #param Array $ingredients['crumbs'] The crumbs array. Default to get_the_crumbs().
* #param Array $ingredients['root'] Root crumb. Default to null.
* #param String $ingredients['root']['slug'] Root crumb slug.
* #param String $ingredients['root']['url'] Root crumb url.
* #param String $ingredients['separator'] The crumb's separator.
* #param Integer $ingredients['offset'] Crumbs offset. Accept positive/negative Integer. Default to "0". Refer to array_slice, https://www.php.net/manual/en/function.array-slice.php.
* #param Integer $ingredients['length'] Crumbs length. Accept positive/negative Integer. Default to "null". Refer to array_slice, https://www.php.net/manual/en/function.array-slice.php.
* #return Array The formatted crumbs list.
*/
if ( ! function_exists( 'the_bread' ) ) {
function the_bread( $ingredients = array() ) {
if ( empty( $ingredients['crumbs'] ) ) {
$crumbs = get_the_crumbs();
} else {
$crumbs = $ingredients['crumbs'];
};
if ( empty( $ingredients['root'] ) ) {
$root = null;
} else {
$root = $ingredients['root'];
};
if ( empty( $ingredients['offset'] ) ) {
$offset = 0;
} else {
$offset = $ingredients['offset'];
};
if ( empty( $ingredients['length'] ) ) {
$length = null;
} else {
$length = $ingredients['length'];
};
/**
* Handling the root crumb case.
* Prepend one or more elements to the beginning of an array.
* #see https://www.php.net/manual/en/function.array-unshift.php
*/
if ( ! empty( $root ) ) {
array_unshift( $crumbs, $ingredients['root'] );
};
/**
* Handling the length case.
* Extract a slice of the array.
* #see https://www.php.net/manual/en/function.array-slice.php
*/
$crumbs = array_slice( $crumbs, $offset, $length );
if ( ! empty( $crumbs ) ) {
echo '<ol class="🍞 bread" itemscope itemtype="https://schema.org/BreadcrumbList">';
$i = 0;
foreach ( $crumbs as $crumb ) {
$i++;
/**
* Unparsing the slug.
*/
if ( url_to_postid( $crumb['url'] ) ) {
$title = get_the_title( url_to_postid( $crumb['url'] ) );
} elseif ( get_page_by_path( $crumb['slug'] ) ) {
$title = get_the_title( get_page_by_path( $crumb['slug'] ) );
} else {
$title = ucfirst( str_replace( '-', ' ', $crumb['slug'] ) );
};
echo '<li class="crumb" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
<a itemprop="item" href="' . $crumb['url'] . '">
<span itemprop="name">' . $title . '</span>
</a>
<meta itemprop="position" content="' . $i . '">
</li>';
if ( $i !== sizeof( $crumbs ) && ! empty( $ingredients['separator'] ) ) {
echo $ingredients['separator'];
};
};
echo '</ol>';
};
};
};
Displaying the bread, a formatted crumbs list.
<?php
the_bread( $ingredients = array() );
Parameters
Parameter
Description
$ingredients
(Optional) Array The bread arguments.
$ingredients['crumbs']
Array The crumbs array. Default to get_the_crumbs().
$ingredients['root']
Array Root crumb. Default to null.
$ingredients['root']['slug']
(Required if $ingredients['root']). Root crumb slug.
$ingredients['root']['url']
(Required if $ingredients['root']). Root crumb url.
$ingredients['separator']
The crumb's separator.
$ingredients['offset']
Crumbs offset. Accept positive/negative Integer. Default to 0. Refer to array_slice.
$ingredients['length']
Crumbs length. Accept positive/negative Integer. Default to null. Refer to array_slice.
Example: The bread with a custom separator
<?php
$ingredients = array(
'separator' => 'β†’',
);
the_bread( $ingredients );
Example: Displaying the last 3 crumbs
<?php
$ingredients = array(
'offset' => -3,
'length' => 3,
);
the_bread( $ingredients );
Example: The bread with a root crumb
<?php
$ingredients = array(
'root' => array(
'slug' => 'home',
'url' => get_home_url(),
),
);
the_bread( $ingredients );
Example: Intercepting the crumbs array
<?php
//Intercept the crumbs array...
$crumbs = get_the_crumbs();
//... Do something with it:
//In our case we're appending a new crumb to the crumbs array.
array_push( $crumbs, array(
'slug' => 'search',
'url' => 'https://.../search/',
) );
$ingredients = array(
'crumbs' => $crumbs,
);
the_bread( $ingredients );
HTML5 structure output
<ol class="🍞 bread" itemscope="" itemtype="https://schema.org/BreadcrumbList">
<li class="crumb" itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem">
<a itemprop="item" href="http://example.com/where/">
<span itemprop="name">Where</span>
</a>
<meta itemprop="position" content="1">
</li>
>
<li class="crumb" itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem">
<a itemprop="item" href="http://example.com/where/is/">
<span itemprop="name">Is</span>
</a>
<meta itemprop="position" content="2">
</li>
>
<li class="crumb" itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem">
<a itemprop="item" href="http://example.com/where/is/my/">
<span itemprop="name">My</span>
</a>
<meta itemprop="position" content="3">
</li>
>
<li class="crumb" itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem">
<a itemprop="item" href="http://example.com/where/is/my/bread/">
<span itemprop="name">Bread</span>
</a>
<meta itemprop="position" content="4">
</li>
</ol>
Minimal css boilerplate (Optional)
.🍞,
.bread {
list-style-type: none;
margin:0;
padding:0;
}
.🍞 li,
.bread li {
display:inline-block;
}
.🍞 li.crumb:last-child a,
.bread li.crumb:last-child a {
text-decoration: none;
pointer-events: none;
color: inherit;
}
Retrieving the crumbs
Even tho we recommend you to use the_bread() function to display and build your own breadcrumb, you can use get_the_crumbs() to retrieve the crumbs object.
Example: Outputting the crumbs object
<?php
var_dump( get_the_crumbs() );
A minimalistic breadcrumbs generator in a few lines as a filter:
add_filter( 'my_get_breadcrumbs', [ $this, 'the_breadcrumbs' ], 10, 1 );
/**
* Returns a list of all the breadcrumbs for the current page.
* usage: apply_filters( 'my_get_breadcrumbs', false )
*
* #param $max_depth int
*
* #return string
*/
function the_breadcrumbs() {
$crumbs = '';
$current_page_id = get_the_ID();
$parent = wp_get_post_parent_id( $current_page_id );
$index = 0;
while ( $parent ) {
$index ++;
$crumbs = '<li>' . get_the_title( $parent ) . '</li>' . $crumbs;
$parent = wp_get_post_parent_id( $parent );
if ( $index > 10 ) {
break;
}
}
return $crumbs . '<li><a>' . get_the_title( $current_page_id ) . '</a></li>';
}

how to get wp_editor to save data in plugin admin page

I'm trying to use plugin settings api to add wp_editor, but the text/html is not saving.
// add the admin settings and such
add_action('admin_init', 'wp_myplugin_admin_init');
function wp_myplugin_admin_init(){
register_setting( 'wp_myplugin_settings', 'wp_myplugin_settings', 'wp_myplugin_settings_validate');
add_settings_field('wp_myplugin_user_custom_text', __('Enter your message','WP-wp_myplugin'), 'wp_myplugin_user_custom_text', 'wp_myplugin', 'wp_myplugin_main');
function wp_myplugin_user_custom_text() {
$options = get_option('wp_myplugin_settings');
$settings = array('textarea_rows' => 5,'textarea_name' => 'user_cutom _text_msg');
wp_editor( $options['user_custom_text'],'user_custom_text', $settings );}
// validate
function wp_myplugin_settings_validate() {
$options = get_option('wp_myplugin_settings');
$user_custom_text = $input['user_custom_text'];
if ( empty($user_custom_text) ){
$options['user_custom_text'] = $user_custom_text;
}else{
$options['user_custom_text'] = __('Enter your own text','WP-wp_myplugin');// as set when the plugin activated
I used the $input['user_custom_text'];
all I needed was $_POST['user_custom_text'];
also to get the media to work need wordpress Sanitize:
<?php wp_kses_post( $data ); ?>
http://codex.wordpress.org/Function_Reference/wp_kses_post
Incase there are anyone who followed the steps on the Creating Options Page on the Wordpress Codex and finding a hard time saving their input, you can use the below code to make sure the wp_editor saves your input.
<?php
class MySettingsPage
{
/**
* Holds the values to be used in the fields callbacks
*/
private $options;
/**
* Start up
*/
public function __construct()
{
add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
add_action( 'admin_init', array( $this, 'page_init' ) );
}
/**
* Add options page
*/
public function add_plugin_page()
{
// This page will be under "Settings"
add_options_page(
'Settings Admin',
'My Settings',
'manage_options',
'my-setting-admin',
array( $this, 'create_admin_page' )
);
}
/**
* Options page callback
*/
public function create_admin_page()
{
// Set class property
$this->options = get_option( 'my_option_name' );
?>
<div class="wrap">
<h1>My Settings</h1>
<form method="post" action="options.php">
<?php
// This prints out all hidden setting fields
settings_fields( 'my_option_group' );
do_settings_sections( 'my-setting-admin' );
submit_button();
?>
</form>
</div>
<?php
}
/**
* Register and add settings
*/
public function page_init()
{
register_setting(
'my_option_group', // Option group
'my_option_name', // Option name
array( $this, 'sanitize' ) // Sanitize
);
add_settings_section(
'setting_section_id', // ID
'My Custom Settings', // Title
array( $this, 'print_section_info' ), // Callback
'my-setting-admin' // Page
);
add_settings_field(
'my_content', //This ID of the field you want to use wp_editor for
'Write Your Content Here',
array( $this, 'my_content_callback' ),
'my-setting-admin',
'setting_section_id'
);
}
/**
* Sanitize each setting field as needed
*
* #param array $input Contains all settings fields as array keys
*/
public function sanitize( $input )
{
$new_input = array();
if( isset( $input['my_content'] ) )
$new_input['my_content'] = wp_kses_post( $input['my_content'] );
return $new_input;
}
/**
* Print the Section text
*/
public function print_section_info()
{
print 'Enter your settings below:';
}
/**
* Get the settings option array and print one of its values
*/
public function my_content_callback()
{
$args = array (
'media_buttons' => false,
'textarea_rows' => '10',
'textarea_name' => 'my_option_name[my_content]'
);
$options = get_option('my_option_name');
wp_editor( $options['my_content'], 'my_content', $args );
}
}
if( is_admin() )
$my_settings_page = new MySettingsPage();

Create template for custom post types in Wordpress

I know how to create a custom template for a specific page. However I would like to create a template for a specific custom post type. Is that possible and if true how can I do that?
If I create a new template it will show in admin only when I'm adding a page, but when I'm adding a new post type I don't have the option to select a certain template.
Problem resolved:
/*
Show the list of available custom templates templates in the Custom Post Type admin section
*/
/**
* Post_type
*/
define( 'MY_THEME_POST_TYPE', 'cases' );
/**
* Load the page template for any post object
* having the appropriate meta key set.
*/
add_action( 'template_redirect', 'mytheme_template_redirect' );
function mytheme_template_redirect() {
global $wp_query;
$id = (int) $wp_query->get_queried_object_id();
$template = get_post_meta( $id, '_wp_page_template', true );
if ( $template && 'default' !== $template ) {
$file = STYLESHEETPATH . '/' . $template;
if( is_file( $file ) ) {
require_once $file;
exit;
}
}
}
/**
* Process the Meta Box
* #todo Permissions check.
* #todo Filter input.
* #todo Nonces.
*/
add_action( 'save_post', 'mytheme_process_resource_template' );
function mytheme_process_resource_template() {
global $post;
/* Sanitize $_POST array. */
$clean_id = ( isset( $_POST['ID'] ) ) ? intval( $_POST['ID'] ) : 0;
if ( !empty( $_POST['page_template'] ) && MY_THEME_POST_TYPE == $post->post_type ) {
$page_templates = get_page_templates();
if ( 'default' != $page_template && !in_array( $_POST['page_template'], $page_templates ) ) {
if ( $wp_error )
return new WP_Error('invalid_page_template', __('The page template is invalid.'));
else
return 0;
}
update_post_meta( $clean_id, '_wp_page_template', $_POST['page_template'] );
}
}
/**
* Registers the Meta Box
* #uses mytheme_page_attributes_meta_box()
*/
add_action( 'admin_init', 'mytheme_register_meta_boxes', 10 );
function mytheme_register_meta_boxes() {
add_meta_box(
'mytheme_post_type_template',
'Template',
'mytheme_page_attributes_meta_box',
MY_THEME_POST_TYPE,
'side',
'low'
);
}
/**
* Creates the Meta Box
*/
function mytheme_page_attributes_meta_box() {
global $post;
$post_type_object = get_post_type_object($post->post_type);
if ( 0 != count( get_page_templates() ) ) {
$template = get_post_meta( $post->ID, '_wp_page_template', true );
?>
<p><strong><?php _e('Template') ?></strong></p>
<label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label><select name="page_template" id="page_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php page_template_dropdown( $template ); ?>
</select>
<?php
}
}
Create page that is called:
single-{cpt-slug}.php e.g. single-product.php
It will be used when showing a page of a custom post type. i.e. when someone goes to http://example.com/product/awesome-shoes/

Resources