Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Please vote on the question and any answers you find useful by clicking on the UP arrow on the left hand side of the question or answer.

As with many others who are now viewing this post, I have been reading various blogs, forums, and discussion groups to learn and improve my wordpress skills. Over the past 12 months I have been on a mission to substitute my use of plugins by adding code to my functions.php file instead. While I completely agree that plugins are very useful in many situations my experience proved that in 90% of usage cases although a plugin might exist, actually utilizing it could create unnecessary complications and compatibility issues. Additionally in a great deal of cases such plugins added menus and other admin elements which I don't want or need.

More often than not I have found that by analyzing the code of plugins I was able to strip out the piece of code I wanted and hard code it into my functions.php. This provided me with the exact functionality I needed without having to include unnecessary elements.

So, the purpose of this post is my attempt to engage you, the reader/admin/developer, to share with me and other here any code bits which you find useful and have added to your theme's function.php file to extend or enhance WordPress without utilizing a plugin.

When you submit a response here please kindly give each code bit a title, let us know if with what version of wordpress you know its compatible with, include whatever description you feel best describes its function and (if applicable) include a link to the original plugin or source where you found the information.

I am looking forward to all your responses and will of course continually add my own new finds whenever I find them.

share|improve this question

closed as not constructive by Rarst Feb 15 '12 at 12:44

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.If this question can be reworded to fit the rules in the help center, please edit the question.

10  
Considering the first 5 answers were by the OP and the question seems more geared at collecting an array of responses rather than a single, definitive answer, this should be a community wiki. –  EAMann Sep 9 '10 at 14:43
14  
All answers not related to a theme should be removed. This thread is a good example for bad coding practices. –  toscho Jun 13 '11 at 12:09
14  
I think it'd be better to encourage people to create a custom functionality plugin instead of using their theme's functions.php –  Ian Dunn Jan 16 '12 at 18:49
2  
@NetConstructor.com The pure number of page views is not an indicator for quality. We should encourage specific questions with specific answers and good coding practices. This thread is the opposite. –  toscho Feb 22 '12 at 2:44
5  
@NetConstructor.com Discuss it on Meta where people can see your arguments better. :) –  toscho Feb 24 '12 at 17:10

108 Answers 108

Change the "Howdy" message to "Welcome"

With this function you can customize the "Howdy" message in top right of your admin area.
This function make use of JQuery to change the "Howdy" message to "Welcome".

/****** Customize admin message "Howdy" to "Welcome" ******/
$nohowdy = "Welcome";

if (is_admin()) {
    add_action('init', 'artdev_nohowdy_h');
    add_action('admin_footer', 'artdev_nohowdy_f');
}
// Load jQuery
function artdev_nohowdy_h() {
    wp_enqueue_script('jquery');
}
// Modify
function artdev_nohowdy_f() {
global $nohowdy;
echo <<<JS
<script type="text/javascript">
//<![CDATA[
var nohowdy = "$nohowdy";
jQuery('#user_info p')
    .html(
    jQuery('#user_info p')
        .html()
        .replace(/Howdy/,nohowdy)
    );
//]]>
JS;
}

PHP version, using gettext filter:

add_filter('gettext', 'change_howdy', 10, 3);

function change_howdy($translated, $text, $domain) {

    if (!is_admin() || 'default' != $domain)
        return $translated;

    if (false !== strpos($translated, 'Howdy'))
        return str_replace('Howdy', 'Welcome', $translated);

    return $translated;
}
share|improve this answer
1  
Can't this already be edited on the PHP side so it doesn't get output at all? –  hakre Feb 14 '11 at 19:13

Add a codex search form to the dashboard header

This is a simple way to add a codex search form to the dashboard header, on the top-right next to the quicklinks drop-down.

/**
 * ADD WP CODEX SEARCH FORM TO DASHBOARD HEADER
 */
function wp_codex_search_form() {
    echo '<form target="_blank" method="get" action="http://wordpress.org/search/do-search.php" class="alignright" style="margin: 11px 5px 0;">
        <input type="text" onblur="this.value=(this.value==\'\') ? \'Search the Codex\' : this.value;" onfocus="this.value=(this.value==\'Search the Codex\') ? \'\' : this.value;" maxlength="150" value="Search the Codex" name="search" class="text"> <input type="submit" value="Go" class="button" />
    </form>';
}

if( current_user_can( 'manage_plugins' )) {
// The number 11 needs to be a 10 for this to work!
    add_filter( 'in_admin_header', 'wp_codex_search_form', 11 );
}
share|improve this answer
1  
@NetConstructor.com I edited it to show if current_user_can manage plugins, then add the filter. It's that simple. –  jaredwilli Feb 23 '11 at 0:56

New Media Library Column to Re-Attach Images

This code adds a new column to the Media Library Page allowing you to re-attach images

add_filter("manage_upload_columns", 'upload_columns');
add_action("manage_media_custom_column", 'media_custom_columns', 0, 2);

function upload_columns($columns) {
    unset($columns['parent']);
    $columns['better_parent'] = "Parent";
    return $columns;
}
function media_custom_columns($column_name, $id) {
    $post = get_post($id);
    if($column_name != 'better_parent')
        return;
        if ( $post->post_parent > 0 ) {
            if ( get_post($post->post_parent) ) {
                $title =_draft_or_post_title($post->post_parent);
            }
            ?>
            <strong><a href="<?php echo get_edit_post_link( $post->post_parent ); ?>"><?php echo $title ?></a></strong>, <?php echo get_the_time(__('Y/m/d')); ?>
            <br />
            <a class="hide-if-no-js" onclick="findPosts.open('media[]','<?php echo $post->ID ?>');return false;" href="#the-list"><?php _e('Re-Attach'); ?></a>
            <?php
        } else {
            ?>
            <?php _e('(Unattached)'); ?><br />
            <a class="hide-if-no-js" onclick="findPosts.open('media[]','<?php echo $post->ID ?>');return false;" href="#the-list"><?php _e('Attach'); ?></a>
            <?php
        }
}
share|improve this answer

Only show posts and media of the logged-in Author & fix the post/media counts on the filter bars.

Tested on: Wordpress 3.4.1

By default, WordPress allows Authors to see the titles of other users posts, unpublished drafts, and all media, even though they cannot be edited.

Use this code to only allow posts and media of the currently logged in Author to be displayed.

Unlike other solutions, this also fixes the post/media count on the filter bars (All|Published|Draft|Pending|Trash; All|Images|Videos|Unattached).

// Show only posts and media related to logged in author
add_action('pre_get_posts', 'query_set_only_author' );
function query_set_only_author( $wp_query ) {
    global $current_user;
    if( is_admin() && !current_user_can('edit_others_posts') ) {
        $wp_query->set( 'author', $current_user->ID );
        add_filter('views_edit-post', 'fix_post_counts');
        add_filter('views_upload', 'fix_media_counts');
    }
}

// Fix post counts
function fix_post_counts($views) {
    global $current_user, $wp_query;
    unset($views['mine']);
    $types = array(
        array( 'status' =>  NULL ),
        array( 'status' => 'publish' ),
        array( 'status' => 'draft' ),
        array( 'status' => 'pending' ),
        array( 'status' => 'trash' )
    );
    foreach( $types as $type ) {
        $query = array(
            'author'      => $current_user->ID,
            'post_type'   => 'post',
            'post_status' => $type['status']
        );
        $result = new WP_Query($query);
        if( $type['status'] == NULL ):
            $class = ($wp_query->query_vars['post_status'] == NULL) ? ' class="current"' : '';
            $views['all'] = sprintf(__('<a href="%s"'. $class .'>All <span class="count">(%d)</span></a>', 'all'),
                admin_url('edit.php?post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'publish' ):
            $class = ($wp_query->query_vars['post_status'] == 'publish') ? ' class="current"' : '';
            $views['publish'] = sprintf(__('<a href="%s"'. $class .'>Published <span class="count">(%d)</span></a>', 'publish'),
                admin_url('edit.php?post_status=publish&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'draft' ):
            $class = ($wp_query->query_vars['post_status'] == 'draft') ? ' class="current"' : '';
            $views['draft'] = sprintf(__('<a href="%s"'. $class .'>Draft'. ((sizeof($result->posts) > 1) ? "s" : "") .' <span class="count">(%d)</span></a>', 'draft'),
                admin_url('edit.php?post_status=draft&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'pending' ):
            $class = ($wp_query->query_vars['post_status'] == 'pending') ? ' class="current"' : '';
            $views['pending'] = sprintf(__('<a href="%s"'. $class .'>Pending <span class="count">(%d)</span></a>', 'pending'),
                admin_url('edit.php?post_status=pending&post_type=post'),
                $result->found_posts);
        elseif( $type['status'] == 'trash' ):
            $class = ($wp_query->query_vars['post_status'] == 'trash') ? ' class="current"' : '';
            $views['trash'] = sprintf(__('<a href="%s"'. $class .'>Trash <span class="count">(%d)</span></a>', 'trash'),
                admin_url('edit.php?post_status=trash&post_type=post'),
                $result->found_posts);
        endif;
    }
    return $views;
}

// Fix media counts
function fix_media_counts($views) {
    global $wpdb, $current_user, $post_mime_types, $avail_post_mime_types;
    $views = array();
    $_num_posts = array();
    $count = $wpdb->get_results( "
        SELECT post_mime_type, COUNT( * ) AS num_posts 
        FROM $wpdb->posts 
        WHERE post_type = 'attachment' 
        AND post_author = $current_user->ID 
        AND post_status != 'trash' 
        GROUP BY post_mime_type
    ", ARRAY_A );
    foreach( $count as $row )
        $_num_posts[$row['post_mime_type']] = $row['num_posts'];
    $_total_posts = array_sum($_num_posts);
    $detached = isset( $_REQUEST['detached'] ) || isset( $_REQUEST['find_detached'] );
    if ( !isset( $total_orphans ) )
        $total_orphans = $wpdb->get_var("
            SELECT COUNT( * ) 
            FROM $wpdb->posts 
            WHERE post_type = 'attachment' 
            AND post_author = $current_user->ID 
            AND post_status != 'trash' 
            AND post_parent < 1
        ");
    $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts));
    foreach ( $matches as $type => $reals )
        foreach ( $reals as $real )
            $num_posts[$type] = ( isset( $num_posts[$type] ) ) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real];
    $class = ( empty($_GET['post_mime_type']) && !$detached && !isset($_GET['status']) ) ? ' class="current"' : '';
    $views['all'] = "<a href='upload.php'$class>" . sprintf( __('All <span class="count">(%s)</span>', 'uploaded files' ), number_format_i18n( $_total_posts )) . '</a>';
    foreach ( $post_mime_types as $mime_type => $label ) {
        $class = '';
        if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) )
            continue;
        if ( !empty($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) )
            $class = ' class="current"';
        if ( !empty( $num_posts[$mime_type] ) )
            $views[$mime_type] = "<a href='upload.php?post_mime_type=$mime_type'$class>" . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), $num_posts[$mime_type] ) . '</a>';
    }
    $views['detached'] = '<a href="upload.php?detached=1"' . ( $detached ? ' class="current"' : '' ) . '>' . sprintf( __( 'Unattached <span class="count">(%s)</span>', 'detached files' ), $total_orphans ) . '</a>';
    return $views;
}
share|improve this answer

Themed custom loop using shortcodes

Arguments are the same as the ones from query_posts. The content wrapped between the query tag is the template.

add_shortcode('query', 'shortcode_query');

function shortcode_query($atts, $content){
  extract(shortcode_atts(array( // a few default values
   'posts_per_page' => '10',
   'caller_get_posts' => 1,
   'post__not_in' => get_option('sticky_posts'),
  ), $atts));

  global $post;

  $posts = new WP_Query($atts);
  $output = '';
  if ($posts->have_posts())
    while ($posts->have_posts()):
      $posts->the_post();

      // these arguments will be available from inside $content
      $parameters = array(
        'PERMALINK' => get_permalink(),
        'TITLE' => get_the_title(),
        'CONTENT' => get_the_content(),
        'COMMENT_COUNT' => $post->comment_count,
        'CATEGORIES' => get_the_category_list(', '),
        // add here more...
      );

      $finds = $replaces = array();
      foreach($parameters as $find => $replace):
        $finds[] = '{'.$find.'}';
        $replaces[] = $replace;
      endforeach;
      $output .= str_replace($finds, $replaces, $content);

    endwhile;
  else
    return; // no posts found

  wp_reset_query();
  return html_entity_decode($output);
}

Usage:

[query post_type=page posts_per_page=5]
Listing some pages:    
<h5>{TITLE}</h5>
<div>{CONTENT}</div>
<p><a href="{PERMALINK}">{COMMENT_COUNT} comments</a></p>
[/query]

(will make a query for 5 pages)


Inserting pre-configured widgets anywhere using shortcodes

(some ideas from http://webdesign.anmari.com/shortcode-any-widget)

add_action('widgets_init', 'create_arbitrary_sidebar');
function create_arbitrary_sidebar(){
  register_sidebar(array(
    'name' => __('Arbitrary Widgets'),
    'id' => 'arbitrary',
    'description' => sprintf(__('Widgets from this area can added into posts/pages using the %1$s or %2$s shortcodes.'), '[widget ID]', '[widget Name]'),
    'before_widget' => '<div class="block"><div class="block-content block-%2$s clear-block" id="instance-%1$s">',
    'after_widget' => '</div></div>',
    'before_title' => '<h3 class="title">',
    'after_title' => '</h3>'
   ));
}

add_action('in_widget_form', 'widget_shortcodes_info', 10, 3);
function widget_shortcodes_info($widget, $return, $instance){
  if(!is_numeric($widget->number)) return; // wp-save bug :( widget needs to be saved first...

  global $wp_registered_widgets;

  // get the active widgets from all sidebars
  $sidebars_widgets = wp_get_sidebars_widgets();

  // prepare matches
  $matches = array();
  foreach($wp_registered_widgets as $i => $w)
    if($w['name'] == $widget->name) $matches[] = $w['id'];

  // find out the widget position (number)
  $number = 0;
  $is_arbitrary = false;
  if(!empty($sidebars_widgets['arbitrary']))
    foreach($sidebars_widgets['arbitrary'] as $i => $value):
      if(in_array($value, $matches) && !$is_arbitrary) $number = $number +1;
      if($value == $widget->id) $is_arbitrary = true;
    endforeach;

  echo '<div style="background:#eee; padding: 5px;">To include this widget into your posts or pages use one of the following shortcodes: <br />';
  echo '<code>[widget '.substr(md5($widget->id), 0, 8).']</code> <br /> <code>[widget "'.$widget->name.'"'.(($number > 1) ? ' number='.$number : null).']</code></div>';
}

add_shortcode('widget', 'shortcode_widget');
function shortcode_widget($atts){
  global $wp_registered_widgets, $wp_registered_sidebars;
  extract(shortcode_atts(array(
    'number' => false,        // only taken in consideration if the 1st argument is the "Widget Name" (not the hashed ID)
    'title' => true,          // show titles?
    'area' => 'arbitrary'     // sidebar to search
  ), $atts));

  // get 1st parameter (assuming this is the target widget id or name)
  if (!empty($atts[0])) $widget = esc_attr($atts[0]); else return;

  $sidebar = esc_attr($area);
  $number = intval($number);

  $callback = false;
  $possible_matches = array();
  $sidebars_widgets = wp_get_sidebars_widgets();
  if((empty($sidebars_widgets[$sidebar]) || empty($wp_registered_widgets)) && (current_user_can('edit_themes')))
    return "no valid active widgets in {$sidebar}";

  // assuming we get the md5 hashed ID
  foreach ($wp_registered_widgets as $i => $w)
    if ($widget == substr(md5($w['id']), 0, 8)):
      $callback = ($w['callback']);
      $widget = $w['id']; // real widget ID

    // compare widget names as well, and build a array with the possible widget matches array
    // (which is used later if ID match fails)
    elseif($widget == $w['name']):
      $possible_matches[] = $w['id'];

    endif;

  // nothing found, assume it's the "Widget Name".
  if(!$callback):
    $valid_matches = array();
    foreach($sidebars_widgets[$sidebar] as $i => $w)
      foreach($possible_matches as $id) if($id == $w) $valid_matches[] = $w;

    if(!empty($valid_matches)) $widget = $number ? $valid_matches[$number-1] : $widget = $valid_matches[0];
    if($widget && isset($wp_registered_widgets[$widget]['callback'])) $callback = $wp_registered_widgets[$widget]['callback'];
  endif;

  // yey. we found it
  if($callback):
    ob_start();

    $params = array_merge(array(array_merge($wp_registered_sidebars[$sidebar], array('widget_id' => $widget, 'widget_name' => $wp_registered_widgets[$widget]['name']))), (array)$wp_registered_widgets[$widget]['params']);

    $classname_ = '';
    foreach ((array)$wp_registered_widgets[$widget]['classname'] as $cn)
      if (is_string($cn)) $classname_ .= '_'.$cn; elseif (is_object($cn)) $classname_ .= '_'.get_class($cn);
    $classname_ = ltrim($classname_, '_');
    $params[0]['before_widget'] = sprintf($params[0]['before_widget'], $widget, $classname_);
    $params = apply_filters('dynamic_sidebar_params', $params);

    if (is_callable($callback)) call_user_func_array($callback, $params);
    $output = ob_get_clean();

    // remove h3 if title = false
    if(!$title) $output = preg_replace('#<h3 class="title">(.*?)</h3>#', '', $output);
    return $output;
  else:
   return "widget instance not found: ".esc_attr($atts[0]);
  endif;
}

Usage:

Drop a widget in the "arbitrary widgets" sidebar, save it and you'll get the shortcodes :)


Get a custom field value through shortcodes

add_shortcode('field', 'shortcode_field');

function shortcode_field($atts){
  extract(shortcode_atts(array(
   'post_id' => NULL,
  ), $atts));

  if(!isset($atts[0])) return;
  $field = esc_attr($atts[0]);

  global $post;
  $post_id = (NULL === $post_id) ? $post->ID : $post_id;

  return get_post_meta($post_id, $field, true);
}

Usage:

  • [field "my_key"]
  • [field "my_key" post_id=1]

Get the TinyURL of a link through shortcodes

add_shortcode('tinyurl', 'shortcode_tinyurl'); 

function shortcode_tinyurl($atts){
  extract(shortcode_atts(array(
   'url' => get_permalink(),
   'title' => '',
   'rel' => 'nofollow'
  ), $atts));
  if(!$title) $title = $url;

  if (FALSE === ($cache = get_transient('tinyurl_'+md5($url)))):
    $cache = wp_remote_retrieve_body(wp_remote_get('http://tinyurl.com/api-create.php?url='.$url));

    set_transient('tinyurl_'+md5($url), $cache, 60*60*24); // 1 day cache, could be incresed
  endif;

  return '<a href="'.esc_url($cache).'" rel="'.esc_attr($rel).'">'.esc_attr($title).'</a>';
}

Usage:

  • [tinyurl]
  • [tinyurl url="http://google.com" title="google"]
share|improve this answer

Fixed: Remove Default Wordpress Meta Boxes

This was very handy but had some errors

// REMOVE META BOXES FROM DEFAULT POSTS SCREEN
function remove_default_post_screen_metaboxes() {
 remove_meta_box( 'postcustom','post','normal' ); // Custom Fields Metabox
 remove_meta_box( 'postexcerpt','post','normal' ); // Excerpt Metabox
 remove_meta_box( 'commentstatusdiv','post','normal' ); // Comments Metabox
 remove_meta_box( 'trackbacksdiv','post','normal' ); // Talkback Metabox
 remove_meta_box( 'slugdiv','post','normal' ); // Slug Metabox
 remove_meta_box( 'authordiv','post','normal' ); // Author Metabox
}
add_action('admin_menu','remove_default_post_screen_metaboxes');


// REMOVE META BOXES FROM DEFAULT PAGES SCREEN
function remove_default_page_screen_metaboxes() {
 global $post_type;
 remove_meta_box( 'postcustom','page','normal' ); // Custom Fields Metabox
 remove_meta_box( 'postexcerpt','page','normal' ); // Excerpt Metabox
 remove_meta_box( 'commentstatusdiv','page','normal' ); // Comments Metabox
 remove_meta_box('commentsdiv','page','normal'); // Comments
 remove_meta_box( 'trackbacksdiv','page','normal' ); // Talkback Metabox
 remove_meta_box( 'slugdiv','page','normal' ); // Slug Metabox
 remove_meta_box( 'authordiv','page','normal' ); // Author Metabox
}
add_action('admin_menu','remove_default_page_screen_metaboxes');
share|improve this answer

Quickly Determine Server & Environment Details

If you have multiple servers and multiple environments such as development, QA, and production environments, this can be very useful.

For my systems, environment is determined by the first 3 letters of the hostname, but this could easily be changed to whatever suits your needs.

add_action( 'admin_notices', 'report_environment_status', 3 );

// Report on which server and environment details
function report_environment_status() {
    $server = php_uname('n');
    switch (strtolower(substr($server,0,3))) {
        case 'pXX':
            $msg = "PRODUCTION";
            break;
        case 'qXX':
            $msg = "QA";
            break;
        case 'dXX':
            $msg = "DEVELOPMENT";
            break;
        default :
            $msg = 'UNKNOWN';
    }
    echo "<div id='update-nag'>";
    echo "<b>You are in the $msg environment. (Server: $server)</b>";
    echo "</div>";
}

This has saved me many times from making updates to the wrong environment.

You can also turn this into a plugin and network activate it so all sites get the notification.

share|improve this answer

Return the number of comments

This is like count_user_posts(), but returns the number of comments instead:

function count_user_comments($id) {
global $wpdb;
$users = $wpdb->get_var("
        SELECT COUNT( * ) AS total
        FROM $wpdb->comments
        WHERE comment_approved = 1 
        AND user_id = $id");
return $users;
}

More: Count User's posts (including custom post types) or comments:

function atom_count($user_id, $what_to_count = 'post') {
  global $wpdb;    
  $where = $what_to_count == 'comment' ? "WHERE comment_approved = 1 AND user_id = {$user_id}" : get_posts_by_author_sql($what_to_count, TRUE, $user_id);
  $from = "FROM ".(($what_to_count == 'comment') ? $wpdb->comments : $wpdb->posts);    
  $count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) {$from} {$where}"));
  return $count;
}

Usage examples:

<?php echo atom_count(1, 'movie'); // displays 'movie' post type count ?>

<?php echo atom_count(1, 'comment'); // displays comment count ?>

share|improve this answer

Set Editor Defaults to WYSIWYG or HTML

function my_default_editor() {
    $r = 'tinymce'; // html or tinymce
    return $r;
}
add_filter( 'wp_default_editor', 'my_default_editor' );

Here is how to remove the HTML Editor

jQuery(document).ready(function($) {
$("#edButtonHTML").remove();
});

UPDATED here is another way to set the default editor to HTML

add_filter('wp_default_editor', create_function('', 'return "html";'));
share|improve this answer

Remove Author Metabox/Options & Move to Publish MetaBox

Tested on: Wordpress 3.0.1

One of the things that drive me crazy is a cluttered Wordpress Admin area. One of the elements which I now always setup from the start in my functions.php file is removing the Author MetaBox and Screen Options and then adding the option into the publish metabox. In my opinion this just makes sense and keep things clean. This also respects applicable permissions.

To achieve this goal, just copy and past the following code into your functions.php file.

If you feel there is a better way of doing this please suggest.

NOTE: UPDATED THE CODE TO FIX A CODING ISSUE

// MOVE THE AUTHOR METABOX INTO THE PUBLISH METABOX
add_action( 'admin_menu', 'remove_author_metabox' );
add_action( 'post_submitbox_misc_actions', 'move_author_to_publish_metabox' );
function remove_author_metabox() {
    remove_meta_box( 'authordiv', 'post', 'normal' );
}
function move_author_to_publish_metabox() {
    global $post_ID;
    $post = get_post( $post_ID );
    echo '<div id="author" class="misc-pub-section" style="border-top-style:solid; border-top-width:1px; border-top-color:#EEEEEE; border-bottom-width:0px;">Author: ';
    post_author_meta_box( $post );
    echo '</div>';
}
share|improve this answer
1  
@NetConstructor: I just gave it a test yesterday (3.0.4) and yes, the author box is gone, but not moved to the publish box. When looking at the code i can't see any way, because the function is no where triggered... you just added the remove_author_box() fn to admin_menu action hook, but not the move_author_to_publish_box() fn. –  kaiser Feb 1 '11 at 18:55
1  
@kaiser -- your right, after reviewing this I did noticed the issue. I updated the code in my answer so just delete everything you included from this before hand and just past in the full code above. Let me know if this fixes things. Vote up the question and answer if it fixes the problem - CH :) –  NetConstructor.com Feb 1 '11 at 22:29

Remove Private and Protected Prefix

This function removes the "Privite:" prefix from posts and pages marked private. Useful for content only visible to logged in users or groups.

function the_title_trim($title) {
$title = attribute_escape($title);
$findthese = array(
    '#Protected:#',
    '#Private:#'
);
$replacewith = array(
    '', // What to replace "Protected:" with
    '' // What to replace "Private:" with
);
$title = preg_replace($findthese, $replacewith, $title);
return $title;
}
add_filter('the_title', 'the_title_trim');

EDIT: Updated to include the removal of Protected: as well.

share|improve this answer

Enable oEmbed in Text/HTML Widgets

add_filter( 'widget_text', array( $wp_embed, 'run_shortcode' ), 8 );
add_filter( 'widget_text', array( $wp_embed, 'autoembed'), 8 );

I use this for youtube video widgets and flickr stuff.

share|improve this answer

Remove Auto Linking of URLs in WordPress Comments

remove_filter('comment_text', 'make_clickable', 9);
share|improve this answer

Remove XML-RPC when not in use for performance boost

Tested on: Wordpress 3.0.1

WordPress uses a CURL operation to test for SSL capability for XML-RPC. If you're using XML-RPC but not using, then you can remove the filter. This is a small performance boost (since basically WP does a cURL GET on the https url and either 1) gets a denied message, or 2) times out, and it can take upwards of 5 seconds), but in our case it actually prevented a gateway timeout where a proxy was timing out before the cURL GET was timing out rendering XML-RPC unusable.

// Prevents WordPress from testing ssl capability on domain.com/xmlrpc.php?rsd
remove_filter('atom_service_url','atom_service_url_filter');
share|improve this answer

Extending Auto Logout Period

Tested on: Wordpress 3.0.1

Using the code below you can increase the time cookies are kept and therefor users who are logged in remain logged in longer:

function keep_me_logged_in_for_1_year( $expirein ) {
   return 31556926; // 1 year in seconds
}
add_filter( 'auth_cookie_expiration', 'keep_me_logged_in_for_1_year' );
share|improve this answer
3  
It should be noted that the session timeout is there as a security precaution, so extending/removing it makes your site more vulnerable. –  Ian Dunn Jan 16 '12 at 18:58

Grab all custom fields globally

function get_custom_field($key, $echo = FALSE) {
    global $post;
    $custom_field = get_post_meta( $post->ID, $key, true );
    if ( $echo == false ) 
        return $custom_field;
    echo $custom_field;
}

Then call the field with a single line

<?php get_custom_field('custom-field-name', TRUE); ?>
share|improve this answer
1  
for sites / themes that use a lot of custom fields (which I use often for client work) it allows for less code in the theme, and also for adding conditionals on whether or not to display the field at all. –  Norcross Dec 10 '10 at 22:44

Add parent page slug to body_class

/***************************************************************
* Function body_class_section
* Add the top level page to the body class for coloured sections
***************************************************************/

add_filter('body_class','body_class_section');

function body_class_section($classes) {
    global $wpdb, $post;
    if (is_page()) {
        if ($post->post_parent) {
            $parent  = end(get_post_ancestors($current_page_id));
        } else {
            $parent = $post->ID;
        }
        $post_data = get_post($parent, ARRAY_A);
        $classes[] = 'section-' . $post_data['post_name'];
    }
    return $classes;
}

This filter adds a unique body class based on the highest level parent of the current page. I use this for sites that have specific colours or layouts for each section of the site. It works best with sites based around pages. CSS examples:

.section-about { background: red; }
.section-portfolio { background: blue; }

Your theme must also make use of the body_class function.

Fix oEmbed flash objects

/***************************************************************
* Function my_oembed_wmode
* Fix oEmbed window mode for flash objects
***************************************************************/

add_filter('embed_oembed_html', 'my_oembed_wmode', 1);

function my_oembed_wmode( $embed ) {
    if ( strpos( $embed, '<param' ) !== false ) {
        $embed = str_replace( '<embed', '<embed wmode="transparent" ', $embed );
        $embed = preg_replace( '/param>/', 'param><param name="wmode" value="transparent" />', $embed, 1);
    }
    return $embed;
}

I have had problems in the past where oEmbed Flash objects collide with drop down navigation menus. This filter fixes that problem by adding a transparent window mode to the embeds.

Remove the "comments" column from Admin page list

/***************************************************************
* Function custom_pages_columns
* Remove "comments" from pages overview (rarely use comments on pages)
***************************************************************/

add_filter('manage_pages_columns', 'custom_pages_columns');

function custom_pages_columns($defaults) {
    unset($defaults['comments']);
    return $defaults;
}

I hardly ever make use of commenting on pages and this helps keep things tidy in the WordPress dashboard.

share|improve this answer

Add a "Settings" link for plugins on the plugin list page

Set "Settings" link for plugins on plugin-page in WordPress backend, easy to use jump to settings for users (the code is also with an solution for WordPress version smaller 2.9)

// plugin definitions
define( 'FB_BASENAME', plugin_basename( __FILE__ ) );
define( 'FB_BASEFOLDER', plugin_basename( dirname( __FILE__ ) ) );
define( 'FB_FILENAME', str_replace( FB_BASEFOLDER.'/', '', plugin_basename(__FILE__) ) );
function filter_plugin_meta($links, $file) {
  /* create link */
  if ( $file == FB_BASENAME ) {
    array_unshift(
      $links,
      sprintf( '<a href="options-general.php?page=%s">%s</a>', FB_FILENAME, __('Settings') )
    );
  }
  return $links;
}

global $wp_version;
if ( version_compare( $wp_version, '2.7alpha', '>' ) ) {
    add_filter( 'plugin_action_links_' . FB_WM_BASENAME, 'filter_plugin_meta', 10, 2);
} else {
    add_filter( 'plugin_action_links', 'filter_plugin_meta', 10, 2 );
}
share|improve this answer

Add page template filter to page listing

Tested on: WP 3.1

Adds a page template filter to the page listing, so you can view a list of pages that have a given template attached.

class Page_Template_Filter {
    private $templates = array();
    public function __construct() {
        // If it's not the admin area or the current user can't edit pages let's just bail here
        if( !is_admin() || !current_user_can('edit_pages') )
            return;
        add_action( 'parse_query',           array( $this, 'pt_parse_query' ) );
        add_action( 'restrict_manage_posts', array( $this, 'pt_restrict_manage_posts' ) );
    }
    public function pt_parse_query( $query ) {
        global $pagenow, $post_type;
        if( 'edit.php' != $pagenow )
            return;

        switch( $post_type ) {
            case 'post':

            break;
            case 'page':
                $this->templates = get_page_templates();

                if( empty( $this->templates ) )
                    return;

                if( !$this->is_set_template() )
                    return;

                $meta_group = array( 'key' => '_wp_page_template', 'value' => $this->get_template() );
                set_query_var( 'meta_query', array( $meta_group ) );
            break;
        }
    }
    public function pt_restrict_manage_posts() {
        if( empty( $this->templates ) )
            return;
        $this->template_dropdown();
    }
    private function get_template() {
        if( $this->is_set_template() )
            foreach( $this->templates as $template ) {
                if( $template != $_GET['page_template'] )
                    continue;
                return $template;
            }
        return '';
    }
    private function is_set_template() {
        return (bool) ( isset( $_GET['page_template'] ) && ( in_array( $_GET['page_template'], $this->templates ) ) );
    }
    private function template_dropdown() {
        ?>
        <select name="page_template" id="page_template">
            <option value=""> - no template - </option>
            <?php foreach( $this->templates as $name => $file ): ?>
            <option value="<?php echo $file; ?>"<?php selected( $this->get_template() == $file ); ?>><?php _e( $name ); ?></option>
            <?php endforeach;?>
        </select>
        <?php 
    }
}

add_action('admin_init', 'load_ptf');
function load_ptf() {
    $Page_Template_Filter = new Page_Template_Filter;
}

Requires at least 3.1 to work, though the meta_query could be replaced with the older meta_key and meta_value for 3.0.

share|improve this answer

Collection of quick function.php edits

I have a few awesome tweaks in functions.php as well. Found most of these by searching for them over the years.

Excerpt Ending

function new_excerpt_more($more) {
    return '...';
}
add_filter('excerpt_more', 'new_excerpt_more');

Replace WP Admin Logo

function new_admin_logo() {
  echo '<style type="text/css">#header-logo { background-image: url('.get_bloginfo('template_directory').'/images/admin_logo.png) !important; }</style>';
}
add_action('admin_head', 'new_admin_logo');

Custom Favicon WP-Admin

function admin_favicon() {
 echo '<link rel="shortcut icon" type="image/x-icon" href="' . get_bloginfo('template_directory') . '/images/favicon.ico" />';
}
add_action( 'admin_head', 'admin_favicon' );

Custom Admin Footer

function custom_admin_footer() {
echo 'Welcome to my blog! No More Documentation Links!';
}
add_filter('admin_footer_text', 'custom_admin_footer');
share|improve this answer

Display Posts from Different Custom Post Types on homepage

By dropping the following code on the bottom of this post into your functions.php file you can get wordpress to automatically display posts from different custom post types you have created. Currently by default wordpress only display posts which belong to the default "posts" post type.

In the example provided below you will need to change the section which calls:

$query->set( 'post_type', array('post', 'page', 'services', 'attachment'));

With your own custom post types which you would like to include in the homepage post list results. In this case we are asking wordpress to return to us all posts belonging to the default "post" and "page" post_type then asking wordpress to also include the custom post type we created for "services" and finally the default wordpress post type of "attachment" which just means that anytime something is added to the media library it will automatically get displayed on the homepage as a separate entry.

// CUSTOM HOMEPAGE POST LIST INCLUDING DIFFERENT POST_TYPES
// make sure to edit the post types you wanted included in the list below
add_filter( 'pre_get_posts', 'my_homepage_post_list' );
function my_homepage_post_list ( $query ) {
    if ( is_home() && false == $query->query_vars['suppress_filters'] )
        $query->set( 'post_type', array('post', 'page', 'services', 'attachment'));
    return $query;
}

You can also utilize this custom query in different locations, such as in a custom feed through something like this

if (( is_home() && false == $query->query_vars['suppress_filters'] ) || is_feed())
share|improve this answer

Custom Dashboard CSS

/* Change WordPress dashboard CSS */
function custom_admin_styles() {
    echo '<style type="text/css">#wphead{background:#069}</style>';
}
add_action('admin_head', 'custom_admin_styles');

You can add any changes to the css between the tags.

share|improve this answer

Check if a post has embedded content.

Check if a post has embedded content, works inside the loop using the current post's ID, or alternatively can be passed an ID to determine the post to check for embedded content.

function has_embed( $post_id = false ) {
    if( !$post_id ) $post_id = get_the_ID();
    else $post_id = absint( $post_id );
    if( !$post_id ) return false;

    $post_meta = get_post_custom_keys( $post_id );
    $post_meta = array_map( 'trim' , $post_meta );

    foreach( $post_meta as $meta ) {
        if( '_oembed' != substr( $meta , 0 , 7 ) )
            continue;
        return true;
    }
    return false;
}

You'd use the function in the same way you check if a post has a tag..

if( has_embed() ) {
   // do whatever
}

Function returns true if an embed is found, false on fail.

share|improve this answer

Pre-populating post types

Here is one for this collection.

////////////////////////////////////////////////////////////////////////////////////
// This auto populates post types and posts.
///////////////////////////////////////////////////////////////////////////////////

add_filter( 'default_content', 'my_editor_content' );

function my_editor_content( $content ) {

    global $post_type;

    switch( $post_type ) {
        case 'your_post_type_here': //auto populate
            $content = 'The content you want to pre-populate the post type with.';
break;
     }

    return $content;
}

This can come in handy for when you need to post the same info over and over again with slight differences.

share|improve this answer

Make your Shortlinks Shorter by Removing WWW

Tested on: Wordpress 3.0.1

Make your shortlinks shorter if you include www. in your domain. Via scratch99.com:

add_filter('get_shortlink','sjc_alter_shortlink');
function sjc_alter_shortlink($shortlink) {
    $shortlink = preg_replace('/^(https?:\/\/)?(www\.)/','$1',$shortlink);
    return $shortlink;
}
share|improve this answer
1  
A check should be added to make sure the string "www." is only removed if it is found at the very beginning of the domain part of the original URL. Naively replacing it anywhere in the URL will lead to bugs if it had been used on a domain like owww.com (which actually appears to be running WordPress) :) –  Ingve May 28 '12 at 21:30

Remove default fields contact info user profile and replace them with something more usable

The second part of this function has already been mentioned above, but removing the default fields - AIM, Yahoo IM and Jabber/Google Talk - not yet:

function update_contact_methods( $contactmethods ) {

// Remove annoying and unwanted default fields  
unset($contactmethods['aim']);  
unset($contactmethods['jabber']);  
unset($contactmethods['yim']);  

// Add new fields  
$contactmethods['phone'] = 'Phone';  
$contactmethods['mobile'] = 'Mobile';  
$contactmethods['address'] = 'Address';  

return $contactmethods;
}
add_filter('user_contactmethods', 'update_contact_methods');

Of course you can add as many fields as you want (see previous examples earlier in this thread) under "Add new fields"

share|improve this answer

Conditional to check for hierarchy descendant

A conditional function to check if the current page is a descendant of the ID given to it. Useful for determining if a page is a grandchild, great-grandchild or father down the hierarchy tree.

function is_tree($pid) {      // $pid = The ID of the page we're looking for pages underneath
    global $post;         // load details about this page

    $anc = get_post_ancestors( $post->ID );
    foreach($anc as $ancestor) {
        if(is_page() && $ancestor == $pid) {
            return true;
        }
    }
    if(is_page()&&(is_page($pid))) 
               return true;   // we're at the page or at a sub page
    else 
               return false;  // we're elsewhere
};
share|improve this answer

Custom excerpt length

function excerpt($num) {
    $limit = $num+1;
    $excerpt = explode(' ', get_the_excerpt(), $limit);
    array_pop($excerpt);
    $excerpt = implode(" ",$excerpt)."... (<a href='" .get_permalink($post->ID) ." '>Read more</a>)";
    echo $excerpt;
}

Limit the length of the displayed excerpt by writing in the theme: excerpt('20');

Example: <?php excerpt('22'); ?> This will limit the excerpt to 22 characters.

The excerpt will be interupted with ... (Read More)

share|improve this answer

Add auto-update/plugin-installer on you localhost

define ('FS_METHOD', 'direct');

Put this in your wp-config.php.

share|improve this answer

Post Word Count

Tested on: Wordpress 3.0.1

(Originally extracted from the Post Word Count plug-in by Nick Momrick)

Adds a count of total published words to the bottom of the "Right Now" box on the admin dashboard. Useful if you're using your blog as an outlet for something like NaNoWriMo or if you just want to keep track of how prolific your blogging skills have become.

function post_word_count() {
    $count = 0;
    $posts = get_posts( array(
        'numberposts' => -1,
        'post_type' => array( 'post', 'page' )
    ));
    foreach( $posts as $post ) {
        $count += str_word_count( strip_tags( get_post_field( 'post_content', $post->ID )));
    }
    $num =  number_format_i18n( $count );
    // This block will add your word count to the stats portion of the Right Now box
    $text = _n( 'Word', 'Words', $num );
    echo "<tr><td class='first b'>{$num}</td><td class='t'>{$text}</td></tr>";
    // This line will add your word count to the bottom of the Right Now box.
    echo '<p>This blog contains a total of <strong>' . $num . '</strong> published words!</p>';
}

// add to Content Stats table
add_action( 'right_now_content_table_end', 'post_word_count');
// add to bottom of Activity Box
add_action('activity_box_end', 'post_word_count');

Kudos to Rarst for the query-free cleanup of the code!

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.