Giter Club home page Giter Club logo

gamajo-template-loader's Introduction

Gamajo Template Loader

Code Climate

A class to copy into your WordPress plugin, to allow loading template parts with fallback through the child theme > parent theme > plugin.

Description

Easy Digital Downloads, WooCommerce, and Events Calendar plugins, amongst others, allow you to add files to your theme to override the default templates that come with the plugin. As a developer, adding this convenience in to your own plugin can be a little tricky.

The get_template_part() function in WordPress was never really designed with plugins in mind, since it relies on locate_template() which only checks child and parent themes. So we can add in a final fallback that uses the templates in the plugin, we have to use a custom locate_template() function, and a custom get_template_part() function. The solution here just wraps them up as a class for convenience.

Installation

This isn't a WordPress plugin on its own, so the usual instructions don't apply. Instead:

Manually install class

  1. Copy class-gamajo-template-loader.php into your plugin. It can be into a file in the plugin root, or better, an includes directory.

or:

Install class via Composer

  1. Tell Composer to install this class as a dependency: composer require gamajo/template-loader
  2. Recommended: Install the Mozart package: composer require coenjacobs/mozart --dev and configure it.
  3. The class is now renamed to use your own prefix, to prevent collisions with other plugins bundling this class.

Implement class

  1. Create a new file, such as class-your-plugin-template-loader.php, in the same directory.
  2. Create a class in that file that extends Gamajo_Template_Loader (or the new prefixed name, if you installed via Composer/Mozart). You can see the Meal Planner Template Loader example class below as a starting point if it helps.
  3. Override the class properties to suit your plugin. You could also override the get_templates_dir() method if it isn't right for you.
  4. You can now instantiate your custom template loader class, and use it to call the get_template_part() method. This could be within a shortcode callback, or something you want theme developers to include in their files.
// Template loader instantiated elsewhere, such as the main plugin file.
$meal_planner_template_loader = new Meal_Planner_Template_Loader();
  • Use it to call the get_template_part() method. This could be within a shortcode callback, or something you want theme developers to include in their files.

    $meal_planner_template_loader->get_template_part( 'recipe' );
  • If you want to pass data to the template, call the set_template_data() method with an array before calling get_template_part(). set_template_data() returns the loader object to allow for method chaining.

    $data = array( 'foo' => 'bar', 'baz' => 'boom' );
    $meal_planner_template_loader
        ->set_template_data( $data )
        ->get_template_part( 'recipe' );

    The value of bar is now available inside the recipe template as $data->foo.

    If you wish to use a different variable name, add a second parameter to set_template_data():

    $data = array( 'foo' => 'bar', 'baz' => 'boom' );
    $meal_planner_template_loader
        ->set_template_data( $data, 'context' )
        ->get_template_part( 'recipe', 'ingredients' );

    The value of bar is now available inside the recipe template as $context->foo.

    This will try to load up wp-content/themes/my-theme/meal-planner/recipe-ingredients.php, or wp-content/themes/my-theme/meal-planner/recipe.php, then fallback to wp-content/plugins/meal-planner/templates/recipe-ingredients.php or wp-content/plugins/meal-planner/templates/recipe.php.

  • You can also pass the template loader object into the template as well:

    $template_loader = new Your_Template_Loader();
    $template_loader->set_template_data(
        array(
      	      'template_loader' => $template_loader,
      		  // Optional other data as needed.
          )
    );

    Then in the template you can use:

    $data->template_loader->get_template_part( 'recipe' );

Meal Planner Example Class

<?php
/**
 * Meal Planner
 *
 * @package   Meal_Planner
 * @author    Gary Jones
 * @link      http://example.com/meal-planner
 * @copyright 2013 Gary Jones
 * @license   GPL-2.0+
 */

if ( ! class_exists( 'Gamajo_Template_Loader' ) ) {
  require plugin_dir_path( __FILE__ ) . 'class-gamajo-template-loader.php';
}

/**
 * Template loader for Meal Planner.
 *
 * Only need to specify class properties here.
 *
 * @package Meal_Planner
 * @author  Gary Jones
 */
class Meal_Planner_Template_Loader extends Gamajo_Template_Loader {
  /**
   * Prefix for filter names.
   *
   * @since 1.0.0
   *
   * @var string
   */
  protected $filter_prefix = 'meal_planner';

  /**
   * Directory name where custom templates for this plugin should be found in the theme.
   *
   * @since 1.0.0
   *
   * @var string
   */
  protected $theme_template_directory = 'meal-planner';

  /**
   * Reference to the root directory path of this plugin.
   *
   * Can either be a defined constant, or a relative reference from where the subclass lives.
   *
   * In this case, `MEAL_PLANNER_PLUGIN_DIR` would be defined in the root plugin file as:
   *
   * ~~~
   * define( 'MEAL_PLANNER_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
   * ~~~
   *
   * @since 1.0.0
   *
   * @var string
   */
  protected $plugin_directory = MEAL_PLANNER_PLUGIN_DIR;

  /**
   * Directory name where templates are found in this plugin.
   *
   * Can either be a defined constant, or a relative reference from where the subclass lives.
   *
   * e.g. 'templates' or 'includes/templates', etc.
   *
   * @since 1.1.0
   *
   * @var string
   */
  protected $plugin_template_directory = 'templates';
}

Usage Example

The Cue plugin from AudioTheme uses this class. Starting at https://github.com/AudioTheme/cue/tree/develop/includes, it has this class in the vendor directory, then the required subclass of my class in the class-cue-template-loader.php file, which sets a few basic properties. It also has a template in https://github.com/AudioTheme/cue/tree/develop/templates.

If you wanted the playlist to have different markup for your theme, you'd copy templates/playlist.php to wp-content/themes/{your-active-theme}/cue/playlist.php and do whatever changes you wanted. WordPress will look for that file first, before then checking a parent theme location (if your active theme is a child theme), before falling back to the default template that comes with the Cue plugin.

Change Log

See the change log.

License

GPL 2.0 or later.

Contributions

Contributions are welcome - fork, fix and send pull requests against the develop branch please.

Credits

Built by Gary Jones
Copyright 2013 Gary Jones

gamajo-template-loader's People

Contributors

alanef avatar bradvin avatar bradyvercher avatar cliffordp avatar coenjacobs avatar garyjones avatar grappler avatar jondcampbell avatar jtsternberg avatar leewillis77 avatar pippinsplugins avatar rarst avatar rtpharry avatar samlasserson avatar zackkatz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gamajo-template-loader's Issues

Add Composer support

...to all the things. :)

I can do PR if you let me know preferences on author/package name/site/etc.

Fatal error: Call to a member function get_template_part() only on plugin's activation

Hi there,

First of all thanks a lot for this awesome class. I'm using it with composer and it's super easy to intergrate. I'm using your class within a plugin of mine https://wordpress.org/plugins/wp-user-manager/, while 99.99% of users have no issues with it, I've had 2 cases now where the user is unable to activate the plugin because of the following error

Fatal error: Call to a member function get_template_part() on null in /wp-content/plugins/wp-user-manager/includes/wpum-shortcodes/shortcodes.php on line 38

This is the file the error is referring to https://github.com/WPUserManager/wp-user-manager/blob/master/includes/wpum-shortcodes/shortcodes.php#L38 I can't seem to understand what's the issue, have I done something wrong?

What I've noticed trying to understand the issue, is that this happens only on plugin's activation.

The only time I've been able to replicate the issue on my end was when I had installed a premium version of the Yoast SEO plugin, it's was parsing shortcodes and doing some weird stuff, an update for the plugin was released and the issue disappeared ¯_(ツ)_/¯.

The first user that had issue, I logged in via ftp, commented the shortcode, enabled the plugin, re-enabled the shortcode and everything just works fine, again ¯_(ツ)_/¯. Now I've had a second report of a user with the same issue but I have no idea what's going on.

Have you encountered this issue before?

Thank you!

Theme children wordpress 4.7

Hello, I am implementing this class in my plugin but I noticed that it is not working for theme children, is there an incompatibility with wordpres 4.7 to work on theme children?

Use template loader object within template

Hello is it possible to use template loader inside template that is called within get_template_part function? For example, template for table which iterates data and load row template for every item. Thank you in advance.

Looping Templates in foreach() only returns final template

I'm trying to allow ordering of which templates get shown through a foreach loop, (essentially i'm building a slider thats generated through lots of template parts being pulled together, very specific use case but it has standard slides built into the plugin, then these will be overwritable within the theme)

however my foreach loop is only returning the final item
foreach ($orderArr as $template_slug) { $my_template_loader->set_template_data( $userData )->get_template_part( $template_slug ); }

My orderArr is Array ( [0] => welcome [1] => slide1 [2] => slide2 )

However if i manually call the template parts
$my_template_loader->set_template_data( $userData )->get_template_part( 'welcome' ); $my_template_loader->set_template_data( $userData )->get_template_part( 'slide1' ); $my_template_loader->set_template_data( $userData )->get_template_part( 'slide2' );
It all works as expected.

Any suggestions would be helpful

Mozart-created class non-functional

Installing using mozart as recommended in the docs results in the following code which means that if there is a non-prefixed version somewhere in the software, the prefixed class doesn't get defined:

if ( ! class_exists( 'Gamajo_Template_Loader' ) ) {

	class MyPrefix_Gamajo_Template_Loader {

Attempting to add a class that extends MyPrefix_Gamajo_Template_Loader on a software stack that already includes a non-prefixed version of Gamajo_Template_Loader results in :

Fatal error: Class 'MyPrefix_Gamajo_Template_Loader' not found in /src/TemplateLoader.php

If all non-prefix instances are removed then this code works as expected.

Inherited static properties breaks template_paths()

In PHP 8.1, If a class is extended, static methods aren't inherited. In this case, the static $file_paths; definition isn't inherited.

class Example_Template extends Gamajo_Template_Loader {}
class Example_Template_Two extends Example_Template {}

$one = new Example_Template();

$two = new Example_Template_Two();
$two->plugin_template_directory = 'path-override'

$one->locate_template(); // Paths are added, returns true
$two->locate_template(); // New paths aren't added, returns false

I propose switching to a private property instead. PR incoming.

Order of templates

From #7:

[Change break; to break 2; in locate_template().] I ran into an instance where it was grabbing the generic template over the specific template due to possible names.

Need to document what order this class runs through templates, and check it matches to WP, and then, for instance, EDD, to ensure consistency.

Cannot use in head.php or wp_head()

Hello,

First off, thank you so much for a valuable tool such as this!

However, I ran into a hickup today as I attempted to use a template part in the header.php file. I run into this error:

PHP Fatal error: Uncaught Error: Call to a member function get_template_part() on null in [MY PLUGIN FILE.PHP]:144\nStack trace:\n#0 [MY WP DIR]/wp-includes/class-wp-hook.php(305): [MYPREFIX]_banner_images(NULL)\n#1 

[MY WP DIR]/wp-includes/class-wp-hook.php(327): WP_Hook->apply_filters('', Array)\n#2 

[MY WP DIR]/wp-includes/plugin.php(470): WP_Hook->do_action(Array)\n#3 

[MY WP DIR]/wp-includes/general-template.php(38): do_action('get_header', NULL, Array)\n#4 

[MY THEME DIR]/home-page.php(6): get_header()\n#5 

[MY WP DIR]/wp-includes/template-loader.php(106): include('/nas/content/li...')\n#6 

[MY WP DIR]/wp-blog-header.php(19): require_once('/nas/content/li...')\n#7 

[MY WP DIR]/index.php(17): require('/nas/content/li...')\n#8 

{main}\n thrown in [MY PLUGIN FILE.PHP] on line 144

In this specific example it mentions line 144 in my plugin only because I attempted to add an action to the header as a workaround. Here's what I tried in addition to editing header.php directly:

add_action('get_header', '[MY FUNCTION WITH TEMPLATE PART]');

Is there any way to get this working in the header?

To extend or rename the class -- that is the question

I notice that the documentation suggests including class-gamajo-template-loader.php and then extending Gamajo_Template_Loader. Won't we end up with hard-to-debug plugin conflicts doing it this way?

If Plugin A expects to use a method of Gamajo_Template_Loader but Plugin B has already loaded an old version without that method, we'll have problems.

Am I missing something here? Thanks.

Data parameter in get_template_part

Hi @GaryJones

While looking at the code I noticed that get_template_part is not using the $args array which was introduced in WP 5.5.

And I was wondering are you planning to add this or maybe PR is welcome for this?

Retrieving custom fields/post data when loading templates using the class.

Hi Gary,

I've been spending most of today and yesterday trying to get this to work, but I'm afraid I'm a bit over my head here. What I'm trying to do is implement your class to load a template part from inside my plugin. The template part contains custom field queries and basic WordPress data (the_title etc). Sadly the custom field data seems to be unavailable when loading the template. It does fetch the Post Title and excerpt.

I'm pretty sure it has something to do with how I use your class but I have no idea how to fix it..

My code that loads the template part
https://gist.github.com/BoweFrankema/c37844c56305aa2878c5

The template part:
https://gist.github.com/BoweFrankema/4b7ec2bbc8aee51bf27b

Any help would be awesome and thanks for creating the class :-)

brightnucleus/shortcodes v0.2.9 requires gamajo/template-loader dev-template-data

I'm not sure if this is the right place to raise an issue.

When I try to run composer require gamajo/template-loader or composer require gaa/gaa-services, I get this error.

- brightnucleus/shortcodes v0.2.9 requires gamajo/template-loader dev-template-data -> no matching package found. - brightnucleus/shortcodes v0.2.8 requires gamajo/template-loader dev-template-data -> no matching package found. - brightnucleus/shortcodes v0.2.7 requires gamajo/template-loader dev-template-data -> no matching package found. - brightnucleus/shortcodes v0.2.6 requires gamajo/template-loader dev-template-data -> no matching package found. - brightnucleus/shortcodes v0.2.14 requires gamajo/template-loader dev-template-data -> no matching package found. - brightnucleus/shortcodes v0.2.13 requires gamajo/template-loader dev-template-data -> no matching package found. - brightnucleus/shortcodes v0.2.12 requires beberlei/assert dev-schlessera-138-functions-file-causes-collisions -> no matching package found. - brightnucleus/shortcodes v0.2.11 requires beberlei/assert dev-schlessera-138-functions-file-causes-collisions -> no matching package found. - brightnucleus/shortcodes v0.2.10 requires gamajo/template-loader dev-template-data -> no matching package found. - brightnucleus/config v0.2.5 requires beberlei/assert dev-schlessera-138-functions-file-causes-collisions -> no matching package found. - Conclusion: don't install gaa/corp-manager v2.1.7 - Conclusion: don't install gaa/corp-manager v2.1.6 - Conclusion: don't install gaa/corp-manager v2.1.5 - Conclusion: don't install gaa/corp-manager v2.1.4 - Conclusion: don't install gaa/corp-manager v2.1.3 - Conclusion: don't install gaa/corp-manager v2.1.2 - Conclusion: don't install gaa/corp-manager 2.1.1 - Conclusion: remove brightnucleus/config v0.4.12 - Conclusion: don't install brightnucleus/config v0.4.12 - brightnucleus/shortcodes v0.2.0 requires brightnucleus/config 0.2.* -> satisfiable by brightnucleus/config[v0.2.0, v0.2.1, v0.2.2, v0.2.3, v0.2.4, v0.2.5, v0.2.6, v0.2.7, v0.2.8]. - brightnucleus/shortcodes v0.2.1 requires brightnucleus/config ^0.2 -> satisfiable by brightnucleus/config[v0.2.0, v0.2.1, v0.2.2, v0.2.3, v0.2.4, v0.2.5, v0.2.6, v0.2.7, v0.2.8]. - brightnucleus/shortcodes v0.2.2 requires brightnucleus/config ^0.2 -> satisfiable by brightnucleus/config[v0.2.0, v0.2.1, v0.2.2, v0.2.3, v0.2.4, v0.2.5, v0.2.6, v0.2.7, v0.2.8]. - brightnucleus/shortcodes v0.2.3 requires brightnucleus/config ^0.2 -> satisfiable by brightnucleus/config[v0.2.0, v0.2.1, v0.2.2, v0.2.3, v0.2.4, v0.2.5, v0.2.6, v0.2.7, v0.2.8]. - brightnucleus/shortcodes v0.2.4 requires brightnucleus/config ^0.2 -> satisfiable by brightnucleus/config[v0.2.0, v0.2.1, v0.2.2, v0.2.3, v0.2.4, v0.2.5, v0.2.6, v0.2.7, v0.2.8]. - brightnucleus/shortcodes v0.2.5 requires brightnucleus/config ^0.2 -> satisfiable by brightnucleus/config[v0.2.0, v0.2.1, v0.2.2, v0.2.3, v0.2.4, v0.2.5, v0.2.6, v0.2.7, v0.2.8]. - brightnucleus/shortcodes v0.2.15 requires brightnucleus/config ^0.2.4 -> satisfiable by brightnucleus/config[v0.2.4, v0.2.5, v0.2.6, v0.2.7, v0.2.8]. - Can only install one of: brightnucleus/config[v0.2.0, v0.4.12]. - Can only install one of: brightnucleus/config[v0.2.1, v0.4.12]. - Can only install one of: brightnucleus/config[v0.2.2, v0.4.12]. - Can only install one of: brightnucleus/config[v0.2.3, v0.4.12]. - Can only install one of: brightnucleus/config[v0.2.4, v0.4.12]. - Can only install one of: brightnucleus/config[v0.2.6, v0.4.12]. - Can only install one of: brightnucleus/config[v0.2.7, v0.4.12]. - Can only install one of: brightnucleus/config[v0.2.8, v0.4.12].

What could be the possible issue?

Thank you in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.