Is there a way to get widget $instance variable values in custom_widget_init function?
public function __construct() {
....
add_action( 'wp_head', array( __CLASS__, 'custom_widget_init' ) );
}
function custom_widget_init() {
}
Related
I have created 2 basic shipping methods in 2 different plugins, each plugin are below, one is Royal Mail the other is Courier. They both show up in the drop down in the shipping zone:
I can then add say Royal Mail to the zone, but if i now come to add Courier as well, Royal Mail disappears and vice versa, it's only letting me add one of my custom methods at a time and i'm stumped as to why.
The next problem is, when i delete one of my custom methods and hit save, i'm getting this fatal error and it doesn't remove, as far as i can see both of these classes are done correctly to the point they are at:
[14-Dec-2021 13:54:59 UTC] PHP Fatal error: Uncaught Error: Call to a
member function get_instance_option_key() on bool in
/Volumes/Work/project/public_html/wp-content/plugins/woocommerce/includes/class-wc-ajax.php:2923
add_action( 'woocommerce_shipping_init', function() : void {
/**
* Class Utterly_Courier_Shipping_Method
*/
class Utterly_Courier_Shipping_Method extends WC_Shipping_Method
{
/**
* Utterly_Royal_Mail_Shipping_Method constructor.
*/
public function __construct()
{
$this->id = 'utterly_courier';
$this->method_title = 'Courier delivery (Tracked & Signed)';
$this->method_description = 'Shipping via Courier';
$this->supports = [
'shipping-zones'
];
$this->init();
$this->enabled = 'yes';
$this->title = 'Courier delivery (Tracked & Signed)';
}
/**
*
*/
public function init() : void
{
$this->init_form_fields();
$this->init_settings();
// Save settings in admin if you have any defined
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
*
*/
public function init_form_fields() : void
{
parent::init_form_fields();
}
/**
* #param array $package
*/
public function calculate_shipping($package = [])
{
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => 10
);
$this->add_rate( $rate );
}
}
});
add_filter( 'woocommerce_shipping_methods', function( array $methods ) : array {
$methods['utterly_courier'] = 'Utterly_Courier_Shipping_Method';
return $methods;
});
add_action( 'woocommerce_shipping_init', function() : void {
/**
* Class Utterly_Royal_Mail_Shipping_Method
*/
class Utterly_Royal_Mail_Shipping_Method extends WC_Shipping_Method
{
/**
* Utterly_Royal_Mail_Shipping_Method constructor.
*/
public function __construct()
{
$this->id = 'utterly_royal_mail';
$this->method_title = 'Royal Mail 1st Class (Tracked)';
$this->method_description = 'Shipping via Royal Mail';
$this->supports = [
'shipping-zones'
];
$this->init();
$this->enabled = 'yes';
$this->title = 'Royal Mail 1st Class (Tracked)';
}
/**
*
*/
public function init() : void
{
$this->init_form_fields();
$this->init_settings();
// Save settings in admin if you have any defined
add_action( 'woocommerce_update_options_shipping_' . $this->id, [ $this, 'process_admin_options' ] );
}
/**
*
*/
public function init_form_fields() : void
{
parent::init_form_fields();
}
/**
* #param array $package
*/
public function calculate_shipping($package = [])
{
$rate = array(
'id' => $this->id,
'label' => $this->title,
'cost' => 10
);
$this->add_rate( $rate );
}
}
});
add_filter( 'woocommerce_shipping_methods', function( array $methods ) : array {
$methods['utterly_royal_mail'] = 'Utterly_Royal_Mail_Shipping_Method';
return $methods;
});
I am learning about wordpress code and have read a lot of posts about add_action, but haven't found one yet that fits my situation. I want to make use of a hook that exists in another WP plugin. In rough outline, it looks like this:
// This part is not my code
class CDH {
function do_stuff() {
// important stuff
do_action( 'hook_i_want_to_use', $parameter );
// more stuff
}
global $cdh;
$cdh = new CDH();
}
// My first attempt code:
add_action( 'hook_i_want_to_use', 'my_function', 10, 1 );
function my_function( $parameter ) {
echo $parameter;
}
// My second attempt code:
class my_CDH extends CDH {
public function __construct() {
add_action( 'hook_i_want_to_use', array( $this, 'my_function' ), 10, 1 );
}
function my_function( $parameter ) {
echo $parameter;
}
}
In both attempts, my_function() is never called. How do I hook on to the do_action in the instance $cdh?
I want to perform unit tests on a Class, my goal is: I want to check if the plugin is activated or not by using the function: is_plugin_active
class WC_Custom_Variable_Products_Dependencies {
public function __construct() {
add_action( 'admin_init', [$this, 'check_environment']);
}
public function check_environment(){
return is_plugin_active(
'woocommerce-custom-variable-products/woocommerce-custom-variable-products.php'
);
}
}
CLass de test :
require_once 'class-wc-custom-variable-products-dependencies.php';
class WC_Custom_Variable_Products_DependenciesTest extends WP_UnitTestCase {
public function setUp() {
parent::setUp();
$this->class_instance = new WC_Custom_Variable_Products_Dependencies();
}
public function test_check_environment(){
$result = $this->class_instance->check_environment();
$this->assertTrue($result);
}
The assertion return always False .
My plugin is activated, and the function is_plugin_active returns True if I execute it from the browser:
add_action('admin_init', function(){
var_dump(is_plugin_active(
'woocommerce-custom-variable-products/woocommerce-custom-variable-products.php'
));
});
I think the admin_init hook is not executed in the test. is it true or not?
I found out why. here is the solution: you have to activate the plugin in the tests / bootstrap.php file:
$GLOBALS[ 'wp_tests_options' ] = array(
'active_plugins' => array(
'YOUR-PLUGIN/YOUR-PLUGIN.php'
)
)
On the Wordpress Codex page for 'register widget' there is basic example code given for registering a widget via your plugin:-
class MyNewWidget extends WP_Widget {
function __construct() {
// Instantiate the parent object
parent::__construct( false, 'My New Widget Title' );
}
function widget( $args, $instance ) {
// Widget output
}
function update( $new_instance, $old_instance ) {
// Save widget options
}
function form( $instance ) {
// Output admin widget options form
}
}
function myplugin_register_widgets() {
register_widget( 'MyNewWidget' );
}
add_action( 'widgets_init', 'myplugin_register_widgets' );
In this code, as you can see the three functions I mentioned are provided. I want to know if I can change their names or are they pre-created Wordpress functions?
You can name your members in MyNewWidget whatever you like, but the point of extending WP_Widget is that WP_Widget's methods are all available to MyNewWidget but you can override them by writing a method of the same name. This may help explain.
I'm trying to check if WooCommerce is active or not, I created a property with with a default value of false, then I created a method to check if WooCommerce is active using is_plugin_active() and admin_init hook, if active the value of the property must be updated to true: here is the code:
class MyClass{
public $woo_active = false;
public function __construct(){
add_action( 'admin_init', array( $this, 'check_if_woo_active' ) );
}
// check if WooCommerce is active
public function check_if_woo_active(){
if( is_plugin_active( 'woocommerce/woocommerce.php' ) ){
$this->woo_active = true;
}
}
// is_woo_active()
public function is_woo_active(){
return $this->woo_active;
}
}
$var = new MyClass();
var_dump( $var->is_woo_active() );
the issue is that var_dump returns false even if WooCommerce is active, BUT, if I use var_dump inside the function check_if_woo_active(), it returns true.
Why the property value is not updated? thanks
Updated:
The Second Solution as #helgatheviking sugested works fine, also this works very well and short
class MyClass{
// check if WooCommerce is active
public function is_woo_active(){
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
if( is_plugin_active( 'woocommerce/woocommerce.php' ) ){
return true;
}else{
return false;
}
}
}
$var = new MyClass();
var_dump( $var->is_woo_active() );
If I had to guess, then $var = new MyClass(); is run before admin_init so the check_if_woo_active() isn't run.
Couple things you could do. First, I will usually launch my plugin on the woocommerce_loaded hook. That way I am 100% sure WooCommerce is running.
class MyClass{
protected static $instance = null;
/**
* Main MyClass Instance
*
* Ensures only one instance of MyClass is loaded or can be loaded.
*
* #static
* #see MyClass()
* #return MyClass - Main instance
* #since 0.1.0
*/
public static function instance() {
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof MyClass ) ) {
self::$instance = new MyClass();
}
return self::$instance;
}
public function __construct(){
// Do what you want, WC is definitely active
}
}
/**
* Returns the main instance of class.
*
* #return MyClass
*/
function MyClass() {
return MyClass::instance();
}
// Launch the class if WooCommerce is loaded:
add_action( 'woocommerce_loaded', 'MyClass' );
You could also mimic what WooCommerce does with their premium plugins and check the option that stores the active plugins:
class MyClass{
private static $active_plugins;
public static function get_active_plugins() {
self::$active_plugins = (array) get_option( 'active_plugins', array() );
if ( is_multisite() ){
self::$active_plugins = array_merge( self::$active_plugins, get_site_option( 'active_sitewide_plugins', array() ) );
}
}
// check if WooCommerce is active
public static function check_if_woo_active() {
if ( ! self::$active_plugins ) self::get_active_plugins();
return in_array( 'woocommerce/woocommerce.php', self::$active_plugins ) || array_key_exists( 'woocommerce/woocommerce.php', self::$active_plugins );
}
}
var_dump( MyClass::check_if_woo_active() );