Singleton pattern in PHP seems to not work - php
My singleton pattern instance seems to lose its instance and becomes null between each request.
Whenever I call validate_api_endpoint_field when the settings are saved, my breakpoint is hit inside in the MyPlugin_Request_Manager::instance() and its value is null.
any tips?
MyPlugin_Settings.php
<?php
defined('ABSPATH') || exit;
if (!class_exists('MyPlugin_Settings')) {
class MyPlugin_Settings
{
const page = "myPlugin-settings";
const option_group_name = 'myPlugin_option_group';
const domain = "myPlugin";
protected static $_instance = null;
public function __construct()
{
self::load_dependencies();
}
public function load_dependencies()
{
require_once PAYDAY_PATH . 'classes/class-myPlugin-repository.php';
require_once PAYDAY_PATH . 'classes/class-myPlugin-request-manager.php';
}
public static function instance()
{
if (is_null(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
public function admin_menu()
{
// Add a separator before the menu item.
// Bug: Makes the WooCommerce Product menu disappear
// slef::add_admin_menu_separator( 26 );
add_menu_page(
'MyPlugin',
'MyPlugin',
'manage_options',
'myPlugin-settings',
null,
'dashicons-building',
27
);
add_submenu_page('myPlugin', 'MyPlugin Settings', 'Settings', 'manage_options', self::page, array($this, 'render_plugin_settings'));
// TODO: Uncomment when Dashboard will be implemented
// add_submenu_page( 'myPlugin', 'Dashboard', 'Dashboard', 'manage_options', 'myPlugin', array(
// $this,
// 'display_page'
// ) );
}
function add_admin_menu_separator($position)
{
global $menu;
$index = 0;
foreach ($menu as $offset => $section) {
if (substr($section[2], 0, 9) == 'separator') {
$index++;
}
if ($offset >= $position) {
$menu[$position] = array('', 'read', "separator{$index}", '', 'wp-menu-separator');
break;
}
}
ksort($menu);
}
public function admin_init()
{
self::register_api_settings();
self::register_payment_methods_mapping();
self::register_payment_methods_create_invoice_on_order_status_mapping();
self::register_additional_invoice_settings_section();
}
public function admin_footer_text()
{
$current_screen = get_current_screen();
$base = $current_screen->parent_base;
if (substr($base, 0, 6) === "myPlugin") {
echo '<span id="footer-thankyou">' . esc_html__('Developed by MyPlugin ehf.', 'myPlugin') . '</span>';
}
}
public function register_api_settings()
{
$settings_section_id = 'myPlugin_api_section';
add_settings_section(
$settings_section_id,
esc_html__('API Settings', 'myPlugin'),
function () {
echo '<p>' . esc_html__('Access your ClientId and ClientSecret on MyPlugin.is underneath Settings -> Company Settings -> API', 'myPlugin') . '</p>';
},
self::page
);
// ClientId
$client_id_settings_field_id = "myPlugin_client_id";
add_settings_field(
$client_id_settings_field_id,
esc_html__('ClientID', 'myPlugin'),
array($this, 'display_field'),
self::page,
$settings_section_id,
array(
'type' => 'text', // Type of input field
'id' => $client_id_settings_field_id,
'class' => 'input-lg',
'name' => 'myPlugin_client_id',
'value' => get_option($client_id_settings_field_id, '') // The current value of the field, or set default value
)
);
register_setting(self::option_group_name, $client_id_settings_field_id, array($this, 'validate_clientId_field'));
// ClientSecret
$client_secret_settings_field_id = "myPlugin_client_secret";
add_settings_field(
$client_secret_settings_field_id,
esc_html__('ClientSecret', 'myPlugin'),
array($this, 'display_field'),
self::page,
$settings_section_id,
array(
'type' => 'password', // Type of input field
'id' => $client_secret_settings_field_id,
'class' => 'input-lg',
'name' => 'myPlugin_client_secret',
'value' => get_option($client_secret_settings_field_id, '') // The current value of the field, or set default value
)
);
register_setting(self::option_group_name, $client_secret_settings_field_id, array($this, 'validate_clientSecret_field'));
// API Endpoint
$api_endpoint_field_id = 'myPlugin_api_endpoint';
add_settings_field(
$api_endpoint_field_id,
esc_html__('API Endpoint', 'myPlugin'),
array($this, 'display_select_field'),
self::page,
$settings_section_id,
array(
'name' => 'myPlugin_api_endpoint',
'options' => [
esc_html__("Production", 'myPlugin') => "https://api.myPlugin.is",
esc_html__("Test", 'myPlugin') => "https://api.test.myPlugin.is",
esc_html__("Localhost", 'myPlugin') => "http://localhost:57283"
]
)
);
register_setting(self::option_group_name, $api_endpoint_field_id, array($this, 'validate_api_endpoint_field'));
}
public function register_payment_methods_mapping()
{
$settings_section_id = 'myPlugin_payment_methods_mapping_section';
add_settings_section(
$settings_section_id, // ID used to identify this section and with which to register options
// Title to be displayed on the administration page
__("Payment Methods - Mapping", 'myPlugin'),
// Callback used to render the description of the section
function () {
// TODO: Update if needed for redirecting for creating a new Payment Type within MyPlugin
echo '<p>' . __('Make sure the WooCommerce payment methods corresponds to the correct MyPlugin payment type.', 'myPlugin') . '</p>';
echo '<p>' . __('You might need to create a new payment type in MyPlugin first.', 'myPlugin') . '</p>';
},
// The page where to display the section
self::page
);
//$woocommerce_payment_methods = WC_Payment_Gateways::instance()->get_available_payment_gateways();
$woocommerce_payment_methods = WC_Payment_Gateways::instance()->payment_gateways();
$myPlugin_payment_types = MyPlugin_Repository::instance()->get_payment_types();
if (!isset($myPlugin_payment_types)) {
$myPlugin_payment_types = MyPlugin_Request_Manager::instance()->get_sales_payment_types();
MyPlugin_Repository::instance()->set_payment_types($myPlugin_payment_types);
}
$payment_type_select_options = array();
$payment_type_select_options[__('None', 'myPlugin')] = 'None';
if (isset($myPlugin_payment_types)) {
foreach ($myPlugin_payment_types as &$payment_type) {
// key => value
if (isset($payment_type) and gettype($payment_type) === "object") {
$payment_type = get_object_vars($payment_type);
$payment_type_select_options[$payment_type['title']] = $payment_type['id'];
}
if (isset($payment_type) and gettype($payment_type) === "array") {
$payment_type_select_options[$payment_type['title']] = $payment_type['id'];
}
}
}
foreach ($woocommerce_payment_methods as $payment_method) {
if ($payment_method->enabled == 'no') {
continue;
}
$id = $payment_method->id;
$title = $payment_method->get_method_title();
if ($title == "") {
try {
$title = $payment_method->title;
} catch (Exception $e) {
$title = "";
}
}
$field_id = 'myPlugin_payment_method_' . $id;
add_settings_field(
$field_id,
esc_html__($title, 'myPlugin'),
array($this, 'display_select_field'),
self::page,
$settings_section_id,
array(
'name' => esc_html__($field_id, 'myPlugin'),
'options' => $payment_type_select_options
)
);
register_setting(self::option_group_name, $field_id);
}
}
public function register_payment_methods_create_invoice_on_order_status_mapping()
{
$settings_section_id = 'myPlugin_create_invoice_on_order_status_section';
add_settings_section(
$settings_section_id,
'Payment Methods - Action: Create an invoice and mark it as paid',
function () {
echo '<p>' . esc_html__('Please select the corresponding WooCommerce Order Status to execute the following action:', 'myPlugin') . '</p>';
echo '<p>' . esc_html__('Create a new invoice in MyPlugin and mark it as paid.', 'myPlugin') . '</p>';
},
self::page
);
$woocommerce_payment_methods = WC_Payment_Gateways::instance()->payment_gateways();
foreach ($woocommerce_payment_methods as $payment_method) {
if ($payment_method->enabled == 'no') {
continue;
}
$id = $payment_method->id;
$title = $payment_method->get_method_title();
if ($title == "") {
try {
$title = $payment_method->title;
} catch (Exception $e) {
$title = "";
}
}
$field_id = 'myPlugin_payment_method_' . $id . '_create_invoice_on_action';
$order_statuses = wc_get_order_statuses();
add_settings_field(
$field_id,
esc_html__($title, 'myPlugin'),
array($this, 'display_select_field'),
self::page,
$settings_section_id,
array(
'name' => $field_id,
'options' => [
__("None", 'myPlugin') => "None",
__($order_statuses["wc-processing"], 'myPlugin') => "processing",
__($order_statuses["wc-completed"], 'myPlugin') => "completed",
]
)
);
register_setting(self::option_group_name, $field_id);
}
}
public function register_additional_invoice_settings_section()
{
$settings_section_id = 'myPlugin_invoice_settings_section';
add_settings_section(
$settings_section_id,
'Invoice Settings',
function () {
},
self::page
);
$send_email_on_invoice_create_field_id = "myPlugin_send_email_on_invoice_create";
add_settings_field(
$send_email_on_invoice_create_field_id,
esc_html__("Email the invoice as a PDF to customer when created", "myPlugin"),
array($this, 'display_select_field'),
self::page,
$settings_section_id,
array(
'name' => "myPlugin_send_email_on_invoice_create",
'options' => [
esc_html__('Yes', 'myPlugin') => "yes",
esc_html__('No', 'myPlugin') => "no",
]
)
);
register_setting(self::option_group_name, $send_email_on_invoice_create_field_id);
$invoice_date_option = "myPlugin_invoice_date_option";
add_settings_field(
$invoice_date_option,
esc_html__("When Invoice is created, invoice date and due date set to", "myPlugin"),
array($this, 'display_select_field'),
self::page,
$settings_section_id,
array(
'name' => "myPlugin_invoice_date_option",
'options' => [
esc_html__('to the date the order was first created', 'myPlugin') => "0",
esc_html__('to the date when the request is made to create an invoice', 'myPlugin') => "1",
]
)
);
register_setting(self::option_group_name, $invoice_date_option);
}
public function validate_clientId_field($input)
{
$valid = true;
$value = $input;
if (!isset($value) || empty(trim($value))) {
// We must support empty string when we clear cache and set value to empty string
return "";
// $valid = false;
// add_settings_error(
// 'myPlugin_option_group',
// 'myPlugin_clientId_error',
// esc_html__('ClientID is required.', 'myPlugin')
// );
}
if ($valid) {
$value = sanitize_text_field($value);
$value = strtolower($value);
}
if ($valid) {
if (strlen($value) != 32) {
$valid = false;
add_settings_error(
'myPlugin_option_group',
'myPlugin_clientId_error',
esc_html__('Invalid value for ClientID. Value has to be 32 characters long.', 'myPlugin')
);
}
}
if ($valid) {
if (!ctype_xdigit($value) || !self::is_valid_guid($value)) {
$valid = false;
add_settings_error(
'myPlugin_option_group',
'myPlugin_clientId_error',
esc_html__('Invalid value for ClientID. Value has to be a hexadecimal number.', 'myPlugin')
);
}
}
// Ignore the user's changes and use the old database value.
if (!$valid) {
$value = get_option('myPlugin_client_id');
}
return $value;
}
public function validate_clientSecret_field($input)
{
$valid = true;
$value = $input;
if (!isset($value) || empty(trim($value))) {
return "";
// $valid = false;
// add_settings_error(
// 'myPlugin_option_group',
// 'myPlugin_clientSecret_error',
// esc_html__('ClientSecret is required.', 'myPlugin')
// );
}
if ($valid) {
$value = trim($value);
$value = sanitize_text_field($value);
$value = strtolower($value);
}
if ($valid) {
if (strlen($value) != 32) {
$valid = false;
add_settings_error(
'myPlugin_option_group',
'myPlugin_clientSecret_error',
esc_html__('Invalid value for ClientSecret. Value has to be 32 characters long.', 'myPlugin')
);
}
}
if ($valid) {
if (!ctype_xdigit($value) || !self::is_valid_guid($value)) {
$valid = false;
add_settings_error(
'myPlugin_option_group',
'myPlugin_clientSecret_error',
esc_html__('Invalid value for ClientSecret. Value has to be a hexadecimal number.', 'myPlugin')
);
}
}
// Ignore the user's changes and use the old database value.
if (!$valid) {
$value = get_option('myPlugin_client_secret');
}
return $value;
}
// Last of three main credentials validation functions.
// we will validate all three credentials at once if the values have changed. if it is valid we will save the new values to this instance.
public function validate_api_endpoint_field($input)
{
$valid = true;
$value = $input;
$value = trim($value);
if (!isset($value) || empty($value)) {
return "";
// $valid = false;
// add_settings_error(
// 'myPlugin_option_group',
// 'myPlugin_api_endpoint_error',
// esc_html__('API Endpoint is required.', 'myPlugin')
// );
}
$value = sanitize_text_field($value);
if (!filter_var($value, FILTER_VALIDATE_URL)) {
$valid = false;
add_settings_error(
'myPlugin_option_group',
'myPlugin_api_endpoint_error',
esc_html__('Invalid value for API Endpoint. Value has to be a valid URL.', 'myPlugin')
);
}
if ($valid) {
$credential_changed = false;
$old_clientId = MyPlugin_Request_Manager::instance()->get_client_id();
$old_clientSecret = MyPlugin_Request_Manager::instance()->get_client_secret();
$old_api_endpoint = MyPlugin_Request_Manager::instance()->get_api_endpoint();
$new_clientId = get_option('myPlugin_client_id');
$new_clientSecret = get_option('myPlugin_client_secret');
$new_api_endpoint = $value;
if ($new_clientId != $old_clientId)
$credential_changed = true;
if ($new_clientSecret != $old_clientSecret)
$credential_changed = true;
if ($new_api_endpoint != $old_api_endpoint)
$credential_changed = true;
if ($credential_changed) {
if(isset($new_clientId) && !empty(trim($new_clientId))
&& isset($new_clientSecret) && !empty(trim($new_clientSecret))
&& isset($new_api_endpoint) &&! empty(trim($new_api_endpoint))) {
MyPlugin_Request_Manager::instance()->set_client_id($new_clientId);
MyPlugin_Request_Manager::instance()->set_client_secret($new_clientSecret);
MyPlugin_Request_Manager::instance()->set_api_endpoint($new_api_endpoint);
$new_auth_token = MyPlugin_Request_Manager::instance()->get_new_auth_token_and_save();
if (!isset($new_auth_token) || empty($new_auth_token)) {
$valid = false;
add_settings_error(
'myPlugin_option_group',
'myPlugin_api_endpoint_error',
esc_html__('Credentials are invalid. Please check your ClientID, ClientSecret and selected Api Endpoint. Make sure you have the correct values, and that you have saved the settings in MyPlugin.', 'myPlugin')
);
}
}else{
$valid = false;
}
}
}
// Ignore the user's changes and use the old database value.
if (!$valid) {
// $value = get_option('myPlugin_api_endpoint');
// MyPlugin_Request_Manager::instance()->set_client_id(get_option('myPlugin_client_id'));
// MyPlugin_Request_Manager::instance()->set_client_secret(get_option('myPlugin_client_secret'));
// MyPlugin_Request_Manager::instance()->set_api_endpoint(get_option('myPlugin_api_endpoint'));
} else {
add_settings_error(
'myPlugin_option_group',
'myPlugin_api_endpoint_updated',
esc_html('Connection established.', 'myPlugin'),
'updated'
);
}
return $value;
}
public function display_field($args)
{
if ($args['type'] == 'password') {
}
echo "<input class=" . esc_html($args['class']) . " id=" . esc_html($args['id']) . " name=" . esc_html($args['name']) . " type='" . esc_html($args['type']) . "' value='" . esc_html($args['value']) . "' />";
}
public function display_select_field($args)
{
print("<select name=" . $args['name'] . ">");
foreach ($args['options'] as $key => $value) {
print("<option value=" . esc_html($value) . (selected(get_option(esc_html($args['name'])), esc_html($value)) ? " selected>" : ">") . esc_html__($key, 'myPlugin') . "</option>");
}
print("</select>");
}
public function plugin_action_links($links, $file)
{
if (substr($file, 0, 6) === "myPlugin") {
$settings_link = "" . esc_html__('Settings', 'myPlugin') . "";
// Insert in front
array_unshift($links, $settings_link);
}
return $links;
}
// Refresh Values button handler
public function admin_post_myPlugin_settings_refresh()
{
if (isset($_POST['refresh'])) {
$repository = MyPlugin_Repository::instance();
$repository->delete_payment_types();
$myPlugin_payment_types = MyPlugin_Request_Manager::instance()->get_sales_payment_types();
$repository->set_payment_types($myPlugin_payment_types);
wp_safe_redirect(esc_url(admin_url('admin.php?page=' . self::page)));
}
}
// Clear Cache button handler
public function admin_post_myPlugin_settings_clear_cache()
{
if (isset($_POST['clear_cache'])) {
$repository = MyPlugin_Repository::instance();
$repository->delete_payment_types();
$repository->delete_invoice_meta();
$repository->delete_auth_tokens();
$all_options = wp_load_alloptions();
if (isset($all_options)) {
foreach ($all_options as $option_name => $option_value) {
if (substr($option_name, 0, 6) === "myPlugin") {
update_option($option_name, "");
}
}
}
MyPlugin_Request_Manager::instance()->set_client_id("");
MyPlugin_Request_Manager::instance()->set_client_secret("");
MyPlugin_Request_Manager::instance()->set_api_endpoint("");
wp_safe_redirect(esc_url(admin_url('admin.php?page=' . self::page)));
}
}
public function is_valid_guid($str)
{
return preg_match('/^[0-9a-f]{12}[4][0-9a-f]{19}$/', $str);
}
public function render_plugin_settings()
{
?>
<div class="myPlugin_settings_wrap">
<h1><?php echo esc_html__("Settings", 'myPlugin'); ?></h1>
<div class="clear">
<a href="<?php echo esc_url(admin_url('admin.php?page=wc-settings&tab=checkout§ion=myPlugin')); ?>">
<input type="button" class="button" value="<?php echo esc_html__('MyPlugin Claim Service Settings', 'myPlugin') ?>">
</a>
</div>
<?php
if(MyPlugin_Request_Manager::instance()->is_connected_to_endpoint()) {
echo "<h2 style='color:green;'>" . esc_html__("Active.", 'myPlugin') . "</h2>";
}else{
echo "<h2 style='color:red;'>" . esc_html__("This plugin is not active. Please fill in your credentials and save.", 'myPlugin') . "</h2>";
}
?>
<form method="POST" action="options.php">
<?php
settings_errors('myPlugin_option_group');
// Allocate all fields for a option group
settings_fields('myPlugin_option_group');
// Displays all the sections that are assigned to a certain page
do_settings_sections('myPlugin-settings');
// Render a Save Change button
submit_button();
?>
</form>
<!-- Inline Button Row - START -->
<form method="POST" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display: inline-block">
<input type="hidden" name="action" value="myPlugin_settings_refresh">
<input type="submit" id="refresh" name="refresh" class="button" value="<?php echo esc_html__("Refresh Values", 'myPlugin'); ?>">
</form>
<form method="POST" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display: inline-block; padding-left: 5px;">
<input type="hidden" name="action" value="myPlugin_settings_clear_cache">
<input type="submit" id="Disconnect" name="clear_cache" class="button" value="<?php echo esc_html__("Clear Cache", 'myPlugin'); ?>">
</form>
</div>
<?php
}
}
}
MyPlugin_Request_Manager.php
<?php
defined('ABSPATH') || exit;
if (!class_exists('MyPlugin_Request_Manager')) {
class MyPlugin_Request_Manager
{
// This is the singleton instance
private static $_instance = null;
protected $client_id;
protected $client_secret;
protected $api_endpoint;
protected $token;
protected $token_created_at;
// The constructor is private
// to prevent initiation with outer code.
private function __construct()
{
// Use $this instead of static::$_instance
$this->load_dependencies();
}
public function load_dependencies()
{
require_once MYPLUGIN_PATH . 'classes/class-myPlugin-repository.php';
require_once MYPLUGIN_PATH . 'classes/class-myPlugin-utils.php';
}
public static function instance()
{
if (static::$_instance == null) {
static::$_instance = new MyPlugin_Request_Manager();
static::$_instance->set_client_id(get_option('myPlugin_client_id'));
static::$_instance->set_client_secret(get_option('myPlugin_client_secret'));
static::$_instance->set_api_endpoint(get_option('myPlugin_api_endpoint'));
}
return static::$_instance;
}
public function get_client_id()
{
return static::$_instance->client_id;
}
public function set_client_id(string $client_id)
{
static::$_instance->client_id = $client_id;
}
public function get_client_secret()
{
return static::$_instance->client_secret;
}
public function set_client_secret(string $client_secret)
{
static::$_instance->client_secret = $client_secret;
}
public function get_api_endpoint()
{
return static::$_instance->api_endpoint;
}
public function set_api_endpoint(string $api_endpoint)
{
static::$_instance->api_endpoint = $api_endpoint;
}
}
}
Related
Change dates via wp_update_post
So I am trying to manually update the Subscription Dates and show a notice on the for the subsrriptions here. The goal is to make all the subscriptions trigger on the 1st of every month let's say. So in the wp_posts meta we have post_date and post_date_gmt class ChiChi_SubscriptionMetaBoxes { /** * To load Schedule meta box * */ public static function redateSchedule() { add_meta_box('chichi-redate-schedule', _x('Redate Schedule', 'meta box title'), 'ChiChi_SubscriptionMetaBoxes::output', 'shop_subscription', 'side', 'default'); } /** * To display Redate Schedule * * #param object $post * */ public static function output($post) { global $theorder; if (wcs_is_subscription($theorder) && !$theorder->has_status(wcs_get_subscription_ended_statuses())) { include(get_theme_file_path('/lib/woocommerce/templates/html-redate-schedule.php')); } } public static function save($order_id) { global $wpdb; if (!isset($_POST['redate_schedule_date_nonce']) || !isset($_POST['redate_schedule'])) { return $order_id; } $nonce = $_REQUEST['redate_schedule_date_nonce']; if (!is_numeric($_POST['redate_schedule'])) { return $order_id; } $newDay = (int)$_POST['redate_schedule']; //Verify that the nonce is valid. if (!wp_verify_nonce($nonce) || wp_is_post_revision($order_id)) { return $order_id; } // If this is an autosave, our form has not been submitted, so we don't want to do anything. if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $order_id; } // Check the user's permissions. if ('page' == $_POST['post_type']) { if (!current_user_can('edit_page', $order_id)) { return $order_id; } } else { if (!current_user_can('edit_post', $order_id)) { return $order_id; } } // Update the meta field in the database. $subscription = wcs_get_subscription($order_id); $pending_status = 'pending'; if (class_exists('ActionScheduler_Store')) { $pending_status = ActionScheduler_Store::STATUS_PENDING; } $amSchedule = '_action_manager_schedule'; try { $redatedShedule = []; $schedules = as_get_scheduled_actions([ 'hook' => 'woocommerce_subscription_upfront_renewal', 'args' => [ 'subscription_id' => $subscription->get_id() ], 'status' => $pending_status, 'per_page' => 100 ]); if (!empty($schedules)) { foreach ($schedules as $key => $schedule) { $scheduledPost = get_post($key); if (!empty($scheduledPost)) { $originalDateTs = strtotime($scheduledPost->post_date); $originalGmtDateTs = strtotime($scheduledPost->post_date_gmt); $newDate = date("Y-m-" . $newDay . " H:i:s", $originalDateTs); $gmtDate = get_gmt_from_date($newDate); // Update Post wp_update_post([ 'ID' => $key, 'post_date' => $newDate, 'post_date_gmt' => $gmtDate ]); // Update meta time stamps $sql = "UPDATE " . $wpdb->postmeta . " SET meta_value = REPLACE(meta_value, '" . $_schedule_start . "', '" . strtotime($gmtDate) . "') WHERE `post_id` = '" . esc_sql($key) . "' AND `meta_key` = '" . $wpdb->escape($amSchedule) . "'"; $wpdb->get_results($sql); $redatedShedule[] = $gmtDate; } } if (count($redatedShedule) > 0) { // Update End Date $dates['end'] = date('Y-m-d H:i:s', strtotime(end($redatedShedule) . '+1 month')); $subscription->update_dates($dates); $order = new WC_Order($order_id); $order->add_order_note("Subscription has been manually re-dated to: <br/>" . implode('<br>', $redatedShedule)); } } return $order_id; // wp_cache_delete($post_id, 'posts'); } catch (Exception $e) { wcs_add_admin_notice($e->getMessage(), 'error'); } } } add_action('add_meta_boxes', 'ChiChi_SubscriptionMetaBoxes::redateSchedule', 26); add_action('woocommerce_before_save_order_items', 'ChiChi_SubscriptionMetaBoxes::save', 10, 1); let me know please if someone spots any issue. The code itself is commented so you know what the specific sections of code are doing. thanks
json_decode as a global variable
I am trying to make some information widget for the console on client sites (wordpress). The code below works as I need it, perfectly. $url = 'https://example.site/wp-json/'; function _dashboard_clients_info() { global $url; $request = wp_remote_get(esc_url_raw($url)); if (is_wp_error($request)) { return false; } $html = wp_remote_retrieve_body($request); $data = json_decode($html); $head = current(array_filter($data, function ($current) { return $current->_ID == 2; })); $posts = $data; $foot = current(array_filter($data, function ($current) { return $current->_ID == 3; })); $exclude = array(1, 2, 3, 4); if (!empty($head->dash_description)) { echo wpautop('<div class="dash_head">' . $head->dash_description . '</div>'); echo $head->html_css_js; } else { }; foreach ($posts as $post) { if (!in_array($post->_ID, $exclude)) { if (!empty($posts)) { echo '<div class="dash_post">'; echo '<h3 class="dash_title">' . $post->dash_title . '</h3>'; echo wpautop('<div class="dash_description">' . $post->dash_description . '</div>'); echo $post->html_css_js; echo '</div>'; } } else { }; } if (!empty($foot->dash_description)) { echo wpautop('<div class="dash_foot">' . $foot->dash_description . '</div>'); echo $foot->html_css_js; } else { }; } function _add_dashboard_clients_widget() { global $url; $request = wp_remote_get(esc_url_raw($url)); if (is_wp_error($request)) { return false; } $html = wp_remote_retrieve_body($request); $data = json_decode($html); $title = current(array_filter($data, function ($current) { return $current->_ID == 1; })); if (!empty($title->dash_description)) { $title = '<div class="dash_title">' . $title->dash_description . '</div>'; } else { }; add_meta_box('dashboard-clients-info', '' . $title . '', '_dashboard_clients_info', $screen, 'normal', 'high'); } add_action('wp_dashboard_setup', '_add_dashboard_clients_widget'); But I understand that it is not perfect. In particular, I have to include $url twice to get the widget title and body. I would like to make the $data variable global in order to get the $url once, and then take what me need. I tried it like this, but for some reason it doesn't work, it doesn't return anything. $url = 'https://example.site/wp-json/'; $request = wp_remote_get(esc_url_raw($url)); if (is_wp_error($request)) { return false; } $html = wp_remote_retrieve_body($request); $data = json_decode($html); function _dashboard_clients_info() { global $data; $head = current(array_filter($data, function ($current) { return $current->_ID == 2; })); $posts = $data; $foot = current(array_filter($data, function ($current) { return $current->_ID == 3; })); $exclude = array(1, 2, 3, 4); if (!empty($head->dash_description)) { echo wpautop('<div class="dash_head">' . $head->dash_description . '</div>'); echo $head->html_css_js; } else { }; foreach ($posts as $post) { if (!in_array($post->_ID, $exclude)) { if (!empty($posts)) { echo '<div class="dash_post">'; echo '<h3 class="dash_title">' . $post->dash_title . '</h3>'; echo wpautop('<div class="dash_description">' . $post->dash_description . '</div>'); echo $post->html_css_js; echo '</div>'; } } else { }; } if (!empty($foot->dash_description)) { echo wpautop('<div class="dash_foot">' . $foot->dash_description . '</div>'); echo $foot->html_css_js; } else { }; } function _add_dashboard_clients_widget() { global $data; $title = current(array_filter($data, function ($current) { return $current->_ID == 1; })); if (!empty($title->dash_description)) { $title = '<div class="dash_title">' . $title->dash_description . '</div>'; } else { }; add_meta_box('dashboard-clients-info', 'test', '_dashboard_clients_info', $screen, 'normal', 'high'); } add_action('wp_dashboard_setup', '_add_dashboard_clients_widget'); I will be grateful for any help in improving this. I'm just learning, I try to get knowledge in this way)))
You can easily define your API URL in wp-config.php, in the theme's functions.php or in a plugin's 'root' file (my-plugin.php for ex.): define( 'DASHBOARD_API_URL', 'https://example.site/wp-json/' ); Then, create a method to receive the dashboard data making use of the defined DASHBOARD_API_URL: function wp68412621_get_dashboard_data() { $response = wp_remote_get( DASHBOARD_API_URL ); if ( is_wp_error( $response ) ) { return false; } return wp_remote_retrieve_body( $response ); } You should make use of transients to cache the API response in order to avoid excessive API calls. Let's adjust the previous method to: function wp68412621_get_dashboard_data() { $transient_key = 'dashboard_data'; $dashboard_data = get_transient( $transient_key ); if ( false === $dashboard_data ) { $response = wp_remote_get( DASHBOARD_API_URL ); if ( is_wp_error( $response ) ) { return false; } $dashboard_data = wp_remote_retrieve_body( $response ); set_transient( $transientKey, $dashboard_data, 900 ); } return $dashboard_data; } Then, you can call the data method from any other method: function wp68412621_dashboard_clients_info() { $data = wp68412621_get_dashboard_data(); if ( empty( $data ) ) { return false; } // ... } function wp68412621_add_dashboard_clients_widget() { $data = wp68412621_get_dashboard_data(); if ( empty( $data ) ) { return false; } // ... } add_action( 'wp_dashboard_setup', 'wp68412621_add_dashboard_clients_widget' );
How to make hyperlink from author name in Wordpress?
I'm a total newbie to Wordpress and having a hard time figuring things out. I'm using plugin called "WP-Pro-Quiz", a quiz plugin, and within the plugin there's an option to show "Leaderboard" of all users who completed the quiz. In the leaderboard on the frontend, there's user id, time, points and user's Display Name, etc for each user.. What I want to achieve is to make Display name clickable (and then to go to author's profile once clicked). That is, to connect Display Name with author profile who took the quiz, to create hyperlink from Display Name. This is from controller WpProQuiz_Controller_Toplist.php : <?php class WpProQuiz_Controller_Toplist extends WpProQuiz_Controller_Controller { public function route() { $quizId = $_GET['id']; $action = isset($_GET['action']) ? $_GET['action'] : 'show'; switch ($action) { default: $this->showAdminToplist($quizId); break; } } private function showAdminToplist($quizId) { if (!current_user_can('wpProQuiz_toplist_edit')) { wp_die(__('You do not have sufficient permissions to access this page.')); } $view = new WpProQuiz_View_AdminToplist(); $quizMapper = new WpProQuiz_Model_QuizMapper(); $quiz = $quizMapper->fetch($quizId); $view->quiz = $quiz; $view->show(); } public function getAddToplist(WpProQuiz_Model_Quiz $quiz) { $userId = get_current_user_id(); if (!$quiz->isToplistActivated()) { return null; } $data = array( 'userId' => $userId, 'token' => wp_create_nonce('wpProQuiz_toplist'), 'canAdd' => $this->preCheck($quiz->getToplistDataAddPermissions(), $userId), ); if ($quiz->isToplistDataCaptcha() && $userId == 0) { $captcha = WpProQuiz_Helper_Captcha::getInstance(); if ($captcha->isSupported()) { $data['captcha']['img'] = WPPROQUIZ_CAPTCHA_URL . '/' . $captcha->createImage(); $data['captcha']['code'] = $captcha->getPrefix(); } } return $data; } private function handleAddInToplist(WpProQuiz_Model_Quiz $quiz) { if (!wp_verify_nonce($this->_post['token'], 'wpProQuiz_toplist')) { return array('text' => __('An error has occurred.', 'wp-pro-quiz'), 'clear' => true); } if (!isset($this->_post['points']) || !isset($this->_post['totalPoints'])) { return array('text' => __('An error has occurred.', 'wp-pro-quiz'), 'clear' => true); } $quizId = $quiz->getId(); $userId = get_current_user_id(); $points = (int)$this->_post['points']; $totalPoints = (int)$this->_post['totalPoints']; $name = !empty($this->_post['name']) ? trim($this->_post['name']) : ''; $email = !empty($this->_post['email']) ? trim($this->_post['email']) : ''; $ip = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP); $captchaAnswer = !empty($this->_post['captcha']) ? trim($this->_post['captcha']) : ''; $prefix = !empty($this->_post['prefix']) ? trim($this->_post['prefix']) : ''; $quizMapper = new WpProQuiz_Model_QuizMapper(); $toplistMapper = new WpProQuiz_Model_ToplistMapper(); if ($quiz == null || $quiz->getId() == 0 || !$quiz->isToplistActivated()) { return array('text' => __('An error has occurred.', 'wp-pro-quiz'), 'clear' => true); } if (!$this->preCheck($quiz->getToplistDataAddPermissions(), $userId)) { return array('text' => __('An error has occurred.', 'wp-pro-quiz'), 'clear' => true); } $numPoints = $quizMapper->sumQuestionPoints($quizId); if ($totalPoints > $numPoints || $points > $numPoints) { return array('text' => __('An error has occurred.', 'wp-pro-quiz'), 'clear' => true); } $clearTime = null; if ($quiz->isToplistDataAddMultiple()) { $clearTime = $quiz->getToplistDataAddBlock() * 60; } if ($userId > 0) { if ($toplistMapper->countUser($quizId, $userId, $clearTime)) { return array('text' => __('You can not enter again.', 'wp-pro-quiz'), 'clear' => true); } $user = wp_get_current_user(); $email = $user->user_email; $name = $user->display_name; } else { if ($toplistMapper->countFree($quizId, $name, $email, $ip, $clearTime)) { return array('text' => __('You can not enter again.', 'wp-pro-quiz'), 'clear' => true); } if (empty($name) || empty($email) || filter_var($email, FILTER_VALIDATE_EMAIL) === false) { return array('text' => __('No name or e-mail entered.', 'wp-pro-quiz'), 'clear' => false); } if (strlen($name) > 15) { return array('text' => __('Your name can not exceed 15 characters.', 'wp-pro-quiz'), 'clear' => false); } if ($quiz->isToplistDataCaptcha()) { $captcha = WpProQuiz_Helper_Captcha::getInstance(); if ($captcha->isSupported()) { if (!$captcha->check($prefix, $captchaAnswer)) { return array('text' => __('You entered wrong captcha code.', 'wp-pro-quiz'), 'clear' => false); } } } } $toplist = new WpProQuiz_Model_Toplist(); $toplist->setQuizId($quizId) ->setUserId($userId) ->setDate(time()) ->setName($name) ->setEmail($email) ->setPoints($points) ->setResult(round($points / $totalPoints * 100, 2)) ->setIp($ip); $toplistMapper->save($toplist); return true; } private function preCheck($type, $userId) { switch ($type) { case WpProQuiz_Model_Quiz::QUIZ_TOPLIST_TYPE_ALL: return true; case WpProQuiz_Model_Quiz::QUIZ_TOPLIST_TYPE_ONLY_ANONYM: return $userId == 0; case WpProQuiz_Model_Quiz::QUIZ_TOPLIST_TYPE_ONLY_USER: return $userId > 0; } return false; } public static function ajaxAdminToplist($data) { if (!current_user_can('wpProQuiz_toplist_edit')) { return json_encode(array()); } $toplistMapper = new WpProQuiz_Model_ToplistMapper(); $j = array('data' => array()); $limit = (int)$data['limit']; $start = $limit * ($data['page'] - 1); $isNav = isset($data['nav']); $quizId = $data['quizId']; if (isset($data['a'])) { switch ($data['a']) { case 'deleteAll': $toplistMapper->delete($quizId); break; case 'delete': if (!empty($data['toplistIds'])) { $toplistMapper->delete($quizId, $data['toplistIds']); } break; } $start = 0; $isNav = true; } $toplist = $toplistMapper->fetch($quizId, $limit, $data['sort'], $start); foreach ($toplist as $tp) { $j['data'][] = array( 'id' => $tp->getToplistId(), 'name' => $tp->getName(), 'email' => $tp->getEmail(), 'type' => $tp->getUserId() ? 'R' : 'UR', 'date' => WpProQuiz_Helper_Until::convertTime($tp->getDate(), get_option('wpProQuiz_toplistDataFormat', 'Y/m/d g:i A')), 'points' => $tp->getPoints(), 'result' => $tp->getResult() ); } if ($isNav) { $count = $toplistMapper->count($quizId); $pages = ceil($count / $limit); $j['nav'] = array( 'count' => $count, 'pages' => $pages ? $pages : 1 ); } return json_encode($j); } public static function ajaxAddInToplist($data) { // workaround ... $_POST = $_POST['data']; $ctn = new WpProQuiz_Controller_Toplist(); $quizId = isset($data['quizId']) ? $data['quizId'] : 0; $prefix = !empty($data['prefix']) ? trim($data['prefix']) : ''; $quizMapper = new WpProQuiz_Model_QuizMapper(); $quiz = $quizMapper->fetch($quizId); $r = $ctn->handleAddInToplist($quiz); if ($quiz->isToplistActivated() && $quiz->isToplistDataCaptcha() && get_current_user_id() == 0) { $captcha = WpProQuiz_Helper_Captcha::getInstance(); if ($captcha->isSupported()) { $captcha->remove($prefix); $captcha->cleanup(); if ($r !== true) { $r['captcha']['img'] = WPPROQUIZ_CAPTCHA_URL . '/' . $captcha->createImage(); $r['captcha']['code'] = $captcha->getPrefix(); } } } if ($r === true) { $r = array('text' => __('You signed up successfully.', 'wp-pro-quiz'), 'clear' => true); } return json_encode($r); } public static function ajaxShowFrontToplist($data) { // workaround ... $_POST = $_POST['data']; $quizIds = empty($data['quizIds']) ? array() : array_unique((array)$data['quizIds']); $toplistMapper = new WpProQuiz_Model_ToplistMapper(); $quizMapper = new WpProQuiz_Model_QuizMapper(); $j = array(); foreach ($quizIds as $quizId) { $quiz = $quizMapper->fetch($quizId); if ($quiz == null || $quiz->getId() == 0) { continue; } $toplist = $toplistMapper->fetch($quizId, $quiz->getToplistDataShowLimit(), $quiz->getToplistDataSort()); foreach ($toplist as $tp) { $j[$quizId][] = array( 'name' => $tp->getName(), 'date' => WpProQuiz_Helper_Until::convertTime($tp->getDate(), get_option('wpProQuiz_toplistDataFormat', 'Y/m/d g:i A')), 'points' => $tp->getPoints(), 'result' => $tp->getResult() ); } } return json_encode($j); } } and from model WpProQuiz_Model_Toplist.php: <?php class WpProQuiz_Model_Toplist extends WpProQuiz_Model_Model { protected $_toplistId; protected $_quizId; protected $_userId; protected $_date; protected $_name; protected $_email; protected $_points; protected $_result; protected $_ip; public function setToplistId($_toplistId) { $this->_toplistId = (int)$_toplistId; return $this; } public function getToplistId() { return $this->_toplistId; } public function setQuizId($_quizId) { $this->_quizId = (int)$_quizId; return $this; } public function getQuizId() { return $this->_quizId; } public function setUserId($_userId) { $this->_userId = (int)$_userId; return $this; } public function getUserId() { return $this->_userId; } public function setDate($_date) { $this->_date = (int)$_date; return $this; } public function getDate() { return $this->_date; } public function setName($_name) { $this->_name = (string)$_name; return $this; } public function getName() { return $this->_name; } public function setEmail($_email) { $this->_email = (string)$_email; return $this; } public function getEmail() { return $this->_email; } public function setPoints($_points) { $this->_points = (int)$_points; return $this; } public function getPoints() { return $this->_points; } public function setResult($_result) { $this->_result = (float)$_result; return $this; } public function getResult() { return $this->_result; } public function setIp($_ip) { $this->_ip = (string)$_ip; return $this; } public function getIp() { return $this->_ip; } }
add icon to error message using php session
I have this class for show error with session method using PHP. class Messages { //----------------------------------------------------------------------------------------------- // Class Variables //----------------------------------------------------------------------------------------------- var $msgId; var $msgTypes = array( 'help', 'info', 'warning', 'success', 'danger' ); var $msgClass = 'alert'; var $msgWrapper = " <div class='alert %s-%s flashit'> <button class='close' aria-hidden='true' data-dismiss='alert' type='button'>×</button> <p><i style='vertical-align: middle;' class='%s icon-2x'></i> %s</p> </div>"; var $msgBefore = ''; var $msgAfter = ""; public function __construct() { // Generate a unique ID for this user and session $this->msgId = md5(uniqid()); // Create the session array if it doesnt already exist if( !array_key_exists('flash_messages', $_SESSION) ) $_SESSION['flash_messages'] = array(); } public function add($type, $message, $redirect_to=null) { if( !isset($_SESSION['flash_messages']) ) return false; if( !isset($type) || !isset($message[0]) ) return false; // Replace any shorthand codes with their full version if( strlen(trim($type)) == 1 ) { $type = str_replace( array('h', 'i', 'w', 'e', 's'), array('help', 'info', 'warning', 'danger', 'success'), $type ); $icon = str_replace( array('h', 'i', 'w', 'e', 's'), array('fa-help', 'fa-info', 'fa-warning', 'fa-danger', 'fa-success'), $type ); // Backwards compatibility... } elseif( $type == 'information' ) { $type = 'info'; $icon = 'fa-info'; } // Make sure it's a valid message type if( !in_array($type, $this->msgTypes) ) die('"' . strip_tags($type) . '" is not a valid message type!' ); // If the session array doesn't exist, create it if( !array_key_exists( $type, $_SESSION['flash_messages'] ) ) $_SESSION['flash_messages'][$type] = array(); $_SESSION['flash_messages'][$type][] = $message; if( !is_null($redirect_to) ) { header("Location: $redirect_to"); exit(); } return true; } //----------------------------------------------------------------------------------------------- // display() // print queued messages to the screen //----------------------------------------------------------------------------------------------- public function display($type='all', $print=true) { $messages = ''; $data = ''; if( !isset($_SESSION['flash_messages']) ) return false; if( $type == 'g' || $type == 'growl' ) { $this->displayGrowlMessages(); return true; } // Print a certain type of message? if( in_array($type, $this->msgTypes) ) { foreach( $_SESSION['flash_messages'][$type] as $msg ) { $messages .= $this->msgBefore . $msg . $this->msgAfter; } $data .= sprintf($this->msgWrapper, $this->msgClass, $type,$icon,$messages); // Clear the viewed messages $this->clear($type); // Print ALL queued messages } elseif( $type == 'all' ) { foreach( $_SESSION['flash_messages'] as $type => $msgArray ) { $messages = ''; foreach( $msgArray as $msg ) { $messages .= $this->msgBefore . $msg . $this->msgAfter; } $data .= sprintf($this->msgWrapper, $this->msgClass, $type,$icon,$messages); } // Clear ALL of the messages $this->clear(); // Invalid Message Type? } else { return false; } // Print everything to the screen or return the data if( $print ) { echo $data; } else { return $data; } } //..... more } Call: $msg = new Messages(); $msg->add('i', 'This is a Information message!'); echo $msg->display(); Now in Output: <i style="vertical-align: middle;" class=" icon-2x"></i> Icon class not printed and empty: class=" icon-2x". how do can i fix this ? EDit: Indeed i need to print for each type One class name.
posting in group on behalf of user using facebook graph API
I am trying to post on behalf of user. I have used tutorial given on this page: http://25labs.com/updated-post-to-multiple-facebook-pages-or-groups-efficiently-v2-0/ . I could successfully perform authentication but could not post on behalf. Here is the source code : https://github.com/karimkhanp/fbPostOnBehalf Testing can be done here: http://ec2-54-186-110-98.us-west-2.compute.amazonaws.com/fb/ Does any one experienced this?
I'm not familiar with the batch process that the tutorial is using but below is a code sample that posts to a Facebook group <?php # same this file as # test.php include_once "src/facebook.php"; $config = array( 'appId' => "YOURAPPID", 'secret' => "YOURAPPSECRET", 'allowSignedRequest' => false, // optional, but should be set to false for non-canvas apps ); class PostToFacebook { private $facebook; private $pages; public function initialise($config){ $this->name = "Facebook"; // current necessary configs to set // $config = array( // 'appId' => FB_APP_ID, // 'secret' => FB_APP_SECRET, // 'allowSignedRequest' => false, // optional, but should be set to false for non-canvas apps // ); $this->facebook = new Facebook($config); try{ // if user removes app authorization $this->hasAccess = $this->has_permissions(); if($this->hasAccess){ $this->groups = $this->getGroupData(); } } catch(Exception $err){ } } public function postMessageToGroup($message, $groupid){ $messageResponse = array( 'STATUS' => 0 ); $fbMessageObj = array( "message" => strip_tags($message), ); try { $user_page_post = $this->facebook->api("/$groupid/feed", 'POST', $fbMessageObj); if($user_page_post && !empty($user_page_post['id'])){ $messageResponse['STATUS'] = 200; $messageData = array( 'id' => $user_page_post['id'], 'link' => 'http://facebook.com/' . $user_page_post['id'], ); $messageResponse['data'] = $messageData; } else{ $messageResponse['STATUS'] = 302; } } catch(Exception $err){ $messageResponse['STATUS'] = 500; $messageResponse['data'] = array($err); } return $messageResponse; } // TODO: should read a template somewhere function show_login() { $login_url = $this->facebook->getLoginUrl( array( 'scope' => implode(",",$this->permissions()) )); return 'Login to Facebook and Grant Necessary Permissions'; } // TODO: should read a template somewhere public function toString() { if($this->hasAccess){ if($this->groups){ $msg = ""; $msg .= '<select name="group_id"><option value=""></option>'; foreach($this->groups as $group) { $msg .= '<option value="' . '' . urlencode($group['id']) . '">' . $group['name'] . '</option>' . ''; } $msg .= '</select>'; return $msg; } else return "No Groups"; } else{ return $this->show_login(); } } function getGroupData(){ $raw = $this->facebook->api('/me/groups', 'GET'); $data = array(); if (null != $raw && array_key_exists('data', $raw)) return $raw['data']; return null; } // check if current instance has access to facebook function has_permissions() { $user_id = #$this->facebook->getUser(); #print_r($user_id); if($user_id == null) return false; $permissions = $this->facebook->api("/me/permissions"); foreach($this->permissions() as $perm){ if( !array_key_exists($perm, $permissions['data'][0]) ) { return false; } } return true; } // permissins needed to post function permissions(){ return array('manage_pages', 'user_groups'); } } $fb = new PostToFacebook(); $fb->initialise($config); if(!$fb->has_permissions()) { echo $fb->show_login(); } else{ ?> <form method="post" action="test.php"> <textarea name='message'></textarea> <?php echo $fb->toString(); ?> <input type='submit'> </form> <?php } if(!empty($_POST)){ $response = $fb->postMessageToGroup($_POST['message'], $_POST['group_id']); if($response['STATUS'] == 200) print_r("<a href='" . $response['data']['link'] . "'>" . $response['data']['id'] ."</a>"); else { echo "ERROR!"; print_r($response); } } ?>