Тестовое задание на разработку Плагина новостей:
- создать программно 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=" echo $admin_comment;"> </p> <p> Alt title: <input type="text" name="alt_title" id="alt_title" value=" echo $alt_title;"> </p> } // 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 последними новостями". Стандартная задача, вопрос только - какую информацию выводтиь в виджет? Решил название и дату публикации. Исходник виджета, проверен в бложике ;)
/* 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=" echo $this->get_field_id('title'); "> _e('Title', 'recent_CPT'); </label> <input class="widefat" id=" echo $this->get_field_id('title'); " name=" echo $this->get_field_name('title'); " type="text" value=" echo $title; " /> </p> <p> <label for=" echo $this->get_field_id('numberOfListings'); "> _e('Number of Listings:', 'recent_CPT'); </label> <select id=" echo $this->get_field_id('numberOfListings'); " name=" echo $this->get_field_name('numberOfListings'); "> for($x=1;$x<=10;$x++): <option echo $x == $numberOfListings ? 'selected="selected"' : ''; value=" echo $x;"> echo $x; </option> endfor; </select> </p> } 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"> _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%;"> echo get_post_meta( $post->ID, 'ssd-admin-comment')[0];</textarea> </p> } function ssd_newspage_meta_title_display( $post, $metabox ) { wp_nonce_field( basename( __FILE__ ), 'ssd-newspage-item-info-nonce' ); <p> <label for="ssd-alt-title"> _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=" echo get_post_meta( $post->ID, 'ssd-alt-title')[0]; " size="30" tabindex="30" style="width: 99%;" /> </p> } /** * 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"> do_settings_fields( 'permalink', 'custom-content-newspage' ); </table> } /** * 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=" echo esc_attr( $settings['newspage_root'] ); " /> <code> echo home_url( $settings['newspage_root'] ); </code> } /** * 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=" echo esc_attr( $settings['newspage_base'] ); " /> <code> echo trailingslashit( home_url( "{$settings['newspage_root']}/{$settings['newspage_base']}" ) ); </code> } /** * 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=" echo esc_attr( $settings['newspage_item_base'] ); " /> <code> echo trailingslashit( home_url( "{$settings['newspage_root']}/{$settings['newspage_item_base']}" ) ); %postname%</code> } /** * 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( ' echo ssd_URI . 'images/screen-icon.png'; ' ) no-repeat; } </style> } } //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=" echo $this->get_field_id('title'); "> _e('Title', 'recent_CPT'); </label> <input class="widefat" id=" echo $this->get_field_id('title'); " name=" echo $this->get_field_name('title'); " type="text" value=" echo $title; " /> </p> <p> <label for=" echo $this->get_field_id('numberOfListings'); "> _e('Number of Listings:', 'recent_CPT'); </label> <select id=" echo $this->get_field_id('numberOfListings'); " name=" echo $this->get_field_name('numberOfListings'); "> for($x=1;$x<=10;$x++): <option echo $x == $numberOfListings ? 'selected="selected"' : ''; value=" echo $x;"> echo $x; </option> endfor; </select> </p> } 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!