How to add sub-menu in My Account WooCommerce? - woocommerce

I would like to ask some help.
add_filter ( 'woocommerce_account_menu_items', 'misha_one_more_link' );
function misha_one_more_link( $menu_links ){
// we will hook "anyuniquetext123" later
$new = array( 'anyuniquetext123' => 'Gift for you' );
// or in case you need 2 links
// $new = array( 'link1' => 'Link 1', 'link2' => 'Link 2' );
// array_slice() is good when you want to add an element between the other ones
$menu_links = array_slice( $menu_links, 0, 1, true )
+ $new
+ array_slice( $menu_links, 1, NULL, true );
return $menu_links;
}
add_filter( 'woocommerce_get_endpoint_url', 'misha_hook_endpoint', 10, 4 );
function misha_hook_endpoint( $url, $endpoint, $value, $permalink ){
if( $endpoint === 'anyuniquetext123' ) {
// ok, here is the place for your custom URL, it could be external
$url = site_url();
}
return $url;
}
I am using this code to add custom menu on My Account page of WooCommerce:
This worked pretty well but it only adds menu link. I would like to add submenus under Gift for You for example is "For Her" or "For Him".

The only solution I found is to override the file plugins/woocommerce/templates/myaccount/navigation.php and do whatever you want inside ;)

Related

Woocommerce - Adding Custom Fields to Checkout & Custom Dashboard Tab

I have an Multistep Checkout and for that reason i have created a new custom step called "Card-Data", where i want the customer to fill the inputs. This inputs should also appear on a Tab in My Account. I already created a new custom tab for My Account Dashboard.
Can you tell me please, how i can create Custom Fields in the checkout process and and make them visible in the Custom Dashboard Tab. The customer should has the possibility to change data entries on his own through the dashboard.
Many Thanks
// i use multistep checkout wizzard plugin. here i create a step, where user
enters the card data
add_action('woocommerce_multistep_checkout_before', 'add_visica_step');
function add_visica_step() {
$contents = '<h1>Visica Daten</h1>';
$contents .= '<div class="visica-step"> Please Enter something </div>';
echo $contents;
}
add_filter ( 'woocommerce_account_menu_items', 'one_more_link' );
function one_more_link( $menu_links ){
$new = array( 'carddata' => 'Card Data' );
$menu_links = array_slice( $menu_links, 0, 1, true )
+ $new
+ array_slice( $menu_links, 1, NULL, true );
return $menu_links;
}
/*
* Step 2. Register Permalink Endpoint
*/
add_action( 'init', 'add_endpoint' );
function add_endpoint() {
// WP_Rewrite is my Achilles' heel, so please do not ask me for detailed
explanation
add_rewrite_endpoint( 'visicadata', EP_PAGES );
}
/*
* Step 3. Content for the new page in My Account, woocommerce_account_{ENDPOINT
NAME}_endpoint
*/
add_action( 'woocommerce_account_visicadata_endpoint',
'my_account_endpoint_content' );
function my_account_endpoint_content() {
echo 'Here I want do display custom fields from checkout';
}
add_filter( 'woocommerce_checkout_fields' ,
'woocommerce_checkout_field_editor' );
// Our hooked in function - $fields is passed via the filter!
function woocommerce_checkout_field_editor( $fields ) {
$fields['shipping']['shipping_field_value'] = array(
'label' => __('Field Value', 'woocommerce'),
'placeholder' => _x('Field Value', 'placeholder', 'woocommerce'),
'required' => true
);
return $fields;
}
// Display Field on Order Page, but i would like to display it on custom tab
add_action( 'woocommerce_admin_order_data_after_shipping_address',
'edit_woocommerce_checkout_page', 10, 1 );
function edit_woocommerce_checkout_page($order){
global $post_id;
$order = new WC_Order( $post_id );
echo '<p><strong>'.__('Field Value').':</strong> ' . get_post_meta($order->get_id(), '_shipping_field_value', true ) . '</p>';

Solution to Excerpt Customisation with new Gutenberg Editor

I have made several customisations to the native Wordpress Excerpt metabox which no longer seem to work with the new Gutenberg editor and I can find no documentation online that guides me to a solution.
Does anyone know how the following code snippets can be amended to work with the new Gutenberg Editor?
This snippet removes the native Excerpt and repositions it at the top of the Editor screen below the Title metabox:
function remove_normal_excerpt() {
remove_meta_box( 'postexcerpt' , 'post' , 'normal' );
}
add_action( 'admin_menu' , 'remove_normal_excerpt' );
function add_new_excerpt_meta( $post_type ) {
$post_types = get_post_types( array ( 'public' => true ) );
$excluded_posttypes = array ();
$post_type = array_diff($post_types, $excluded_posttypes);
add_meta_box(
'postexcerpt',
__( 'Excerpt', '' ),
'post_excerpt_meta_box',
$post_type,
'advanced',
'high', 0, 0
);
}
add_action( 'add_meta_boxes', 'add_new_excerpt_meta' );
This snippet adds an information notice to the Excerpt metabox:
function excerpt_add_notice( $translation, $original ) {
if ( 'Excerpt' == $original ) {
return 'Excerpt';
}else{
$pos = strpos($original, 'Excerpts are optional hand-crafted summaries of
your');
if ($pos !== false) {
return '<h5 class="notice notice info">Always complete your excerpt
sections.</h5>';
}
}
return $translation;
}
add_filter( 'gettext', 'excerpt_add_notice', 10, 2 );
This snippet adds a javascript character count limit to the Excerpt:
function excerpt_count_js(){
global $post;
if ( get_post_type($post) != 'storefront' ) {
echo '<script>jQuery(document).ready(function(){
jQuery("#postexcerpt .handlediv").after("<div
style=\"position:absolute;top:12px;right:34px;color:#666;\"><small>Excerpt
length: </small><span id=\"excerpt_counter\"></span><span style=\"font-
weight:bold; padding-left:7px;\">/ 170</span><small><span style=\"font-
weight:bold; padding-left:7px;\">character(s).</span></small></div>");
jQuery("span#excerpt_counter").text(jQuery("#excerpt").val().length);
jQuery("#excerpt").keyup( function() {
if(jQuery(this).val().length > 170){
jQuery(this).val(jQuery(this).val().substr(0, 170));
}
jQuery("span#excerpt_counter").text(jQuery("#excerpt").val().length);
});
});</script>';
}
}
add_action( 'admin_head-post.php', 'excerpt_count_js');
add_action( 'admin_head-post-new.php', 'excerpt_count_js');
Is it just a case of something simple as the Excerpt metabox identifiers having been changed?

Custom permalink with dynamic rewrite tags on a Wordpress custom post type

I have a custom post type named location and I'm trying to set posts of this type as children of existing pages, to achieve a permalink structure like this:
example.com/alabama <-- Page with generic content
example.com/alabama/locations <-- Another page, child of a state page
example.com/alabama/locations/location-name <- Custom type, child of alabama/locations seen above and titled `Location Name`
The closest I've got to create hierarchical relationships between two distinct post types was through a meta box where I can assign a post ID as the post_parent of my custom type posts when saving them. However despite the page ID being indeed saved to the CPT post_parent field, it has no effect on the permalinks. They are coming as defined in the rewrite CPT option. But I don't know how to make the ['rewrite']['slug'] option dynamic, or if it's even possible.
This is how my post type is being defined:
add_action( 'init', function() {
register_post_type( 'location', [
'label' => 'Location',
'menu_icon' => 'dashicons-location-alt',
'supports' => [ 'title', 'editor', 'custom-fields' ],
'public' => true,
'hierarchical' => false,
'has_archive' => false,
'rewrite' => false,
] );
} );
How can I configure the rewrite rules for locations to get the permalinks I need?
I'm assuming that all the location posts will have a permalink structure that looks like this:
example.com/{STATE NAME}/locations/{CPT SLUG}
Sample URL addresses:
http://example.com/alabama/locations/location-1
http://example.com/alabama/locations/location-2
http://example.com/new-york/locations/location-3
So if that is correct, then:
• Use the add_rewrite_rule() function to add a custom rewrite rule for those permalinks.
• You don't need the /locations/ Page.
add_action( 'init', function(){
// Handles requests to `your-site-domain.com/{STATE NAME}/locations/{CPT SLUG}`
add_rewrite_rule(
'([^/]+)/locations/([^/]+)(?:/([0-9]+))?/?$',
'index.php?location=$matches[2]&page=$matches[3]&state_name=$matches[1]',
'top'
);
// Allows you to retrieve the `state_name`; for example using `get_query_var()`.
add_rewrite_tag( '%state_name%', '([\w\-]+)' );
} );
(You can change state_name to another name; it's up to you. And don't forget to flush the rewrite rules — go to the Permalink Settings page and click on the Save Changes button without having to make any changes.)
Next, when you create or edit a location post, set the value of the post_parent custom field to the ID of the 'state Page' — e.g. the /alabama/ Page.
And this code will filter the get_permalink() output, and returns the appropriate permalink for a location post:
add_filter( 'post_type_link', 'so51217355_post_type_link', 10, 2 );
function so51217355_post_type_link( $permalink, $post ) {
if ( 'location' === $post->post_type ) {
$page_id = get_post_meta( $post->ID, 'post_parent', true );
$state_name = ( is_numeric( $page_id ) && $page_id ) ?
get_post_field( 'post_name', $page_id ) : null;
// Make sure the post is associated to a valid 'state Page'.
if ( $state_name ) {
$permalink = $state_name . '/locations/' . $post->post_name;
$permalink = home_url( user_trailingslashit( $permalink ) );
}
}
return $permalink;
}
So for example, get_permalink( 123 ) would return http://example.com/alabama/locations/location-1, if the location post's slug is location-1, and its 'state Page' is /alabama/.
UPDATE
When the permalink is requested (i.e. users visit example.com/{STATE NAME}/locations/{CPT SLUG}), and you want to make sure the 'state Page' and location post both exist, and that the 'state Page' was indeed associated to the location post, then this code can help you:
// Validates the `state_name` of the current page/URL.
add_action( 'parse_request', 'so51217355_parse_request' );
function so51217355_parse_request( $wp ) {
if ( ! empty( $wp->query_vars['state_name'] ) &&
! empty( $wp->query_vars['location'] ) ) {
global $wpdb;
$page_id = $wpdb->get_var( $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} WHERE post_name = %s",
$wp->query_vars['state_name']
) );
if ( ! is_numeric( $page_id ) || ! $page_id ) {
$wp->query_vars['error'] = '404';
// Don't let WordPress finds a post with nearest match.
remove_action( 'template_redirect', 'redirect_canonical' );
return;
}
$post_id = $wpdb->get_var( $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} WHERE post_name = %s",
$wp->query_vars['location']
) );
$page_id2 = get_post_meta( $post_id, 'post_parent', true );
if ( (int) $page_id2 !== (int) $page_id ) {
$wp->query_vars['error'] = '404';
// Don't let WordPress finds a post with nearest match.
remove_action( 'template_redirect', 'redirect_canonical' );
}
}
}
UPDATE #2
Refer to the // Comment in the code below this image — see the _so51217355_admin_ajax_js() function.
add_action( 'wp_ajax_so51217355_admin_ajax', '_so51217355_admin_ajax_php' );
function _so51217355_admin_ajax_php() {
$post_id = filter_input( INPUT_POST, 'post_id' );
echo get_sample_permalink_html( $post_id );
wp_die();
}
add_action( 'admin_print_footer_scripts', '_so51217355_admin_ajax_js', 11 );
function _so51217355_admin_ajax_js() {
$screen = get_current_screen();
if ( 'location' === $screen->id ) :
?>
<script>
// This script will sync the Permalink under the big/main post title box on
// the Edit Post page; but only if and when editing or deleting the custom
// field as in `meta_key` below. Make sure to change it, if necessary.
jQuery( function( $ ){
var meta_key = 'post_parent';
function ajax() {
$.post( ajaxurl, {
action: 'so51217355_admin_ajax',
post_id: $( '#post_ID' ).val()
}, function( s ){
$( '#edit-slug-box' ).html( s );
} );
}
function _go( e, a ) {
var $input = $( a.target ),
mid, mkey;
if ( /^meta\-(\d+)\-submit$/.test( $input.attr( 'name' ) ) ||
/^deletemeta\[(\d+)\]$/.test( $input.attr( 'name' ) ) ) {
mid = RegExp.$1;
mkey = $( 'input[name="meta[' + mid + '][key]"]' ).val();
if ( meta_key === mkey ) {
ajax();
}
}
}
$( '#the-list' )
.on( 'wpListAddEnd', _go )
.on( 'wpListDelEnd', _go );
} );
</script>
<?php
endif;
}

Display Slug in WordPress Admin Columns posts/products custom post type

I'v searched around a good bit and can't find anything but a plugin, which breaks WP.
I'm using WooCommerce, so a custom post type is involved.
In the Products list page, I'd like to add a new Column, that displays the Slug of each product url next to each product.
I found a way to show the ID really easy, but not the slug.
Thank you
First you want to add a slug column after the product name.
// Add product slug column after product name
function add_product_slug_column_heading( $columns ) {
$slug_column = array(
'product_slug' => __( 'Slug' )
);
$columns = array_slice( $columns, 0, 3, true ) + $slug_column + array_slice( $columns, 3, count( $columns ) - 1, true );
return $columns;
}
Then use the manage_product_posts_custom_column filter to display the slug value.
// Display product slug
function add_product_slug_column_value( $column_name, $id ) {
if ( 'product_slug' == $column_name ) {
echo get_post_field( 'post_name', $id, 'raw' );
}
}
add_action( "manage_product_posts_custom_column", 'add_product_slug_column_value', 10, 2 );
No coding solution
If you're just looking for a quick solution without coding you could use admin columns, completely free. It allows you to add the same slug column with just a few clicks.
Here is the exact working code:
// Add product slug column after product name
function add_product_slug_column_heading( $columns ) {
$slug_column = array(
'product_slug' => __( 'Slug' )
);
$columns = array_slice( $columns, 0, 3, true ) + $slug_column + array_slice( $columns, 3, count( $columns ) - 1, true );
return $columns;
}
add_filter('manage_edit-product_columns','add_product_slug_column_heading');
// Display product slug
function add_product_slug_column_value( $column_name, $id ) {
if ( 'product_slug' == $column_name ) {
echo get_post_field( 'post_name', $id, 'raw' );
}
}
add_action( "manage_product_posts_custom_column", 'add_product_slug_column_value', 10, 2 );

How can I use category IDs in WordPress permalinks?

I want to use something like:
http://example.com/%category_id%/%postname%/
for the permalink structure.
For example, if a post has a category with an ID of 3, then the URL for the post will be
http://example.com/3/post-name/
Does anyone know how this can be done? I don't mind modifying WordPress core.
This code adds the %category_id% rewrite tag, and filters post permalinks to replace them with the actual category ID (lowest if there are multiple categories). You can place this in a plugin or in your theme file.
add_action( 'init', 'so6159452_init' );
function so6159452_init()
{
add_rewrite_tag( '%category_id%', '([0-9]+)' );
}
add_filter( 'post_link', 'so6159452_post_link', 10, 2 );
function so6159452_post_link( $permalink, $post )
{
if ( false !== strpos( $permalink, '%category_id%' ) ) {
$cats = get_the_category( $post->ID );
if ( $cats ) {
usort( $cats, '_usort_terms_by_ID' ); // order by ID
$category_id = $cats[0]->cat_ID;
} else {
// Error: no category assigned to this post
// Just use a dummy variable
$category_id = '0';
}
$permalink = str_replace( '%category_id%', $category_id, $permalink );
}
return $permalink;
}

Resources