I'm creating a WordPress plugin for a custom menu layout. I am well aware that I could just as easily implement this menu directly into the theme and I've read up quite thoroughly on the features and limitations of wp_nav_menu(), plus I have already tried and tested every plugin already created for replacing the default WordPress menu.
I wish to use a plugin since my client will be implementing this on several different WordPress sites, many of which run on different themes - and most of those are themes which I did not create and I do not wish to re-write their code in case they update the theme in the future.
When I've looked into a way to implement the menu into the theme I found that there are only two good methods since there is no hook or filter called at menu display time. The first is to change the theme to look for the plugin (this is similar to the method used by PixoPoint and many other menu plugins):
header.php:
if(function_exists('pixopoint_menu')){
pixopoint_menu();
} else {
wp_nav_menu();
}
The second method is a walker class:
plugin.php:
class my_walker_class Extends Walker_Nav_Menu {
function start_el(&$output, $item, $depth, $args) {
/*
* Etc. Etc.
*/
}
}
header.php:
wp_nav_menu( Array( 'walker' => 'my_walker_class' ) );
However as you'll note both of these methods require a modification to the standard header.php file.
Ideally I would like to simply replace the wp_nav_menu() function if my plugin is loaded, as this would give my plugin support for the majority of themes without having to edit any of the theme files. Is there a good way to do this? Or is there a better way to write a menu plugin which I am not seeing?
You can use the wp_nav_menu_args filter to modify the arguments passed to wp_nav_menu, so you can specify your custom walker class.
add_filter('wp_nav_menu_args', 'my_wp_nav_menu_args_filter');
function my_wp_nav_menu_args_filter($args = array()) {
$args['walker'] = new my_walker_class();
return $args;
}
Related
I've created a custom module based on Divi's Blog module. Ever since the 4.10 the module's grid layout does not work anymore because of the Dynamic CSS feature. When this is enabled Divi basically only loads the required assets when a specific module is used. So if the Divi Blog Module is not in the page the required CSS is not included and my custom module displays bad.
I saw a filter that should force the assets of a default module and used it inside my custom module:
//force the blog assets to be included inside this custom module
function include_module_assets($assets_list) {
return ['et_pb_blog'];
}
add_filter( 'et_required_module_assets', 'include_module_assets' );
Now this adds some column styles, but the column widths are not being set. So there are still some styles that are not being loaded.
Anybody experienced this yet with their Divi extensions?
Thanks
As there doesn't seem to be a filter for $grid_items_deps found in ET_Dynamic_Assets::get_global_assets_list you can use the et_global_assets_list filter.
You'll probably find you need to add_filter earlier than when your module class is initialized, perhaps one level back in the constructor of your extension class.
function init() {
parent::init();
/** Removed other code the sake of simplicity **/
add_filter( 'et_required_module_assets', array($this, 'include_module_assets') );
}
// Make sure we include gutters3_grid_items
public function include_early_global_assets($global_asset_list, $assets_args, $dynamic_assets_class){
$assets_prefix = et_get_dynamic_assets_path();
$gutters_3_grid_path = $assets_prefix . '/css/gutters3_grid_items.css';
$global_asset_list['some_custom_blog'] = array(
'css' => $gutters_3_grid_path
);
return $global_asset_list;
}
Hopefully ET adds a filter in the future for $grid_items_deps in the near future. They do seem to be getting a little better with providing filters, still many more could be added.
If anyone knows of a better solution I'd be keen know, as there is an issue with the below that we include gutters3_grid_items.css even when not using a grid layout.
Cheers
I am doing some work on a site and everything is made in Divi.
I just want to build out a few custom woocommerce templates for product page etc.. using code but when I add the templates to the theme folder it doesn't override the product page.
When I look in debug query it shows the et page builder template is being used instead of regular product template.
Their docs are all geared up for non-coders and only code related stuff is on making modules.
How do I just make a normal template override from a child theme?
You just have to make sure your path to the template files is correct. For instance, if you're trying to overwrite the single-product template, which is located at:
wp-content/plugins/woocommerce/templates/single-product.php
just copy it to:
wp-content/themes/{your-child-theme}/woocommerce/single-product.php
and make your changes there.
For any template files, just match the path minus the templates folder.
If you have any caching plugins installed, you may need to clear your cache before the changes show up.
To test it, I copied single-product.php and product-image.php and made the following changes.
And you can see the result here:
If that doesn't work for you, make sure your child theme is set up correctly.
Edit: Divi's Theme Builder, once activated, causes the site to no longer use page templates. So there is no way (short of rewriting the Theme Builder) to override it with your own template files.
However, you can customize the Divi modules that are used by the Theme Builder, although editing them is a bit more complicated.
The modules are found in:
wp-content/themes/Divi/includes/builder/module/
For example, I'll override the WooCommerce Title module.
wp-content/themes/Divi/includes/builder/module/woocommerce/Title.php
First, copy that file into your child theme and place it in a new folder:
wp-content/themes/Divi-child/custom-modules/Title.php
Next, add the following code your child theme's functions.php to replace the existing module:
function divi_child_theme_setup() {
if ( class_exists('ET_Builder_Module')) {
get_template_part( 'custom-modules/custom-title' );
$TE_ct = new Custom_ET_Builder_Module_Woocommerce_Title();
remove_shortcode( 'et_pb_wc_title' );
add_shortcode( 'et_pb_wc_title', array($TE_ct, '_shortcode_callback') );
}
}
add_action('wp', 'divi_child_theme_setup', 9999);
Call your variable ($TE_ct) and the module (Custom_ET_Builder_Module_Woocommerce_Title) whatever you want.
Finally, edit the module in your child theme. Make sure the class name matches what you used in functions.php.
...
class Custom_ET_Builder_Module_Woocommerce_Title extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
echo "<h1>CUSTOMIZED!!</h1>";
$this->name = esc_html__( 'Woo Title', 'et_builder' );
$this->plural = esc_html__( 'Woo Titles', 'et_builder' );
$this->slug = 'et_pb_wc_title';
$this->vb_support = 'on';
...
Here, I've added a simple echo to show that the module is being overridden.
Result:
I know there are lists of hooks for WordPress like --> http://adambrown.info/p/wp_hooks/hook
But if I want to find hooks for a plugin like WC Vendors there is a much shorter list of hooks on their website.
Are 'do_action' and 'apply filter' functions the only thing we can modify?
If given a class like --> https://github.com/wcvendors/wcvendors/blob/master/classes/admin/class-product-meta.php#L10, is there any way to modify it?
Are we limited to the do_action hooks or is there a way to modify other areas as well? Can we use the WordPress hooks to hook into the WC Vendors plugin as well?
Mostly you should try to accomplish any task with hooks, but some tasks are just not possible without actually modifying the actual code. But we all know its not good to modify core code, as all changes disappear after an update. So instead of modifying a class, you can extend it. You can override the current features and also add new ones. Extending a class is as easy as using a relavant hook in functions.php and then extending it in the same file or requiring it from another file. Here is an official tutorial on how to add a new shipping method to the woocommerce shipping class.
Sometimes you dont even need all the hooks, you just need to find the ones that are running on a specific page. For this you can use the code below to list all the current hooks.
$debug_tags = array();
add_action( 'all', function ( $tag ) {
global $debug_tags;
if ( in_array( $tag, $debug_tags ) ) {
return;
}
echo "<pre>" . $tag . "</pre>";
$debug_tags[] = $tag;
} );
Or you can use this plugin "simply show hooks"which is really helpful while development as it gives you an idea of where each hook is being triggered on the page.
I tried adding page classes via Appearance => Menus => Screen Options => CSS Classes, but when I update my pages the classes don't show up.
I tried with another theme, it works, so my problem is theme-related. I didn't develop this theme, I took it back from another developer. Can someone explain me what I should look for in the code to make it back to normal?
Thank you for the help.
It could be a couple of things, where to look first.
Look for some standard functions are in the templates file such as body_class(), post_class(). As it print standard Wordpress used class within the context it needs to.
If its more menu related look for add_filters() within the functions.php filters that allow css to be added or removed such as.
add_filter('nav_menu_css_class' , 'some_function_called' , 10 , 2);
function some_function_called($classes, $item){
if(is_single() && $item->title == "Blog"){ //Notice you can change the conditional from is_single() and $item->title
$classes[] = "special-class";
}
return $classes;
}
Best of luck.
On my blog landing page the body_class() injects the blog style (http://madgreens.com/blog). But, when a blog page loads, the single-post style is injected (http://www.madgreens.com/blog/2015/02/chicken/).
I did upgrade 4 plugins recently but have moved them to a folder 'plugins-temp' until I sort this out.
Is there a way to force Wordpress to load the correct css on all blog pages?
That is the default behavior of body_class(). If there are other classes that you want in addition to the standard classes, you can add them by:
body_class( 'classname' )
or
body_class( array( 'classname1', 'classname2' ) )
So if there is some class you always want, just modify the body_class function in your template to include it.
For more control, you can add a filter in your functions.php file, like so:
function enhanceBodyClass($classes)
{
global $post;
// Add any classes you want to the $classes array
return $classes;
}
add_filter('body_class', 'enhance_body_class');