The permalinks on my website breaks frequently. I found out that it's being caused by a plugin I created.
The plugin basically creates a custom post type with custom fields and stores in the wp-posts and wp-post-meta tables.
I heard that it's occurring because I'm saving them to the wp-post table. So how do I save them to a different table? And how do I fetch them from that table. I can do it by the conventional PHP and MySQL ways but I want to take advantage of the WordPress functions. Can this be done?
Code to create custom post type and taxonomy
function dwwp_register_post_type(){
$singular = 'Speaker';
$plural = 'Speakers';
$labels = array(
'name' => $plural,
'singular_name' => $singular,
'add_name' => 'Add New',
'add_new_item' => 'Add New '.$singular,
'edit' => 'Edit',
'edit_item' => 'Edit '.$singular,
'new_item' => 'New '.$singular,
'view' => 'View '.$singular,
'view_item' => 'View '.$singular,
'search_term' => 'Search '.$plural,
'parent' => 'Parent '.$singular,
'not_found' => 'No '.$plural.' Found',
'not_found_in_trash' => 'No '.$plural.' in Trash',
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'show_in_nav_menus' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_admin_bar' => true,
'menu_position' => 6,
'menu_icon' => 'dashicons-businessman',
'can_export' => true,
'delete_with_user' => false,
'hierarchical' => false,
'has_archive' => true,
'query_var' => true,
'capability_type' => 'post',
'map_meta_cap' => true,
'rewrite' => array(
'slug' => 'speakers',
'with_front' => true,
'pages' => true,
'feeds' => true,
),
'supports' => array(
'title',
//'editor',
//'author',
//'custom-fields',
'thumbnail'
)
);
register_post_type('speakers', $args);
}
add_action('init', 'dwwp_register_post_type');
function dwwp_register_taxonomy(){
$plural = 'Years';
$singular = 'Year';
$labels = array(
'name' => $plural,
'singular_name' => $singular,
'search_items' => 'Search '.$plural,
'popular_items' => 'Popular '.$plural,
'all_items' => 'All '.$plural,
'parent_item' => null,
'parent_item_colon' => null,
'edit_item' => 'Edit '.$singular,
'update_item' => 'Update '.$singular,
'add_new_item' => 'Add New '.$singular,
'new_item_name' => 'New '.$singular.' Name',
'separate_items_with_commas' => 'Separate '.$plural.' with commas',
'add_or_remove_items' => 'Add or Remove '.$plural,
'choose_from_most_used' => 'Choose from the most used '.$plural,
'not_found' => 'No '.$plural.' found',
'menu_name' => $plural,
);
$args = array(
'hierarchical' => true,
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'update_count_callback' => '_update_post_term_count',
'query_var' => true,
'rewrite' => array(
'slug' => 'year'
)
);
register_taxonomy('year', 'speakers', $args);
}
add_action('init', 'dwwp_register_taxonomy');
Now I created 3 custom fields for all the speakers: Short description, Full Description and the Year is the custom taxonomy. Code to store in Database From Input Fields
function dwwp_add_custom_metabox(){
add_meta_box('dwwp_meta', 'Speakers Description', 'dwwp_meta_callback', 'speakers', 'normal', 'core');
}
add_action('add_meta_boxes', 'dwwp_add_custom_metabox');
function dwwp_meta_callback( $post ){
wp_nonce_field(basename(__FILE__), 'dwwp_speakers_nonce');
$dwwp_stored_meta = get_post_meta($post->ID);
?>
<div class="meta-th">
<div class="meta-th">
<span>Short Description</span>
</div>
<div class="meta-editor"></div>
<?php
$content = get_post_meta($post->ID, 'short-description', true);
$editor = 'short-description';
$settings = array(
'textarea_rows' => 5,
);
wp_editor($content, $editor, $settings);
?>
</div>
<div class="meta-th">
<div class="meta-th">
<span>Long Description</span>
</div>
<div class="meta-editor"></div>
<?php
$content = get_post_meta($post->ID, 'long-description', true);
$editor = 'long-description';
$settings = array(
'textarea_rows' => 10,
);
wp_editor($content, $editor, $settings);
?>
</div>
<?php }
function dwwp_meta_save($post_id){
$is_autosave = wp_is_post_autosave($post_id);
$is_revision = wp_is_post_revision($post_id);
$is_valid_nonce = (isset($_POST['dwwp_speakers_nonce']) && wp_verify_nonce($_POST['dwwp_speakers_nonce'], basename(__FILE__))) ? 'true' : 'false' ;
if ($is_autosave || $is_revision || !$is_valid_nonce){
return;
}
if (isset($_POST['short-description'])){
update_post_meta($post_id, 'short-description', sanitize_text_field($_POST['short-description']));
}
if (isset($_POST['long-description'])){
update_post_meta($post_id, 'long-description', sanitize_text_field($_POST['long-description']));
}
}
add_action('save_post', 'dwwp_meta_save');
Then to display the speakers in a grid and have a popup to display their details in other places. Code to create a shortcode to display in other places
<?php
/*
==============================================
Display the speakers in a grid system
==============================================
*/
function speakers_grid_display($atts, $content = null){
$atts = shortcode_atts(
array(
'years' => array('2018', '2017', '2016')
), $atts
);
$return_args[] = '<div id="section3">
<div class="animation-element slide slide-left testimonial">
<div class="row text-center">
<h1 class="heading-1">Speakers</h1>
</div>
</div>
<div class="container gal-container">';
$args = array(
'post_type' => 'speakers',
'orderby' => 'menu_order',
'order' => 'ASC',
'post_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'year',
'field' => 'name',
'terms' => $atts['years']
),
),
);
$speakers_list = new WP_Query($args);
if ($speakers_list->have_posts()):
while ($speakers_list->have_posts()): $speakers_list->the_post();
$return_args[] = '<div class="gal-item show_info">
<div class="box" style="background-image: url('.get_the_post_thumbnail_url(get_the_ID()).')">
<div class="overlay">
<div class="text">
<span class="name">'.get_the_title().'</span>
<br />
</div>
</div>
</div>
</div>';
endwhile;
endif;
$return_args[] = '</div></div>';
$args = join($return_args);
return $args;
}
add_shortcode('speakers-grid-display', 'speakers_grid_display');
/*
=============================================================
Display speakers with pop ups
=============================================================
*/
function speakers_popup($atts, $content = null){
$atts = shortcode_atts(
array(
'years' => array('2018', '2017', '2016')
), $atts
);
$return_args[] = '<div id="section3">
<div class="animation-element slide slide-left testimonial">
<div class="row text-center">
<h1 class="heading-1">Speakers</h1>
</div>
</div>
<div class="container gal-container">';
$args = array(
'post_type' => 'speakers',
'orderby' => 'menu_order',
'order' => 'ASC',
'post_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'year',
'field' => 'name',
'terms' => $atts['years']
),
),
);
$speakers_list = new WP_Query($args);
$i = 1;
if ($speakers_list->have_posts()):
while ($speakers_list->have_posts()): $speakers_list->the_post();
$return_args[] = '<a href="#" data-target="#div'.$i.'" class="gal-item show_info">
<div class="box" style="background-image: url('.get_the_post_thumbnail_url(get_the_ID()).')">
<div class="overlay">
<div class="text">
<span class="name">'.get_the_title().'</span>
<br />
</div>
</div>
</div>
</a>';
$i++;
endwhile;
endif;
$return_args[] = '</div></div>';
$speakers_list = new WP_Query($args);
$i = 1;
if ($speakers_list->have_posts()):
while ($speakers_list->have_posts()): $speakers_list->the_post();
$return_args[] = '<div id="div'.$i.'" class="show_speakers_info" style="display:none;">
<div class="profile-header-container">
<div class="profile-header-img">
<img src="'.get_the_post_thumbnail_url(get_the_ID()).'" />
<!-- badge -->
<div class="profile-heading">
<h3 class="heading-2">'.get_the_title().'</h3>
<em>'.get_post_meta(get_the_ID(), "short-description", true).'</em>
</div>
</div>
</div>
<div class="text-justify">
'.get_post_meta(get_the_ID(), "long-description", true).'
</div>
</div>';
$i++;
endwhile;
endif;
$return_args = join($return_args);
return $return_args;
}
add_shortcode('speakers-popup', 'speakers_popup');
And then I created another page to just reorder the list of the speakers
<?php
//Add submenu
function dwwp_add_submenu_page(){
add_submenu_page(
'edit.php?post_type=speakers',
'Reorder Speakers',
'Reorder Speakers',
'manage_options',
'reorder_speakers',
'reorder_callback'
);
}
add_action('admin_menu', 'dwwp_add_submenu_page');
//Reorder speakers
function reorder_callback(){
$args = array(
'post_type' => 'speakers',
'orderby' => 'menu_order',
'order' => 'ASC',
'no_found_rows' => true,
'update_post_term_cache' => false,
'post_per_page' => 50
);
$speakers_list = new WP_Query($args);?>
<div id="speakers-sort" class="sort">
<div id="icon-job-admin" class="icon32"><br/></div>
<h2>Reorder Speakers
<img src = "<?php echo esc_url(admin_url() .'/images/loading.gif'); ?>" alt="loading.gif" id="loading-animation" ></h2>
<?php
if ($speakers_list->have_posts()): ?>
<ul id="custom-type-list">
<?php
while ($speakers_list->have_posts()): $speakers_list->the_post();
?>
<li id="<?php the_id(); ?>">
<?php the_title(); ?>
</li>
<?php endwhile; ?>
</ul>
<?php else: ?>
<p>No Speakers</p>
<?php endif; ?>
</div>
<?php
}
function dwwp_save_reorder(){
if (!check_ajax_referer('wp-speakers-order', 'security')){
return wp_send_json_error('Invalid Nonce');
}
if (!current_user_can('manage_options')){
return wp_send_json_error( 'You are not allowed to do this.' );
}
$order = $_POST['order'];
$count = 0;
foreach( $order as $item_id ){
$post = array(
'ID' => (int)$item_id,
'menu_order' => $count
);
wp_update_post($post);
$count++;
}
wp_send_json_success('Post Saved.');
}
add_action('wp_ajax_save_post', 'dwwp_save_reorder');
And then finally in the index page, the code is
<?php
/*
Plugin Name: Speakers
Plugin URI: Speakers
Author: Speakers
Version: 1.0.0
*/
if (!defined('ABSPATH')){
exit;
}
require ( plugin_dir_path(__FILE__) . 'speakers_custom_post_type.php' );
require ( plugin_dir_path(__FILE__) . 'speakers_custom_meta_box.php' );
require ( plugin_dir_path(__FILE__) . 'speakers_reorder_submenu.php' );
require ( plugin_dir_path(__FILE__) . 'speakers_shortcode.php');
function dwwp_admin_enqueue_scripts(){
global $pagenow, $typenow;
if ($typenow == 'speakers'){
wp_enqueue_style('dwwp-admin-css', plugins_url('css/style.css', __FILE__));
wp_enqueue_script('dwwp-admin-js', plugins_url('js/style.js', __FILE__), array( 'jquery' , 'jquery-ui-datepicker' ), '1.0.0', true);
}
if (($pagenow == 'post.php' || $pagenow == 'post-new.php') && $typenow == 'speakers'){
wp_enqueue_style('dwwp-admin-css', plugins_url('css/style.css', __FILE__));
wp_enqueue_script('dwwp-admin-js', plugins_url('js/reorder.js', __FILE__), array( 'jquery' , 'jquery-ui-datepicker' ), '1.0.0', true);
}
if ($pagenow == 'edit.php' && $typenow == 'speakers'){
wp_enqueue_script('dwwp-reorder-admin-js', plugins_url('js/reorder.js', __FILE__), array( 'jquery' , 'jquery-ui-sortable' ), '1.0.0', true);
wp_localize_script('dwwp-reorder-admin-js', 'WP_SPEAKERS_LISTING', array(
'security' => wp_create_nonce('wp-speakers-order'),
'success' => __('Speakers sort order has been saved.'),
'failure' => __('There was an error saving the sort order, or you do not have priviledges')
));
}
}
add_action('admin_enqueue_scripts', 'dwwp_admin_enqueue_scripts');