You are previewing Professional WordPress® Plugin Development.
O'Reilly logo
Professional WordPress® Plugin Development

Book Description

As one of the most popular open source content management systems available today, WordPress boasts a framework that allows you to easily customize and extend it through plugins. This comprehensive book shows you how plugins work, reviews the tools and APIs available in WordPress, and demonstrates how to extend the functionality of WordPress with plugins.

The trio of established authors provides a practical, solutions-based approach along with a collection of timely examples and plenty of code, all aimed at clearly explaining how to create a plugin file, work with users, integrate widgets, add menus and submenus, secure your plugins, and more. You will quickly come to understand how to develop custom plugins so that you can take WordPress to the next corporate and enterprise level.

Professional WordPress Plugin Development:

  • Details the range of complexity in plugins, from a very simple plugin to an extremely elaborate social network package

  • Addresses how to integrate into WordPress, save settings, create widgets and shortcodes, and implement uninstall

  • Learn the proper techniques for storing data, customizing user roles, and security best practices

  • Shares techniques for using custom post types and creating and using custom taxonomies

  • How to create plugins for WordPress Multisite networks

  • Integrate user and role management

  • Explores the HTTP API, JavaScript and AJAX, Cron, the Rewrite API, and more

Table of Contents

  1. Copyright
  2. CREDITS
  3. ABOUT THE AUTHORS
  4. ACKNOWLEDGMENTS
  5. FOREWORD
  6. INTRODUCTION
    1. WHO THIS BOOK IS FOR
    2. WHAT YOU NEED TO USE THIS BOOK
    3. WHAT THIS BOOK COVERS
    4. HOW THIS BOOK IS STRUCTURED
    5. CONVENTIONS
    6. SOURCE CODE
    7. ERRATA
    8. P2P.WROX.COM
  7. 1. An Introduction to Plugins
    1. 1.1. WHAT IS A PLUGIN?
      1. 1.1.1. How Plugins Interact with WordPress
      2. 1.1.2. When Are Plugins Loaded?
    2. 1.2. AVAILABLE PLUGINS
      1. 1.2.1. Official Plugin Directory
      2. 1.2.2. Popular Plugin Examples
      3. 1.2.3. Popular Plugin Tags
    3. 1.3. ADVANTAGES OF PLUGINS
      1. 1.3.1. Not Modifying Core
      2. 1.3.2. Why Reinvent the Wheel
      3. 1.3.3. Separating Plugins and Themes
      4. 1.3.4. Easy Updates
      5. 1.3.5. Easier to Share and Reuse
      6. 1.3.6. Plugin Sandbox
      7. 1.3.7. Plugin Community
    4. 1.4. INSTALLING AND MANAGING PLUGINS
      1. 1.4.1. Installing a Plugin
      2. 1.4.2. Managing Plugins
      3. 1.4.3. Editing Plugins
      4. 1.4.4. Plugin Directories
      5. 1.4.5. Types of Plugins
      6. 1.4.6. Testing Plugin Functionality
    5. 1.5. SUMMARY
  8. 2. Plugin Foundation
    1. 2.1. CREATING A PLUGIN FILE
      1. 2.1.1. Naming Your Plugin
      2. 2.1.2. Using a Folder
    2. 2.2. SANITY PRACTICES
      1. 2.2.1. Prefix Everything
      2. 2.2.2. File Organization
      3. 2.2.3. Folder Structure
    3. 2.3. HEADER REQUIREMENTS
      1. 2.3.1. Creating the Header
      2. 2.3.2. Plugin License
    4. 2.4. DETERMINING PATHS
      1. 2.4.1. Plugin Paths
      2. 2.4.2. Local Paths
      3. 2.4.3. URL Paths
    5. 2.5. ACTIVATE/DEACTIVATE FUNCTIONS
      1. 2.5.1. Plugin Activation Function
      2. 2.5.2. Create Default Settings on Activate
      3. 2.5.3. Plugin Deactivation Function
      4. 2.5.4. Deactivate Is Not Uninstall
    6. 2.6. UNINSTALL METHODS
      1. 2.6.1. Why Uninstall Is Necessary
      2. 2.6.2. Uninstall.php
      3. 2.6.3. Uninstall Hook
    7. 2.7. CODING STANDARDS
      1. 2.7.1. Document Your Code
      2. 2.7.2. Naming Variables, Functions, and Files
      3. 2.7.3. Single and Double Quotes
      4. 2.7.4. Indentation
      5. 2.7.5. Brace Style
      6. 2.7.6. Space Usage
      7. 2.7.7. Shorthand PHP
      8. 2.7.8. SQL Statements
    8. 2.8. PLUGIN DEVELOPMENT CHECKLIST
    9. 2.9. SUMMARY
  9. 3. Hooks
    1. 3.1. ACTIONS
      1. 3.1.1. What Is an Action?
      2. 3.1.2. Action Hook Functions
        1. 3.1.2.1. do_action_ref_array
        2. 3.1.2.2. remove_action
        3. 3.1.2.3. remove_all_actions
        4. 3.1.2.4. has_action
        5. 3.1.2.5. did_action
        6. 3.1.2.6. register_activation_hook and register_deactivation_hook
      3. 3.1.3. Commonly Used Action Hooks
        1. 3.1.3.1. plugins_loaded
        2. 3.1.3.2. init
        3. 3.1.3.3. admin_menu
        4. 3.1.3.4. template_redirect
        5. 3.1.3.5. wp_head
    2. 3.2. FILTERS
      1. 3.2.1. What Is a Filter?
      2. 3.2.2. Filter Hook Functions
        1. 3.2.2.1. apply_filters_ref_array
        2. 3.2.2.2. remove_filter
        3. 3.2.2.3. remove_all_filters
        4. 3.2.2.4. has_filter
        5. 3.2.2.5. current_filter
      3. 3.2.3. Quick Return Functions
      4. 3.2.4. Commonly Used Filter Hooks
        1. 3.2.4.1. the_content
        2. 3.2.4.2. the_title
        3. 3.2.4.3. comment_text
        4. 3.2.4.4. template_include
    3. 3.3. USING HOOKS FROM WITHIN A CLASS
    4. 3.4. CREATING CUSTOM HOOKS
      1. 3.4.1. Benefits of Creating Custom Hooks
      2. 3.4.2. Custom Action Hook Example
      3. 3.4.3. Custom Filter Hook Example
    5. 3.5. HOW TO FIND HOOKS
      1. 3.5.1. Searching for Hooks in the Core Code
      2. 3.5.2. Variable Hooks
      3. 3.5.3. Hook Reference Lists
    6. 3.6. SUMMARY
  10. 4. Integrating in WordPress
    1. 4.1. ADDING MENUS AND SUBMENUS
      1. 4.1.1. Creating a Top-Level Menu
      2. 4.1.2. Adding a Submenu
      3. 4.1.3. Adding a Menu Item to an Existing Menu
    2. 4.2. CREATING WIDGETS
      1. 4.2.1. Creating a Widget
      2. 4.2.2. Advanced Widget
      3. 4.2.3. Creating Dashboard Widgets
      4. 4.2.4. Creating a Dashboard Widget with Options
    3. 4.3. META BOXES
      1. 4.3.1. Adding a Custom Meta Box
      2. 4.3.2. Saving Meta Box Data
      3. 4.3.3. Advanced Meta Box
    4. 4.4. KEEPING IT CONSISTENT
      1. 4.4.1. Using the WordPress UI
      2. 4.4.2. Headings
      3. 4.4.3. Icons
      4. 4.4.4. Messages
      5. 4.4.5. Buttons
      6. 4.4.6. Links
      7. 4.4.7. Form Fields
      8. 4.4.8. Tables
      9. 4.4.9. Pagination
    5. 4.5. SUMMARY
  11. 5. Internationalization
    1. 5.1. INTERNATIONALIZATION AND LOCALIZATION
      1. 5.1.1. Why Internationalize?
      2. 5.1.2. Understanding Internationalization in Professional Work
      3. 5.1.3. Getting Your Plugin Ready for Translation
      4. 5.1.4. Echoing and Returning Strings
        1. 5.1.4.1. The __() Function
        2. 5.1.4.2. The _e() Function
        3. 5.1.4.3. The esc_attr__() Function
        4. 5.1.4.4. The esc_attr_e() Function
        5. 5.1.4.5. The esc_html__() Function
        6. 5.1.4.6. The esc_html_e() Function
        7. 5.1.4.7. The _x() Function
        8. 5.1.4.8. The _ex() Function
        9. 5.1.4.9. The esc_attr_x() Function
        10. 5.1.4.10. The esc_html_x() Function
        11. 5.1.4.11. The _n() Function
        12. 5.1.4.12. The _nx() Function
        13. 5.1.4.13. The _n_noop() Function
        14. 5.1.4.14. The _nx_noop() Function
      5. 5.1.5. Using Placeholders
      6. 5.1.6. Internationalizing JavaScript
    2. 5.2. CREATING TRANSLATION FILES
      1. 5.2.1. The MO and PO Files
      2. 5.2.2. Translation Tools
      3. 5.2.3. How to Create a POT File
      4. 5.2.4. Where to Store Translation Files
    3. 5.3. SUMMARY
  12. 6. Plugin Security
    1. 6.1. SECURING YOUR PLUGIN
      1. 6.1.1. What Securing Your Plugin Is
      2. 6.1.2. What Securing Your Plugin Is Not
    2. 6.2. USER PERMISSIONS
      1. 6.2.1. How to Check current_user_can()
      2. 6.2.2. Do Not Check Too Early
    3. 6.3. NONCES
      1. 6.3.1. Authority Versus Intention
      2. 6.3.2. What Is a Nonce?
      3. 6.3.3. How to Create and Verify Nonces
        1. 6.3.3.1. Creating a URL Nonce
        2. 6.3.3.2. Creating a Form Nonce
        3. 6.3.3.3. Verifying a Nonce
        4. 6.3.3.4. Wrapping It Up: The Entire "Unused Tags" Plugin
      4. 6.3.4. Nonces in Ajax Scripts
    4. 6.4. DATA VALIDATION AND SANITIZATION
      1. 6.4.1. The Need for Data Validation and Sanitization
      2. 6.4.2. Good Practice: Identifying Potentially Tainted Data
      3. 6.4.3. Validating or Sanitizing Input?
      4. 6.4.4. Validating and Sanitizing Cookbook
        1. 6.4.4.1. Integers
        2. 6.4.4.2. Arbitrary Pure Text Strings
        3. 6.4.4.3. Arbitrary Mixed Text Strings
        4. 6.4.4.4. Internal Identifier Strings
        5. 6.4.4.5. String Patterns
          1. 6.4.4.5.1. Example 1: Telephone Number
          2. 6.4.4.5.2. Example 2: Product Serial Number
          3. 6.4.4.5.3. Example 3: Dates
        6. 6.4.4.6. Email Strings
        7. 6.4.4.7. HTML (or XML)
          1. 6.4.4.7.1. HTML Fragments
          2. 6.4.4.7.2. HTML Nodes
        8. 6.4.4.8. URLs
          1. 6.4.4.8.1. URLs in a Database
          2. 6.4.4.8.2. URLs in Redirects
        9. 6.4.4.9. JavaScript
        10. 6.4.4.10. Server or Environment Variables
        11. 6.4.4.11. Cookies
        12. 6.4.4.12. Arrays of Data
        13. 6.4.4.13. Data from a Defined Set
        14. 6.4.4.14. Database Queries
    5. 6.5. FORMATTING SQL STATEMENTS
      1. 6.5.1. The $wpdb Object
      2. 6.5.2. Why wpdb Methods Are Superior
      3. 6.5.3. All-in-One Methods
        1. 6.5.3.1. $wpdb->update()
        2. 6.5.3.2. $wpdb->insert()
      4. 6.5.4. Common Methods
        1. 6.5.4.1. SELECT a Variable
        2. 6.5.4.2. SELECT a Row
        3. 6.5.4.3. SELECT a Column
        4. 6.5.4.4. SELECT Generic Results
        5. 6.5.4.5. Generic Queries
      5. 6.5.5. Protecting Queries Against SQL Injections
      6. 6.5.6. Miscellaneous wpdb Methods and Properties
        1. 6.5.6.1. Toggling Error Display
        2. 6.5.6.2. Tracking the Number of Queries
        3. 6.5.6.3. Other Class Variables
    6. 6.6. SECURITY GOOD HABITS
    7. 6.7. SUMMARY
  13. 7. Plugin Settings
    1. 7.1. THE OPTIONS API
      1. 7.1.1. Saving Options
      2. 7.1.2. Saving an Array of Options
      3. 7.1.3. Retrieving Options
      4. 7.1.4. Loading an Array of Options
      5. 7.1.5. Deleting Options
      6. 7.1.6. The Autoload Parameter
        1. 7.1.6.1. Segregating Plugin Options
        2. 7.1.6.2. Toggling the Autoload Parameter
    2. 7.2. THE SETTINGS API
      1. 7.2.1. Benefits of the Settings API
      2. 7.2.2. Settings API Functions
        1. 7.2.2.1. Creating the Plugin Administration Page
        2. 7.2.2.2. Registering New Settings
        3. 7.2.2.3. Defining Sections and Settings
        4. 7.2.2.4. Validating User Input
        5. 7.2.2.5. Rendering the Form
        6. 7.2.2.6. All Done!
      3. 7.2.3. Wrapping It Up: A Complete Plugin Management Page
      4. 7.2.4. Improving Feedback on Validation Errors
      5. 7.2.5. Adding Fields to an Existing Page
        1. 7.2.5.1. How It Works
        2. 7.2.5.2. Adding a Section to an Existing Page
        3. 7.2.5.3. Adding Only Fields
        4. 7.2.5.4. WordPress' Sections and Setting Fields
        5. 7.2.5.5. User Interface Concerns
    3. 7.3. THE TRANSIENTS API
      1. 7.3.1. Saving an Expiring Option
      2. 7.3.2. Retrieving an Expiring Option
      3. 7.3.3. Deleting an Expiring Option
      4. 7.3.4. A Practical Example Using Transients
      5. 7.3.5. Technical Details
      6. 7.3.6. Transient Ideas
    4. 7.4. SAVING PER-USER SETTINGS
      1. 7.4.1. Crafting a Plugin
      2. 7.4.2. User Metadata
      3. 7.4.3. Saving User Metadata
      4. 7.4.4. Updating User Metadata
      5. 7.4.5. Getting User Metadata
      6. 7.4.6. Deleting User Metadata
      7. 7.4.7. Getting a User's ID
      8. 7.4.8. Adding Input Fields to a Profile Page
      9. 7.4.9. BOJ's Admin Lang Plugin
      10. 7.4.10. Per-User Settings: Best Practices
    5. 7.5. STORING DATA IN CUSTOM TABLES
      1. 7.5.1. Types of Data
      2. 7.5.2. WordPress' Standard Tables
      3. 7.5.3. Creating a Custom Table
        1. 7.5.3.1. Checking if a Table Already Exists
      4. 7.5.4. Updating the Structure of a Custom Table
      5. 7.5.5. dbDelta() Tips for Success
        1. 7.5.5.1. Watching Your SQL Syntax and Style
        2. 7.5.5.2. Checking the Return Value in a Debug Sandbox
        3. 7.5.5.3. Test Running Your SQL Statement
      6. 7.5.6. Accessing Your Custom Table
    6. 7.6. SUMMARY
  14. 8. Users
    1. 8.1. WORKING WITH USERS
      1. 8.1.1. User Functions
        1. 8.1.1.1. is_user_logged_in()
        2. 8.1.1.2. get_users()
        3. 8.1.1.3. get_users_of_blog()
        4. 8.1.1.4. count_users
      2. 8.1.2. Creating, Updating, and Deleting Users
        1. 8.1.2.1. wp_insert_user
        2. 8.1.2.2. wp_create_user
        3. 8.1.2.3. wp_update_user
        4. 8.1.2.4. wp_delete_user
      3. 8.1.3. User Data
        1. 8.1.3.1. get_userdata
        2. 8.1.3.2. wp_get_current_user
        3. 8.1.3.3. get_currentuserinfo
        4. 8.1.3.4. count_user_posts
        5. 8.1.3.5. count_many_users_posts
      4. 8.1.4. User Metadata
        1. 8.1.4.1. add_user_meta
        2. 8.1.4.2. get_user_meta
        3. 8.1.4.3. update_user_meta
        4. 8.1.4.4. delete_user_meta
        5. 8.1.4.5. user_contactmethods
        6. 8.1.4.6. Creating a Plugin with User Metadata
    2. 8.2. ROLES AND CAPABILITIES
      1. 8.2.1. What Are Roles and Capabilities?
      2. 8.2.2. Default Roles
      3. 8.2.3. Custom Roles
    3. 8.3. LIMITING ACCESS
      1. 8.3.1. Checking User Permissions
        1. 8.3.1.1. current_user_can
        2. 8.3.1.2. current_user_can_for_blog
        3. 8.3.1.3. author_can
        4. 8.3.1.4. user_can
        5. 8.3.1.5. map_meta_cap
      2. 8.3.2. Is the User an Admin?
        1. 8.3.2.1. is_super_admin
      3. 8.3.3. Allowing Custom Permissions
    4. 8.4. CUSTOMIZING ROLES
      1. 8.4.1. Creating a Role
        1. 8.4.1.1. add_role
      2. 8.4.2. Deleting a Role
        1. 8.4.2.1. remove_role
      3. 8.4.3. Adding Capabilities to a Role
        1. 8.4.3.1. get_role
      4. 8.4.4. Removing Capabilities from a Role
      5. 8.4.5. A Custom Role and Capability Plugin
    5. 8.5. SUMMARY
  15. 9. HTTP API
    1. 9.1. HTTP REQUESTS CRASH COURSE
      1. 9.1.1. What Is an HTTP Request?
        1. 9.1.1.1. HTTP Request Concepts
        2. 9.1.1.2. Dissecting an HTTP Transaction
          1. 9.1.1.2.1. The Client Sends a Request
          2. 9.1.1.2.2. The Server Sends a Response
        3. 9.1.1.3. Possibilities for Crafting HTTP Requests
      2. 9.1.2. How to Make HTTP Requests in PHP
        1. 9.1.2.1. Using the HTTP Extension
        2. 9.1.2.2. Using fopen() Streams
        3. 9.1.2.3. Using a Standard fopen()
        4. 9.1.2.4. Using fsockopen()
        5. 9.1.2.5. Using the CURL Extension
        6. 9.1.2.6. Too Many Ways?
    2. 9.2. WORDPRESS' HTTP FUNCTIONS
      1. 9.2.1. The wp_remote_ Functions
        1. 9.2.1.1. wp_remote_* Input Parameters
        2. 9.2.1.2. wp_remote_* Return Values
          1. 9.2.1.2.1. Unsuccessful Requests
          2. 9.2.1.2.2. Successful Requests
        3. 9.2.1.3. wp_remote_ Companion Functions
      2. 9.2.2. Advanced Configuration and Tips
        1. 9.2.2.1. Proxy Support
        2. 9.2.2.2. Filtering Requests and Responses
          1. 9.2.2.2.1. Example: Modify a Default Parameter
          2. 9.2.2.2.2. Example: Log HTTP Requests and Responses
          3. 9.2.2.2.3. Example: Advanced Filtering
        3. 9.2.2.3. Some Caveats on Checking HTTP Responses
    3. 9.3. PRACTICE: READING JSON FROM A REMOTE API
      1. 9.3.1. Getting and Reading JSON
      2. 9.3.2. Your Functional Plugin
    4. 9.4. PRACTICE: SENDING DATA TO A REMOTE API
      1. 9.4.1. Formatting Parameters for POST Requests
      2. 9.4.2. Your Functional Plugin
    5. 9.5. PRACTICE: READING ARBITRARY CONTENT
    6. 9.6. MAKE YOUR OWN PLUGIN REPOSITORY
      1. 9.6.1. How Plugin Upgrades Work in WordPress
      2. 9.6.2. Polling an Alternative API from a Plugin
      3. 9.6.3. Building the Alternative API
      4. 9.6.4. A Few Words of Caution About Self-Hosted API
    7. 9.7. SPECIAL CASE: FETCHING REMOTE FEEDS
    8. 9.8. SUMMARY
  16. 10. The Shortcode API
    1. 10.1. CREATING SHORTCODES
      1. 10.1.1. What Shortcodes Are
      2. 10.1.2. Register Custom Shortcodes
        1. 10.1.2.1. [book]
        2. 10.1.2.2. [books title="xkcd"]
        3. 10.1.2.3. [amazon asin="12345" ]book title[/amazon]
        4. 10.1.2.4. Wrap Up: add_shortcode() and the callback Function
    2. 10.2. SHORTCODE TIPS
      1. 10.2.1. Think Simplicity for the User
      2. 10.2.2. Remember the Dynamicity
      3. 10.2.3. Look Under the Hoods
        1. 10.2.3.1. $shortcode_tags
        2. 10.2.3.2. remove_shortcode()
        3. 10.2.3.3. remove_all_shortcodes()
        4. 10.2.3.4. strip_shortcodes()
        5. 10.2.3.5. shortcode_atts()
        6. 10.2.3.6. do_shortcode()
        7. 10.2.3.7. Recursive Shortcodes
      4. 10.2.4. A "bb code" for Comments Plugin
      5. 10.2.5. Shortcode Nesting Limitations
    3. 10.3. INTEGRATING GOOGLE MAPS
      1. 10.3.1. Accessing the Google Geocoding API
      2. 10.3.2. Storing API Results
      3. 10.3.3. Accessing the Google Maps API
        1. 10.3.3.1. API Concepts
        2. 10.3.3.2. Plugin Implementation
    4. 10.4. MORE SHORTCODE QUICK IDEAS
      1. 10.4.1. Display Member-Only Content
      2. 10.4.2. Display Time-Limited Content
      3. 10.4.3. Obfuscate Email Addresses
    5. 10.5. SUMMARY
  17. 11. Extending Posts: Metadata, Custom Post Types, and Taxonomies
    1. 11.1. CREATING CUSTOM POST TYPES
      1. 11.1.1. Post Type Possibilities
      2. 11.1.2. Registering a Post Type
        1. 11.1.2.1. register_post_type
          1. 11.1.2.1.1. public
          2. 11.1.2.1.2. show_ui
          3. 11.1.2.1.3. publicy_queryable
          4. 11.1.2.1.4. exclude_from_search
          5. 11.1.2.1.5. supports
          6. 11.1.2.1.6. labels
          7. 11.1.2.1.7. capability_type
          8. 11.1.2.1.8. capabilities
          9. 11.1.2.1.9. hierarchical
          10. 11.1.2.1.10. has_archive
          11. 11.1.2.1.11. query_var
          12. 11.1.2.1.12. rewrite
          13. 11.1.2.1.13. taxonomies
          14. 11.1.2.1.14. menu_position
          15. 11.1.2.1.15. menu_icon
          16. 11.1.2.1.16. show_in_nav_menus
          17. 11.1.2.1.17. can_export
          18. 11.1.2.1.18. register_meta_box_cb
          19. 11.1.2.1.19. permalink_epmask
        2. 11.1.2.2. Registering the Music Album Post Type
      3. 11.1.3. Setting Post Type Labels
      4. 11.1.4. Using Custom Capabilities
      5. 11.1.5. Attaching Existing Taxonomies
    2. 11.2. USING CUSTOM POST TYPES
      1. 11.2.1. Creating a Custom Post Type Loop
      2. 11.2.2. Retrieving Custom Post Type Content
        1. 11.2.2.1. the_title
        2. 11.2.2.2. the_content
          1. 11.2.2.2.1. the_excerpt
          2. 11.2.2.2.2. the_permalink
      3. 11.2.3. Checking if a Post Type Exists
        1. 11.2.3.1. post_type_exists
    3. 11.3. POST METADATA
      1. 11.3.1. Adding Post Metadata
        1. 11.3.1.1. add_post_meta
      2. 11.3.2. Retrieving Post Metadata
        1. 11.3.2.1. get_post_meta
      3. 11.3.3. Updating Post Metadata
        1. 11.3.3.1. update_post_meta
      4. 11.3.4. Deleting Post Metadata
        1. 11.3.4.1. delete_post_meta
    4. 11.4. CREATING CUSTOM TAXONOMIES
      1. 11.4.1. Understanding Taxonomies
      2. 11.4.2. Registering a Custom Taxonomy
        1. 11.4.2.1. register_taxonomy
          1. 11.4.2.1.1. public
          2. 11.4.2.1.2. show_ui
          3. 11.4.2.1.3. hierarchical
          4. 11.4.2.1.4. query_var
          5. 11.4.2.1.5. rewrite
          6. 11.4.2.1.6. update_count_callback
          7. 11.4.2.1.7. show_tagcloud
          8. 11.4.2.1.8. show_in_nav_menus
          9. 11.4.2.1.9. labels
          10. 11.4.2.1.10. capabilities
        2. 11.4.2.2. Registering the Genre and Artist Taxonomies
      3. 11.4.3. Assigning a Taxonomy to a Post Type
        1. 11.4.3.1. register_taxonomy_for_object_type
    5. 11.5. USING CUSTOM TAXONOMIES
      1. 11.5.1. Retrieving a Taxonomy
        1. 11.5.1.1. get_taxonomy
      2. 11.5.2. Using a Taxonomy with Posts
        1. 11.5.2.1. the_terms
      3. 11.5.3. Taxonomy Conditional Tags
        1. 11.5.3.1. taxonomy_exists
        2. 11.5.3.2. is_taxonomy_hierarchical
        3. 11.5.3.3. is_tax
    6. 11.6. A POST TYPE AND TAXONOMY PLUGIN
    7. 11.7. SUMMARY
  18. 12. JavaScript and Ajax in WordPress
    1. 12.1. JQUERY–A BRIEF INTRODUCTION
      1. 12.1.1. Benefits of Using jQuery
      2. 12.1.2. jQuery Crash Course
        1. 12.1.2.1. The jQuery Object
        2. 12.1.2.2. Syntax and Chaining
        3. 12.1.2.3. No-Conflict Mode in WordPress
        4. 12.1.2.4. Launching Code on Document Ready
    2. 12.2. AJAX
      1. 12.2.1. What Is Ajax?
      2. 12.2.2. Ajax Best Practices
    3. 12.3. ADDING JAVASCRIPT IN WORDPRESS
      1. 12.3.1. A Proper Way to Include Scripts
        1. 12.3.1.1. Introducing wp_enqueue_script()
          1. 12.3.1.1.1. Adding a Core Script
          2. 12.3.1.1.2. Adding a Custom Script
          3. 12.3.1.1.3. Adding a Custom Script with Dependencies
          4. 12.3.1.1.4. Adding a Custom Script with a Version Number
          5. 12.3.1.1.5. Adding Scripts in the Footer
          6. 12.3.1.1.6. All Parameters at Once
        2. 12.3.1.2. Default Core Scripts
        3. 12.3.1.3. Removing a Queued Script
        4. 12.3.1.4. Replacing a Core Script with Your Own
        5. 12.3.1.5. Registering and Enqueuing Scripts
        6. 12.3.1.6. Managing Styles in WordPress
      2. 12.3.2. Where to Include Scripts
        1. 12.3.2.1. Head? Footer? Inline?
          1. 12.3.2.1.1. In the Head
          2. 12.3.2.1.2. Near the Footer
          3. 12.3.2.1.3. In the Page Content
          4. 12.3.2.1.4. Inline
        2. 12.3.2.2. Valid Xhtml Syntax
        3. 12.3.2.3. Valid Html 5 Syntax
        4. 12.3.2.4. Pondering the Best Option
      3. 12.3.3. Adding Scripts Only When Needed
        1. 12.3.3.1. Getting the Location of Your Plugin's Scripts
        2. 12.3.3.2. Adding in Admin Pages
        3. 12.3.3.3. Adding in Public Pages
      4. 12.3.4. Dynamic Scripts in WordPress
        1. 12.3.4.1. How Not to Do It and Why
        2. 12.3.4.2. A Better Solution
        3. 12.3.4.3. An Ideal Solution
    4. 12.4. AJAX IN WORDPRESS
      1. 12.4.1. Ajax in WordPress: Principles
        1. 12.4.1.1. Client Side: Send Ajax Request, Receive Response
        2. 12.4.1.2. Server-Side: Receive Ajax Request; Send Response
      2. 12.4.2. A Complete Example: Instant "Read More" Links
        1. 12.4.2.1. Inserting the JavaScript with a Twist
        2. 12.4.2.2. Client-Side JavaScript
        3. 12.4.2.3. Server-Side Ajax Processing
      3. 12.4.3. Another Example: Frontend Comment Deletion
        1. 12.4.3.1. Plugin Basis
        2. 12.4.3.2. Server-Side Ajax Handler: Security Checks and XML Response Parsing
          1. 12.4.3.2.1. Ajax Security: Nonces and Permissions
          2. 12.4.3.2.2. The WP_Ajax_Response Class
        3. 12.4.3.3. Client-Side XML Response Parsing
      4. 12.4.4. Debugging Ajax
    5. 12.5. SUMMARY
  19. 13. Cron
    1. 13.1. WHAT IS CRON?
      1. 13.1.1. How Is Cron Executed?
    2. 13.2. SCHEDULING CRON EVENTS
      1. 13.2.1. Scheduling a Recurring Event
      2. 13.2.2. Scheduling a Single Event
      3. 13.2.3. Unscheduling an Event
      4. 13.2.4. Specifying Your Own Cron Intervals
      5. 13.2.5. Viewing Cron Events Scheduled
    3. 13.3. TRUE CRON
    4. 13.4. PRACTICAL USE
      1. 13.4.1. Deleting Post Revisions Weekly
      2. 13.4.2. The Blog Pester Plugin
      3. 13.4.3. The Delete Comments Plugin
    5. 13.5. SUMMARY
  20. 14. The Rewrite API
    1. 14.1. WHY REWRITE URLS
      1. 14.1.1. Permalink Principles
        1. 14.1.1.1. Search Engine Friendly
        2. 14.1.1.2. User Friendly
      2. 14.1.2. Apache's mod_rewrite
      3. 14.1.3. URL Rewriting in WordPress
    2. 14.2. HOW WORDPRESS HANDLES QUERIES
      1. 14.2.1. Overview of the Query Process
      2. 14.2.2. The rewrite Object
      3. 14.2.3. The query Object
      4. 14.2.4. What Plugins Can Do
    3. 14.3. PRACTICAL USES
      1. 14.3.1. Rewriting a URL to Create a List of Shops
        1. 14.3.1.1. Creating the rewrite Rule
        2. 14.3.1.2. Registering the query Variable
        3. 14.3.1.3. Flushing the Rewrite Rules
        4. 14.3.1.4. The Functional Plugin
        5. 14.3.1.5. Creating the Shops Page that Can Generate Its Children
      2. 14.3.2. Creating a New Permalink Structure and Integrating Non-WordPress Pages
        1. 14.3.2.1. Creating a rewrite Tag
        2. 14.3.2.2. Displaying the Shop Products
        3. 14.3.2.3. The Functional Plugin
      3. 14.3.3. Adding an Endpoint and Altering Output Format
        1. 14.3.3.1. Defining the Endpoint
        2. 14.3.3.2. The Functional Plugin
      4. 14.3.4. Adding a Custom Feed for the Latest Uploaded Images
        1. 14.3.4.1. Registering the New Feed
        2. 14.3.4.2. The Functional Plugin
    4. 14.4. SUMMARY
  21. 15. Multisite
    1. 15.1. DIFFERENCES
      1. 15.1.1. WordPress Versus Multisite Network
      2. 15.1.2. Understanding Multisite Terminology
      3. 15.1.3. Advantages of Multisite
    2. 15.2. ENABLING MULTISITE IN WORDPRESS
    3. 15.3. MULTISITE FUNCTIONS
      1. 15.3.1. The Power of Blog ID
      2. 15.3.2. Common Functions
      3. 15.3.3. Switching and Restoring Sites
      4. 15.3.4. Network Content Shortcode Examples
      5. 15.3.5. A Network Content Widget Example
      6. 15.3.6. Creating a New Site
      7. 15.3.7. Multisite Site Options
      8. 15.3.8. Users in a Network
      9. 15.3.9. Multisite Super Admin
      10. 15.3.10. Checking the Site Owner
      11. 15.3.11. Network Stats
    4. 15.4. MULTISITE DATABASE SCHEMA
      1. 15.4.1. Multisite-Specific Tables
      2. 15.4.2. Site-Specific Tables
    5. 15.5. SUMMARY
  22. 16. Debugging and Optimizing
    1. 16.1. SUPPORTING OLD VERSIONS (NOT)
      1. 16.1.1. Keeping Current with WordPress Development
      2. 16.1.2. Deprecated Functions
      3. 16.1.3. Dealing with Obsolete Client Installs
    2. 16.2. DEBUGGING
      1. 16.2.1. Enabling Debugging
      2. 16.2.2. Displaying Debug Messages
      3. 16.2.3. Correcting Debug Messages
    3. 16.3. ERROR LOGGING
      1. 16.3.1. Enabling Logging
      2. 16.3.2. Setting Log File Location
      3. 16.3.3. Understanding the Log File
    4. 16.4. CACHING
      1. 16.4.1. Saving, Loading, and Deleting Cached Data
        1. 16.4.1.1. wp_cache_add()
        2. 16.4.1.2. wp_cache_replace()
        3. 16.4.1.3. wp_cache_set()
        4. 16.4.1.4. wp_cache_get()
        5. 16.4.1.5. wp_cache_delete()
      2. 16.4.2. Caching Data Within a Plugin
    5. 16.5. SUMMARY
  23. 17. Marketing Your Plugin
    1. 17.1. CHOOSING A LICENSE FOR YOUR PLUGIN
      1. 17.1.1. Different Options
      2. 17.1.2. Why It Matters
      3. 17.1.3. Making Money While Using the GPL
    2. 17.2. SUBMITTING TO WORDPRESS.ORG
      1. 17.2.1. Creating an Account
      2. 17.2.2. Submitting a Plugin
      3. 17.2.3. Setting Up SVN
      4. 17.2.4. Creating a readme.txt File
    3. 17.3. GETTING YOUR PLUGIN RENOWNED
      1. 17.3.1. Naming Your Plugin
        1. 17.3.1.1. Tips on Creating a Plugin Name
        2. 17.3.1.2. How to Not Name Your Plugin
        3. 17.3.1.3. Branding Your Plugin
      2. 17.3.2. Building a Web Site
        1. 17.3.2.1. Creating a Page or Site for All Your Plugins
        2. 17.3.2.2. Having a Great Design
        3. 17.3.2.3. Blogging About WordPress
      3. 17.3.3. Creating a Page for Your Plugin
      4. 17.3.4. Announcing Your Plugin
      5. 17.3.5. Supporting Your Plugins
      6. 17.3.6. Getting Feedback
      7. 17.3.7. Getting Out of the Basement
      8. 17.3.8. Other Promotion Methods
    4. 17.4. SUMMARY
  24. 18. The Developer Toolbox
    1. 18.1. CORE AS REFERENCE
      1. 18.1.1. Inline Documentation
      2. 18.1.2. Finding Functions
      3. 18.1.3. Common Core Files
        1. 18.1.3.1. Formatting.php
        2. 18.1.3.2. Functions.php
        3. 18.1.3.3. Pluggable.php
      4. 18.1.4. Plugin.php
        1. 18.1.4.1. Post.php
    2. 18.2. CODEX
      1. 18.2.1. Searching the Codex
      2. 18.2.2. Function Reference
    3. 18.3. TOOL WEB SITES
      1. 18.3.1. PHPXref
      2. 18.3.2. Hooks Database
    4. 18.4. COMMUNITY RESOURCES
      1. 18.4.1. Support Forums
      2. 18.4.2. Mailing Lists
      3. 18.4.3. WordPress Chat
      4. 18.4.4. WordPress Development Updates
      5. 18.4.5. WordPress Ideas
      6. 18.4.6. Community News Sites
        1. 18.4.6.1. WordPress Planet
        2. 18.4.6.2. Planet WordPress
        3. 18.4.6.3. WPEngineer.com
        4. 18.4.6.4. WeblogToolsCollection.com
        5. 18.4.6.5. Twitter
      7. 18.4.7. Local Events
    5. 18.5. TOOLS
      1. 18.5.1. Browser
      2. 18.5.2. Editor
        1. 18.5.2.1. NetBeans IDE
        2. 18.5.2.2. Notepad++
        3. 18.5.2.3. TextMate
        4. 18.5.2.4. Coda
      3. 18.5.3. Deploying Files with FTP, SFTP, and SSH
      4. 18.5.4. phpMyAdmin
    6. 18.6. SUMMARY