BenchPress is a WordPress library that helps you develop better WordPress themes. It combines a number of helper functions and patterns that will help you increase your WordPress strength!
Often times you need to add a filter or action hook in order to change some behavior or data within your WordPress theme. One option is to add the hook directly in your functions.php file. While this works for simple themes, eventually it will lead to an unmaintainable functions.php.
Instead, you can leverage BenchPress’s BenchPress\Hooks\Base_Action
and BenchPress\Hooks\Base_Filter
classes to create a single class file for a particular hook you are trying to implement.
For example, if you want to add a smiley face to the title of all your theme's posts, it's as simple as creating a class Add_Smiley_To_Post_Titles
and overriding a few methods.
use BenchPress\Hooks\Base_Filter;
class Add_Smiley_To_Post_Titles extends Base_Filter {
protected function get_filter() {
return ‘the_title’;
}
protected function get_arg_count() {
return 2;
}
protected function callback( $title, $post_id ) {
return $title . ' :)';
}
}
And if you only want to add it to the titles for the book post type, you can implement the should_run
method.
The should_run
method will always be invoked the same arguments as the hook callback.
use BenchPress\Hooks\Base_Filter;
class Add_Smiley_To_Book_Titles extends Base_Filter {
protected function get_filter() {
return ‘the_title’;
}
protected function should_run( $title, $post_id ) {
// only run this hook if the post type is book
return get_post_type( $post_id ) == ‘book’;
}
protected function get_arg_count() {
return 2;
}
protected function callback( $title, $post_id ) {
return $title . ‘ :)’;
}
}
In order to initialize this behavior, you would add the following to your functions.php file:
Add_Smiley_To_Book_Titles::init();
And if you wanted to change the number of posts returned for a Book post type archive page:
use BenchPress\Hooks\Base_Action;
class Update_Book_Archive_Query extends Base_Action {
protected function get_action() {
return 'pre_get_posts';
}
protected function should_run( $query ) {
if ( !is_admin() && $query->is_main_query() ) {
if ( is_post_type_archive( 'book' ) ) {
return true;
}
}
return false;
}
protected function callback( $query ) {
$query->set( 'posts_per_page', 30 );
}
}
If you need to remove an action or filter, you can call the inherited static remove
method:
Update_Book_Archive_Query::remove();
BenchPress provides a small abstraction for creating custom post types. Each post type can extend the \BenchPress\Post_Type\Base_Post_Type
class. When extending this class, you must override a few abstract methods:
use BenchPress\Post_Type\Base_Post_Type;
class Book extends Base_Post_Type {
protected function get_post_type() {
return 'book';
}
protected function get_singular_name() {
return 'Book';
}
protected function get_plural_name() {
return 'Books';
}
}
To initialize your post type, add the following to your functions.php file:
Book::init();
If you need to access your post type slug within other areas of your theme code, you can do the following:
if ( is_singular( Book::post_type() ) {
// do something if we are looking at single book post type template
}
If you need to provide more arguments for the post type registration, you can override get_args
:
use BenchPress\Post_Type\Base_Post_Type;
class Book extends Base_Post_Type {
protected function get_post_type() {
return 'book';
}
protected function get_singular_name() {
return 'Book';
}
protected function get_plural_name() {
return 'Books';
}
// set a custom post type slug
protected function get_args() {
return [
'rewrite' => [
'slug' => 'awesome-books'
]
]
}
}
If you need to register a taxonomy for the post type, you can override get_taxonomies
:
use BenchPress\Post_Type\Base_Post_Type;
class Book extends Base_Post_Type {
protected function get_post_type() {
return 'book';
}
protected function get_singular_name() {
return 'Book';
}
protected function get_plural_name() {
return 'Books';
}
protected function get_taxonomies() {
// If you registered your taxonomy using BenchPress's Base_Taxonomy class, you can access
// the taxonomy name by calling the static `taxonomy` method.
return [ Genre::taxonomy() ]
}
}
By extending Base_Post_Type
, all of the post type labels and updated messages will be set for you automatically based on the singular and plural name you provided.
BenchPress also provides a small abstraction for creating custom taxonomies. You can extend the \BenchPress\Taxonomy\Base_Taxonomy
class. When extending this class, you must override a few abstract methods:
use BenchPress\Taxonomy\Base_Taxonomy;
class Genre extends Base_Taxonomy {
protected function get_taxonomy() {
return 'genre';
}
protected function get_post_types() {
// If you registered your post type using BenchPress's Base_Post_Type class, you can
// access the post type slug by calling the static `post_type` method.
return Book::post_type();
}
protected function get_singular_name() {
return 'Genre';
}
protected function get_plural_name() {
return 'Genres';
}
}
To initialize your taxonomy, add the following to your functions.php file:
Genre::init();
If you need to access your taxonomy name within other areas of your theme code, you can do the following:
Genre::taxonomy();
If you need to provide more arguments for the taxonomy registration, you can override get_args
:
use BenchPress\Taxonomy\Base_Taxonomy;
class Genre extends Base_Taxonomy {
protected function get_taxonomy() {
return 'genre';
}
protected function get_post_types() {
// If you registered your post type using BenchPress's Base_Post_Type class, you can
// access the post type slug by calling the static `post_type` method.
return Book::post_type();
}
protected function get_singular_name() {
return 'Genre';
}
protected function get_plural_name() {
return 'Genres';
}
protected function get_args() {
// Don't show the taxonomy in the menu.
return [
'show_in_menu' => false
]
}
}
By extending Base_Taxonomy
, all of the taxonomy labels and updated messages will be set for you automatically based on the singular and plural name you provided.
BenchPress provides a convenient way to create shortcodes by extending the \BenchPress\Shortcode\Shortcode
class.
use BenchPress\Shortcode\Shortcode;
class Face_Emoji extends Shortcode {
protected function get_name() {
return 'face_emoji';
}
// These defaults will be merged into `$atts` for you automatically.
protected function get_defaults() {
return [
'mood' => 'happy'
];
}
protected function get_content( $atts, $content, $tag ) {
if ( $atts['mood'] == 'happy' ) {
return ':)';
} else {
return ':(';
}
}
}
To initialize your shortcode, add the following to your functions.php file:
Face_Emoji::init();
Sometimes you may wish to do a bit more with your shortcode, such as adding a button to the WYSIWYG to insert the shortcode. You can implement register_hooks
in your shortcode class in order to do so:
use BenchPress\Shortcode\Shortcode;
class Face_Emoji extends Shortcode {
protected function get_name() {
return 'face_emoji';
}
// These defaults will be merged into `$atts` for you automatically.
protected function get_defaults() {
return [
'mood' => 'happy'
];
}
protected function get_content( $atts, $content, $tag ) {
if ( $atts['mood'] == 'happy' ) {
return ':)';
} else {
return ':(';
}
}
protected function register_hooks() {
// add filters/actions to add shortcode button to WYSIWYG
}
}
BenchPress provides quite a few theme support functions to use within your theme.
To use them, you will first need to initialize BenchPress's theme support class:
use \BenchPress\Theme_Support\Theme_Support;
Theme_Support::init();
Clean Up
This theme support function will remove a bunch of the WordPress generated tags that are output within the <head>
tag of your theme. It also cleans up the output of body_class()
.
add_theme_support( Theme_Support::CLEAN_UP );
Favicon
This theme support function will add a favicon for your theme.
add_theme_support( Theme_Support::FAVICON, get_template_directory_uri() . '/favicon.png' );
string $favicon_url
- The URL of your favicon file.
Google Analytics
This theme support function will add Google Analytics tracking code to your theme.
add_theme_support( Theme_Support::GOOGLE_ANALYTICS, 'UA-1234567' );
string $ua_id
- Your Google Analytics UA identifier.
Login Logo
This theme support function will add a custom logo to the WordPress login screen.
add_theme_support( Theme_Support::LOGIN_LOGO, [
'url' => get_template_directory_uri() . '/login_logo.png',
'width' => 200,
'height' => 50
] );
string $url
- The URL of your custom login logo.int $width
- The width of your logo.int $height
- The height of your logo.
Remove Admin Menus
This theme support function removes admin menus from the WordPress admin.
add_theme_support( Theme_Support::REMOVE_ADMIN_MENUS, [
'edit-comments.php'
] );
array $menu_slugs
- An array of menu slugs to remove from the admin menu.
BenchPress provides two functions for rendering partials within your theme. Similar to WordPress's get_template_part
function, \BenchPress\get_partial
and \BenchPress\the_partial
allow you to render a partial while providing a data array to the partial to render. Similar to how most template engines work, you can pass the data array as the second argument:
In my-theme/partials/greeter.php
:
<h1>Hello <?php echo $name; ?></h1>
In another theme file:
\BenchPress\the_partial( 'greeter', [ 'name' => 'Mrs. Smith' ] );
This would output:
<h1>Hello Mrs. Smith</h1>
If want to return the contents of the partial instead of echoing the contents, use \BenchPress\get_partial
.
By default, the partial functions will first look in a partials
directory within your theme followed by looking your theme root. You can also provide an absolute path to the partial which is useful when using the partial functions within a plugin.
If you want to change the search path from partials
to another directory, you can add the below filter:
add_filter( 'benchpress/partials_directory', function() {
return 'parts';
} );
If you want to pass arguments or filter the existing arguments that are passed to a partial, you can use the following filter:
add_filter( 'benchpress/partial/greeter', function() {
return [ 'name' => 'Mrs. Smith' ] ];
} );
In the above example greeter
can be substitued for the partial name that you are wishing to pass data to. So any partial can be targeterd with the filter benchpress/partial/{partial_name}
Sometimes it is necessary to display a custom admin notice when working on admin functionality. WordPress doesn't have a simple way to create the different types of admin notices. However, BenchPress provides an easy way to create them when needed:
use \BenchPress\Admin\Admin_Notice;
Admin_Notice::create( Admin_Notice::Success, 'Your book is safe', true );
You would typically invoke this function within the admin_notices
action.
add_action( 'admin_notices', function() {
Admin_Notice::create( Admin_Notice::Success, 'Your book is safe', true );
} );
The static \BenchPress\Admin_Notice\Admin_Notice::create
method accepts the following arguments:
-
int $type
- The type of notice to display. There are three different types of notices:Admin_Notice::Success; Admin_Notice::Warning; Admin_Notice::Error;
-
string $message
- The message to display in the notice. -
bool $dismissible
- Whether this notice should be dismissible or not
If you need to access the role of a user, you can call \BenchPress\get_user_role( $user )
. It will return the user role if found, or false if one isn't found.