override Wordpress core public function - wordpress

I have 2 separate wp installs that are sharing the same database. My goal is to use the same post table and post meta table for both websites.
I have achieved that by adding in my config.php of the second site, the code:
define( 'CUSTOM_POST_TABLE', 'site1_posts' );
define( 'CUSTOM_POST_META_TABLE', 'site1_postmeta' );
Also I have added in wp-includes/wp-db.php , public function tables, line 1026-1076 the code
if ( isset( $tables['posts'] ) && defined( 'CUSTOM_POST_TABLE' ) )
$tables['posts'] = CUSTOM_POST_TABLE;
if ( isset( $tables['postmeta'] ) && defined( 'CUSTOM_POST_META_TABLE' ) )
$tables['postmeta'] = CUSTOM_POST_META_TABLE;
Now both websites share the same posts but the issue is that the next time wordpress will be updated, I will loose the changes from wp-includes/wp-db.php
So I tried to override the public function with another function inside the function.php file of second website Override arguments of public function in Wordpress but the website crashed and returns 500 error. Propably I am doing sth wrong.
The code I tried is
add_filter( 'tables', 'my_tables', 11, 2 );
public function my_tables( $scope = 'all', $prefix = true, $blog_id = 0 ) {
if ( isset( $tables['posts'] ) && defined( 'CUSTOM_POST_TABLE' ) )
$tables['posts'] = CUSTOM_POST_TABLE;
if ( isset( $tables['postmeta'] ) && defined( 'CUSTOM_POST_META_TABLE' ) )
$tables['postmeta'] = CUSTOM_POST_META_TABLE;
}
return $tables;
}
The original code inside wp-includes/wp-db.php is
public function tables( $scope = 'all', $prefix = true, $blog_id = 0 ) {
switch ( $scope ) {
case 'all' :
$tables = array_merge( $this->global_tables, $this->tables );
if ( is_multisite() )
$tables = array_merge( $tables, $this->ms_global_tables );
break;
case 'blog' :
$tables = $this->tables;
break;
case 'global' :
$tables = $this->global_tables;
if ( is_multisite() )
$tables = array_merge( $tables, $this->ms_global_tables );
break;
case 'ms_global' :
$tables = $this->ms_global_tables;
break;
case 'old' :
$tables = $this->old_tables;
break;
default :
return array();
}
if ( $prefix ) {
if ( ! $blog_id )
$blog_id = $this->blogid;
$blog_prefix = $this->get_blog_prefix( $blog_id );
$base_prefix = $this->base_prefix;
$global_tables = array_merge( $this->global_tables, $this->ms_global_tables );
foreach ( $tables as $k => $table ) {
if ( in_array( $table, $global_tables ) )
$tables[ $table ] = $base_prefix . $table;
else
$tables[ $table ] = $blog_prefix . $table;
unset( $tables[ $k ] );
}
if ( isset( $tables['users'] ) && defined( 'CUSTOM_USER_TABLE' ) )
$tables['users'] = CUSTOM_USER_TABLE;
if ( isset( $tables['usermeta'] ) && defined( 'CUSTOM_USER_META_TABLE' ) )
$tables['usermeta'] = CUSTOM_USER_META_TABLE;
}
return $tables;
}
How could override it so I won't loose my changes after the next update?

Related

Unable to select shipping method after filtering 'woocommerce_package_rates'

I just wrote this filter to disable non-free shipping methods when free shipping is available:
add_filter( 'woocommerce_package_rates', 'disable_paid_shipping', 9999, 2 );
function disable_paid_shipping( $rates, $package ) {
$free_rates = array();
foreach ( $rates as $i => $rate ) {
if ( str_contains( $rate->label, "gratuita" ) OR str_contains( $rate->label, "gratuito" ) ) {
$free_rates[] = $rate;
}
if ( str_contains( $rate->id, "local") ) {
$local = $rate;
}
if ( str_contains( $rate->id, "fermopoint") ) {
$fermopoint = $rate;
}
}
if ( !empty( $free_rates ) ) {
if ( isset($fermopoint) ) {
$fermopoint->cost = 0;
$fermopoint->label .= ' gratuito';
array_unshift( $free_rates, $fermopoint );
}
if ( isset($local) ) {
$free_rates[] = $local;
}
$rates = $free_rates;
}
return $rates;
}
The code works as expected, unless for two unexpected events occurring:
no shipping method is selected by default anymore (both in cart and checkout page)
when I choose one in the cart page, it gets unselected right after (only in cart page)
To solve the 1st problem at checkout, I can work around by forcing the selection through a hook on woocommerce_before_cart (although this looks like a forced trick).
For the 2nd problem I have no idea.
Suggestions?
The problem lies in that the WC $rates array is an associative array:
$rates = Array (
[rate_id_0] => [rate_obj_0]
[rate_id_1] => [rate_obj_1]
...
);
While the newly created $free_rates is an indexed array:
$free_rates = Array (
[0] => [rate_obj_0]
[1] => [rate_obj_1]
...
);
As result, WC is unable to match the new $free_rates array with the user's default rate_id, which is supposed to be used as the array key.
Here's the working code:
add_filter( 'woocommerce_package_rates', 'disable_paid_shipping', 9999, 2 );
function disable_paid_shipping( $rates, $package ) {
$free_rates = array();
foreach ( $rates as $i => $rate ) {
if ( str_contains( $rate->label, "gratuita" ) OR str_contains( $rate->label, "gratuito" ) ) {
$free_rates[$rate->id] = $rate;
}
if ( str_contains( $rate->id, "local") ) {
$local = $rate;
}
if ( str_contains( $rate->id, "fermopoint") ) {
$fermopoint = $rate;
}
}
if ( !empty( $free_rates ) ) {
if ( isset($fermopoint) ) {
$fermopoint->cost = 0;
$fermopoint->label .= ' gratuito';
$free_rates = array($fermopoint->id => $fermopoint) + $free_rates; // to set it as 1st
}
if ( isset($local) ) {
$free_rates[$local->id] = $local;
}
$rates = $free_rates;
}
return $rates;
}

Wordpress add_filter use variable

I'm using Awesome Support and I want to add a filter to manually assign the agent to answer the tickets.
This is the funcition:
function wpas_find_agent( $ticket_id = false ) {
if ( defined( 'WPAS_DISABLE_AUTO_ASSIGN' ) && true === WPAS_DISABLE_AUTO_ASSIGN ) {
return apply_filters( 'wpas_find_available_agent', wpas_get_option( 'assignee_default' ), $ticket_id );
}
$users = shuffle_assoc( wpas_get_users( apply_filters( 'wpas_find_agent_get_users_args', array( 'cap' => 'edit_ticket' ) ) ) );
$agent = array();
foreach ( $users->members as $user ) {
$wpas_agent = new WPAS_Member_Agent( $user );
/**
* Make sure the user really is an agent and that he can currently be assigned
*/
if ( true !== $wpas_agent->is_agent() || false === $wpas_agent->can_be_assigned() ) {
continue;
}
$count = $wpas_agent->open_tickets(); // Total number of open tickets for this agent
if ( empty( $agent ) ) {
$agent = array(
'tickets' => $count,
'user_id' => $user->ID,
);
} else {
if ( $count < $agent['tickets'] ) {
$agent = array(
'tickets' => $count,
'user_id' => $user->ID,
);
}
}
}
if ( is_array( $agent ) && isset( $agent['user_id'] ) ) {
$agent_id = $agent['user_id'];
} else {
$default_id = wpas_get_option( 'assignee_default', 1 );
if ( empty( $default_id ) ) {
$default_id = 1;
}
$agent_id = $default_id;
}
return apply_filters( 'wpas_find_available_agent', (int) $agent_id, $ticket_id );
}
And this is the filter I want to add:
add_filter('wpas_find_available_agent', 'asignar_agente', 10, 2);
function asignar_agente($agent_id){
$term_list = wp_get_post_terms( $ticket_id, 'department', array( 'fields' => 'ids' ) );
if($term_list[0] == 34){
$agent_id = 2;
}else{
$agent_id = 3;
}
return $agent_id;
}
How can I pass the $ticket_id variable to the filter to use it?
I need this variable because I need to know the term (department taxonomy) of the ticket is being submitted.
Thank you.
Since you pass $ticket_id when you call apply_filters('wpas_find_available_agent'....); you will be able to get the $ticket_id if you change your filter function to.
function asignar_agente($agent_id, $ticket_id){ <--- just add this parameter here
...
}
this is possible since you pass the parameter in apply_filters and you say add_filter('wpas_find_available_agent', 'asignar_agente', 10, 2); with emphasis on the last parameter with the value 2, that means your filter function will be able to receive 2 parameters.

WooCommerce Call to a member function get_type() on bool

After updating a plugin on my website, I am getting a fatal error Call to a member function get_type() on bool
/* WooCommerece settings */
if ( defined( 'WOOCOMMERCE_VERSION' ) && isset( $query_post_type ) && $query_post_type == 'product' ) {
if ( function_exists( 'wc_get_product' ) ) {
// WC 3.0+
$woo_product = wc_get_product( $post->ID );
$woo_is_variation = $woo_product->get_type() == 'variable' ? true : false;
} else {
// Old WC
$woo_product = get_product( $post->ID );
$woo_is_variation = isset( $woo_product->product_type ) && ( $woo_product->product_type == 'variation' || $woo_product->product_type == 'variable' ) ? true : false;
if ( $woo_is_variation ) {$post = $woo_product->post;}
}
}
I have tried modifying the code to
if( $product->is_type('variable') ) :
$woo_is_variation = true;
else :
$woo_is_variation = false;
endif;
I have reached out to the plugin author but so far I have had no response.
My product page is down and would appreciate some help with this.

PHPUnit testing coverage help for WordPress

Below function we need to cover,
function get_assets_list() {
static $assets;
if ( ! isset( $assets ) ) {
$assets = load_asset_file( BUILD_PATH . 'asset-manifest.json' );
if ( empty( $assets ) ) {
$assets = array();
}
}
return $assets;
}
But unfortunately we can't cover below lines
if ( ! isset( $assets ) ) {
$assets = load_asset_file( BUILD_PATH . 'asset-manifest.json' );
if ( empty( $assets ) ) {enter code here
$assets = array();
}
}
Because when we execute the this function always getting $assets this variable set. So how we can set this variable unset or undefined. So that we can cover those line.
I am executed below,
public function test_get_assets_list() {
static $assets = null;
// Replace this with some actual testing code.
$output = get_assets_list();
$this->assertArrayHasKey( 'block.js', $output );
}
but its not covered below lines
if ( ! isset( $assets ) ) {
$assets = load_asset_file( BUILD_PATH . 'asset-manifest.json' );
if ( empty( $assets ) ) {
$assets = array();
}
}

Double filters showing on web view on Woocommerce

I'm having a problem with my woocommerce theme, flatsome, but I think the problem is with the widget. The standard woocommerce product filter.
In the web view it shows normally, but on the mobile view the filter gets doubled;
a filter which gives you the standard mobile view-type of filter that pops on the side when clicked,
and another filter which gives an ugly dropdown.
This is the image on mobile view, the one on top has the right filter I want, the one under gives the ugly dropdown
Here's the code of the filter:
<?php
/*
Plugin Name: WooCommerce Product Filter
Plugin URI: http://www.mihajlovicnenad.com/product-filter
Description: Advanced product filter for any Wordpress template! - mihajlovicnenad.com
Author: Mihajlovic Nenad
Version: 6.3.0
Author URI: https://www.mihajlovicnenad.com
Text Domain: prdctfltr
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( !class_exists( 'PrdctfltrInit' ) ) :
final class PrdctfltrInit {
public static $version = '6.3.0';
protected static $_instance = null;
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
public function __construct() {
do_action( 'prdctfltr_loading' );
$this->includes();
$this->init_hooks();
do_action( 'prdctfltr_loaded' );
}
private function init_hooks() {
register_activation_hook( __FILE__, array( $this, 'activate' ) );
add_action( 'init', array( $this, 'check_version' ), 10 );
add_action( 'init', array( $this, 'init' ), 0 );
}
private function is_request( $type ) {
switch ( $type ) {
case 'admin' :
return is_admin();
case 'ajax' :
return defined( 'DOING_AJAX' );
case 'cron' :
return defined( 'DOING_CRON' );
case 'frontend' :
return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' );
}
}
public function includes() {
include_once( 'lib/pf-characteristics.php' );
include_once( 'lib/pf-widget.php' );
include_once( 'lib/pf-fixoptions.php' );
if ( $this->is_request( 'admin' ) ) {
add_action( 'vc_before_init', array( $this, 'composer' ) );
include_once ( 'lib/pf-settings.php' );
$purchase_code = get_option( 'wc_settings_prdctfltr_purchase_code', '' );
if ( $purchase_code ) {
require 'lib/update/plugin-update-checker.php';
$pf_check = PucFactory::buildUpdateChecker(
'http://mihajlovicnenad.com/envato/verify_json.php?k=' . $purchase_code,
__FILE__
);
}
}
if ( $this->is_request( 'frontend' ) ) {
$this->frontend_includes();
}
}
public function frontend_includes() {
include_once( 'lib/pf-frontend.php' );
include_once( 'lib/pf-shortcode.php' );
}
public function include_template_functions() {
}
public function init() {
do_action( 'before_prdctfltr_init' );
$this->load_plugin_textdomain();
do_action( 'after_prdctfltr_init' );
}
public function load_plugin_textdomain() {
$domain = 'prdctfltr';
$dir = untrailingslashit( WP_LANG_DIR );
$locale = apply_filters( 'plugin_locale', get_locale(), $domain );
if ( $loaded = load_textdomain( $domain, $dir . '/plugins/' . $domain . '-' . $locale . '.mo' ) ) {
return $loaded;
}
else {
load_plugin_textdomain( $domain, FALSE, basename( dirname( __FILE__ ) ) . '/lang/' );
}
}
public function setup_environment() {
}
public function plugin_url() {
return untrailingslashit( plugins_url( '/', __FILE__ ) );
}
public function template_path() {
return apply_filters( 'prdctfltr_template_path', '/templates/' );
}
public function plugin_path() {
return untrailingslashit( plugin_dir_path( __FILE__ ) );
}
public function plugin_basename() {
return untrailingslashit( plugin_basename( __FILE__ ) );
}
public function ajax_url() {
return admin_url( 'admin-ajax.php', 'relative' );
}
public function version() {
return self::$version;
}
public function composer() {
require_once( 'lib/pf-composer.php' );
}
function check_version() {
$version = get_option( 'wc_settings_prdctfltr_version', false );
if ( $version === false ) {
$check = get_option( 'wc_settings_prdctfltr_always_visible', false );
if ( $check === false ) {
update_option( 'wc_settings_prdctfltr_version', self::$version, 'yes' );
return '';
}
else {
$version = get_option( 'wc_settings_prdctfltr_version', '5.8.1' );
}
}
if ( version_compare( '5.8.2', $version, '>' ) ) {
add_action( 'admin_init', array( &$this, 'fix_database_582' ), 100 );
}
if ( version_compare( '6.0.6', $version, '>' ) ) {
add_action( 'init', array( &$this, 'fix_database_606' ), 100 );
}
}
function fix_database_606() {
global $wpdb;
$default = $wpdb->get_results( "SELECT `option_name`, `option_value` FROM `$wpdb->options` WHERE `option_name` LIKE CONVERT( _utf8 'wc_settings_prdctfltr_%'USING utf8mb4 ) COLLATE utf8mb4_unicode_ci LIMIT 99999" );
if ( !empty( $default ) ) {
$fix_default = array();
include_once( 'lib/pf-options-autoload.php' );
foreach( $default as $k => $v ) {
if ( in_array( $v->option_name, $forbidden_std ) ) {
$wpdb->query( "update $wpdb->options set autoload='yes' where option_name = '$v->option_name';" );
}
else if ( in_array( $v->option_name, $dont_autoload_std ) || substr( $v->option_name, 0, 41 ) == 'wc_settings_prdctfltr_term_customization_' || substr( $v->option_name, 0, 43 ) == 'wc_settings_prdctfltr_filter_customization_' ) {
$wpdb->query( "update $wpdb->options set autoload='no' where option_name = '$v->option_name';" );
}
else if ( in_array( $v->option_name, $autoload_std ) ) {
$wpdb->query( "update $wpdb->options set autoload='yes' where option_name = '$v->option_name';" );
}
else if ( strpos( $v->option_name, 'transient' ) ) {
delete_option( $v->option_name );
}
else {
$fix_default[$v->option_name] = get_option( $v->option_name );
$wpdb->query( "update $wpdb->options set autoload='no' where option_name = '$v->option_name';" );
}
}
if ( !empty( $fix_default ) ) {
$fix_default = json_encode( $fix_default );
update_option( 'prdctfltr_wc_default', $fix_default, 'no' );
}
$templates = get_option( 'prdctfltr_templates', array() );
if ( !empty( $templates ) && is_array( $templates ) ) {
update_option( 'prdctfltr_backup_templates', $templates, 'no' );
foreach( $templates as $k1 => $v1 ) {
if ( !empty( $v1 ) && substr( $v1, 0, 1 ) == '{' ) {
update_option( 'prdctfltr_wc_template_' . sanitize_title( $k1 ), $v1, 'no' );
$templates[$k1] = array();
}
}
}
update_option( 'prdctfltr_templates', $templates, 'no' );
}
update_option( 'wc_settings_prdctfltr_version', self::$version, 'yes' );
}
function fix_database_582() {
global $wpdb;
$wpdb->query( "update $wpdb->options set autoload='yes' where option_name like '%prdctfltr%';" );
$wpdb->query( "delete from $wpdb->options where option_name like '_transient_prdctfltr_%';" );
$wpdb->query( "delete from $wpdb->options where option_name like '_transient_%_prdctfltr_%';" );
$wpdb->query( "delete from $wpdb->options where option_name like 'wc_settings_prdctfltr_%_end';" );
$wpdb->query( "delete from $wpdb->options where option_name like 'wc_settings_prdctfltr_%_title' and option_value = '' ;" );
delete_option( 'wc_settings_prdctfltr_force_categories' );
delete_option( 'wc_settings_prdctfltr_force_emptyshop' );
delete_option( 'wc_settings_prdctfltr_force_search' );
delete_option( 'wc_settings_prdctfltr_caching' );
delete_option( 'wc_settings_prdctfltr_selected' );
delete_option( 'wc_settings_prdctfltr_attributes' );
update_option( 'wc_settings_prdctfltr_version', '6.0.5', 'yes' );
}
function activate() {
if ( false !== get_transient( 'prdctfltr_default' ) ) {
delete_transient( 'prdctfltr_default' );
}
$active_presets = get_option( 'prdctfltr_templates', array() );
if ( !empty( $active_presets ) && is_array( $active_presets ) ) {
foreach( $active_presets as $k => $v ) {
if ( false !== ( $transient = get_transient( 'prdctfltr_' . $k ) ) ) {
delete_transient( 'prdctfltr_' . $k );
}
}
}
}
}
function Prdctfltr() {
return PrdctfltrInit::instance();
}
PrdctfltrInit::instance();
endif;
?>
Simple CSS should be able to fix this. Use media queries to hide the filter with the ugly dropdown on small screens.
Something like:
#media (max-width: 768px) {
.filter-dropdown{
display: none;
}
}
Substitute filter-dropdown with the class name of that filter. Substitute 768px with whichever number of pixels is right for your situation.
Without you pasting code we can't be more specific than that.

Resources