trigger function in custom class on WooCommerce action - php

I am using the following class to have a directory created with dynamic value - based on a woo custom checkout field. Works perfect on page refresh and directory is created like expected.
just need this to only trigger/instantiate on the WooCommerce actions
woocommerce_order_status_completed
or
woocommerce_order_status_changed
or
woocommerce_thankyou_page
how can this be done so that it does not always run every time a page is loaded to decrease the load and have better efficiency in general.
here is the complete class
//add_action( 'plugins_loaded', array( 'pos__URL', 'init' )); //uncomment to trigger on page refresh
class pos__URL {
public static function init() {
$POS__sys_URL = __CLASS__;
new $POS__sys_URL;
}
public function __construct()
{
add_action('init', array($this, 'pos__URL_Field'));
}
public function pos__URL_Field()
{
//--------to access the value----start-----
$orders = wc_get_orders(array(
'customer_id' => get_current_user_id(),
'return' => 'ids',
));
//add the id of the custom meta field that lies in the order
$meta_data = array();
foreach ($orders as $order_id) {
$meta_data[$order_id] = get_post_meta($order_id, '_engx_text_field_id', true);
}
//--------to access the value----end-----
if( isset($meta_data[$order_id]) ) { //is the field set
$curdir = getcwd(); //delcare variables
if (!file_exists($meta_data[$order_id])) {
if( mkdir( $curdir . "/" . $meta_data[$order_id], 0777) ) {
//below section for for testing purposes to see if the command ran - and yes shows correctly and creates directory as expected IF the POS url is set - (triggers at the moment on page refresh)
echo "directory created"; //comment out when done testing
}else{
echo "directory NOT created"; //comment out when done testing
}
}
}else{
if( empty($meta_data[$order_id]) ) {
//do nothing
}
}
}
} //end function
I have tried the following to set the action on the inside of class but I am not doing it right and it didn't work
class pos__URL
{
public function init()
{
add_action( 'woocommerce_order_status_changed', array('pos__URL') );
}
public function __construct()
{
add_action('init', array($this, 'pos__URL_Field'));
}
public function pos__URL_Field()
{
//--------to access the value----start-----
$orders = wc_get_orders(array(
'customer_id' => get_current_user_id(),
'return' => 'ids',
));
//add the id of the custom meta field that lies in the order
$meta_data = array();
foreach ($orders as $order_id) {
$meta_data[$order_id] = get_post_meta($order_id, '_engx_text_field_id', true);
}
//--------to access the value----end-----
if( isset($meta_data[$order_id]) ) { //is the field set
$curdir = getcwd(); //delcare variables
if (!file_exists($meta_data[$order_id])) {
if( mkdir( $curdir . "/" . $meta_data[$order_id], 0777) ) {
//below section for for testing purposes to see if the command ran - and yes shows correctly and creates directory as expected IF the POS url is set - triggers at momment on page refresh
echo "directory created"; //comment out when done testing
}else{
echo "directory NOT created"; //comment out when done testing
}
}
}else{
if( empty($meta_data[$order_id]) ) {
//do nothing
}
}
}
}

You should follow the same pattern you use for the plugins_loaded but this time replace it with whatever action you want to trigger the callback for. eg:
add_action( 'woocommerce_order_status_completed', array( 'pos__URL', 'init' ));
add_action( 'woocommerce_order_status_changed', array( 'pos__URL', 'init' ));
add_action( 'woocommerce_thankyou_page', array( 'pos__URL', 'init' ));
The init function of the pos_URL class will trigger when any of the above actions occur.

Related

Get Order Ids in a WooCommerce Plugin

Trying to update order post meta in testmain(), I can update it when I manually assign a order id, but struggling to figure out how to get order ids, where am I going wrong?
<?php
/**
* Plugin Name: MyTestPlugin
*/
defined('ABSPATH') or die('Bye');
if (in_array( 'woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))){
if (! wp_next_scheduled('my_test_cron')){
wp_schedule_event(time(), 'hourly', 'my_test_cron');
}
if (! class_exists('MyTest')) :
class MyTest {
public function __construct(){
add_filter('manage_edit-shop_order_columns', array($this, 'my_manage_edit_shop_order_columns'));
add_action('manage_posts_custom_column', array($this, 'my_manage_posts_custom_column'));
add_action('my_test_cron', array($this, 'testmain'));
$this->pluginPath = dirname(__FILE__);
}
public function testmain(){
// $the_id = '9001'; // <-- ORDER ID
$the_data = 'Sample Data';
update_post_meta(get_the_ID(), '_my_test', $the_data);
}
public function my_manage_edit_shop_order_columns($col_th){
return wp_parse_args(array('_my_test' => 'My Test'), $col_th);
}
public function my_manage_posts_custom_column($column_id){
if($column_id == '_my_test')
echo get_post_meta(get_the_ID(), '_my_test', true);
}
}
$MyTest = new MyTest();
endif;
}
I was going the wrong way about trying to update the meta data.
Solved.
public function testmain(){
$args = array(
'limit' => -1,
);
$orders = wc_get_orders( $args );
foreach ($orders as $order){
$order->update_meta_data('_my_test', 'Sample Data');
$order->save();
}
}

Checking user role on a hooked function breaking website in WooCommerce

I am trying to add a tab to the My Account page if a specific user exists.
I created a check_user_role function that checks if a specific role exists.
If the premium_member role exists an extra tab should be added to the My Account page.
Right now when I add the check_user_role function it breaks my website.
Everything is in the functions.php file
function check_user_role($roles, $user_id = null) {
if ($user_id) $user = get_userdata($user_id);
else $user = wp_get_current_user();
if (empty($user)) return false;
foreach ($user->roles as $role) {
if (in_array($role, $roles)) {
return true;
}
}
return false;
}
// ------------------
// 1. Register new endpoint (URL) for My Account page
// Note: Re-save Permalinks or it will give 404 error
function vehicle_intake_form_endpoint() {
add_rewrite_endpoint( 'vehicle-intake-form', EP_ROOT | EP_PAGES );
}
add_action( 'init', 'vehicle_intake_form_endpoint' );
// ------------------
// 2. Add new query var
function vehicle_intake_form_query_vars( $vars ) {
$vars[] = 'vehicle-intake-form';
return $vars;
}
add_filter( 'query_vars', 'vehicle_intake_form_query_vars', 0 );
// ------------------
// 3. Insert the new endpoint into the My Account menu
if(check_user_role(array('premium_member'))) {
function vehicle_intake_form_link_my_account( $items ) {
$items['vehicle-intake-form'] = 'Vehicle Intake Form';
return $items;
}
add_filter( 'woocommerce_account_menu_items', 'vehicle_intake_form_link_my_account' );
}
// ------------------
// 4. Add content to the new tab
function vehicle_intake_form_content() {
echo '<h3>Premium WooCommerce Support</h3><p>Welcome to the WooCommerce support area. As a premium customer, you can submit a ticket should you have any WooCommerce issues with your website, snippets or customization. <i>Please contact your theme/plugin developer for theme/plugin-related support.</i></p>';
//echo do_shortcode( ' /* your shortcode here */ ' );
}
add_action( 'woocommerce_account_vehicle-intake-form_endpoint', 'vehicle_intake_form_content' );
Your If statement needs to be inside the function, never outside it.
You can use current_user_can() function, but inside your hooked function like:
add_filter( 'woocommerce_account_menu_items', 'vehicle_intake_form_link_my_account' );
function vehicle_intake_form_link_my_account( $items ) {
if( current_user_can('premium_member') ) {
$items['vehicle-intake-form'] = __('Vehicle Intake Form');
}
return $items;
}
Or use check_user_role() revisited function to be used inside your hooked function like:
function check_user_role( $roles, $user_id = null ) {
$user = $user_id ? new WP_User( $user_id ) : wp_get_current_user();
if ( is_a($user, 'WP_User') && count( array_intersect($roles, $user->roles) ) > 0 ) {
return true;
}
return false;
}
add_filter( 'woocommerce_account_menu_items', 'vehicle_intake_form_link_my_account' );
function vehicle_intake_form_link_my_account( $items ) {
if( check_user_role( array('premium_member') ) ) {
$items['vehicle-intake-form'] = __('Vehicle Intake Form');
}
return $items;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

WordPress AJAX is_admin is true, causing issues.

i'm trying to make a plugin for WordPress, which is has got an admin section for some basic settings, and also registers some shortcode to display some HTML, which is basically a form.
Here is my main plugin file, plugins/my-plugin/my-plugin.php:
/**
* Plugin Name: Pathway
* Plugin URI: http://www.martynleeball.com/
* Description: Pathway integration.
* Version: 1.0
* Author: Martyn Lee Ball
* Author URI: https://www.martynleeball.com/
**/
define('PATHWAY_VERSION', '0.0.8');
define('PATHWAY_AUTHOR', 'Martyn Lee Ball');
define('PATHWAY__MINIMUM_WP_VERSION', '4.*');
define('PATHWAY_CONTACT', 'martynleeball#gmail.com');
add_action(
'plugins_loaded',
array ( Pathway::get_instance(), 'plugin_setup' )
);
class Pathway
{
protected static $instance = NULL;
public $plugin_url = '';
private $cpt = 'post'; # Adjust the CPT
public function __construct() {}
public static function get_instance()
{
NULL === self::$instance and self::$instance = new self;
return self::$instance;
}
public function plugin_setup()
{
$this->plugin_url = '';
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ) );
// if (is_admin()) {
//
// require_once( $this->plugin_url . 'admin/index.php' );
//
// register_activation_hook( __FILE__, 'install' );
//
// return;
// }
add_shortcode( 'pathway', array($this, 'shortcode'));
add_action( 'wp_ajax_ajax_login', array( $this, 'ajax_login' ) );
add_action( 'wp_ajax_nopriv_ajax_login', array( $this, 'ajax_login' ) );
add_action( 'wp_ajax_ajax_register', array( $this, 'ajax_register' ) );
add_action( 'wp_ajax_nopriv_ajax_register', array( $this, 'ajax_register' ) );
}
public function enqueue()
{
wp_enqueue_script( 'vuejs', 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js' );
wp_enqueue_script(
'ajax-handle-form',
"{$this->plugin_url}/wp-content/plugins/pathway/frontend/js/scripts.js"
);
wp_localize_script(
'ajax-handle-form',
'wp_ajax',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'ajaxnonce' => wp_create_nonce( 'ajax_post_validation' )
)
);
}
public function ajax_login()
{
echo 'login';exit;
}
public function ajax_register()
{
echo 'register';exit;
}
public function shortcode()
{
if (!isset($_SESSION['pathway_login'])) {
self::view('forms/login');
}
}
public static function view( $name, array $args = array() ) {
foreach ( $args AS $key => $val ) {
$$key = $val;
}
// $file = $this->plugin_url . 'views/'. $name . '.php';
$file = 'views/'. $name . '.php';
include( $file );
}
}
Please correct me if i'm going wrong somewhere, there's so many mixed guides online showing different ways. Within this file i'm basically:
Adding my scripts and assigning the PHP values.
I would be then starting the admin section however has to comment this out for the AJAX call, this is my issue.
Registering my shortcode.
Adding the actions for the AJAX form submit.
Obviously my issue is that when I hit the is_admin from the AJAX call it is returning true, when it should be false as an public visitor can submit this form. The wp_ajax_nopriv action doesn't appear to work which would solve the issue, this is probably due to me being logged into WordPress.
I have tried logging out of WordPress but the is_admin still returns true!
Can someone advise?
is_admin will return true on all ajax calls.
It is not actually a useful function to check the user as it checks the uri rather than the user details, i.e. if on a admin page = true, if not false.
Now I was a little confused about your question here, it appears you want the is_admin to return false if its actually an ajax call?
if ( is_admin() && ! wp_doing_ajax() ) {}
It will return false on ajax calls.
If you are checking there is an "admin" logged in, as in can edit posts, see the other capabilities here
if ( current_user_can( 'edit_post' ) ) {}
The no_priv hook will not work when logged in, its not called.

How to get the payment response url in woocommerce?

I have integrated pay4later api in my wordpress. I need to show the payment response details after payment success.
My Plugin file:
class WC_Pay4later extends WC_Payment_Gateway{
add_action('woocommerce_api_' . strtolower( get_class( $this ) ), array($this, 'check_response' ) );
function check_response()
{
/* Update Process*/
}
}
I set My return response url is:
www.mysite/pay4later/?wc-api=WC_Payment_GatewayPay4later_check_response.
When I call this it just displays 1.
How can I Fix this?
Here is the skeleton structure of the Pay4later payment gateway for woocommerce.
if ( ! defined( 'ABSPATH' ) ) { exit; }
add_action( 'plugins_loaded', 'wc_pay4later_init', 0 );
function wc_pay4later_init() {
class WCPay4later extends WC_Payment_Gateway{
public function __construct() {
// Put your initialization scripts here
// Which would be initializing merchan account info, secret keys, from this plugin's settings screen
/* This would be your gateway return url */
$this->callback = str_replace( 'https:', 'http:', home_url( '/wc-api/WCPay4later' ) );
/* This action will redirect the gateway response to your 'check_pay_4_later_response' function */
add_action( 'woocommerce_api_wcpay4later', array( $this, 'check_pay_4_later_response' ) );
/* This is the action where you prepare your digital form and submit to the gateway server */
add_action('woocommerce_receipt_wcpay4later', array( $this, 'receipt_page') );
}
function receipt_page( $order ) {
echo '<p>'.__('Thank you for your order, please click the button below to pay with Pay 4 Later Gateway Service.', 'sark').'</p>';
// prepare your digital form
echo $this -> generate_digital_form( $order );
}
function generate_digital_form( $order ) {
// prepare and redirect to gateway server
}
function check_pay_4_later_response() {
/* Update Process*/
}
}
function woocommerce_add_pay_4_later_gateway( $methods ) {
$methods[] = 'WCPay4later';
return $methods;
}
add_filter('woocommerce_payment_gateways', 'woocommerce_add_pay_4_later_gateway' );
}

WORDPRESS add_filter('cron_schedules', ...) not working in a PHP class

I tried to declare a new time interval for a WP_CRON.
When I do it in a PHP file it works.
When I do it in a PHP Class it doesn't.
Can someone see what I'm doing wrong ?
I'm using the plugin cron view to check if the declaration is working or not.
If I solve this problem I think it will also solve my problem to know why my cron job is not triggered in the class but works properly when not in a class.
=> File myplugin.php
function set_up_option_page() {
add_options_page( [...]);
}
add_action( 'admin_menu', 'set_up_option_page' );
function do_some_rock() {
$instance = My_Plugin_Class::instance();
if ( isset($_POST['action']) && 'do-magic' == $_POST['action'] ) {
$instance->do_stuff();
}else{
// Display the form.
<?
}
}
=> File My_Plugin_Class.php
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
class My_Plugin_Class {
private static $_instance = null;
public function __construct () {
[...]
add_filter( 'cron_schedules', array($this,'cron_time_intervals'));
}
public function cron_time_intervals( $schedules ) {
echo "——— cron time intervals —— ";
$schedules['minutes_1'] = array(
'interval' => 10*60,
'display' => 'Once 10 minutes'
);
return $schedules;
}
public static function instance () {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
} // End instance ()
Best regards.
I am almost sure that do_some_rock() is not called every time - only when someone goes to that page. You can move add_filter( 'cron_schedules', array($this,'cron_time_intervals')); from your class constructor to main plugin file myplugin.php and do more or less something like this
add_action( 'admin_menu', 'set_up_option_page' );
$instance = My_Plugin_Class::instance();
add_filter( 'cron_schedules', array($instance ,'cron_time_intervals'));
One extra question. Does My_Plugin_Class constructor contain any code you would like to prevent being executed during each request?
I think the proper way to do this, is to have a specific class for my Cron.
This class is instanciated on each request this is why the code shouldn't be in a class with a static instance as I did before.
Also I think it's better to have the Cron outside the plugin class for logic and cleaner code purpose. Thanks to Lukas Pawlik for the help.
if (!defined('ABSPATH')) exit;
new My_Cron();
class My_Cron {
public function __construct() {
add_filter('cron_schedules', array($this, 'cron_time_intervals'));
add_action( 'wp', array($this, 'cron_scheduler'));
add_action( 'cast_my_spell', array( $this, 'auto_spell_cast' ) );
}
public function cron_time_intervals($schedules)
{
$schedules['minutes_10'] = array(
'interval' => 10 * 60,
'display' => 'Once 10 minutes'
);
return $schedules;
}
function cron_scheduler() {
if ( ! wp_next_scheduled( 'cast_my_spell' ) ) {
wp_schedule_event( time(), 'minutes_10', 'cast_my_spell');
}
}
function auto_spell_cast(){
My_Plugin_Class::instance()->launch_spell();
}
}
I am not Sure But Try this.
add_filter( 'cron_schedules', array($this,'cron_time_intervals'),1);
And Check cron_time_intervals() Function is Call or Not.

Categories