I've developed some functionality for a company website around job postings. There is a custom post type, with specialized fields, and a widget that displays a summary of current job postings. It's 5 functions and a widget class that was hobbled together from various websites etc and dumped into functions.php. It works.
Now I would like to extract it to a plugin but my understanding is weak... My first attempt was to just dump it into a php file with a header, but that threw a bunch of errors when I tried to activate it. Then I put all of the function hooks into the activation hook for the plugin - which doesn't throw any errors, but doesn't seem to do anything either.
<?php
/**
* Plugin Name: My Careers Plugin
* Description: This plugin adds a Careers Post Type and careers summary widget .
* Version: 1.0.0
* Author: Marc Pelletier
*/
// Exit if accessed directly
if ( !defined( 'ABSPATH' ) ) exit;
function activate_my_careers() {
add_action( 'init', 'create_career_posttype');
add_action( 'admin_bar_menu', 'add_careers_to_admin_bar', 1000000);
add_action( 'add_meta_boxes', 'add_careers_meta_box' );
add_action( 'save_post', 'save_careers_meta_box' );
register_widget('CurrentJobs_Widget');
}
register_activation_hook( __FILE__, 'activate_my_careers' );
function create_career_posttype() {
$args = array(
'labels' => array(
'name' => __('Careers'),
'singular_name' => __('Careers'),
'all_items' => __('All Job Postings'),
'add_new_item' => __('Add New Job Posting'),
'edit_item' => __('Edit Job Posting'),
'view_item' => __('View Job Posting')
),
'public' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'careers'),
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => true,
'capability_type' => 'post',
'supports' => array('title', 'editor', 'thumbnail'),
'exclude_from_search' => true,
'menu_position' => 6,
'has_archive' => true,
'menu_icon' => 'dashicons-universal-access'
);
register_post_type('careers', $args);
}
function add_careers_to_admin_bar($wp_admin_bar){
$wp_admin_bar->add_node(
array(
'title' => '<span class="dashicons-before dashicons-universal-access" >Careers</span>'
)
);
$wp_admin_bar->add_node(
array(
'parent' => 'careers',
'title' => 'All Job Postings',
'href' => get_admin_url().'edit.php?post_type=careers'
)
);
$wp_admin_bar->add_node(
array(
'parent' => 'careers',
'title' => 'New Job Posting',
'href' => get_admin_url().'post-new.php?post_type=careers'
)
);
}
function add_careers_meta_box(){
add_meta_box( 'job-details', 'Job Details', 'careers_meta_box_cb', 'Careers', 'normal', 'default');
}
function careers_meta_box_cb($post){
$Post_ID = get_post_custom( $post->ID );
$salary = isset( $Post_ID['salary'] ) ? esc_attr( $Post_ID['salary'][0] ) : "";
$salary_unit = isset( $Post_ID['salary_unit'] ) ? esc_attr( $Post_ID['salary_unit'][0] ) : "hr";
$qualifications = isset( $Post_ID['qualifications'] ) ? esc_attr( $Post_ID['qualifications'][0] ) : "";
//echo $qualifications;
$desirables = isset( $Post_ID['desirables'] ) ? esc_attr( $Post_ID['desirables'][0] ) : "";
//echo $desirables;
wp_nonce_field( 'job_details_nonce_action', 'job_details_nonce' );
$html = '';
$html .= '<label class="h2">Salary</label>';
$html .= '<input type="number" step="0.05" name="salary" id="salary" style="margin-top:15px; margin-left:9px; margin-bottom:10px;" value="'. $salary .'" />';
$html .= '<label> / </label>';
$html .= '<input type="text" list=salary_units name="salary_unit" id="salary_unit" style="margin-left:9px; margin-top:15px;" value="'. $salary_unit .'" /></br>';
$html .= '<datalist id=salary_units><option>hr<option>day<option>month<option>annum</datalist>';
$html .= '<label class="h2"> <strong>Required </strong>Qualifications (one per line) </label></br>';
$html .= '<textarea name="qualifications" id="qualifications" cols="80" rows="5" style="margin-left:9px; margin-top:15px";>'.$qualifications.'</textarea></br>';
$html .= '<label class="h2">Additional Qualifications (one per line) </label></br>';
$html .= '<textarea name="desirables" id="desirables" cols="80" rows="5" style="margin-left:9px; margin-top:15px";>'.$desirables.'</textarea></br>';
echo $html;
}
function save_careers_meta_box($post_id){
// Bail if we're doing an auto save
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
// if our nonce isn't there, or we can't verify it, bail
if( !isset( $_POST['job_details_nonce'] ) || !wp_verify_nonce( $_POST['job_details_nonce'], 'job_details_nonce_action' ) ) return;
// if our current user can't edit this post, bail
if( !current_user_can( 'edit_post' ) ) return;
if(isset( $_POST['salary'] ) )
update_post_meta( $post_id, 'salary', $_POST['salary']);
if(isset( $_POST['salary_unit'] ) )
update_post_meta( $post_id, 'salary_unit', $_POST['salary_unit']);
if(isset( $_POST['qualifications'] ) )
update_post_meta( $post_id, 'qualifications', $_POST['qualifications']);
if(isset( $_POST['desirables'] ) )
update_post_meta( $post_id, 'desirables', $_POST['desirables']);
}
class CurrentJobs_Widget extends WP_Widget{
function __construct() {
parent::__construct(
'currentjobs_widget', // Base ID
'Current Jobs Widget', // Name
array('description' => __( 'Displays your latest listings. Outputs the title and expiry per listing'))
);
}
function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title']);
$instance['numberOfListings'] = strip_tags($new_instance['numberOfListings']);
return $instance;
}
function form($instance) {
if( $instance) {
$title = esc_attr($instance['title']);
$numberOfListings = esc_attr($instance['numberOfListings']);
} else {
$title = '';
$numberOfListings = '';
}
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title', 'currentjobs_widget'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
</p>
<p>
<label for="<?php echo $this->get_field_id('numberOfListings'); ?>"><?php _e('Number of Listings:', 'currentjobs_widget'); ?></label>
<select id="<?php echo $this->get_field_id('numberOfListings'); ?>" name="<?php echo $this->get_field_name('numberOfListings'); ?>">
<?php for($x=1;$x<=10;$x++): ?>
<option <?php echo $x == $numberOfListings ? 'selected="selected"' : '';?> value="<?php echo $x;?>"><?php echo $x; ?></option>
<?php endfor;?>
</select>
</p>
<?php
}
function widget($args, $instance) {
extract( $args );
$title = apply_filters('widget_title', $instance['title']);
$numberOfListings = $instance['numberOfListings'];
echo $before_widget;
if ( $title ) {
echo $before_title . $title . $after_title;
}
$this->getJobListings($numberOfListings);
echo $after_widget;
}
function getJobListings($numberOfListings) { //html
global $post;
$listings = new WP_Query();
$listings->query('post_type=careers&posts_per_page=' . $numberOfListings );
if($listings->found_posts > 0) {
echo '<ul class="currentjobs_widget">';
while ($listings->have_posts()) {
$listings->the_post();
$listItem = '<li>' . $image;
$listItem .= '<a href="' . get_permalink() . '">';
$listItem .= get_the_title() . '</a></br>';
$listItem .= '<span>Added ' . get_the_date() . '</span></li>';
echo $listItem;
}
echo '</ul>';
wp_reset_postdata();
}else{
echo '<p style="padding:25px;">No postings found</p>';
}
}
} //end class CurrentJobs_Widget
Suggestions for further reading are great.