I develop my first plugin, which creates some pages programatically by this method:
$page_id = wp_insert_post(
array(
'comment_status' => 'close',
'ping_status' => 'close',
'post_author' => 1,
'post_title' => 'HSN Form',
'post_name' => strtolower(str_replace(' ', '-', trim('hsn-form'))),
'post_status' => 'publish',
'post_type' => 'page',
)
);
And I set template file for it:
add_filter( 'page_template', 'hsn_service_form_page_template', 10, 1 );
function hsn_service_form_page_template( $page_template ){
if ( is_page( 'hsn-form' ) ) {
$page_template = plugin_dir_path(__DIR__) . 'service-form/form-template.php';
}
return $page_template;
}
After I would like to hide it completely from wordpress dashboard, but those have to available following way:
wwww.example.com/hsn-form.
I can hide it following code from Pages menu:
add_filter( 'parse_query', 'ts_hide_pages_in_wp_admin' );
function ts_hide_pages_in_wp_admin($query) {
global $pagenow,$post_type;
$page = get_page_by_path('hsn-form');
if (is_admin() && $pagenow=='edit.php' && $post_type =='page') {
$query->query_vars['post__not_in'] = array($page->ID);
}
}
It's ok, but it's still available in Appereance->Menu, where you can create nav menus.
I searched for it, but I can't find complete solution for my problem:
My plugin has to create some pages which are available this way: www.example.com/hsn-form
I need to hide this pages completely from admin dashboard
I would like to apply templates for these pages to add some custom php code.
So If somebody should know a complete solution for it, that should be great.
Thank you in advance!
change parse_query to pre_get_posts
In order to remove a page from the admin nav menu, you can hook into the admin_menu action, then manipulate the global $submenu variable.
add_action('admin_menu', function(){
global $submenu;
array_walk($submenu, function(&$child, $parent){
if( $parent != 'edit.php' )
return;
foreach($child as $key=>$submenu){
if( $submenu[2] == 'post-new.php' ) {
unset($child[$key]);
break;
}
}
});
});
In that example, we are looking for a subpage with the slug of post-new.php
underneath the top level page with the slug edit.php. If found, it gets altogether removed from the navigation menu.
The $submenu[2] part is looking for the slug element in the array. If you want to match by the submenu name instead, you can replace it with $submenu[0].
Related
I have a custom field associated with all posts and pages. It's a dropdown of all the navigation menus.
here is how I'm populating the custom field drop-down: (the field name is custom_menu...)
function acf_load_menu_field_choices( $field ) {
// reset choices
$field['choices'] = array();
$menus = get_terms( 'nav_menu', array( 'hide_empty' => true ) );
$blank_list = json_encode(array( "name" => "Select Menu", "slug" => ""));
$blank_list = json_decode($blank_list);
array_unshift($menus, $blank_list);
foreach ( $menus as $val ) {
$value = $val->slug;
$label = $val->name;
$field['choices'][ $value ] = $label;
}
// return the field
return $field;
}
add_filter('acf/load_field/name=custom_menu', 'acf_load_menu_field_choices');
Here is a common menu location that I'm using on each page:
function register_custom_menu() { //function to register new menu
register_nav_menu('custom-menu',__( 'Custom Menu' ));
}
add_action( 'init', 'register_custom_menu' );
And then I'm assigning a menu dynamically to the location custom-menu based on the custom field menu on each page.
and here is the function the fires on each page when it's loaded:
add_action("wp_ajax_load_custom_menu", "load_custom_menu");
add_action("wp_ajax_nopriv_load_custom_menu", "load_custom_menu");
function load_custom_menu(){
$post_id = $_POST['page_id'];
$page_custom_menu = get_field('custom_menu', $post_id);
if(empty($page_custom_menu) || $page_custom_menu == "primary") return;
$locations = get_theme_mod( 'nav_menu_locations' );
if(!empty($locations)) {
foreach($locations as $locationId => $menuValue) {
if($locationId == "custom-menu") $menu = get_term_by('slug', $page_custom_menu, 'nav_menu');
if(isset($menu)) { $locations[$locationId] = $menu->term_id; }
}
}
set_theme_mod('nav_menu_locations', $locations);
wp_nav_menu( array(
'theme_location' => 'custom-menu',
'menu_id' => 'primary-menu',
'menu_class' => 'main-nav underline-decoration l-to-r-line level-arrows-on outside-item-remove-margin',
'container' => false
)
);
wp_die();
}
This ajax function fires on ready event and recieves a POST value called page_id. This function checks the custom field value of the given page_id for custom-menu and assign that menu to the menu location called custom-menu.
Here's my JavaScript in case you need to have a look on it:
jQuery(document).ready( function($){
let customMenu;
let page_id = script_vars.postID;
$.post(dtLocal.ajaxurl, { action: "load_custom_menu", page_id: page_id }, resp => customMenu = resp);
$(window).scroll(() => {
if(customMenu !== "0"){
$("#phantom .main-nav").remove();
$("#phantom .menu-box").html(customMenu);
}
})
})
This is how my code is working, And everything works fine up to this point.
Now here is the problem
Whenever I delete a Navigation menu from Appearence>Menus>Delete Menu My custom Menu starts behaving unexpectedly because the custom field value is still pointing to the deleted Menu.
What I want to do here is, I want to Delete the Custom Field whenever a menu is deleted. First I want to get the slug of a deleted menu and then find the custom field value with that slug and then finally, delete or reset that custom field.
Menus in WordPress are just terms in a taxonomy. So you can use all of the term hooks.
In particular the pre_delete_term hook.
add_action( 'pre_delete_term', 'my_func' );
function my_func($term, $taxonomy){
// Check the taxonomy is really 'menu', then check term
}
You are looking for action wp_delete_nav_menu that will take one argument - menu id. The problem that at that point your nav menu will be deleted, so you won't be able to take it slug.
If it is possible that you can store nav menu ID instead of slug, that would simplify things greatly.
In acf_load_menu_field_choices replace:
foreach ( $menus as $val ) {
$value = $val->term_id;
$label = $val->name;
$field['choices'][ $value ] = $label;
}
And in load_custom_menu:
$page_custom_menu = get_field('custom_menu', $post_id);
if(empty($page_custom_menu) || $page_custom_menu == /* Should be your primary menu ID */) return;
$locations = get_theme_mod( 'nav_menu_locations' );
if(!empty($locations)) {
foreach($locations as $locationId => $menuValue) {
if($locationId == "custom-menu") $menu = get_term_by('id', $page_custom_menu, 'nav_menu');
if(isset($menu)) { $locations[$locationId] = $menu->term_id; }
}
}
After those changes you will need to rewrite custom_menu in all posts\pages.
After that, following function will remove all related fields when you delete menu. It has been tested only on typical ACF field (string) instead of custom, but should work just fine with your code as well.
add_action('wp_delete_nav_menu', 'delete_all_acf_fields_with_menu', 10, 1);
function delete_all_acf_fields_with_menu($term_id) {
$args = array(
'post_type' => array('post', 'page'),
'posts_per_page' => -1,
'meta_key' => 'custom_menu',
'meta_value' => $term_id,
);
$posts = get_posts($args);
if( $posts ) {
foreach( $posts as $p ) {
delete_field('custom_menu', $p->ID);
}
}
}
I am attempting to display a WooCommerce product category page based on the current user role.
I have created a custom function get_user_role() to get the user role and added the shortcode [user_role] to fetch this.
If I use the shortcode on a page it successfully returns "administrator" so I can confirm this custom shortcode is working.
I am now having trouble using this shortcode as the category slug.
So what I am trying to achieve is essentially the following:
[product_category category='[user_role]']
May be you are doing it in the wrong way, or may be you need to create an additional shortcode.
So the code should be something like:
if( !function_exists('prod_category') ) {
function prod_category( $atts ) {
// Shortcode Attributes
$atts = shortcode_atts(
array(
'per_page' => '12',
'columns' => '4',
'orderby' => 'title',
'order' => 'asc',
'category' => ""
),
$atts, 'prod_category'
);
## User role: ##
// 1. logged in user
if( is_user_logged_in() ){
$current_user = wp_get_current_user();
$current_user_roles = $current_user->roles;
$user_role = $current_user_roles[0]; // The user role
}
else // Not logged in
{
// HERE set the default user role (or any product category).
$user_role = 'visitor';
}
$per_page = $atts['per_page'];
$columns = $atts['columns'];
$orderby = $atts['orderby'];
$order = $atts['order'];
$category = $user_role; // Here you can replace by your function get_user_role();
$output = do_shortcode ( "[product_category per_page=$per_page columns=$columns orderby=$orderby order=$order category=$category]" );
return $output;
}
add_shortcode( 'prod_category', 'prod_category' );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
SIMPLE USAGE (Example):
[prod_category]
You can also use all arguments like in the real shortcode.
This code is tested and works. You will get something like this:
Similar answer: WordCommerce shortcode products list
I am calculating custom title for a product using WooCommerce add product page. After the user post product's information, title is generated and saved by a save_post filter hook.
add_filter('save_post', 'modify_post_title', '99', 1);
function modify_post_title($post_id)
{
// some logic to form a new $title
// ...
if (!empty($title)) {
// update the title in database
$wpdb->update($wpdb->posts, array('post_title' => $title), array('ID' => $post_id));
// UPDATE PERMALINK
}
}
I need to know what function to use to re-generate the permalink after updating title.
Thanks in advance
add_filter( 'wp_insert_post_data', 'custom_slug_change', 50, 2 );
function custom_slug_change( $data, $postarr ) {
//Check for the post statuses you want to avoid
if ( !in_array( $data['post_status'], array( 'draft', 'pending', 'auto-draft' ) ) ) {
$data['post_name'] = sanitize_title( $data['post_title'] );
}
return $data;
}
Would you please add above code in your functions.php ?
I think you can go with the window.history.pushState to maipulate the Browser History.
I think these may help you.
window.history.pushState("object or string", "Title", surl[0]);
I have a custom post type named 'schools' on my wordpress site. When you hover over the schools tab a list of schools are shown in the submenu. These are pages I created with different school names. Now when you click on one of the school pages I have a sidebar with all the schools so they can naviate through the different schools from the sidebar rather than using the menu.
I have the sidebar being populated using the following snippet.
while( $shools_loop->have_posts() ) : $schools_loop->the_post();
$content .= '<li class="schools-list">';
$content .= ''.get_the_title().'';
$content .= '</li>';
endwhile;
This works perfectly and I can navigate through all the schools without a problem from my sidebar. I'm trying to find a way to when I view a school via the sidebar or nav that when I'm on the active page I create some css styling to the li of the ACTIVE page. I've already figured out how to do this with the nav menu. But need help on the sidebar menu. Since the sidebar list menu is being populated I'm unsure how to check if the custom post type link is active and corresponds to the /schools/get-title page.
I found something like this online and I've tried editing it, but I'm not sure if this only works for nav menu
add_action( 'init', 'create_post_type' );
function create_post_type() {
register_post_type( 'services',
array(
'labels' => array(
'name' => __( 'Services' ),
'singular_name' => __( 'Services' )
),
'public' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'services'),
)
);
}
// highlight active custom post page in nav
add_filter( 'nav_menu_css_class', 'namespace_menu_classes', 10, 2 );
function namespace_menu_classes( $classes , $item ){
if ( get_post_type() == 'services' ) {
// remove unwanted classes if found
$classes = str_replace( 'current_page_parent', '', $classes );
// find the url you want and add the class you want
if ( $item->url == 'services/physical-therapy-services/' ) {
$classes = str_replace( 'menu-item', 'menu-item current_page_parent', $classes );
}
}
return $classes;
}
Basically need to find a way to check whether the custom post type is active or not.
You can set a global variable in the main template page with the ID of the current post and then in your sidebar loop, you can retrieve that global variable and compare it with current post's ID by using get_the_ID() function and then perform the necessary actions.
Example:
single-cpt.php
// Inside the loop
global $post_id = get_the_ID();
sidebar-cpt.php
$post_id = isset($_GLOBALS['post_id']) ? $_GLOBALS['post_id'] : 0;
while( $shools_loop->have_posts() ) : $schools_loop->the_post();
if($post_id == get_the_ID()){
// This is the active link
$content .= '<li class="schools-list selected">';
} else {
$content .= '<li class="schools-list">';
}
$content .= ''.get_the_title().'';
$content .= '</li>';
endwhile;
I have custom post type named soto_property in which I have added three wp_editor as post meta, using this code -
wp_editor( htmlspecialchars_decode($valueeee1),
'propertyEditor1',
$settings = array('textarea_name'=>'detail',
'editor_class'=>'propertyEditor')
);
wp_editor( htmlspecialchars_decode($valueeee2),
'propertyEditor2',
$settings = array('textarea_name'=>'features',
'editor_class'=>'propertyEditor')
);
wp_editor( htmlspecialchars_decode($valueeee3),
'propertyEditor3',
$settings = array('textarea_name'=>'text_to_pdf',
'editor_class'=>'propertyEditor')
);
Now I have installed qtranslate plugin to make my site Multilingual. This plugin automaticaly add Language tab in its default content editor. I want to add these languages tabs in my custom editor also, so it can save content in defined languages.
How can I do this.? Please help me.
add_filter('soto_property','qtrans_convertURL');
I guess you need to define translatable strings. Check this page in codex for more details.
Updated code should look like this:
$settings = array('textarea_name'=>__('detail', 'your-text-domain'),
'editor_class'=>'propertyEditor')
If it won't work for you, try the following trick.
Here's a code snippet from the last link:
if ( is_admin() && function_exists("qtrans_getSortedLanguages") ) {
add_action('admin_menu', 'enable_qTranslate_Meta');
}
function enable_qTranslate_Meta() {
global $qtransMETA;
$post_types = get_post_types();
/* post and page types are already processed by the plugin */
$disabled_types = array( 'post', 'page', 'attachment', 'revision', 'nav_menu_item' );
$enabled_types = array_diff( $post_types, $disabled_types );
if ( $enabled_types ) {
foreach( $enabled_types as $enabled_type ) {
add_meta_box(
'qtrans_meta_meta_box', //HTML id
__('Multilingual META', 'qtranslate-meta'), //title
array(&$qtransMETA, 'meta_box_generate'), //callback
$enabled_type, //type
'normal', //context - normal, advanced, side
'high' //priority - high, low
);
}
}
}
Solved!
I have used qranslate-x plugin which makes my custom wp_editor translatable on my custom post type page.