Skip to content

Latest commit

 

History

History
executable file
·
624 lines (533 loc) · 18.1 KB

README.md

File metadata and controls

executable file
·
624 lines (533 loc) · 18.1 KB

wp-bootstrap-hooks

A collection of filters and actions for bootstrap-based themes

When integrating Bootstrap with Wordpress, it is not sufficient to just include assets and add some css-classes to templates. You will also need to inject bootstrap-compatible markup into programmatically generated sections, such as menus, widgets, comments etc. Bootstrap Hooks aims to cover most of these cases to make us immediately start implementing the individual application rather than getting hassled by markup incompatibilities.

Bootstrap Hooks consists of six separate modules for Navigation, Pagination, Forms, Widgets, Comments, Gallery and Blocks which can be used altogether or independently from each other. Every module is customizable by passing options to a central filter method.

Bootstrap Hooks has been optimized for Bootstrap 5, though it can be adjusted to also support older versions. See Recipes for more details on how to do this.

Install

Install preferrably as a must-use plugin. It should be enabled by themes programmatically and updated by theme developers who maintain Bootstrap inside a certain themes.

Initialize

Bootstrap Hooks is made aware that your theme actually supports Bootstrap by calling add_theme_support in your functions.php:

add_theme_support( 'bootstrap' );

Usage

With few exceptions, Bootstrap Hooks works out-of-the-box by injecting its magic via actions and filters. Read further to learn more about the distinct modules.

Content

The Content-Hook takes care of your post content primarily. It sets proper markup and classes to images, captions, blockquotes and tables. It also handles the post thumbnail to add the responsive image class.

In Bootstrap 4, the Tag-component may break Wordpress` default taxonomy styles. See here for reference. To avoid undesired effects, the tag class is replaced with post-tag in body_class- or post_class-methods and also when it's found in the content.

This module also provides a custom method to handle the edit-post-link. Search your theme for occurrences of edit_post_link and replace with wp_bootstrap_edit_post_link:

// Edit post link
wp_bootstrap_edit_post_link(
  sprintf(
    /* translators: %s: Name of current post */
    __( 'Edit<span class="screen-reader-text"> "%s"</span>', 'textdomain' ),
    get_the_title()
  ),
  '<span class="edit-link">',
  '</span>'
) );

When using Bootstrap Hooks as a plugin, you should definitely check if the method has been loaded by wrapping function call into a conditional function_exists-check. See the Recipes section for an example.

Forms

This module handles search- and password-forms.

A search-form is rendered as input-group. You can customize the button's icon by passing arguments from a filter. This example shows how to integrate font-awesome:

// Show Font-Awesome search icon in Searchform
function my_bootstrap_options($options) {
  return array_merge($options, array(
    'search_submit_label' => '<i class="fa fa-search"></i>'
  ));
}
add_filter( 'bootstrap_options', 'my_bootstrap_options' );

Gallery

The gallery hook uses a grid of thumbnails in combination with a carousel inside a modal for zoom view.

In typical Bootstrap-driven layout, column sizes may differ from Wordpress default thumbnail size. You may update thumbnail size to your needs in order to fit thumbnail images into at least three columns:

// Adjust thumbnail size
update_option( 'thumbnail_size_w', 230 );
update_option( 'thumbnail_size_h', 230 );
update_option( 'thumbnail_crop', 1 );

The implementation does not handle different zoom-image heights. An easy way to fix this, is to register a custom image size with cropping enabled and apply to the gallery hook:

// Register custom gallery image size
add_image_size( 'gallery-zoom', 900, 500, true );

// Apply custom image size to gallery zoom
function my_bootstrap_options($options) {
  return array_merge($options, array(
    'gallery_zoom_size' => 'gallery-zoom'
  ));
}
add_filter( 'bootstrap_options', 'my_bootstrap_options' );

Menu

Bootstrap Hooks provides a custom MenuWalker based on the work by Edward McIntyre which is injected into menus per default. For the menus being in primary or top location, the navbar-nav-class will automatically be added.

Bootstrap Hooks also adds a script that handles links on dropdown-toggles which are prevented by default from Bootstrap.

Pagination

Since there's no existing hook for posts-pagination as well as for post-navigation, we need to call custom methods from our templates:

Search your theme for occurrences of the_posts_pagination and replace with wp_bootstrap_posts_pagination:

// Previous/next page navigation.
wp_bootstrap_posts_pagination( array(
  'prev_text'          => __( 'Previous page', 'textdomain' ),
  'next_text'          => __( 'Next page', 'textdomain' ),
  'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'textdomain' ) . ' </span>'
) );

Search your theme for occurrences of the_post_navigation and replace with wp_bootstrap_post_navigation:

// Previous/next post navigation.
wp_bootstrap_post_navigation( array(
  'next_text' => '<span class="meta-nav" aria-hidden="true">' . __( 'Next', 'textdomain' ) . '</span> ' .
    '<span class="screen-reader-text">' . __( 'Next post:', 'textdomain' ) . '</span> ' .
    '<span class="post-title">%title</span>',
  'prev_text' => '<span class="meta-nav" aria-hidden="true">' . __( 'Previous', 'textdomain' ) . '</span> ' .
    '<span class="screen-reader-text">' . __( 'Previous post:', 'textdomain' ) . '</span> ' .
    '<span class="post-title">%title</span>'
) );

Widgets

Widgets are rendered as cards. Some manipulations take care of content that's common to widgets, such as applying list-groups to unordered lists. Make sure that you registered any widget areas in your functions.php:

// Register widget area.
register_sidebar( array(
  'name'          => __( 'Widget Area', 'textdomain' ),
  'id'            => 'sidebar-1',
  'description'   => __( 'Add widgets here to appear in your sidebar.', 'textdomain' )
) );

Comments

Comments are rendered as nested media-objects.

You can customize the label 'Comment' by making use of the bootstrap_options-filter:

// Customize Comment Label
function my_bootstrap_options($args) {
  return array_merge($args, array(
    'comment_label' => ('Comment' , 'textdomain');
  ));
}
add_filter( 'bootstrap_options', 'my_bootstrap_options' );

Recipes

Use as Plugin

When intended to use as plugin or must-use plugin, you should also take care of the situation where the plugin is unistalled and check if any of the functions exist first:

// Previous/next page navigation.
call_user_func_array(function_exists('wp_bootstrap_posts_pagination') ? 'wp_bootstrap_posts_pagination' : 'the_posts_pagination', array( array(
  'prev_text'          => __( 'Previous page', 'textdomain' ),
  'next_text'          => __( 'Next page', 'textdomain' ),
  'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'textdomain' ) . ' </span>'
) ) );

// Previous/next post navigation.
call_user_func_array(function_exists('wp_bootstrap_post_navigation') ? 'wp_bootstrap_post_navigation' : 'the_post_navigation', array( array(
  'next_text' => '<span class="meta-nav" aria-hidden="true">' . __( 'Next', 'textdomain' ) . '</span> ' .
    '<span class="screen-reader-text">' . __( 'Next post:', 'textdomain' ) . '</span> ' .
    '<span class="post-title">%title</span>',
  'prev_text' => '<span class="meta-nav" aria-hidden="true">' . __( 'Previous', 'textdomain' ) . '</span> ' .
    '<span class="screen-reader-text">' . __( 'Previous post:', 'textdomain' ) . '</span> ' .
    '<span class="post-title">%title</span>'
) ) );

// Edit post link
call_user_func_array(function_exists('wp_bootstrap_edit_post_link') ? 'wp_bootstrap_edit_post_link' : 'edit_post_link', array(
  sprintf(
    /* translators: %s: Name of current post */
    __( 'Edit<span class="screen-reader-text"> "%s"</span>', 'textdomain' ),
    get_the_title()
  ),
  '<span class="edit-link">',
  '</span>'
) );

Bootstrap 3

If you're still working with Bootstrap 3, you need to override at least some options.

// Bootstrap 3 Options
function my_bootstrap_options($options) {
  return array_merge($options, array(
    'img_class' => 'img-responsive',
    'align_center_class' => 'center-block',
    'edit_post_link_class' => 'btn btn-default btn-xs',
    'search_submit_label' => '<i class="glyphicon glyphicon-search"></i>',
    'gallery_thumbnail_class' => '',
    'gallery_thumbnail_img_class' => 'img-thumbnail',
    'close_button_class' => 'btn btn-default',
    'carousel_item_class' => 'item',
    'widget_class' => 'panel',
    'widget_modifier_class' => 'panel-default',
    'widget_header_class' => 'panel-heading',
    'widget_content_class' => 'panel-block'
  ));
}
add_filter( 'bootstrap_options', 'my_bootstrap_options', 1 );

API

Bootstrap Hooks is highly customizable. That's mostly required because of managing different Bootstrap versions without splitting up the codebase. Normally there should be no need to change a lot.

Methods

edit_post_link( string $text = null, string $before = '', string $after = '', int $id, string $class = 'post-edit-link' )

Displays the edit post link for post. See edit_post_link for further details.

wp_bootstrap_posts_pagination ( array $args = array() )

Displays a paginated navigation to next/previous set of posts, when applicable. See the_posts_pagination for further details.

wp_bootstrap_post_navigation ( array $args = array() )

Displays the navigation to next/previous post, when applicable. See the_post_navigation for further details.

Filters

bootstrap_options ( array $options = array() )

Inject custom options.

Options

Name Description Default
field_class Sets the field class used in forms form-group
text_input_class Sets the text input class used in forms form-control
submit_class Sets submit button css class btn btn-primary
reply_link_class Set reply link css class btn btn-primary btn-xs
comment_label Sets the comment label Comment
img_class Sets the general image class used in content and thumbnails img-responsive
align_left_class Aligns an image to left pull-left
align_right_class Aligns an image to right pull-right
align_center_class Center an image mx-auto
img_caption_tag Sets the tag for the img caption element figure
img_caption_class Sets the css class for the img caption element figure
img_caption_text_tag Sets the tag for the img caption text element figcaption
img_caption_text_class Sets the css class for the img caption text element figure-caption
img_caption_img_class Sets the css class for the image of the img element of the caption figure-img
table_class Sets the table css class table
table_container_tag Sets the table container tag div
table_container_class Sets the table container class table-responsive
blockquote_class Sets the blockquote css class blockquote
blockquote_footer_tag Sets the blockquote footer tag footer
blockquote_footer_class Sets the blockquote footer css class blockquote-footer
edit_post_link_class Sets the edit post link css class btn btn-secondary
edit_post_link_container_class Sets the edit post link container css class form-group btn-group btn-group-sm
search_submit_label Sets the searchfield's submit label 🔎
text_input_class Sets the class of textfields used in search- and password-forms form-control
submit_button_class Sets the class of submit buttons used in search- and password-forms btn btn-primary
gallery_thumbnail_size Sets the default thumbnail size thumbnail
gallery_thumbnail_class Sets the default thumbnail size
gallery_thumbnail_img_class Sets the default thumbnail size
gallery_zoom_size Sets the image size for the carousel view large
close_button_class Sets the modal's close button class btn btn-secondary
close_button_label Sets the modal's close button label __('Close')
carousel_item_class Sets the carousel's item class _item
menu_item_class Sets the menu item class nav-item
menu_item_link_class Sets the menu item link class nav-link
sub_menu_tag Sets the sub menu tag ul
sub_menu_class Sets the sub menu class dropdown-menu
sub_menu_header_class Sets the sub menu class dropdown-header
sub_menu_item_tag Sets the sub menu item tag li
sub_menu_item_class Sets the sub menu item class
sub_menu_item_link_class Sets the sub menu header class dropdown-item
caret Sets the menu item caret class (bs < 5) <span class="caret"></span>
pagination_class Sets the pagination class pagination
page_item_class Sets the page item class page-item
page_item_active_class Sets the page item active class active
page_link_class Sets the page link css class page-link
post_nav_class Sets the post navigation class nav
post_nav_tag Sets the post navigation tag ul
post_nav_item_class Sets the post navigation item class nav-item
post_nav_item_tag Sets the post navigation item tag li
post_nav_link_class Sets the post navigation link class nav-link
paginated_class Sets the paginated class pagination pagination-sm
paginated_tag Sets the paginated tag ul
paginated_item_class Sets the paginated item class page-item
paginated_item_tag Sets the paginated item tag li
paginated_link_class Sets the paginated link tag page-link
next_posts_link_class Specify next posts link class btn btn-sm btn-secondary
previous_posts_link_class Specify previous posts link class btn btn-sm btn-secondary
widget_class Sets the widget class card
widget_modifier_class Sets the widget modifier class card-widget
widget_header_class Sets the widget header class card-header
widget_content_class Sets the widget content class card-body

Development

Download Docker CE for your OS. Download NodeJS for your OS.

WordPress

Run container. Point your browser to http://localhost:8020.

docker-compose up -d

Import test data. Activate wordpress-importer if needed.

docker compose run wp plugin activate wordpress-importer
docker compose run wp import vendor/wptrt/theme-unit-test --authors=skip

Update composer dependencies

docker-compose run composer update

Stop all globally running docker containers

docker stop $(docker ps -a -q)

Frontend

Install front-end dependencies

npm i

Watch front-end dependencies

npm run watch

Create a build for production

npm run build