My first question is, what is the function or loader that makes this
happen? And secondly, is this a global WordPress feature, or do plugin
developers have to build this functionality into the plugin?
It’s not a WordPress feature. Not exactly. Each plugin that does this has created their own function for loading template files that checks the theme for template files before loading them from the plugin.
In WooCommerce this is the wc_locate_template()
function. This function uses locate_template()
to look in the child theme and theme parent for a given file, and if it finds it, it loads it, otherwise it falls back to the file in its own template directory. Internally, WooCommerce uses this function whenever it loads templates, which allows themes to replace the template files. Beaver Builder likely has a very similar function.
A very simple (untested) version of a function like this would be:
function wpse_336136_load_template( $template_name ) {
$template_name = ltrim( $template_name, "https://wordpress.stackexchange.com/" );
$template_path = locate_template( 'my-plugin/' . $template_name );
if ( ! $template_path ) {
$template_path = plugin_dir_path( 'templates/' . $template_name, __FILE__ );
}
return $template_path;
}
So now the function wpse_336136_load_template()
will check the themes for a given file, inside the my-plugin/
directory, and if it doesn’t find it, it will load it from the templates/
directory of the plugin.
For example, if you use:
$template_path = wpse_336136_load_template( 'partials/header.php' )
It will check these directories, in this order:
wp-content/themes/child-theme/my-plugin/partials/header.php
wp-content/themes/parent-theme/my-plugin/partials/header.php
wp-content/plugins/my-plugin/templates/partials/header.php
So as long as you used wpse_336136_load_template()
internally in your plugin, users would be able to replace any file in your plugin’s templates/
directory by copying the files to the my-plugin/
directory of their theme.