Тестовое задание на разработку Плагина новостей:

  • создать программно post type newspages;
  • создать собственный список новостей (список постов post type newspages) в админ части;
  • возможность сортировать список по полям в хедере (title, date);
  • удаление, редактирование новостей;
  • добавить новые поля: комментарий админа (textarea) и альтернативный тайтл (input);
  • сделать виждет с 3 последними новостями ;
  • написать shortcode с последними 3 новостями ;
  • все исходники плагина

Скачать ZIP архив плагина (версия 0.5)

Плагин установлен в моем бложике - см здесь

Решаем задачу редактированием файла темы functions.php и копированием файлов single.php & archive.php.

// custom function to register a "story" post type
function ssd_register_post_type_story() {
    register_post_type( 'story',
        array(
            'labels' => array(
                'name' => __( 'Story' ),
                'singular_name' => __( 'Story' )
            ),
        'public' => true,
        'has_archive' => true,
        )
    );
}
// call our custom function with the init hook
add_action( 'init', 'ssd_register_post_type_story' );

В админке появился тип контента, с вкладками добавить и список, на последней возможно сортировка по дате и названию. В админке появились пункты "Редагувати | Швидке Редагування | Сміття | Переглянути". ИТОГО - 4 пункта выполнено.

Пункт "добавить новые поля" - Metadata в CPT. Попытка №1:

// use the add_meta_boxes hook to call a custom function to add a new meta box
add_action( 'add_meta_boxes', 'ssd_story_add_meta_boxes' );
 
// this is the callback function called from add_meta_box
function ssd_story_add_meta_boxes( $post ){
 
    // set meta data if already exists
    $admin_comment = get_post_meta( $post->ID, 
        '_ssd_story_admin_comment', "No comment" );
 
    $alt_title = get_post_meta( $post->ID, 
        '_ssd_story_alt_title', "No title" );
    // output meta data fields
    if ( $post != "story" ) return;
    ?>
    <p>
    Input admin comment
    <input type="text" name="admin_comment" value="<?php echo $admin_comment;?>">
    </p>
    <p>
    Alt title:
    <input type="text" name="alt_title" id="alt_title" value="<?php echo $alt_title;?>">
    </p>
 
    <?php
}
 
// function for saving custom meta data to the database
function ssd_story_save_post( $post_id ){
 
  // don't save anything if WP is auto saving
  if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
      return $post_id;
 
  // check if correct post type and that the user has correct permissions
  if ( 'story' == $_POST['post_type'] ) {
 
    if ( ! current_user_can( 'edit_page', $post_id ) )
        return $post_id;
 
  } else {
 
    if ( ! current_user_can( 'edit_post', $post_id ) )
        return $post_id;
  }
 
  // update story meta data
  update_post_meta( $post_id, 
      '_ssd_story_admin_comment', 
      $_POST['admin_comment'] 
  );
  update_post_meta( $post_id, 
      '_ssd_story_alt_title', 
      $_POST['alt_title'] 
  );
 
}
// call a custom function to handle saving our meta data
add_action( 'save_post', 'ssd_story_save_post' );

Попытка закончилась успешно, но с версткой возникли прогнозируемые трудности, но ведь в таске нет ни слова о божеском виде ;)

Переходим к пункту сделать "виждет с 3 последними новостями". Стандартная задача, вопрос только - какую информацию выводтиь в виджет? Решил название и дату публикации. Исходник виджета, проверен в бложике ;)

<?php
/*
        Plugin Name: Show Recent CPTs
        Tags: menu, CPT, widget
        Description: Creates menus from Wordpress recent custom post type
        Author: Serhii Dymenko
        Version: 1.1.0
        Author URI: http://www.proserge.kh.ua
*/
 
class Recent_CPT extends WP_Widget 
{
function __construct() {
    parent::__construct(
        'recent_CPT', // Base ID
        'Recent News', // Name
        array('description' => __( 'Displays your latest news. Outputs the post thumbnail, title and date 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;
}
 
/*The method form() builds the form that we have in the admin section. 
What we’re building is a very simple form with 2 fields: a text field 
for the Widget title, and a drop down list for the number of listings 
we want to show:*/
 
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', 'recent_CPT'); ?></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:', 'recent_CPT'); ?></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->getNewsListings($numberOfListings);
    echo $after_widget;
}
 
function getNewsListings($numberOfListings) { //html
    global $post;
    add_image_size( 'news_widget_size', 85, 45, false );
    $listings = new WP_Query();
    $listings->query('post_type=story&posts_per_page=' . $numberOfListings );    
    if($listings->found_posts > 0) {
        echo '<ul class="story_widget">';
            while ($listings->have_posts()) {
                $listings->the_post();
                $image = (has_post_thumbnail($post->ID)) ? get_the_post_thumbnail($post->ID, 'news_widget_size') : '<div class="noThumb"></div>'; 
                $listItem = '<li>' . $image; 
                $listItem .= '<a href="' . get_permalink() . '">';
                $listItem .= get_the_title() . '</a>';
                $listItem .= '<span>Added ' . get_the_date() . '</span></li>'; 
                echo $listItem; 
            }
        echo '</ul>';
        wp_reset_postdata(); 
    }else{
        echo '<p style="padding:25px;">No News found</p>';
    } 
}
 
function styleRecentNews() {
wp_register_style('ssd_recent_news_css', plugins_url('recent_news.css',__FILE__ ));
wp_enqueue_style('ssd_recent_news_css');
}
 
 
 
} //end class Realty_Widget
 
 
function register_recent_CPT_widget() {
register_widget('Recent_CPT');
}
 
add_action('widgets_init', 'register_recent_CPT_widget');

Таск "написать shortcode с последними 3 новостями". Ну, рискну переписать function widget в функцию для вывода шорткода. Протестим, загнав в functions.php - РАБОТАЕТ!!!

////////-----------------------------   SHORTCODE ----------------------
// Register a new shortcode: [ssd_recent]
add_shortcode( 'ssd_recent', 'ssd_recent_story_newes' );
 
// The callback function that will replace [ssd_recent]
function ssd_recent_story_newes() {
    global $post;
    $blockRecent = "<div class=\"recentShort\">";
    add_image_size( 'news_widget_size', 85, 45, false );
    $listings = new WP_Query();
    $listings->query('post_type=story&posts_per_page=3');    
    if($listings->found_posts > 0) {
        $blockRecent .= "<ul class=\"story_widget\">";
            while ($listings->have_posts()) {
                $listings->the_post();
                $image = (has_post_thumbnail($post->ID)) ? get_the_post_thumbnail($post->ID, 'news_widget_size') : '<div class="noThumb"></div>'; 
                $listItem = "<li>" . $image; 
                $listItem .= "<a href=\"get_permalink()\">";
                $listItem .= get_the_title() . "</a></br>";
                $listItem .= "<span>Added  get_the_date() </span></li>"; 
                $blockRecent .= $listItem;
                //DebugBreak(); 
            }
        $blockRecent .= "</ul>";
        wp_reset_postdata(); 
    }else{
        $blockRecent .= "<p style=\"padding:25px;\">No News found</p>";
    }
    $blockRecent .= "</div>";
    return $blockRecent;
}

Теперь осталось собрать Плагин новостей из функций и виджета, подчистить functions.php и файлы темы (single.php & archive.php). Радует, что по отдельности все работает ;)

Конечный вариант плагина (исходники всех файлов: story.php, admin.php, functions.php, meta.php, post-types.php, widget3news.php, uninstall.php, readme.txt):

//story.php 
<?php
/**
 * Plugin Name: Custom Content Newspage
 * Plugin URI: http://proserge.kh.ua/coding/index.php/post/85/WP+News+Plugin
 * Description: newspage manager for WordPress.  This plugin allows you to manage, edit, and create new newspage items in an unlimited number of newspages.
 * Version: 0.4
 * Author: Serhii Dymenko
 * Author URI: http://proserge.kh.ua/coding/
 *
 * plugin was created because of the need of users who are using WordPress with newspage management built in, which causes problems with content portability. I did my best for give users possibility to switch themes without losing content.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
 *
 * @package   CustomContentNewspage
 * @version   0.5.0
 * @copyright Copyright (c) 2014, Serhii Dymenko
 * @link      http://proserge.kh.ua/coding/index.php/post/85/WP+News+Plugin
 * @license   http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 */
 
class Custom_Content_Newspage {
 
    public function __construct() {
 
        /* Set the constants needed by the plugin. */
        add_action( 'plugins_loaded', array( &$this, 'constants' ), 1 );
 
        /* Load the functions files. */
        add_action( 'plugins_loaded', array( &$this, 'includes' ), 2 );
 
        /* Load the admin files. */
        add_action( 'plugins_loaded', array( &$this, 'admin' ), 3 );
 
        /* Register activation hook. */
        register_activation_hook( __FILE__, array( &$this, 'activation' ) );
    }
 
    /**
     * Defines constants used by the plugin.
     */
    public function constants() {
 
        /* Set constant path to the plugin directory. */
        define( 'SSD_DIR', trailingslashit( plugin_dir_path( __FILE__ ) ) );
 
        /* Set the constant path to the plugin directory URI. */
        define( 'SSD_URI', trailingslashit( plugin_dir_url( __FILE__ ) ) );
 
        /* Set the constant path to the includes directory. */
        define( 'SSD_INCLUDES', SSD_DIR . trailingslashit( 'includes' ) );
 
        /* Set the constant path to the admin directory. */
        define( 'SSD_ADMIN', SSD_DIR . trailingslashit( 'admin' ) );
    }
 
    /**
     * Loads the initial files needed by the plugin.
     */
    public function includes() {
 
        require_once( SSD_INCLUDES . 'functions.php' );
        require_once( SSD_INCLUDES . 'meta.php' );
        require_once( SSD_INCLUDES . 'post-types.php' );
        require_once( SSD_INCLUDES . 'widget3news.php' );
    }
 
    public function i18n() {}
 
    /**
     * Loads the admin functions and files.
     */
    public function admin() {
 
        if ( is_admin() )
            require_once( SSD_ADMIN . 'admin.php' );
    }
 
    /**
     * Method that runs only when the plugin is activated.
     */
    function activation() {
 
        /* Get the administrator role. */
        $role =& get_role( 'administrator' );
 
        /* If exists, add capabilities. */
        if ( !empty( $role ) ) {
 
            $role->add_cap( 'manage_newspage' );
            $role->add_cap( 'create_newspage_items' );
            $role->add_cap( 'edit_newspage_items' );
        }
    }
}
 
new Custom_Content_Newspage();
 
?>
 
//admin.php
<?php
/**
 * Admin functions for the plugin.
 *
 * @package    CustomContentNewspage
 * @subpackage Admin
 * @since      0.5.0
 * @copyright Copyright (c) 2014, Serhii Dymenko
 * @link      http://proserge.kh.ua/coding/index.php/post/85/WP+News+Plugin
 * @license    http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 */
 
/* Set up the admin functionality. */
add_action( 'admin_menu', 'ssd_admin_setup' );
 
/**
 * Adds actions where needed for setting up the plugin's admin functionality.
 */
function ssd_admin_setup() {
 
    /* Custom columns on the edit newspage items screen. */
    add_action( 'manage_newspage_item_posts_custom_column', 'ssd_manage_newspage_item_columns', 10, 2 );
 
    /* Add meta boxes an save metadata. */
    add_action( 'add_meta_boxes', 'ssd_add_meta_boxes' );
    add_action( 'save_post', 'ssd_newspage_item_info_meta_box_save', 10, 2 );
 
    /* Add 32px screen icon. */
    add_action( 'admin_head', 'ssd_admin_head_style' );
}
 
/**
 * Sets up custom columns on the newspage items edit screen.
 */
function ssd_edit_newspage_item_columns( $columns ) {
}
 
/**
 * Displays the content of custom newspage item columns on the edit screen.
 */
function ssd_manage_newspage_item_columns( $column, $post_id ) {
    global $post;
 
    switch( $column ) {
 
        case 'thumbnail' :
 
            if ( has_post_thumbnail() )
                the_post_thumbnail( array( 40, 40 ) );
 
            elseif ( function_exists( 'get_the_image' ) )
                get_the_image( array( 'image_scan' => true, 'width' => 40, 'height' => 40 ) );
 
            break;
 
        /* Just break out of the switch statement for everything else. */
        default :
            break;
    }
}
 
/**
 * Registers new meta boxes for the 'newspage_item' post editing screen in the admin.
 */
function ssd_add_meta_boxes( $post_type ) {
 
    if ( 'newspage_item' === $post_type ) {
 
        add_meta_box( 
            'ssd-admin-comment', 
            __( 'Admin Comment', 'custom-content-newspage' ), 
            'ssd_newspage_meta_comment_display', 
            $post_type, 
            'normal', 
            'core'
        );
 
        add_meta_box( 
            'ssd-alt-title', 
            __( 'Alt Title', 'custom-content-newspage' ), 
            'ssd_newspage_meta_title_display', 
            $post_type, 
            'normal', 
            'core'
        );
    }
}
 
/**
 * Displays the content of the newspage item info meta box.
 */
function ssd_newspage_meta_comment_display( $post, $metabox ) {
 
    wp_nonce_field( basename( __FILE__ ), 'ssd-newspage-item-info-nonce' ); ?>
 
    <p>
        <label for="ssd-admin-comment"><?php _e( 'Input admin comment <abbr title="Uniform Resource Locator">URL</abbr>', 'ssd-admin-cooment' ); ?></label>
        <br />
        <textarea rows="5" cols="50" name="ssd-admin-comment" style="width: 99%;"><?php echo get_post_meta( $post->ID, 'ssd-admin-comment')[0];?></textarea>
    </p>
    <?php
 
}
 
function ssd_newspage_meta_title_display( $post, $metabox ) {
 
    wp_nonce_field( basename( __FILE__ ), 'ssd-newspage-item-info-nonce' ); ?>
 
    <p>
        <label for="ssd-alt-title"><?php _e( 'Input alt title <abbr title="Uniform Resource Locator">URL</abbr>', 'ssd-alt-title' ); ?></label>
        <br />
        <input type="text" name="ssd-alt-title" id="ssd-alt-title" value="<?php echo get_post_meta( $post->ID, 'ssd-alt-title')[0]; ?>" size="30" tabindex="30" style="width: 99%;" />
    </p>
    <?php
 
}
/**
 * Saves the metadata for the newspage item info meta box.
 */
function ssd_newspage_item_info_meta_box_save( $post_id, $post ) {
 
    if ( !isset( $_POST['ssd-newspage-item-info-nonce'] ) || !wp_verify_nonce( $_POST['ssd-newspage-item-info-nonce'], basename( __FILE__ ) ) )
        return;
 
    $meta = array(
        'ssd-admin-comment' => $_POST['ssd-admin-comment'] ,
        'ssd-alt-title' => $_POST['ssd-alt-title']
    );
 
    foreach ( $meta as $meta_key => $new_meta_value ) {
 
        /* Get the meta value of the custom field key. */
 
        $meta_value = get_post_meta( $post_id, $meta_key, true );
 
        /* If there is no new meta value but an old value exists, delete it. */
        if ( current_user_can( 'delete_post_meta', $post_id, $meta_key ) && '' == $new_meta_value && $meta_value )
            delete_post_meta( $post_id, $meta_key, $meta_value );
 
        /* If a new meta value was added and there was no previous value, add it. */
        elseif ( current_user_can( 'add_post_meta', $post_id, $meta_key ) && $new_meta_value && '' == $meta_value )
            add_post_meta( $post_id, $meta_key, $new_meta_value, true );
 
        /* If the new meta value does not match the old value, update it. */
        elseif ( current_user_can( 'edit_post_meta', $post_id, $meta_key ) && $new_meta_value && $new_meta_value != $meta_value )
 
            update_post_meta( $post_id, $meta_key, $new_meta_value );
    }
}
 
/**
 * Adds plugin settings.  At the moment, this function isn't being used because we're waiting for a bug fix
 * in core.  For more information, see: http://core.trac.wordpress.org/ticket/9296
 */
function ssd_plugin_settings() {
 
    /* Register settings for the 'permalink' screen in the admin. */
    register_setting(
        'permalink',
        'plugin_custom_content_newspage',
        'ssd_validate_settings'
    );
 
    /* Adds a new settings section to the 'permalink' screen. */
    add_settings_section(
        'ssd-permalink',
        __( 'Newspage Settings', 'custom-content-newspage' ),
        'ssd_permalink_section',
        'permalink'
    );
 
    /* Get the plugin settings. */
    $settings = get_option( 'plugin_ssd', ssd_get_default_settings() );
 
    add_settings_field(
        'ssd-root',
        __( 'Newspage Archive', 'custom-content-newspage' ),
        'ssd_root_field',
        'permalink',
        'ssd-permalink',
        $settings
    );
 
    add_settings_field(
        'ssd-item-base',
        __( 'newspage item slug', 'custom-content-newspage' ),
        'ssd_item_base_field',
        'permalink',
        'ssd-permalink',
        $settings
    );
}
 
/**
 * Validates the plugin settings.
 */
function ssd_validate_settings( $settings ) {
 
    // @todo Sanitize for alphanumeric characters
    // @todo Both the newspage_base and newspage_item_base can't match.
 
    $settings['newspage_base'] = $settings['newspage_base'];
 
    $settings['newspage_item_base'] = $settings['newspage_item_base'];
 
    $settings['newspage_root'] = !empty( $settings['newspage_root'] ) ? $settings['newspage_root'] : 'newspage';
 
    return $settings;
}
 
/**
 * Adds the newspage permalink section.
 */
function ssd_permalink_section() { ?>
    <table class="form-table">
        <?php do_settings_fields( 'permalink', 'custom-content-newspage' ); ?>
    </table>
<?php }
 
/**
 * Adds the newspage root settings field.
 */
function ssd_root_field( $settings ) { ?>
    <input type="text" name="plugin_ssd[newspage_root]" id="ssd-newspage-root" class="regular-text code" value="<?php echo esc_attr( $settings['newspage_root'] ); ?>" />
    <code><?php echo home_url( $settings['newspage_root'] ); ?></code> 
<?php }
 
/**
 * Adds the newspage (taxonomy) base settings field.
 */
function ssd_base_field( $settings ) { ?>
    <input type="text" name="plugin_ssd[newspage_base]" id="ssd-newspage-base" class="regular-text code" value="<?php echo esc_attr( $settings['newspage_base'] ); ?>" />
    <code><?php echo trailingslashit( home_url( "{$settings['newspage_root']}/{$settings['newspage_base']}" ) ); ?></code> 
<?php }
 
/**
 * Adds the newspage item (post type) base settings field.
 */
function ssd_item_base_field( $settings ) { ?>
    <input type="text" name="plugin_ssd[newspage_item_base]" id="ssd-newspage-item-base" class="regular-text code" value="<?php echo esc_attr( $settings['newspage_item_base'] ); ?>" />
    <code><?php echo trailingslashit( home_url( "{$settings['newspage_root']}/{$settings['newspage_item_base']}" ) ); ?>%postname%</code> 
<?php }
 
/**
 * Overwrites the screen icon for newspage screens in the admin.
 */
function ssd_admin_head_style() {
        global $post_type;
 
    if ( 'newspage_item' === $post_type ) { ?>
        <style type="text/css">
            #icon-edit.icon32-posts-newspage_item {
                background: transparent url( '<?php echo ssd_URI . 'images/screen-icon.png'; ?>' ) no-repeat;
            }
        </style>
    <?php }
}
 
?>
 
//functions.php
<?php
/**
 * Various functions, filters, and actions used by the plugin.
 *
 * @package    CustomContentNewspage
 * @subpackage Includes
 * @since      0.4.0
 * @copyright Copyright (c) 2014, Serhii Dymenko
 * @link      http://proserge.kh.ua/coding/index.php/post/85/WP+News+Plugin
 
/* Filter the post type archive title. */
add_filter( 'post_type_archive_title', 'ssd_post_type_archive_title' );
 
/**
 * Returns the default settings for the plugin.
 */
function ssd_get_default_settings() {
 
    $settings = array(
        'newspage_root'      => 'newspage',
        'newspage_base'      => '',          // defaults to 'newspage_root'
        'newspage_item_base' => ''
    );
 
    return $settings;
}
 
/**
 * Filter on 'post_type_archive_title' to allow for the use of the 'archive_title' label that isn't supported 
 * by WordPress.  That's okay since we can roll our own labels.
 */
function ssd_post_type_archive_title( $title ) {
 
    if ( is_post_type_archive( 'newspage_item' ) ) {
        $post_type = get_post_type_object( 'newspage_item' );
        $title = isset( $post_type->labels->archive_title ) ? $post_type->labels->archive_title : $title;
    }
 
    return $title;
}
 
function ssd_post_type_link( $post_link, $post ) {}
 
function ssd_breadcrumb_trail_items( $items ) {}
 
?>
 
//meta.php
<?php
/**
 * Registers metadata and related functions for the plugin.
 *
 * @package    CustomContentNewspage
 * @subpackage Includes
 * @since      0.5.0
 * @copyright Copyright (c) 2014, Serhii Dymenko
 * @link      http://proserge.kh.ua/coding/index.php/post/85/WP+News+Plugin
/* Register meta on the 'init' hook. */
add_action( 'init', 'ssd_register_meta' );
 
/**
 * Registers custom metadata for the plugin.
 */
function ssd_register_meta() {
 
    register_meta( 'newspage_item', 'ssd-admin-comment', 'ssd_sanitize_meta' );
    register_meta( 'newspage_item', 'ssd-alt-title', 'ssd_sanitize_meta' );
}
 
function ssd_sanitize_meta( $meta_value, $meta_key, $meta_type ) {
 
    if ( 'ssd-admin-comment' === $meta_key || 'ssd-alt-title' === $meta_key)
        return esc_url( $meta_value );
 
    return strip_tags( $meta_value );
}
 
?>
 
//post-types.php
<?php
/**
 * File for registering custom post types.
 *
 * @package    CustomContentNewspage
 * @subpackage Includes
 * @since      0.5.0
 * @copyright Copyright (c) 2014, Serhii Dymenko
 * @link      http://proserge.kh.ua/coding/index.php/post/85/WP+News+Plugin
 * @license    http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 */
 
/* Register custom post types on the 'init' hook. */
add_action( 'init', 'ssd_register_post_types' );
 
/**
 * Registers post types needed by the plugin.
 */
function ssd_register_post_types() {
 
    /* Get the plugin settings. */
    $settings = get_option( 'plugin_custom_content_newspage', ssd_get_default_settings() );
 
    /* Set up the arguments for the newspage item post type. */
    $args = array(
        'description'         => '',
        'public'              => true,
        'publicly_queryable'  => true,
        'show_in_nav_menus'   => false,
        'show_in_admin_bar'   => true,
        'exclude_from_search' => false,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'menu_position'       => 12,
        'menu_icon'           => ssd_URI . 'images/menu-icon.png',
        'can_export'          => true,
        'delete_with_user'    => false,
        'hierarchical'        => false,
        'has_archive'         => $settings['newspage_root'],
        'query_var'           => 'newspage_item',
        'capability_type'     => 'newspage_item',
        'map_meta_cap'        => true,
 
        /* Only 3 caps are needed: 'manage_newspage', 'create_newspage_items', and 'edit_newspage_items'. */
        'capabilities' => array(
 
            // meta caps (don't assign these to roles)
            'edit_post'              => 'edit_newspage_item',
            'read_post'              => 'read_newspage_item',
            'delete_post'            => 'delete_newspage_item',
 
            // primitive/meta caps
            'create_posts'           => 'create_newspage_items',
 
            // primitive caps used outside of map_meta_cap()
            'edit_posts'             => 'edit_newspage_items',
            'edit_others_posts'      => 'manage_newspage',
            'publish_posts'          => 'manage_newspage',
            'read_private_posts'     => 'read',
 
            // primitive caps used inside of map_meta_cap()
            'read'                   => 'read',
            'delete_posts'           => 'manage_newspage',
            'delete_private_posts'   => 'manage_newspage',
            'delete_published_posts' => 'manage_newspage',
            'delete_others_posts'    => 'manage_newspage',
            'edit_private_posts'     => 'edit_newspage_items',
            'edit_published_posts'   => 'edit_newspage_items'
        ),
 
        /* The rewrite handles the URL structure. */
        'rewrite' => array(
            'slug'       => !empty( $settings['newspage_item_base'] ) ? "{$settings['newspage_root']}/{$settings['newspage_item_base']}" : $settings['newspage_root'],
            'with_front' => false,
            'pages'      => true,
            'feeds'      => true,
            'ep_mask'    => EP_PERMALINK,
        ),
 
        /* What features the post type supports. */
        'supports' => array(
            'title',
            'editor',
            'excerpt',
            'author',
            'thumbnail'
        ),
 
        /* Labels used when displaying the posts. */
        'labels' => array(
            'name'               => __( 'newspage Items',                   'custom-content-newspage' ),
            'singular_name'      => __( 'newspage Item',                    'custom-content-newspage' ),
            'menu_name'          => __( 'newspage',                         'custom-content-newspage' ),
            'name_admin_bar'     => __( 'newspage Item',                    'custom-content-newspage' ),
            'add_new'            => __( 'Add New',                           'custom-content-newspage' ),
            'add_new_item'       => __( 'Add New newspage Item',            'custom-content-newspage' ),
            'edit_item'          => __( 'Edit newspage Item',               'custom-content-newspage' ),
            'new_item'           => __( 'New newspage Item',                'custom-content-newspage' ),
            'view_item'          => __( 'View newspage Item',               'custom-content-newspage' ),
            'search_items'       => __( 'Search newspage',                  'custom-content-newspage' ),
            'not_found'          => __( 'No newspage items found',          'custom-content-newspage' ),
            'not_found_in_trash' => __( 'No newspage items found in trash', 'custom-content-newspage' ),
            'all_items'          => __( 'newspage Items',                   'custom-content-newspage' ),
 
            // Custom labels b/c WordPress doesn't have anything to handle this.
            'archive_title'      => __( 'newspage',                         'custom-content-newspage' ),
        )
    );
 
    /* Register the newspage item post type. */
    register_post_type( 'newspage_item', $args );
}
 
?>
 
//widget3news.php
<?php
/*
        Plugin Name: Show Recent CPTs
        Tags: menu, CPT, widget
        Description: Creates menus and shortcode from Wordpress recent custom post type
        Author: Serhii Dymenko
        Version: 0.5.0
        Author URI: http://proserge.kh.ua/coding/index.php/post/85/WP+News+Plugin
*/
 
class Recent_CPT_Plugin extends WP_Widget 
{
    public $SSD_CPT_type = "newspage_item";
 
    //TODO - add a list of CPTs to choose which type to view as $SSD_CPT_type
 
function __construct() {
    parent::__construct(
        'recent_CPT_Plugin', // Base ID
        'Recent Newspage Plugin', // Name
        array('description' => __( 'Displays your latest news. Outputs the post thumbnail, title and date 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;
}
 
/*The method form() builds the form that we have in the admin section. 
What we’re building is a very simple form with 2 fields: a text field 
for the Widget title, and a drop down list for the number of listings 
we want to show:*/
 
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', 'recent_CPT'); ?></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:', 'recent_CPT'); ?></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->getNewsListings($numberOfListings);
    echo $after_widget;
}
 
function getNewsListings($numberOfListings) { //html
    global $post;
    add_image_size( 'news_widget_size', 85, 45, false );
    $listings = new WP_Query();
    $listings->query('post_type='.$this->SSD_CPT_type.'&posts_per_page=' . $numberOfListings );    
    if($listings->found_posts > 0) {
        echo '<ul class="newspage_widget">';
            while ($listings->have_posts()) {
                $listings->the_post();
                $image = (has_post_thumbnail($post->ID)) ? get_the_post_thumbnail($post->ID, 'news_widget_size') : '<div class="noThumb"></div>'; 
                $listItem = '<li>' . $image; 
                $listItem .= '<a href="' . get_permalink() . '">';
                $listItem .= get_the_title() . '</a>';
                $listItem .= '<span>Added ' . get_the_date() . '</span></li>'; 
                echo $listItem; 
            }
        echo '</ul>';
        wp_reset_postdata(); 
    }else{
        echo '<p style="padding:25px;">No News found</p>';
    } 
}
 
function styleRecentNews() {
wp_register_style('ssd_recent_news_css', plugins_url('recent_news.css',__FILE__ ));
wp_enqueue_style('ssd_recent_news_css');
}
 
 
 
} //end class Realty_Widget
 
 
function register_recent_CPT_widget_plugin() {
register_widget('Recent_CPT_Plugin');
}
 
add_action('widgets_init', 'register_recent_CPT_widget_plugin');
 
////////-----------------------------   SHORTCODE ----------------------
// Register a new shortcode: [book]
add_shortcode( 'ssd_recent', 'ssd_recent_newspage_newes_plugin' );
 
// The callback function that will replace [ssd_recent]
function ssd_recent_newspage_newes_plugin() {
    global $post;
    $blockRecent = "<div class=\"recentShort\">";
    add_image_size( 'news_widget_size', 85, 45, false );
    $listings = new WP_Query();
    $listings->query('post_type='.$this->SSD_CPT_type.'&posts_per_page=3');    
    if($listings->found_posts > 0) {
        $blockRecent .= "<ul class=\"newspage_widget\">";
            while ($listings->have_posts()) {
                $listings->the_post();
                $image = (has_post_thumbnail($post->ID)) ? get_the_post_thumbnail($post->ID, 'news_widget_size') : '<div class="noThumb"></div>'; 
                $listItem = "<li>" . $image; 
                $listItem .= "<a href=\"get_permalink()\">";
                $listItem .= get_the_title() . "</a></br>";
                $listItem .= "<span>Added  get_the_date() </span></li>"; 
                $blockRecent .= $listItem;
                //DebugBreak(); 
            }
        $blockRecent .= "</ul>";
        wp_reset_postdata(); 
    }else{
        $blockRecent .= "<p style=\"padding:25px;\">No News found</p>";
    }
    $blockRecent .= "</div>";
    return $blockRecent;
}
 
//uninstall.php
<?php
/**
 * Uninstall procedure for the plugin.
 *
 * @package    CustomContentNewspage
 * @since      0.5.0
 * @copyright  Copyright (c) 2014, Serhii Dymenko
 * @link       http://proserge.kh.ua/coding/index.php/post/85/WP+News+Plugin
/* Make sure we're actually uninstalling the plugin. */
if ( !defined( 'WP_UNINSTALL_PLUGIN' ) )
    wp_die( sprintf( __( '%s should only be called when uninstalling the plugin.', 'custom-content-newspage' ), '<code>' . __FILE__ . '</code>' ) );
 
/* === Delete plugin options. === */
delete_option( 'plugin_custom_content_newspage' );
 
/* === Remove capabilities added by the plugin. === */
$role =& get_role( 'administrator' );
/* If the administrator role exists, remove added capabilities for the plugin. */
if ( !empty( $role ) ) {
 
    $role->remove_cap( 'manage_newspage' );
    $role->remove_cap( 'create_newspage_items' );
    $role->remove_cap( 'edit_newspage_items' );
}
 
?>
 
//readme.txt
=== Custom Content newspage ===
Contributors: snb4crazy
Tags: news, newsnewspage, post type
Requires at least: 3.9.2
Tested up to: 3.9.2
Stable tag: 0.1
License: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 
A complete newspage plugin built with custom post type.
 
== Description ==
 
**Support Questions:**  The official support forum for this plugin is located at <a href="http://proserge.kh.ua/coding/index.php/post/85/WP+News+Plugin">Author's Post</a>.
 
Custom Content newspage is a newspage management plugin for people such as PR - managers, journalists to show events organized.
 
This plugin was created because of the rising need from users who are downloading WordPress themes with newspage management built in (not a good idea for content portability).  I did my best for give users possibility to switch themes without losing content.
 
**Credits**
 
== Installation ==
 
1. Upload `custom-content-newspage` to the `/wp-content/plugins/` directory.
1. Activate the plugin through the 'Plugins' menu in WordPress.
1. Go to "Settings > Permalinks" in the admin to re-save your permalinks.
 
== Frequently Asked Questions ==
 
= How do I use it? =
 
It works just like posts or pages.  You'll get a new menu item in the admin called "newspage".  From there, you can create new stories.
 
= I'm getting 404 errors. How can I fix this? =
 
Just visit "Settings > Permalinks" in your WordPress admin to flush your rewrite rules.  After that, you shouldn't have any 404 issues.
 
= I don't see the "newspage" section. =
 
It should be located just below "Media" in the WordPress admin menu.  By default, only administrators can see this menu item.  If you are an administrator and can't see it after activating the plugin, deactivate and reactivate the plugin.  This should add the required permissions to your administrator role.
 
== Screenshots ==
 
== Changelog ==
 
**Version 0.1**
 
* Plugin launch.  Everything's new!

Leave a Comment

Fields with * are required.

Please enter the letters as they are shown in the image above.
Letters are not case-sensitive.