Changing or removing a function within a plugin - php

Perfect woocommerce brands only allows certain tags to be used and removes the rest via the function
if( isset( $_POST['pwb_brand_description_field'] ) ){
$desc = strip_tags(
wp_unslash( $_POST['pwb_brand_description_field'] ),
'<p><span><a><ul><ol><li><h1><h2><h3><h4><h5><h6><pre><strong><em><blockquote><del><ins><img><code><hr>'
);
global $wpdb;
$wpdb->update( $wpdb->term_taxonomy, [ 'description' => $desc ], [ 'term_id' => $term_id ] );
I am looking for a way to overide this so that I can include all tags, in particular <div>
I was hoping there might be something that I could add to functions.php which would help me achieve this?

Because the plugin author did not add any filters / hooks for this particular function, you have to do a fairly clunky work-around.
Thankfully, this function is called via a couple of actions
add_action( 'edit_pwb-brand', array( $this, 'add_brands_metafields_save' ) );
add_action( 'create_pwb-brand', array( $this, 'add_brands_metafields_save' ) );
That means that we may be able to add our own actions that run after those two, and may be able to do what you want.
Note that this is sub-optimal but cannot be avoided. This function is essentially running twice (the original in the plugin, plus yours), which is not good for performance - however, since this is only happening when an admin saves a brand, it shouldn't be too bad for performance.
First, add your own action(s) with a higher priority, then copy the original function with the desired modifications.
It's often recommended that you do this in your theme's functions.php file, but that's not ideal - what if you want to change themes, or update themes, but keep this functionality? Instead, I strongly recommended you build your own small, light-weight plugin. The complete code for such a plugin is below. (Simply add this code to a PHP file, and place it in your plugins directory).
<?php
/**
* Plugin Name: Override Perfect WooCommerce Brands Meta
* Description: Custom override to permit div tags in brand meta description
* Version: 1.0.0
* Author: SupGen
*/
// Note the higher priority levels - to ensure these run AFTER the main plugin is done
add_action( 'edit_pwb-brand', 'override_add_brands_metafields_save', 9999 );
add_action( 'create_pwb-brand', 'override_add_brands_metafields_save', 9999 );
function override_add_brands_metafields_save( $term_id ) {
// NOTE: hard-coding the file name here in order to verify the nonce. MAY need to be changed
$filename = 'class-brands-custom-fields.php';
if ( ! isset( $_POST[ 'pwb_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'pwb_nonce' ], $filename ) ) {
return;
}
// removed bits you didn't care about, keeping only the relevant part
if ( isset( $_POST[ 'pwb_brand_description_field' ] ) ) {
// added div tag to allowed tags list
$desc = strip_tags(
wp_unslash( $_POST[ 'pwb_brand_description_field' ] ),
'<div><p><span><a><ul><ol><li><h1><h2><h3><h4><h5><h6><pre><strong><em><blockquote><del><ins><img><code><hr>'
);
global $wpdb;
$wpdb->update( $wpdb->term_taxonomy, [ 'description' => $desc ], [ 'term_id' => $term_id ] );
}
}

Related

Pulling shipping details from one wordpress plugin into another

I believe I am close but entirely unsure as my limited php knowledge is based on trial and error. I am trying to pull data from a plugin that creates my shipping label into a plugin that tracks shipping. Specifically Elex EasyPost into Advanced Shipping Tracking.
I have an example snippet for shipstation integration from AST here:
<?php
add_action( 'woocommerce_shipstation_shipnotify', 'add_tracking_information_into_order', 10, 2 );
function add_tracking_information_into_order($order, $tracking_details){
$order_id = $order->get_id();
$args = array(
'tracking_provider' => $tracking_details['carrier'],
'tracking_number' => wc_clean( $tracking_details['tracking_number'] ),
'date_shipped' => wc_clean( $tracking_details['ship_date'] ),
'status_shipped' => 1,
);
$ast = new WC_Advanced_Shipment_Tracking_Actions;
$tracking_item = $ast->insert_tracking_item( $order_id, $args );
}
It should be similar but obviously I need to replace the hook and the items in the array. Here is what Elex sent me when asked for the hooks they are using.
get_post_meta($order_id, ‘wf_easypost_labels’);
Sample output:
array(
0=>(‘url’=>label_url,’tracking_number’=> (string)’tracking code’,’integrator_txn_id’=> ‘integerator_id’,’shipment_id’=>’package_shipment_id’,’order_date’=>order_date,’carrier’=>EX:USPS,”link”=>tracking_link,);//First package
1=>(‘url’=>label_url,’tracking_number’=> (string)’tracking code’,’integrator_txn_id’=> ‘integerator_id’,’shipment_id’=>’package_shipment_id’,’order_date’=>order_date,’carrier’=>EX:USPS,”link”=>tracking_link,);//Second package
)
So here is my attempt to use their array in my own snippet:
<?php
add_action( 'woocommerce_checkout_update_order_meta', 'add_tracking_information_into_order', 10, 2 );
function add_tracking_information_into_order($order, $myship_func){
$myship_func = get_post_meta($order_id, 'wf_easypost_labels');
$order_id = $order->get_id();
$args = array(
'tracking_provider' => $myship_func['carrier'],
'tracking_number' => wc_clean($myship_func['tracking code']),
'date_shipped' => wc_clean($myship_func['order_date']),
'status_shipped' => 1,
);
$ast = new WC_Advanced_Shipment_Tracking_Actions;
$tracking_item = $ast->insert_tracking_item( $order_id, $args );
}
When the order is initially filled and the label is generated Elex grabs all the data from and sticks it in the meta. I need to pull that meta either at the time of generation or post generation and stick it in the AST fields.
My main question is thus - Am I on the right track here? Do I just need to figure out the correct hook or is my method for accessing the Elex array incorrect? Again, I usually compare codes, slice and dice, and get things to "look right" and then they work (or not). I myself don't have too deep of knowledge about arrays or class functions (which I believe the Elex one is).
In this case the code is silently failing so I suspect it is the hook involved or a combination of the hook and my code.

Woocommerce Multiple single product templates using single-product.php to redirect

I've been pulling my hair out with this all day, please forgive the short description, I just need to validate my sanity!!
As the title says, I'm trying to create two or three different single-product layouts within woocommerce. The minimum is trying to achieve would be to have multiple single-product folders each with their own name and configurations.
No matter which way I try to override the single-product.php and make this file use logic to check for the product_cat and give out templates accordingly, I either the page not loading or what I write is skipped over and the default is loaded.
So far I've been through the following methods multiple times, trying to piece together what may be outdated code or otherwise causing all the fuss:
WooCommerce - How to create multiple single product template based on category?
Woocommerce single product - template by categories
Creating a different template file for certain Product Categories - Wordpress/Woocommerce?
I was more hoping someone may know something about this that I'm obviously missing as there are many articles out there on what to try and most claim success but I'm unable to do so.
[Update] using template_include code from #helgatheviking
No success just yet but here's where I'm up to;
File structure
team-shops is the category I'm trying to get
/mytheme/woocommerce/single-product.php - no changes
/mytheme/woocommerce/content-single-product.php
/mytheme/woocommerce/single-product-team-shops.php - changed line 37 to<?php wc_get_template_part( 'content', 'single-product-team-shops' ); ?>
/mytheme/woocommerce/content-single-product-team-shops.php - added additional id to #product-id (line 39)
/mytheme/woocommerce/single-product-team-shops/ folder with all single product files to change.
As I said above this isn't working but hopefully with what I've provided the problem may be more obvious.
Thanks again for any help :)
[Think I've got it]
Ok so I think I've something that works, at least for now it seems to, still have some further testing to do but any thoughts more than welcome, this is what I've got so far along with a single-product-team-shops folder in my theme
add_filter( 'woocommerce_locate_template', 'so_25789472_locate_template', 10, 3 );
function so_25789472_locate_template( $template, $template_name, $template_path ){
$term_id = 2854;
$taxonomy_name = 'product_cat';
$term_children = get_term_children( $term_id, $taxonomy_name );
foreach ( $term_children as $child ) {
// on single posts with mock category and only for single-product/something.php templates
if( is_product() && has_term( $child, 'product_cat' ) && strpos( $template_name, 'single-product/') !== false ){
// replace single-product with single-product-mock in template name
$mock_template_name = str_replace("single-product/", "single-product-team-shops/", $template_name );
// look for templates in the single-product-mock/ folder
$mock_template = locate_template(
array(
trailingslashit( $template_path ) . $mock_template_name,
$mock_template_name
)
);
// if found, replace template with that in the single-product-mock/ folder
if ( $mock_template ) {
$template = $mock_template;
}
}}
return $template;
}
Use a single-product-custom.php template for any product in the "custom" category:
add_filter( 'template_include', 'so_43621049_template_include' );
function so_43621049_template_include( $template ) {
if ( is_singular('product') && (has_term( 'custom', 'product_cat')) ) {
$template = get_stylesheet_directory() . '/woocommerce/single-product-custom.php';
}
return $template;
}
NB: If you use the same action hooks in your single-product-custom.php template you will get the same look as the default single-product.php. You could 'rename' all the hooks and then could add existing functions (such as those for add to cart buttons, etc) to the new hooks in order to achieve a totally custom look.

Accessing post data before functions.php in Wordpress

I am updating my custom Wordpress theme, but as it is rather time consuming process I would like to launch one section at a time.
In other words there would be several versions of a theme for different parts of the website.
To keep things tidy I would like to keep them in separate folders, with all the assets such as js, images, css.
I managed to rewrite template hierarchy using conditional tags but got stuck on functions.php
I was trying to use custom filed (post meta) to switch between several functions.php files but unfortunately $post is not available there so I am unable to use get_post_meta().
I could only find a trace of a solution with custom db queries, $wpdb etc. but can't really figure it out.
Is there any fairly simple solution to hook-up into post data (wp_query) before functions.php is loaded? Or to somehow differently modify where the functions are loaded from?
To illustrate what I'm writing about I pasted my main index.php
<?
get_header();
/*
* Get theme version according to the custom field 'section'
*/
if( function_exists ( 'theme_version' ) ){
$theme = theme_version( #get_the_ID() );
} else {
$theme = 'v2';
}
include_once( 'theme/'. $theme .'/TEMPLATE_BUILDER.php' );
get_footer();
?>
Thanks!
Hopefully found a right answer (after couple of hours of research, trial and error)
I placed the below code in main (wp-native) functions.php
in attempt to keep the code and file structure tidy, works as a charm.
add_action('after_setup_theme', function(){
// parse_url tidies-up the uri
$section = get_post_meta( url_to_postid( parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ) ),'section', true);
if ( !empty( $section )){
// assign sections to the theme versions below
$theme_version = array(
'v3' => array(
'Sixth Form',
[ ... ]
),
'v3.1' => array(
'Contact',
[ ... ]
)
);
foreach($theme_version as $key => $value) { if(in_array( $section, $value )) $theme = $key; }
}
if( empty($theme) ) $theme = 'v2'; // default theme version
require_once( 'theme/' . $theme . '/functions.php' );
$GLOBALS['theme-ver'] = $theme; // set the global to use in index.php (and somewhere else perhaps)
});
The code is not complete yet – needs some conditional clauses as the functions.php is sometimes called multiple times within the loop (especially with custom wp_query)
Perhaps someone will find the above useful. By the way it's quite surprising that WP doesn't natively support some kind of 'theme version control' – I can see strong benefits of not having to upgrade the whole website at once for instance to e. g. resp.

woo commerece short codes not working on all posts

I have created a short code to display short description in woo commerce but it is not working on all posts. It is displaying the short description on some posts and not on others.
Function to create that short code in functions.php
function product_shortdesc_shortcode( $atts ){
// use shortcode_atts() to set defaults then extract() to variables
extract( shortcode_atts( array( 'id' => false ), $atts ) );
// if an $id was passed, and we could get a Post for it, and it's a product....
if ( ! empty( $id ) && null != ( $product = get_post( $id ) ) && $product->post_type = 'product' ){
// apply woocommerce filter to the excerpt
echo apply_filters( 'woocommerce_short_description', $product->post_excerpt );
}
}
// process [product_shortdesc] using product_shortdesc_shortcode()
add_shortcode( 'product_shortdesc', 'product_shortdesc_shortcode' );
The way i am getting the data in my single.php file
$custom = get_post_custom(get_the_ID());
$my_custom_field = $custom['woo_id'];
foreach ( $my_custom_field as $key => $value ) {
echo do_shortcode('[product_shortdesc id='.$value.']');
}
PS: in my normal post i have a custom field which has the value of product id of the product in woo commerece.
Your issue is that you are expecting shortcodes to function which no longer exist. On new installs, these pages won't be created, but if you are updating you may already have those pages in place.
Although the upgrade script does attempt to trash them for you, this might not have happened if they were customised. Delete them. Delete edit-account and change password, then go to your 'my account' page and click the change password/edit account links. You'll be taken to and endpoint which offers the same functionality.
Thanks
Short Code must not echo code instead return the things that needs to be rendered
Change this
echo apply_filters( 'woocommerce_short_description', $product->post_excerpt );
to
return apply_filters( 'woocommerce_short_description', $product->post_excerpt );

Wordpress NextGen Remove "Set NextGEN Featured Image" From Edit Page

I'm using NextGen for some galleries and noticed that since loading this plugin, in the edit page area under the Featured Image Meta box there is now a link to "Set NextGEN Featured Image". I don't want to confuse the user (by having two "set featured image" links, so I'd like to remove the NextGEN option, leaving only the one default WP link to set the featured image.
I've found tutorials on how to change the text of the standard WordPress "Set Featured Image" Meta Box, but nothing on how to remove the NextGEN link, (I did find a post for adding a plugin to remove it: http://wordpress.org/support/topic/remove-set-nextgen-featured-image)
However, I would like to just remove it in my functions.php file (not use a plugin).
I've tried the following in my functions.php file:
remove_meta_box
remove_filter
remove_action
But I'm not 100% sure which I need to use (none have worked so far).
The file that is adding this function to the page edit area is: https://github.com/mneuhaus/foo/blob/master/nextgen-gallery/products/photocrati_nextgen/modules/ngglegacy/lib/post-thumbnail.php.
I realize that I would just comment out the text in this file that produces the link, but if I ever updated the plugin it would be overwritten.
Any help or suggestions are greatly appreciated! Thank you.
If you don't have/need anything customized for the Featured Image meta box, you can simply remove all filters:
function so_23984689_remove_nextgen_post_thumbnail_html() {
remove_all_filters( 'admin_post_thumbnail_html' );
}
add_action( 'do_meta_boxes', 'so_23984689_remove_nextgen_post_thumbnail_html' );
If there are any other filters, which you would want to keep, you have to loop through the filter array and remove the according element:
function so_23984689_remove_nextgen_post_thumbnail_html() {
global $wp_filter;
if ( ! isset( $wp_filter[ 'admin_post_thumbnail_html' ] ) ) {
return;
}
foreach ( $wp_filter[ 'admin_post_thumbnail_html' ] as $priority => $filters ) {
foreach ( $filters as $id => $filter ) {
if (
isset( $filter[ 'function' ] )
&& is_object( $filter[ 'function' ][ 0 ] )
&& $filter[ 'function' ][ 0 ] instanceof nggPostThumbnail
) {
unset( $wp_filter[ 'admin_post_thumbnail_html' ][ $priority ][ $id ] );
}
}
}
}
add_action( 'do_meta_boxes', 'so_23984689_remove_nextgen_post_thumbnail_html' );

Categories