Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Advanced Actions & Filters

Advanced Actions & Filters

Learn how actions & filters work in WordPress core, discover more about the template_redirect action, and learn how (and why) to make your own hooks.

Alison Barrett

January 19, 2013
Tweet

More Decks by Alison Barrett

Other Decks in Programming

Transcript

  1. function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {

    return add_filter($tag, $function_to_add, $priority, $accepted_args); } ...but actions are filters.
  2. function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {

    ! global $wp_filter, $merged_filters; ! $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority); ! $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args); ! unset( $merged_filters[ $tag ] ); ! return true; } add_filter()
  3. $tag = 'the_content' $function_to_add = 'show_author_bio' $priority = 10 (default)

    $accepted_args = 1 (default) function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
  4. function _wp_filter_build_unique_id(...) { ! ... ! if ( is_string($function) )

    ! ! return $function; ! ... } global $wp_filter, $merged_filters; $idx = _wp_filter_build_unique_id( $tag, $function_to_add, $priority );
  5. ! $wp_filter[$tag][$priority][$idx] = array( 'function' => $function_to_add, 'accepted_args' => $accepted_args

    ! ); ! unset( $merged_filters[ $tag ] ); ! return true; } $wp_filter['the_content'][10]['show_author_bio'] = array( 'function' => 'show_author_bio', 'accepted_args' => 1 );
  6. function apply_filters($tag, $value) { ! global $wp_filter, $merged_filters, $wp_current_filter; !

    $args = array(); ! // Do 'all' actions first ! if ( isset($wp_filter['all']) ) { ! ! $wp_current_filter[] = $tag; ! ! $args = func_get_args(); ! ! _wp_call_all_hook($args); ! } ! if ( !isset($wp_filter[$tag]) ) { ! ! if ( isset($wp_filter['all']) ) ! ! ! array_pop($wp_current_filter); ! ! return $value; ! } ! if ( !isset($wp_filter['all']) ) ! ! $wp_current_filter[] = $tag; ! // Sort ! if ( !isset( $merged_filters[ $tag ] ) ) { ! ! ksort($wp_filter[$tag]); ! ! $merged_filters[ $tag ] = true; ! } ! reset( $wp_filter[ $tag ] ); ! if ( empty($args) ) ! ! $args = func_get_args(); ! do { ! ! foreach( (array) current($wp_filter[$tag]) as $the_ ) ! ! ! if ( !is_null($the_['function']) ){ ! ! ! ! $args[1] = $value; ! ! ! ! $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args'])); ! ! ! } ! } while ( next($wp_filter[$tag]) !== false ); ! array_pop( $wp_current_filter ); ! return $value; } apply_filters()
  7. ! // Do 'all' actions first ! if ( isset($wp_filter['all'])

    ) { ! ! $wp_current_filter[] = $tag; ! ! $args = func_get_args(); ! ! _wp_call_all_hook($args); ! } ! if ( !isset($wp_filter[$tag]) ) { ! ! if ( isset($wp_filter['all']) ) ! ! ! array_pop($wp_current_filter); ! ! return $value; ! }
  8. ! if ( !isset($wp_filter['all']) ) ! ! $wp_current_filter[] = $tag;

    ! // Sort ! if ( !isset( $merged_filters[ $tag ] ) ) { ! ! ksort($wp_filter[$tag]); ! ! $merged_filters[ $tag ] = true; ! } ! reset( $wp_filter[ $tag ] ); ! if ( empty($args) ) ! ! $args = func_get_args(); stores all arguments passed to apply_filters sorts by priority
  9. ! do { ! ! foreach( (array) current($wp_filter[$tag]) as $the_

    ) ! ! ! if ( !is_null($the_['function']) ){ ! ! ! ! $args[1] = $value; ! ! ! ! $value = call_user_func_array( ! ! ! ! ! $the_['function'], ! ! ! ! ! array_slice( ! ! ! ! ! ! $args, 1, (int) $the_['accepted_args'] ! ! ! ! ! ) ! ! ! ! ); ! ! ! } ! } while ( next($wp_filter[$tag]) !== false ); ! array_pop( $wp_current_filter ); ! return $value; }
  10. ! do { ! ! foreach( (array) current($wp_filter[$tag]) as $the_

    ) Looping through $wp_filter['the_content'][10] $wp_filter['the_content'][10]['show_author_bio'] $wp_filter['the_content'][10]['wp_texturize'] $wp_filter['the_content'][10]['convert_smilies'] $wp_filter['the_content'][10]['convert_chars'] $wp_filter['the_content'][10]['wpautop'] $wp_filter['the_content'][10]['shortcode_unautop'] $wp_filter['the_content'][10]['prepend_attachment']
  11. ! do { ! ! foreach( (array) current($wp_filter[$tag]) as $the_

    ) ! ! ! if ( !is_null($the_['function']) ){ $the_ = $wp_filter['the_content'][10]['show_author_bio'] $wp_filter['the_content'][10]['show_author_bio'] = array( 'function' => 'show_author_bio', 'accepted_args' => 1 ); $the_['function']: 'show_author_bio' $the_['accepted_args']: 1
  12. ! do { ! ! foreach( (array) current($wp_filter[$tag]) as $the_

    ) ! ! ! if ( !is_null($the_['function']) ){ ! ! ! ! $args[1] = $value; $args = func_get_args(); $args = array( $tag, $value [, $param1, $param2, ...] ); apply_filters( 'the_content', $content ); $args = array( 'the_content', 'This is an example of a page.' ); apply_filters( 'the_category', $thelist, $separator, $parents ); $args = array( 'the_category', $thelist, $separator, $parents );
  13. ! do { ! ! foreach( (array) current($wp_filter[$tag]) as $the_

    ) ! ! ! if ( !is_null($the_['function']) ){ ! ! ! ! $args[1] = $value; first time through loop: original post content
  14. ! do { ! ! foreach( (array) current($wp_filter[$tag]) as $the_

    ) ! ! ! if ( !is_null($the_['function']) ){ ! ! ! ! $args[1] = $value; ! ! ! ! $value = call_user_func_array( ! ! ! ! ! $the_['function'], ! ! ! ! ! array_slice( ! ! ! ! ! ! $args, 1, (int) $the_['accepted_args'] ! ! ! ! ! ) ! ! ! ! ); ! ! ! } subsequent loops: $value is updated each time
  15. ! do { ! ! foreach( (array) current($wp_filter[$tag]) as $the_

    ) ! ! ! if ( !is_null($the_['function']) ){ ! ! ! ! $args[1] = $value; ! ! ! ! $value = call_user_func_array( ! ! ! ! ! $the_['function'], ! ! ! ! ! array_slice( ! ! ! ! ! ! $args, 1, (int) $the_['accepted_args'] ! ! ! ! ! ) ! ! ! ! ); ! ! ! } call this function with these arguments
  16. ! do { ! ! foreach( (array) current($wp_filter[$tag]) as $the_

    ) ! ! ! if ( !is_null($the_['function']) ){ ! ! ! ! $args[1] = $value; ! ! ! ! $value = call_user_func_array( ! ! ! ! ! $the_['function'], ! ! ! ! ! array_slice( ! ! ! ! ! ! $args, 1, (int) $the_['accepted_args'] ! ! ! ! ! ) ! ! ! ! ); ! ! ! } ! } while ( next($wp_filter[$tag]) !== false ); ! array_pop( $wp_current_filter ); ! return $value; }
  17. function do_action($tag, $arg = '') { ! global $wp_filter, $wp_actions,

    $merged_filters, $wp_current_filter; ! if ( ! isset($wp_actions) ) ! ! $wp_actions = array(); ! if ( ! isset($wp_actions[$tag]) ) ! ! $wp_actions[$tag] = 1; ! else ! ! ++$wp_actions[$tag]; ! // Do 'all' actions first ! if ( isset($wp_filter['all']) ) { ! ! $wp_current_filter[] = $tag; ! ! $all_args = func_get_args(); ! ! _wp_call_all_hook($all_args); ! } ! if ( !isset($wp_filter[$tag]) ) { ! ! if ( isset($wp_filter['all']) ) ! ! ! array_pop($wp_current_filter); ! ! return; ! } ! if ( !isset($wp_filter['all']) ) ! ! $wp_current_filter[] = $tag; ! $args = array(); ! if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this) ! ! $args[] =& $arg[0]; ! else ! ! $args[] = $arg; ! for ( $a = 2; $a < func_num_args(); $a++ ) ! ! $args[] = func_get_arg($a); ! // Sort ! if ( !isset( $merged_filters[ $tag ] ) ) { ! ! ksort($wp_filter[$tag]); ! ! $merged_filters[ $tag ] = true; ! } ! reset( $wp_filter[ $tag ] ); ! do { ! ! foreach ( (array) current($wp_filter[$tag]) as $the_ ) ! ! ! if ( !is_null($the_['function']) ) ! ! ! ! call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); ! } while ( next($wp_filter[$tag]) !== false ); ! array_pop($wp_current_filter); } do_action()
  18. differences in do_action() ‣ does not keep track of $value

    ‣ does not return anything ‣ stores number of times each tag is fired in $wp_actions[$tag] (global) ‣ ...that's it.
  19. if ( is_robots() ) : ! do_action('do_robots'); ! return; elseif

    ( is_feed() ) : ! do_feed(); ! return; elseif ( is_trackback() ) : ! include( ABSPATH . 'wp-trackback.php' ); ! return; endif; if ( defined('WP_USE_THEMES') && WP_USE_THEMES ) : ! $template = false; ! if ( is_404() && $template = get_404_template() ) : ! elseif ( is_search() && $template = get_search_template() ) : ! elseif ( is_tax() && $template = get_taxonomy_template() ) : ! elseif ( is_front_page() && $template = get_front_page_template() ) : ! elseif ( is_home() && $template = get_home_template() ) : ! elseif ( is_attachment() && $template = get_attachment_template() ) : ! ! remove_filter('the_content', 'prepend_attachment'); ! elseif ( is_single() && $template = get_single_template() ) : ! elseif ( is_page() && $template = get_page_template() ) : ! elseif ( is_category() && $template = get_category_template() ) : ! elseif ( is_tag() && $template = get_tag_template() ) : ! elseif ( is_author() && $template = get_author_template() ) : ! elseif ( is_date() && $template = get_date_template() ) : ! elseif ( is_archive() && $template = get_archive_template() ) : ! elseif ( is_comments_popup() && $template = get_comments_popup_template() ) : ! elseif ( is_paged() && $template = get_paged_template() ) : ! else : ! ! $template = get_index_template(); ! endif; ! if ( $template = apply_filters( 'template_include', $template ) ) ! ! include( $template ); ! return; endif;
  20. ‣ log search queries ‣ bypass template decision process and

    use custom theme structure ‣ custom URLs: load template before 404 is chosen what you can do with template_redirect
  21. ‣ init ‣ wp_enqueue_scripts ‣ wp_head & wp_footer ‣ the_content

    & the_excerpt ‣ post_class & body_class you might have heard of:
  22. you might not have heard of: ‣ posts_where ‣ style_loader_tag

    ‣ login_message ‣ post_updated ‣ wp_mail_from & wp_mail_from_name
  23. you should make hooks when: ‣ making a theme framework

    ‣ releasing a public plugin ‣ making something big or complex
  24. you should make hooks because: ‣ easier for other developers

    ‣ keeps code organized ‣ it's really, really easy
  25. <footer id="site-footer"> <p>Powered by <a href="http://wordpress.org">WordPress</a>.</p> <?php do_action( 'copyright_message' );

    ?> </footer> add_action( 'copyright_message', 'my_groovy_copyright' ); function my_groovy_copyright() { echo '<p>&copy;2013 Groovy Inc. All rights reserved.</p>'; } footer.php functions.php
  26. echo apply_filters( 'archive_excerpt', get_the_excerpt() ); add_filter( 'archive_excerpt', 'auto_link_blog_title' ); function

    auto_link_blog_title( $text ) { $search = get_bloginfo('name'); $replace = '<a href="' . home_url() . '">' . get_bloginfo('name') . '</a>'; $new_text = str_replace( $search, $replace, $text ); return $new_text; } home.php functions.php