WordPress Plugin #3
Mar. 2nd, 2017
changwoo
Recap
Hooks in Nutshell
Recap
Hooks in Nutshell
Recap
Database Nutshell
Recap
Database Nutshell
Recap
Note: Slides Repository
Today's Topics
Entry Points in Plugin
Entry Points
Plugins run on the server side.
Server only responds when it is requested.
Requested moment → entry point
Entry Points
Q. When the server is requested?
A. It is when clients access via a URL.
Q. Why a URL is used?
A. To define a resource: output to clients
A. To receive data: input from clients
Entry Points
Q. Output form?
A. Whatever.
Images, audio, video, html documents, ...
Q. Input form?
A. Generally submitting forms
via GET/POST method.
Entry Points
There are some special entry points for plugins�
Menu Items
Callback from admin menu clicking
add_menu_page()
add_submenu_page()
remove_menu_page()
remove_submenu_page()
Where is default menu?
wp-admin/menu-header.php
<ul id="adminmenu">
<?php
_wp_menu_output( $menu, $submenu );
function _wp_menu_output( $menu, $submenu, $submenu_as_parent = true )
here menus are printed in html
Where is default menu?
wp-admin/menu.php (admin.php includes it)
wp-admin/includes/menu.php
builds administrative menus
global $menu, $submenu stores menu information
Our custom menus
wp-admin/includes/menu.php
do_action( 'admin_menu', '' );
Menu API are defined in wp-admin/includes/plugin.php
add_menu_page
function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) {
...
$new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url );
if ( null === $position )
$menu[] = $new_menu;
else
$menu[$position] = $new_menu;
add_submenu_page
function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
...
$submenu[$parent_slug][] = array (
$menu_title, $capability, $menu_slug, $page_title );
...
}
derivatives
Shortcodes
What is shortcode?
A "magic word" in post content that is replaced by some process defined in plugin or themes in runtime.
Good for displaying complex, dynamic contents
Shortcodes
Sample:
[gallery id="123" size="medium"]
[gallery]
or
[caption]My Caption[/caption] *enclosed form
Shortcodes
add_shortcode()
$shortcode_tags = array();
function add_shortcode($tag, $func) {
global $shortcode_tags;
if ( is_callable($func) )
$shortcode_tags[$tag] = $func;
}
Shortcodes
function do_shortcode($content) {
global $shortcode_tags;
if ( false === strpos( $content, '[' ) ) {
return $content;
}
if (empty($shortcode_tags) || !is_array($shortcode_tags))
return $content;
$pattern = get_shortcode_regex();
return preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );
}
Shortcodes
function do_shortcode_tag( $m ) {
...
$content = isset( $m[5] ) ? $m[5] : null;
$output = $m[1] . call_user_func( $shortcode_tags[ $tag ], $attr, $content, $tag ) . $m[6];
...
}
Shortcodes
callback params
Admin-post
Data from clients.
Processing requests.
You can just process requests in your own page because $_REQUEST, $_GET, $_POST is global.
Admin-post
But in your own handler,
You cannot use WP core functions.
You cannot authenticate.
Do not reinvent the wheel!
So there is admin-post.php
Admin-post
wp-admin/admin-post.php
define & include minimal settings,
and do_action
$action = empty( $_REQUEST['action'] ) ? '' : $_REQUEST['action'];
admin_post_nopriv, admin_post_nopriv_{$action}
admin_post, admin_post_{$action}
finish using die() in callback function!
AJAX
Very similar to admin-post, but 'DOING_AJAX' is defined:
define( 'DOING_AJAX', true );
also use die() in callback function
if ( is_user_logged_in() ) {
do_action( 'wp_ajax_' . $_REQUEST['action'] );
} else {
do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] );
}
// Default status
die( '0' );
Redirect
You can generate custom page in plugin, by using 'template_redirect' action.
function my_page_template_redirect() {
if( is_page( 'goodies' ) && ! is_user_logged_in() ) {
wp_redirect( home_url( '/signup/' ) );
exit();
}
}
add_action( 'template_redirect', 'my_page_template_redirect' );
Redirect
You can generate web pages on-the-fly by utilizing these 3 hooks.
Detailed instructions, later
(de)activation, uninstall
register_activation_hook($file, $cb)
register_deactivation_hook($file, $cb)
register_uninstall_hook($file, $cb)
$file: full path of plugin file
$cb: callback function
Summary
I know you want to do something!
You understand hook concept.
You know database detail.
Now you know entry points
Definitely, you wanna make something.
Visit http://[ip]/03-entry-point/ and download entry-points.php
Source code explained
소스코드:
<author> 부분은 자신의 이름으로 일괄변경하고,
적절히 콜백 함수를 정의해 주세요.
10 minutes break
Managing Your Own Contents
Wow, there are too many things about posts!
For today, just focus on
"custom post type"
Arguments are too complex!
Just use Types, or Pods plugin.
That's all, problem solved!
Yeah!
... of course, you might not want this.
Custom Post
You want to manage your own contents.
That's why custom post type is.
Custom Post: Motivation
Well, with just one type "post", and you may define many categories and use them to organize all contents.
JUST ONE TYPE: POST
MANY CATEGORIES:
portfolio, calendar, music db, ...
Custom Post: Motivation
But you might feel that some post types:
Custom Post: Motivation
Moreover, "category" is just for classification of your posts. It is only related to its contents.
Not for ACL or administrative management facilities: categories must be de-coupled from those "heavy" burdens
Custom Post: Motivation
Why re-invent wheel again?
By extending built-in post type system,
you can REUSE whole facilities related to posts easily!
UI, and all thing about managing
Built-in Custom Post Types
wp-includes/post.php (included in wp-settings.php)
function create_initial_post_types() {
register_post_type( 'post', array( ...
register_post_type( 'page', array( ...
register_post_type( 'attachment', array( ...
register_post_type( 'revision', array( ...
register_post_type( 'nav_menu_item', array( ...
register_post_status( 'publish', array( ...
...
register_post_type
<?php register_post_type( $post_type, $args ); ?>
$arg is very complex.
But I think it should be explained in detail. Actually, you cannot avoid it, because eventually all post type plugins will use that function, too.
Those plugins also have difficult UIs, too.
register_post_type
Let's take a look how Types, and Pods create their custom posts...
They have easy (really?) UI and provide better functionality, but you can see horribly many options there.
register_post_type $post_type
$args:everything is optional
Total 24+
$args: categorize'em
$args: categorize'em
$args: categorize'em
Exposure: interface exposure
public: TRUE
$args: categorize'em
Exposure: interface exposure
public: FALSE
$args: categorize'em
Visual Queue: if visible, then how?
$args: categorize'em
Resource Location: accessing
$args: categorize'em
Access Control: permission
$args: categorize'em
Content Characteristics:
$args: categorize'em
ETC:
register_post_type $args
public:
visible to authors�
true implies
exclude_from_search: false,
publicly_queryable, show_in_nav_manues, show_ui�
false implies
exclude_from_search: true, publicly_queryable: false,
show_in_nav_manues: false, show_ui: false
register_post_type $args
exclude_from_search:
do not search this post type
try '/s=beatles'
register_post_type $args
publicly_queryable:
can use query
e.g) /?post_type=music_collection
register_post_type $args
show_ui:
display default UI
register_post_type $args
show_in_nav_menus:
show in navigation menus
be careful! 'publicly_queryable'
must be true
register_post_type $args
show_in_menu:
show admin_menu. show_ui must be true.
Just showing menu.
true, false, else some strings
(tools.php / edit.php)
although it is false,
you can access URLS like:
/wp-admin/edit.php?post_type=music_collection
(show_ui must be true!)
register_post_type $args
show_in_admin_bar:
available in admin bar
register_post_type $args
label:
plural descriptive name
e.g: __(Music Collections, textdomain)
menu_postion:
default: below comments
menu_icon
see dashicons
register_post_type $args
permalink_epmask:
rewrite endpoint bitmask
query_var:
to query posts /?{query_var}={slug}
rewrite:
to use pretty permalinks.
register_post_type $args
labels: more specific text labels
name
sigular_name
menu_name
name_admin_bar
all_items
add_new
add_new_item
edit_item
view_item
search_items
search_items
not_found
not_found in trash
parent_item_colon
register_post_type $args
capability_type:
string or array to build capabilities
in our example,
edit_music_collections
edit_others_music_collections
publish_music_collections
read_private_music_collections
register_post_type $args
capabilities:
to give specific names to each capability
map_meta_cap:
if true, default meta capability will be added
and then, your role or account need capabilities
register_post_type $args
hierarchical:
post type can be hierarchical.
this is for page-styles.
supports:
editable components
register_post_type $args
register_meta_box_cb: meta box
taxonomies:
has_archive:
Enables post type archive
register_post_type $args
description:
summary of this post type
can_export:
true makes the post can be exported
Too exhaustive... but worth it.
Practice Custom Post
Create custom-post-<author>.php
Create a simple custom post.
Display admin menu,
Hide admin_bar,
Write your post:
Next Week.
Customizing Visual Components
Underneath WordPress System
Appendix