settings = subscriptio_plugin_settings();
// Load/parse plugin settings
$this->opt = $this->get_options();
// Maybe set Stripe gateway for migration
$this->maybe_set_stripe_gateway_for_migration();
// Load payment gateway classes
$this->load_payment_gateways();
// Cache objects in admin list view
$this->cache = array(
'subscriptions' => array(),
'transactions' => array(),
);
// Hook to WordPress 'init' action
add_action('init', array($this, 'on_init_pre'), 1);
add_action('init', array($this, 'on_init_post'), 99);
// Admin-only hooks
if (is_admin() && !defined('DOING_AJAX')) {
// Add settings page menu link
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_init', array($this, 'plugin_options_setup'));
// Use correct capability for settings page
add_filter('option_page_capability_subscriptio_opt_group_general', array($this, 'custom_options_capability'));
add_filter('option_page_capability_subscriptio_opt_group_capabilities', array($this, 'custom_options_capability'));
add_filter('option_page_capability_subscriptio_opt_group_flow', array($this, 'custom_options_capability'));
add_filter('option_page_capability_subscriptio_opt_group_gateways', array($this, 'custom_options_capability'));
// Load backend assets conditionally
if (self::is_subscriptio_page()) {
add_action('admin_enqueue_scripts', array($this, 'enqueue_backend_assets'));
}
// ... and load some assets on all pages
add_action('admin_enqueue_scripts', array($this, 'enqueue_backend_assets_all'));
}
// Frontend-only hooks
else {
if (!(defined('DOING_AJAX') && DOING_AJAX)) {
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
}
}
// Add payment gateways
add_filter('woocommerce_payment_gateways', array($this, 'add_payment_gateways'));
// Customer My Account hooks
add_filter('woocommerce_my_account_my_orders_query', array($this, 'woocommerce_my_orders_query'));
add_filter('woocommerce_my_account_my_orders_title', array($this, 'woocommerce_my_orders_title'));
add_filter('query_vars', array($this, 'add_query_vars'));
add_action('wp_loaded', array($this, 'maybe_flush_rewrite_rules'));
add_filter('rewrite_rules_array', array($this, 'insert_rewrite_rules'));
if (!Subscriptio::my_account_supports_tabbed_navigation()) {
add_action('woocommerce_before_my_account', array($this, 'display_customer_subscription_list'), 1);
}
// Other hooks
add_action('restrict_manage_posts', array($this, 'add_list_filters'));
add_action('manage_subscription_posts_columns', array($this, 'manage_subscription_list_columns'));
add_action('manage_sub_transaction_posts_columns', array($this, 'manage_transaction_list_columns'));
add_action('manage_subscription_posts_custom_column', array($this, 'manage_subscription_list_column_values'), 10, 2);
add_action('manage_sub_transaction_posts_custom_column', array($this, 'manage_transaction_list_column_values'), 10, 2);
add_filter('parse_query', array($this, 'handle_list_filter_queries'));
add_filter('bulk_actions-edit-subscription', array($this, 'manage_subscription_list_bulk_actions'));
add_filter('bulk_actions-edit-sub_transaction', array($this, 'manage_transaction_list_bulk_actions'));
add_filter('views_edit-subscription', array($this, 'manage_subscription_list_views'));
add_filter('views_edit-sub_transaction', array($this, 'manage_transaction_list_views'));
add_filter('posts_join', array($this, 'expand_list_search_context_join'));
add_filter('posts_where', array($this, 'expand_list_search_context_where'));
add_filter('posts_groupby', array($this, 'expand_list_search_context_group_by'));
add_action('woocommerce_before_checkout_form', array($this, 'enforce_registration'), 99);
add_filter('woocommerce_checkout_registration_required', array($this, 'enforce_registration_new'), 99);
add_filter('woocommerce_checkout_registration_enabled', array($this, 'enforce_registration_new'), 99);
add_action('woocommerce_checkout_process', array($this, 'enforce_createaccount_option'), 99);
add_filter('wc_checkout_params', array($this, 'enforce_registration_js'), 99);
add_action('before_delete_post', array($this, 'post_deleted_event'));
add_action('save_post', array($this, 'save_subscription_meta_box'), 9, 2);
add_action('init', array($this, 'maybe_save_main_site_url'), 1);
add_action('admin_notices', array($this, 'url_mismatch_notification'));
add_action('add_meta_boxes', array($this, 'remove_meta_boxes'), 99, 2);
add_action('admin_init', array($this, 'admin_redirect'));
add_action('admin_head', array($this, 'admin_remove_new_post_links'));
// Add shortcode to display customer's subscription list
add_shortcode('subscriptio_customer_subscriptions', array($this, 'shortcode_customer_subscriptions'));
// AJAX handler for subscription date change
add_action('wp_ajax_change_scheduled_date', array('Subscriptio_Subscription', 'ajax_change_scheduled_date'));
// Debug class
if (self::$debug) {
add_action('init', array($this, 'debug'));
}
// Intercept PayPal's response
add_action('parse_request', array($this, 'paypal_express_return_page'), 10);
// Maybe print Stripe gateway migration notice
add_action('admin_notices', array($this, 'maybe_print_stripe_gateway_migration_notice'), -1);
// Maybe migrate Stripe gateway
add_action('admin_init', array($this, 'maybe_migrate_stripe_gateway'));
// Show old versio notice
add_action('admin_notices', array($this, 'print_old_version_notice'));
}
/**
* Debug function run on WordPress init action - do your testing here
*
* @access public
* @return void
*/
public function debug()
{
}
/**
* Add settings link on plugins page
*
* @access public
* @param array $links
* @return void
*/
public function plugins_page_links($links)
{
// Support
$settings_link = ''.esc_html__('Support', 'subscriptio').'';
array_unshift($links, $settings_link);
// Settings
if (self::check_environment()) {
$settings_link = ''.esc_html__('Settings', 'subscriptio').'';
array_unshift($links, $settings_link);
}
return $links;
}
/**
* WordPress 'init' @ position 1
*
* @access public
* @return void
*/
public function on_init_pre()
{
// Register new post type to store subscriptions
$this->add_custom_post_types();
// Register endpoints
foreach (self::$query_vars as $var) {
add_rewrite_endpoint($var, EP_ROOT | EP_PAGES);
}
}
/**
* WordPress 'init' @ position 99
*
* @access public
* @return void
*/
public function on_init_post()
{
// Add menu item to tabbed navigation (works starting from WooCommerce 2.6)
if (Subscriptio::my_account_supports_tabbed_navigation()) {
add_filter('woocommerce_account_menu_items', array($this, 'my_account_menu_items'));
add_action('woocommerce_account_subscriptions_endpoint', array($this, 'display_customer_subscription_list'));
add_filter('the_title', array($this, 'subscriptions_endpoint_title'));
}
// Replace woocommerce_my_account shortcode with our own
if (shortcode_exists('woocommerce_my_account')) {
remove_shortcode('woocommerce_my_account');
include SUBSCRIPTIO_PLUGIN_PATH . 'includes/classes/lazy/subscriptio-my-account.class.php';
add_shortcode(apply_filters('woocommerce_my_account_shortcode_tag', 'woocommerce_my_account'), array($this, 'intercept_woocommerce_my_account_shortcode'));
}
// Display related subscriptions on frontend single order view page
add_action(
apply_filters('subscriptio_order_view_hook', 'woocommerce_order_details_after_order_table'),
array($this, 'display_frontend_order_related_subscriptions'),
apply_filters('subscriptio_order_view_position', 9)
);
}
/**
* Check if current user has admin capability
*
* @access public
* @return bool
*/
public static function is_admin()
{
return current_user_can(Subscriptio::get_admin_capability());
}
/**
* Get admin capability
*
* @access public
* @return string
*/
public static function get_admin_capability()
{
return apply_filters('subscriptio_capability', 'manage_woocommerce');
}
/**
* Custom capability for options
*
* @access public
* @param string $capability
* @return string
*/
public function custom_options_capability($capability)
{
return Subscriptio::get_admin_capability();
}
/**
* Add menu item to tabbed navigation
*
* @access public
* @param array $items
* @return array
*/
public function my_account_menu_items($items)
{
// Check if subscription list needs to be displayed
if (self::display_frontend_subscriptions_list()) {
$menu_item = array('subscriptions' => esc_html__('Subscriptions', 'subscriptio'));
// Insert after dashboard or after orders
if (isset($items['dashboard']) || isset($items['orders'])) {
$where = isset($items['dashboard']) ? 'dashboard' : 'orders';
$items = RightPress_Helper::insert_to_array_after_key($items, $where, $menu_item);
}
// ... or at the beginning of the list
else {
$items = array_merge($menu_item, $items);
}
}
return $items;
}
/**
* Change subscriptions endpoint title
*
* @access public
* @param string $title
* @return string
*/
public function subscriptions_endpoint_title($title)
{
global $wp_query;
// Check if we are in My Account
if (!is_null($wp_query) && !is_admin() && is_main_query() && in_the_loop() && is_account_page()) {
// Subscriptions
if (isset($wp_query->query_vars['subscriptions'])) {
$title = esc_html__('Subscriptions', 'subscriptio');
}
// Shipping address
else if (isset($wp_query->query_vars['subscription-address'])) {
$title = esc_html__('Shipping Address', 'subscriptio');
}
// Single subscription
else {
foreach (array('view-subscription', 'pause-subscription', 'resume-subscription', 'cancel-subscription') as $var) {
if (isset($wp_query->query_vars[$var])) {
$subscription = Subscriptio_Subscription::get_by_id($wp_query->query_vars[$var]);
$title = esc_html__('Subscription', 'subscriptio') . ' ' . $subscription->get_subscription_number();
break;
}
}
}
// Remove filter so that no further changes can be made to the page title
remove_filter('the_title', array($this, 'subscriptions_endpoint_title'));
}
return $title;
}
/**
* Exctract some options from plugin settings array
*
* @access public
* @param string $name
* @param bool $split_by_page
* @return array
*/
public function options($name, $split_by_page = false)
{
$results = array();
// Iterate over settings array and extract values
foreach ($this->settings as $page => $page_value) {
$page_options = array();
foreach ($page_value['children'] as $section => $section_value) {
foreach ($section_value['children'] as $field => $field_value) {
if (isset($field_value[$name])) {
$page_options['subscriptio_' . $field] = $field_value[$name];
}
}
}
$results[preg_replace('/_/', '-', $page)] = $page_options;
}
$final_results = array();
if (!$split_by_page) {
foreach ($results as $value) {
$final_results = array_merge($final_results, $value);
}
}
else {
$final_results = $results;
}
return $final_results;
}
/**
* Get options saved to database or default options if no options saved
*
* @access public
* @return array
*/
public function get_options()
{
// Get options from database
$saved_options = get_option('subscriptio_options', array());
// Get current version (for major updates in future)
if (!empty($saved_options)) {
if (isset($saved_options[SUBSCRIPTIO_OPTIONS_VERSION])) {
$saved_options = $saved_options[SUBSCRIPTIO_OPTIONS_VERSION];
}
else {
// Migrate options here if needed...
}
}
if (is_array($saved_options)) {
return array_merge($this->options('default'), $saved_options);
}
else {
return $this->options('default');
}
}
/*
* Update single option
*
* @access public
* @return bool
*/
public function update_option($key, $value)
{
$this->opt[$key] = $value;
return update_option('subscriptio_options', $this->opt);
}
/**
* Add custom post types
*
* @access public
* @return void
*/
public function add_custom_post_types()
{
/**
* SUBSCRIPTION
*/
// Define labels
$labels = array(
'name' => esc_html__('Subscriptions', 'subscriptio'),
'singular_name' => esc_html__('Subscription', 'subscriptio'),
'add_new' => esc_html__('Add Subscription', 'subscriptio'),
'add_new_item' => esc_html__('Add New Subscription', 'subscriptio'),
'edit_item' => esc_html__('Edit Subscription', 'subscriptio'),
'new_item' => esc_html__('New Subscription', 'subscriptio'),
'all_items' => esc_html__('Subscriptions', 'subscriptio'),
'view_item' => esc_html__('View Subscription', 'subscriptio'),
'search_items' => esc_html__('Search Subscriptions', 'subscriptio'),
'not_found' => esc_html__('No Subscriptions Found', 'subscriptio'),
'not_found_in_trash' => esc_html__('No Subscriptions Found In Trash', 'subscriptio'),
'parent_item_colon' => '',
'menu_name' => esc_html__('Subscriptions', 'subscriptio'),
);
// Define settings
$args = array(
'labels' => $labels,
'description' => esc_html__('WooCommerce Subscriptions', 'subscriptio'),
'public' => false,
'show_ui' => true,
'menu_position' => 56,
'capability_type' => 'post',
'capabilities' => array(
'create_posts' => 'do_not_allow',
),
'map_meta_cap' => true,
'supports' => array(''),
'register_meta_box_cb' => array($this, 'add_subscription_meta_box'),
);
// Register new post type
register_post_type('subscription', $args);
// Register custom taxonomy (subscription status)
register_taxonomy('subscription_status', 'subscription', array(
'label' => esc_html__('Status', 'subscriptio'),
'labels' => array(
'name' => esc_html__('Status', 'subscriptio'),
'singular_name' => esc_html__('Status', 'subscriptio'),
),
'public' => false,
'show_admin_column' => true,
'query_var' => true,
));
// Register custom terms - subscription status
foreach (Subscriptio_Subscription::get_statuses() as $status_key => $status) {
if (!term_exists($status_key, 'subscription_status')) {
wp_insert_term($status['title'], 'subscription_status', array(
'slug' => $status_key,
));
}
}
/**
* SUBSCRIPTION TRANSACTION
*/
// Define labels
$labels = array(
'name' => esc_html__('Transactions', 'subscriptio'),
'singular_name' => esc_html__('Transaction', 'subscriptio'),
'add_new' => esc_html__('Add Transaction', 'subscriptio'),
'add_new_item' => esc_html__('Add New Transaction', 'subscriptio'),
'edit_item' => esc_html__('Edit Transaction', 'subscriptio'),
'new_item' => esc_html__('New Transaction', 'subscriptio'),
'all_items' => esc_html__('Transactions', 'subscriptio'),
'view_item' => esc_html__('View Transaction', 'subscriptio'),
'search_items' => esc_html__('Search Transactions', 'subscriptio'),
'not_found' => esc_html__('No Transactions Found', 'subscriptio'),
'not_found_in_trash' => esc_html__('No Transactions Found In Trash', 'subscriptio'),
'parent_item_colon' => '',
'menu_name' => esc_html__('Transactions', 'subscriptio'),
);
// Define settings
$args = array(
'labels' => $labels,
'description' => esc_html__('WooCommerce Subscriptions', 'subscriptio'),
'public' => false,
'show_ui' => true,
'show_in_menu' => 'edit.php?post_type=subscription',
'menu_position' => 59,
'capability_type' => 'post',
'capabilities' => array(
'create_posts' => 'do_not_allow',
),
'map_meta_cap' => true,
'supports' => array('title'),
);
// Register new post type
register_post_type('sub_transaction', $args);
// Edit this custom post type a bit
add_filter('post_row_actions', array($this, 'sub_transaction_remove_actions'));
// Register custom taxonomy (transaction action)
register_taxonomy('sub_transaction_action', 'sub_transaction', array(
'label' => esc_html__('Action', 'subscriptio'),
'labels' => array(
'name' => esc_html__('Action', 'subscriptio'),
'singular_name' => esc_html__('Action', 'subscriptio'),
),
'public' => false,
'show_admin_column' => true,
'query_var' => true,
));
// Register custom taxonomy (transaction result)
register_taxonomy('sub_transaction_result', 'sub_transaction', array(
'label' => esc_html__('Result', 'subscriptio'),
'labels' => array(
'name' => esc_html__('Result', 'subscriptio'),
'singular_name' => esc_html__('Result', 'subscriptio'),
),
'public' => false,
'show_admin_column' => true,
'query_var' => true,
));
// Register custom terms - action
foreach (Subscriptio_Transaction::get_actions() as $action_key => $action) {
if (!term_exists($action_key, 'sub_transaction_action')) {
wp_insert_term($action['title'], 'sub_transaction_action', array(
'slug' => $action_key,
));
}
}
// Register custom terms - result
foreach (Subscriptio_Transaction::get_results() as $result_key => $result) {
if (!term_exists($result_key, 'sub_transaction_result')) {
wp_insert_term($result['title'], 'sub_transaction_result', array(
'slug' => $result_key,
));
}
}
}
/**
* Add filtering capabilities to custom taxonomies for custom post types
*
* @access public
* @return void
*/
public function add_list_filters()
{
global $typenow;
global $wp_query;
// Extract selected filter options
$selected = array();
foreach (array('subscription_status', 'sub_transaction_action', 'sub_transaction_result') as $taxonomy) {
if (!empty($wp_query->query[$taxonomy]) && is_numeric($wp_query->query[$taxonomy])) {
$selected[$taxonomy] = $wp_query->query[$taxonomy];
}
else if (!empty($wp_query->query[$taxonomy])) {
$term = get_term_by('slug', $wp_query->query[$taxonomy], $taxonomy);
$selected[$taxonomy] = $term ? $term->term_id : 0;
}
else {
$selected[$taxonomy] = 0;
}
}
if ($typenow == 'subscription') {
// Statuses
wp_dropdown_categories(array(
'show_option_all' => esc_html__('All statuses', 'subscriptio'),
'taxonomy' => 'subscription_status',
'name' => 'subscription_status',
'selected' => $selected['subscription_status'],
'show_count' => true,
'hide_empty' => false,
));
}
else if ($typenow == 'sub_transaction') {
// Actions
if (!empty($wp_query->query['sub_transaction_action'])) {
$term = get_term_by('slug', $wp_query->query['sub_transaction_action'], 'sub_transaction_action');
}
wp_dropdown_categories(array(
'show_option_all' => esc_html__('All actions', 'subscriptio'),
'taxonomy' => 'sub_transaction_action',
'name' => 'sub_transaction_action',
'selected' => $selected['sub_transaction_action'],
'show_count' => true,
'hide_empty' => false,
));
// Results
wp_dropdown_categories(array(
'show_option_all' => esc_html__('All results', 'subscriptio'),
'taxonomy' => 'sub_transaction_result',
'name' => 'sub_transaction_result',
'selected' => $selected['sub_transaction_result'],
'show_count' => true,
'hide_empty' => false,
));
}
}
/**
* Handle list filter queries
*
* @access public
* @param object $query
* @return void
*/
public function handle_list_filter_queries($query)
{
global $pagenow;
$qv = &$query->query_vars;
if ($pagenow == 'edit.php' && isset($qv['post_type'])) {
$taxonomies = array(
'subscription' => array('subscription_status'),
'sub_transaction' => array('sub_transaction_action', 'sub_transaction_result'),
);
if (!is_array($qv['post_type']) && isset($taxonomies[$qv['post_type']])) {
foreach ($taxonomies[$qv['post_type']] as $taxonomy) {
if (isset($qv[$taxonomy]) && is_numeric($qv[$taxonomy]) && $qv[$taxonomy] != 0) {
$term = get_term_by('id', $qv[$taxonomy], $taxonomy);
$qv[$taxonomy] = $term->slug;
}
}
}
}
}
/**
* Manage subscription list columns
*
* @access public
* @param array $columns
* @return array
*/
public function manage_subscription_list_columns($columns)
{
$new_columns = array();
foreach ($columns as $column_key => $column) {
$allowed_columns = array(
'cb',
);
if (in_array($column_key, $allowed_columns)) {
$new_columns[$column_key] = $column;
}
}
$new_columns['id'] = esc_html__('ID', 'subscriptio');
$new_columns['status'] = esc_html__('Status', 'subscriptio');
$new_columns['subscriptio_product'] = esc_html__('Product', 'subscriptio');
$new_columns['subscriptio_user'] = esc_html__('User', 'subscriptio');
$new_columns['recurring_amount'] = esc_html__('Recurring', 'subscriptio');
$new_columns['last_order'] = esc_html__('Last Order', 'subscriptio');
$new_columns['started'] = esc_html__('Started', 'subscriptio');
$new_columns['payment_due'] = esc_html__('Payment Due', 'subscriptio');
$new_columns['expires'] = esc_html__('Expires', 'subscriptio');
return $new_columns;
}
/**
* Manage transaction list columns
*
* @access public
* @param array $columns
* @return array
*/
public function manage_transaction_list_columns($columns)
{
$new_columns = array();
foreach ($columns as $column_key => $column) {
$allowed_columns = array(
'cb',
);
if (in_array($column_key, $allowed_columns)) {
$new_columns[$column_key] = $column;
}
}
$new_columns['time'] = esc_html__('Timestamp', 'subscriptio');
$new_columns['action'] = esc_html__('Action', 'subscriptio');
$new_columns['result'] = esc_html__('Result', 'subscriptio');
$new_columns['subscription'] = esc_html__('Subscription', 'subscriptio');
$new_columns['order'] = esc_html__('Order', 'subscriptio');
$new_columns['product'] = esc_html__('Product', 'subscriptio');
$new_columns['subscriptio_note'] = esc_html__('Note', 'subscriptio');
return $new_columns;
}
/**
* Manage subscription list column values
*
* @access public
* @param array $column
* @param int $post_id
* @return void
*/
public function manage_subscription_list_column_values($column, $post_id)
{
$subscription = $this->load_from_cache('subscriptions', $post_id);
switch ($column) {
case 'id':
RightPress_Helper::print_link_to_post($subscription->id);
break;
case 'status':
echo '' . $subscription->status_title . '';
break;
case 'subscriptio_product':
$products = array();
foreach (Subscriptio_Subscription::get_subscription_items($subscription->id) as $item) {
if (!$item['deleted']) {
// WC31: Products will no longer be posts
$products[] = RightPress_Helper::get_link_to_post_html($item['product_id'], $item['name'], '', ($item['quantity'] > 1 ? 'x ' . $item['quantity'] : ''));
}
else {
$products[] = $item['name'];
}
}
echo implode('
', $products);
break;
case 'subscriptio_user':
echo Subscriptio::get_user_full_name_link($subscription->user_id, $subscription->user_full_name);
break;
case 'recurring_amount':
echo $subscription->get_formatted_price($subscription->renewal_order_total);
break;
case 'last_order':
// WC31: Orders will no longer be posts
if (RightPress_Helper::post_is_active($subscription->last_order_id)) {
RightPress_Helper::print_link_to_post($subscription->last_order_id);
}
else {
echo '#' . $subscription->last_order_id . ' (' . esc_html__('deleted', 'subscriptio') . ')';
}
break;
case 'started':
if ($subscription->started) {
$date_format = apply_filters('subscriptio_date_format', get_option('date_format'), 'subscription_list_started');
$date = Subscriptio::get_adjusted_datetime($subscription->started, $date_format);
$date_time = Subscriptio::get_adjusted_datetime($subscription->started, null, 'subscription_list_started');
echo '' . $date . '';
}
else {
echo '—';
}
break;
case 'payment_due':
if ($subscription->payment_due) {
$date_format = apply_filters('subscriptio_date_format', get_option('date_format'), 'subscription_list_payment_due');
$date = Subscriptio::get_adjusted_datetime($subscription->payment_due, $date_format);
$date_time = Subscriptio::get_adjusted_datetime($subscription->payment_due, null, 'subscription_list_payment_due');
echo '' . $date . '';
}
else {
echo '—';
}
break;
case 'expires':
if ($subscription->expires) {
$date_format = apply_filters('subscriptio_date_format', get_option('date_format'), 'subscription_list_expires');
$date = Subscriptio::get_adjusted_datetime($subscription->expires, $date_format);
$date_time = Subscriptio::get_adjusted_datetime($subscription->expires, null, 'subscription_list_expires');
echo '' . $date . '';
}
else {
echo '—';
}
break;
default:
break;
}
}
/**
* Manage transaction list column values
*
* @access public
* @param array $column
* @param int $post_id
* @return void
*/
public function manage_transaction_list_column_values($column, $post_id)
{
$transaction = $this->load_from_cache('transactions', $post_id);
switch ($column) {
case 'time':
echo Subscriptio::get_adjusted_datetime($transaction->time, null, 'subscription_edit_started');
break;
case 'subscription':
if ($transaction->subscription_id) {
if (RightPress_Helper::post_is_active($transaction->subscription_id)) {
RightPress_Helper::print_link_to_post($transaction->subscription_id);
}
else {
echo '#' . $transaction->subscription_id . ' (' . esc_html__('deleted', 'subscriptio') . ')';
}
}
break;
case 'order':
if ($transaction->order_id) {
// WC31: Orders will no longer be posts
if (RightPress_Helper::post_is_active($transaction->order_id)) {
RightPress_Helper::print_link_to_post($transaction->order_id);
}
else {
echo '#' . $transaction->order_id . ' (' . esc_html__('deleted', 'subscriptio') . ')';
}
}
break;
case 'product':
if ($transaction->product_id) {
// Is this a variable product?
$title = $transaction->variation_id ? sprintf(esc_html__('Variation #%1$s of', 'subscriptio'), $transaction->variation_id) . ' #' . $transaction->product_id : '#' . $transaction->product_id;
// Is this product still active?
if (self::product_is_active($transaction->product_id)) {
RightPress_Helper::print_link_to_post($transaction->product_id, $title);
}
else {
echo $title . ' (' . esc_html__('deleted', 'subscriptio') . ')';
}
}
break;
case 'action':
echo '' . $transaction->action_title . '';
break;
case 'result':
echo '' . $transaction->result_title . '';
break;
case 'subscriptio_note':
echo $transaction->note;
break;
default:
break;
}
}
/**
* Load object from cache
*
* @access public
* @param string $type
* @param int $id
* @return object
*/
public function load_from_cache($type, $id)
{
if (!isset($this->cache[$type][$id])) {
$object = $type == 'subscriptions' ? Subscriptio_Subscription::get_by_id($id) : new Subscriptio_Transaction($id);
if (!$object) {
return false;
}
$this->cache[$type][$id] = $object;
}
return $this->cache[$type][$id];
}
/**
* Remove some post actions for custom post type sub_transaction
*
* @access public
* @param array $actions
* @return array
*/
public function sub_transaction_remove_actions($actions)
{
global $post;
if ($post->post_type == 'sub_transaction') {
unset($actions['edit']);
unset($actions['inline hide-if-no-js']);
unset($actions['trash']);
}
return $actions;
}
/**
* Manage subscription list bulk actions
*
* @access public
* @param array $actions
* @return array
*/
public function manage_subscription_list_bulk_actions($actions)
{
$new_actions = array();
foreach ($actions as $action_key => $action) {
if (in_array($action_key, array('trash', 'untrash', 'delete'))) {
$new_actions[$action_key] = $action;
}
}
return $new_actions;
}
/**
* Manage transaction list bulk actions
*
* @access public
* @param array $actions
* @return array
*/
public function manage_transaction_list_bulk_actions($actions)
{
$new_actions = array();
foreach ($actions as $action_key => $action) {
if (in_array($action_key, array('trash', 'untrash', 'delete'))) {
$new_actions[$action_key] = $action;
}
}
return $new_actions;
}
/**
* Manage subscription list views (All, Trash ...)
*
* @access public
* @param array $views
* @return array
*/
public function manage_subscription_list_views($views)
{
$new_views = array();
foreach ($views as $view_key => $view) {
if (in_array($view_key, array('all', 'trash'))) {
$new_views[$view_key] = $view;
}
}
return $new_views;
}
/**
* Manage transaction list views (All, Trash ...)
*
* @access public
* @param array $views
* @return array
*/
public function manage_transaction_list_views($views)
{
$new_views = array();
foreach ($views as $view_key => $view) {
if (in_array($view_key, array('all', 'trash'))) {
$new_views[$view_key] = $view;
}
}
return $new_views;
}
/**
* Expand list search context with more fields
*
* @access public
* @param string $join
* @return string
*/
public function expand_list_search_context_join($join)
{
global $pagenow;
global $wpdb;
$post_types = array('subscription', 'sub_transaction');
if ($pagenow == 'edit.php' && isset($_GET['post_type']) && in_array($_GET['post_type'], $post_types) && isset($_GET['s']) && $_GET['s'] != '') {
$join .= 'LEFT JOIN ' . $wpdb->postmeta . ' pm ON ' . $wpdb->posts . '.ID = pm.post_id ';
}
return $join;
}
/**
* Expand list search context with more fields
*
* @access public
* @param string $where
* @return string
*/
public function expand_list_search_context_where($where)
{
global $pagenow;
global $wpdb;
// Define post types with search contexts, meta field whitelist (searchable meta fields) etc
$post_types = array(
'subscription' => array(
'contexts' => array(
'subscription' => 'ID',
'user' => 'user_id',
'name' => 'user_full_name',
'order' => 'all_order_ids',
'product' => 'product_id',
'variation' => 'variation_id',
),
'meta_whitelist' => array(
'product_name',
'user_full_name',
'all_order_ids',
'product_id',
'variation_id',
),
),
'sub_transaction' => array(
'contexts' => array(
'order' => 'order_id',
'product' => 'product_id',
'variation' => 'variation_id',
'subscription' => 'subscription_id',
),
'meta_whitelist' => array(
'order_id',
'product_id',
'variation_id',
'subscription_id',
),
),
);
if ($pagenow == 'edit.php' && isset($_GET['post_type']) && isset($post_types[$_GET['post_type']]) && !empty($_GET['s'])) {
$search_phrase = trim($_GET['s']);
$exact_match = false;
$context = null;
// Exact match?
if (preg_match('/^\".+\"$/', $search_phrase) || preg_match('/^\'.+\'$/', $search_phrase)) {
$exact_match = true;
$search_phrase = substr($search_phrase, 1, -1);
}
else if (preg_match('/^\\\\\".+\\\\\"$/', $search_phrase) || preg_match('/^\\\\\'.+\\\\\'$/', $search_phrase)) {
$exact_match = true;
$search_phrase = substr($search_phrase, 2, -2);
}
// Or search with context?
else {
foreach ($post_types[$_GET['post_type']]['contexts'] as $context_key => $context_value) {
if (preg_match('/^' . $context_key . '\:/i', $search_phrase)) {
$context = $context_value;
$search_phrase = trim(preg_replace('/^' . $context_key . '\:/i', '', $search_phrase));
break;
}
}
}
// Search by ID?
if ($context == 'ID') {
$replacement = $wpdb->prepare(
'(' . $wpdb->posts . '.ID LIKE %s)',
$search_phrase
);
}
// Search within other context
else if ($context) {
$replacement = $wpdb->prepare(
'(pm.meta_key LIKE %s) AND (pm.meta_value LIKE %s)',
$context,
$search_phrase
);
}
// Regular search
else {
$whitelist = 'pm.meta_key IN (\'' . join('\', \'', $post_types[$_GET['post_type']]['meta_whitelist']) . '\')';
// Exact match?
if ($exact_match) {
$replacement = $wpdb->prepare(
'(' . $wpdb->posts . '.ID LIKE %s) OR (pm.meta_value LIKE %s)',
$search_phrase,
$search_phrase
);
$replacement = '(' . $whitelist . ' AND ' . $replacement . ')';
}
// Regular match
else {
$replacement = '(' . $whitelist . ' AND ((' . $wpdb->posts . '.ID LIKE $1) OR (pm.meta_value LIKE $1)))';
}
}
$where = preg_replace('/\(\s*' . $wpdb->posts . '.post_title\s+LIKE\s*(\'[^\']+\')\s*\)/', $replacement, $where);
}
return $where;
}
/**
* Expand list search context with more fields - group results by id
*
* @access public
* @param string $groupby
* @return string
*/
public function expand_list_search_context_group_by($groupby)
{
global $pagenow;
global $wpdb;
$post_types = array('subscription', 'sub_transaction');
if ($pagenow == 'edit.php' && isset($_GET['post_type']) && in_array($_GET['post_type'], $post_types) && isset($_GET['s']) && $_GET['s'] != '') {
$groupby = $wpdb->posts . '.ID';
}
return $groupby;
}
/**
* Maybe display URL mismatch notification
*
* @access public
* @return void
*/
public function url_mismatch_notification()
{
if (!Subscriptio::is_admin()) {
return;
}
$current_url = $this->get_main_site_url();
if (!empty($_POST['subscriptio_url_mismatch_action'])) {
if ($_POST['subscriptio_url_mismatch_action'] == 'change') {
$this->save_main_site_url($this->get_main_site_url());
}
else if ($_POST['subscriptio_url_mismatch_action'] == 'ignore') {
$this->update_option('subscriptio_ignore_url_mismatch', $current_url);
}
}
else if (!self::is_main_site() && (empty($this->opt['subscriptio_ignore_url_mismatch']) || $this->opt['subscriptio_ignore_url_mismatch'] != $current_url)) {
// Do not display notification on a demo site
if (!RightPress_Helper::is_demo()) {
include SUBSCRIPTIO_PLUGIN_PATH . 'includes/views/backend/admin/url-mismatch-notification.php';
}
}
}
/**
* Maybe save main site URL
*
* @access public
* @return void
*/
public function maybe_save_main_site_url()
{
if (empty($this->opt['subscriptio_main_site_url'])) {
$this->save_main_site_url($this->get_main_site_url());
}
}
/**
* Save main site URL so we can disable some actions on development/staging websites
*
* @access public
* @param string $url
* @return void
*/
public function save_main_site_url($url)
{
$this->update_option('subscriptio_main_site_url', $url);
}
/**
* Get main site URL with placeholder in the middle
*
* @access public
* @return string
*/
public function get_main_site_url()
{
$current_site_url = get_site_url();
return substr_replace($current_site_url, '%%%SUBSCRIPTIO%%%', strlen($current_site_url) / 2, 0);
}
/**
* Check if this is main site - some actions must be cancelled on development/staging websites
*
* @access public
* @return bool
*/
public static function is_main_site()
{
$is_main_site = false;
$subscriptio = self::get_instance();
$current_site_url = get_site_url();
// Make sure we have saved original URL, otherwise treat as duplicate site
if (!empty($subscriptio->opt['subscriptio_main_site_url'])) {
$main_site_url = set_url_scheme(str_replace('%%%SUBSCRIPTIO%%%', '', $subscriptio->opt['subscriptio_main_site_url']));
$is_main_site = $current_site_url == apply_filters('subscriptio_site_url', $main_site_url) ? true : false;
}
return apply_filters('subscriptio_is_main_site', $is_main_site);
}
/**
* Add subscription edit page meta box
*
* @access public
* @param mixed $post
* @return void
*/
public function add_subscription_meta_box($post)
{
if (in_array($post->post_type, array('subscription'))) {
// General subscription details block
add_meta_box(
'subscriptio_subscription_details',
esc_html__('Subscription Details', 'subscriptio'),
array($this, 'render_subscription_meta_box_details'),
'subscription',
'normal',
'high'
);
// Subscription items
add_meta_box(
'subscriptio_subscription_items',
esc_html__('Subscription Items', 'subscriptio'),
array($this, 'render_subscription_meta_box_items'),
'subscription',
'normal',
'high'
);
// Subscription actions
add_meta_box(
'subscriptio_subscription_actions',
esc_html__('Subscription Actions', 'subscriptio'),
array($this, 'render_subscription_meta_box_actions'),
'subscription',
'side',
'default'
);
// Subscription transactions
add_meta_box(
'subscriptio_subscription_transactions',
esc_html__('Transactions', 'subscriptio'),
array($this, 'render_subscription_meta_box_transactions'),
'subscription',
'side',
'default'
);
}
}
/**
* Save subscription custom fields from edit page
*
* @access public
* @param int $post_id
* @param object $post
* @return void
*/
public function save_subscription_meta_box($post_id, $post)
{
// Check if required properties were passed in
if (empty($post_id) || empty($post)) {
return;
}
// Make sure user has permissions to edit this post
if (!current_user_can('edit_post', $post_id)) {
return;
}
// Make sure the correct post ID was passed from form
if (empty($_POST['post_ID']) || $_POST['post_ID'] != $post_id) {
return;
}
// Make sure it is not a draft save action
if (defined('DOING_AUTOSAVE') || is_int(wp_is_post_autosave($post)) || is_int(wp_is_post_revision($post))) {
return;
}
// Proceed only if post type is subscription
if ($post->post_type != 'subscription') {
return;
}
$subscription = $this->load_from_cache('subscriptions', $post_id);
if (!$subscription) {
return;
}
// Actions
if (!empty($_POST['subscriptio_subscription_button']) && $_POST['subscriptio_subscription_button'] == 'actions' && !empty($_POST['subscriptio_subscription_actions'])) {
switch ($_POST['subscriptio_subscription_actions']) {
// Cancel
case 'cancel':
if ($subscription->can_be_cancelled()) {
// Write transaction
$transaction = new Subscriptio_Transaction(null, 'manual_cancellation');
$transaction->add_subscription_id($subscription->id);
$transaction->add_product_id($subscription->product_id);
$transaction->add_variation_id($subscription->variation_id);
try {
// Cancel subscription
$subscription->cancel();
// Update transaction
$transaction->update_result('success');
$transaction->update_note(esc_html__('Subscription cancelled manually by administrator.', 'subscriptio'), true);
}
catch (Exception $e) {
$transaction->update_result('error');
$transaction->update_note($e->getMessage());
$transaction->add_backtrace(debug_backtrace());
}
}
break;
// Pause
case 'pause':
// Make sure that subscription can be paused
if ($subscription->can_be_paused()) {
// Write transaction
$transaction = new Subscriptio_Transaction(null, 'subscription_pause');
$transaction->add_subscription_id($subscription->id);
$transaction->add_product_id($subscription->product_id);
$transaction->add_variation_id($subscription->variation_id);
try {
// Pause subscription
$subscription->pause();
// Update transaction
$transaction->update_result('success');
$transaction->update_note(esc_html__('Subscription paused by administrator.', 'subscriptio'), true);
}
catch (Exception $e) {
$transaction->update_result('error');
$transaction->update_note($e->getMessage());
$transaction->add_backtrace(debug_backtrace());
}
}
break;
// Resume
case 'resume':
// Make sure that subscription can be resumed (was paused)
if ($subscription->can_be_resumed()) {
// Write transaction
$transaction = new Subscriptio_Transaction(null, 'subscription_resume');
$transaction->add_subscription_id($subscription->id);
$transaction->add_product_id($subscription->product_id);
$transaction->add_variation_id($subscription->variation_id);
try {
// Resume subscription
$subscription->resume();
// Update transaction
$transaction->update_result('success');
$transaction->update_note(esc_html__('Subscription resumed by administrator.', 'subscriptio'), true);
}
catch (Exception $e) {
$transaction->update_result('error');
$transaction->update_note($e->getMessage());
$transaction->add_backtrace(debug_backtrace());
}
}
break;
default:
break;
}
}
// Address update
else if (!empty($_POST['subscriptio_subscription_button']) && $_POST['subscriptio_subscription_button'] == 'address') {
$subscription->update_shipping_address($_POST);
}
}
/**
* Render subscription edit page meta box Subscription Details content
*
* @access public
* @param mixed $post
* @return void
*/
public function render_subscription_meta_box_details($post)
{
$subscription = $this->load_from_cache('subscriptions', $post->ID);
if (!$subscription) {
return;
}
// Get subscription statuses
$subscription_statuses = Subscriptio_Subscription::get_statuses();
// Load view
include SUBSCRIPTIO_PLUGIN_PATH . 'includes/views/backend/subscription/subscription-details.php';
}
/**
* Render subscription edit page meta box Subscription Items content
*
* @access public
* @param mixed $post
* @return void
*/
public function render_subscription_meta_box_items($post)
{
$subscription = $this->load_from_cache('subscriptions', $post->ID);
if (!$subscription) {
return;
}
// Load view
include SUBSCRIPTIO_PLUGIN_PATH . 'includes/views/backend/subscription/subscription-items.php';
}
/**
* Render subscription edit page meta box Subscription Actions content
*
* @access public
* @param mixed $post
* @return void
*/
public function render_subscription_meta_box_actions($post)
{
$subscription = $this->load_from_cache('subscriptions', $post->ID);
if (!$subscription) {
return;
}
// Load view
include SUBSCRIPTIO_PLUGIN_PATH . 'includes/views/backend/subscription/subscription-actions.php';
}
/**
* Render subscription edit page meta box Subscription Transactions content
*
* @access public
* @param mixed $post
* @return void
*/
public function render_subscription_meta_box_transactions($post)
{
$subscription = $this->load_from_cache('subscriptions', $post->ID);
if (!$subscription) {
return;
}
// Pass a prepared list of transactions to view
$transactions = array();
// Get all transaction IDs
$query = new WP_Query(array(
'post_type' => 'sub_transaction',
'fields' => 'ids',
'meta_query' => array(
array(
'key' => 'subscription_id',
'value' => $subscription->id,
'compare' => '=',
),
),
));
// Populate list of transactions
foreach ($query->posts as $transaction_id) {
$transactions[] = new Subscriptio_Transaction($transaction_id);
}
// Load view
include SUBSCRIPTIO_PLUGIN_PATH . 'includes/views/backend/subscription/subscription-transactions.php';
}
/**
* Add admin menu items
*
* @access public
* @return void
*/
public function add_admin_menu()
{
// Add submenu links
add_submenu_page(
'edit.php?post_type=subscription',
esc_html__('Settings', 'subscriptio'),
esc_html__('Settings', 'subscriptio'),
Subscriptio::get_admin_capability(),
'subscriptio_settings',
array($this, 'set_up_settings_pages')
);
// Remove Add Subscription if other plugins have set it back
global $submenu;
if (isset($submenu['edit.php?post_type=subscription'])) {
foreach ($submenu['edit.php?post_type=subscription'] as $item_key => $item) {
if (in_array('post-new.php?post_type=subscription', $item)) {
unset($submenu['edit.php?post_type=subscription'][$item_key]);
}
}
}
}
/**
* Register our settings fields with WordPress
*
* @access public
* @return void
*/
public function plugin_options_setup()
{
// Check if current user can manage Subscriptio options
if (Subscriptio::is_admin()) {
// Iterate over tabs
foreach ($this->settings as $tab_key => $tab) {
register_setting(
'subscriptio_opt_group_' . $tab_key,
'subscriptio_options',
array($this, 'options_validate')
);
// Iterate over sections
foreach ($tab['children'] as $section_key => $section) {
// Do not show PayPal Adaptive Payments if it's not enabled
if ($section_key === 'paypal_gateway' && !Subscriptio::option('paypal_enabled')) {
continue;
}
// Add section
add_settings_section(
$section_key,
$section['title'],
array($this, 'render_section_info'),
'subscriptio-admin-' . str_replace('_', '-', $tab_key)
);
// Iterate over fields
foreach ($section['children'] as $field_key => $field) {
// Maybe hide Stripe checkbox
if ($field_key === 'stripe_enabled' && !get_option('rp_sub_stripe_not_migrated')) {
continue;
}
// Add text to display after a field
if (in_array($field_key, array('stripe_enabled', 'paypal_enabled', 'paypal_ec_enabled')) && $this->option($field_key)) {
$payment_gateway_section = 'subscriptio_' . str_replace('_enabled', '', $field_key);
$after = ''.esc_html__('Settings', 'subscriptio').'';
}
else {
$after = isset($field['after']) ? $field['after'] : '';
}
// Add field
add_settings_field(
'subscriptio_' . $field_key,
$field['title'],
array($this, 'render_field_' . $field['type']),
'subscriptio-admin-' . str_replace('_', '-', $tab_key),
$section_key,
array(
'name' => 'subscriptio_' . $field_key,
'options' => $this->opt,
'values' => isset($field['values']) ? $field['values'] : '',
'placeholder' => isset($field['placeholder']) ? $field['placeholder'] : '',
'after' => $after,
)
);
}
}
}
}
}
/**
* Render section info
*
* @access public
* @param array $section
* @return void
*/
public function render_section_info($section)
{
// Subscription Flow
if ($section['id'] === 'subscription_flow') {
echo '
';
echo '
' . esc_html__('Payment reminders, overdue period and suspensions are optional.', 'subscriptio') . '
' . esc_html__('Not displayed in illustration are trial periods, expiration dates and subscription pausing and resuming capability.', 'subscriptio') . '
' . sprintf(esc_html__('You can enable/disable email notifications on the %s page.', 'subscriptio'), ('' . esc_html__('Emails', 'subscriptio') . '')) . '
'; } // PayPal Adaptive Payments warning else if ($section['id'] === 'paypal_gateway' && Subscriptio::option('paypal_enabled')) { echo '' . esc_html__('This payment gateway extension is now deprecated, use PayPal Express Checkout instead.', 'subscriptio') . '
' . esc_html__('Please note that you will not be allowed to enable this extension again after disabling it.', 'subscriptio') . '
' . sprintf(esc_html__('PayPal Express Checkout payment gateway extension comes bundled with Subscriptio. You can use it to enable automatic recurring payments via PayPal. Special %s is required.', 'subscriptio'), ('' . esc_html__('configuration on the PayPal side', 'subscriptio') . '')) . '
'; } // Stripe details else if ($section['id'] === 'stripe_gateway') { // Migration pending if (get_option('rp_sub_stripe_not_migrated')) { echo 'Action required
'; echo 'Subscriptio Stripe payment gateway extension has been discontinued in favour of the WooCommerce Stripe Payment Gateway extension. Subscriptio now includes compatibility code that enables automatic payments using this extension.
'; echo 'Please install the WooCommerce Stripe Payment Gateway extension now, configure and enable it, then click on the migration button below. This will migrate saved payment methods for all customers and their subscriptions, disable the discontinued Subscriptio Stripe extension and enable support for the WooCommerce Stripe Payment Gateway extension. The page may reload a few times in case of larger data sets - please keep this browser tab open until the process is completed.
'; echo 'Please note that the Subscriptio Stripe payment gateway extension will no longer be available after the switch. You must therefore make sure that the new extension is ready to process payments. We recommend to make a test purchase after configuring the new extension.
'; echo 'Your current subscribers will not be affected in any way - their linked cards will continue to be billed as usual.
'; echo '' . sprintf(esc_html__('If you have any questions, please contact %s.', 'subscriptio'), '' . esc_html__('RightPress Support', 'subscriptio') . '') . '
'; echo ''; echo '' . sprintf(esc_html__('Subscriptio integrates with the %s extension to enable automatic subscription payments via Stripe. This payment gateway extension is completely free and is maintained by core WooCommerce developers.', 'subscriptio'), ('' . esc_html__('WooCommerce Stripe Payment Gateway', 'subscriptio') . '')) . '
'; echo '' . esc_html__('Simply offer this payment method during checkout - subsequent subscription payments will be processed automatically.', 'subscriptio') . '
'; } } } /** * Render checkbox field * * @access public * @return void */ public function render_field_checkbox($args = array()) { printf( '%s', $args['name'], $args['name'], checked($args['options'][$args['name']], true, false), !empty($args['after']) ? ' ' . $args['after'] : '' ); } /** * Render checkbox field * * @access public * @return void */ public function render_field_text($args = array()) { if (in_array($args['name'], array('subscriptio_renewal_order_day_offset', 'subscriptio_reminders_days', 'subscriptio_overdue_length', 'subscriptio_suspensions_length', 'subscriptio_max_pauses', 'subscriptio_max_pause_duration'))) { $field_width_class = 'subscriptio_field_width_third'; } else { $field_width_class = 'subscriptio_field_width'; } printf( '%s', $args['name'], $args['name'], $args['options'][$args['name']], $args['placeholder'], !empty($args['after']) ? ' ' . $args['after'] : '' ); } /** * Render a dropdown * * @access public * @param array $args * @return void */ public function render_field_dropdown($args = array()) { printf( ''; } /** * Validate saved options * * @access public * @param array $input * @return void */ public function options_validate($input) { $output = $this->opt; if (empty($_POST['current_tab']) || !isset($this->settings[$_POST['current_tab']])) { return $output; } $errors = array(); // Iterate over fields and validate new values foreach ($this->settings[$_POST['current_tab']]['children'] as $section_key => $section) { foreach ($section['children'] as $field_key => $field) { $current_field_key = 'subscriptio_' . $field_key; switch($field['validation']['rule']) { // Checkbox case 'bool': $input[$current_field_key] = (!isset($input[$current_field_key]) || $input[$current_field_key] == '') ? '0' : $input[$current_field_key]; if (in_array($input[$current_field_key], array('0', '1')) || ($input[$current_field_key] == '' && $field['validation']['empty'] == true)) { $output[$current_field_key] = $input[$current_field_key]; } else { array_push($errors, array('setting' => $current_field_key, 'code' => 'bool', 'title' => $field['title'])); } break; // Number case 'number': if (is_numeric($input[$current_field_key]) || ($input[$current_field_key] == '' && $field['validation']['empty'] == true)) { $output[$current_field_key] = $input[$current_field_key]; } else if ($current_field_key == 'subscriptio_reminders_days') { $reminder_days = explode(',', trim($input[$current_field_key], ',')); $is_ok = true; foreach ($reminder_days as $reminder_day) { if (!is_numeric($reminder_day)) { $is_ok = false; break; } } if ($is_ok) { $output[$current_field_key] = trim($input[$current_field_key], ','); } else { array_push($errors, array('setting' => $current_field_key, 'code' => 'number', 'title' => $field['title'])); } } else { array_push($errors, array('setting' => $current_field_key, 'code' => 'number', 'title' => $field['title'])); } break; // Option case 'option': if (isset($input[$current_field_key]) && (isset($field['values'][$input[$current_field_key]]) || ($input[$current_field_key] == '' && $field['validation']['empty'] == true))) { $output[$current_field_key] = $input[$current_field_key]; } else if (!isset($input[$current_field_key])) { $output[$current_field_key] = ''; } else { array_push($errors, array('setting' => $current_field_key, 'code' => 'option', 'title' => $field['title'])); } break; // Text input and others - default validation rule default: // Make sure the field is set $input[$current_field_key] = (isset($input[$current_field_key])) ? $input[$current_field_key] : ''; if ($input[$current_field_key] == '' && $field['validation']['empty'] === false) { array_push($errors, array('setting' => $current_field_key, 'code' => 'string', 'title' => $field['title'])); } else { $output[$current_field_key] = esc_attr(trim($input[$current_field_key])); } break; } } } // Display settings updated message add_settings_error( 'subscriptio', 'subscriptio_' . 'settings_updated', esc_html__('Your settings have been saved.', 'subscriptio'), 'updated' ); // Display errors foreach ($errors as $error) { $reverted = esc_html__('Reverted to a previous value.', 'subscriptio'); $messages = array( 'number' => esc_html__('must be numeric', 'subscriptio') . '. ' . $reverted, 'bool' => esc_html__('must be either 0 or 1', 'subscriptio') . '. ' . $reverted, 'option' => esc_html__('is not allowed', 'subscriptio') . '. ' . $reverted, 'email' => esc_html__('is not a valid email address', 'subscriptio') . '. ' . $reverted, 'url' => esc_html__('is not a valid URL', 'subscriptio') . '. ' . $reverted, 'string' => esc_html__('is not a valid text string', 'subscriptio') . '. ' . $reverted, ); add_settings_error( 'subscriptio', $error['code'], esc_html__('Value of', 'subscriptio') . ' "' . $error['title'] . '" ' . $messages[$error['code']] ); } return $output; } /** * Set up settings pages * * @access public * @return void */ public function set_up_settings_pages() { // Get current page & tab ids $current_tab = $this->get_current_settings_tab(); // Open form container echo ''; } /** * Get current settings tab * * @access public * @return string */ public function get_current_settings_tab() { // Check if we know tab identifier if (isset($_GET['tab']) && isset($this->settings[$_GET['tab']])) { $tab = $_GET['tab']; } else { $keys = array_keys($this->settings); $tab = array_shift($keys); } return $tab; } /** * Check if it's Subscriptio page and whether to load scripts for backend * * @access public * @return void */ public static function is_subscriptio_page() { // Check the query string if (!isset($_SERVER['QUERY_STRING'])) { return false; } $query = $_SERVER['QUERY_STRING']; if (preg_match('/post_type=(subscription|sub_transaction)/i', $query)) { return true; } // And also check post edit page else if (!empty($_REQUEST['post']) && is_numeric($_REQUEST['post'])) { $post = get_post($_REQUEST['post']); if (is_a($post, 'WP_Post') && in_array($post->post_type, array('subscription', 'sub_transaction'))) { return true; } } return false; } /** * Load backend assets conditionally * * @access public * @return bool */ public function enqueue_backend_assets() { // Our own scripts and styles wp_register_script('subscriptio-backend-scripts', SUBSCRIPTIO_PLUGIN_URL . '/assets/js/backend.js', array('jquery'), SUBSCRIPTIO_VERSION); wp_register_style('subscriptio-backend-styles', SUBSCRIPTIO_PLUGIN_URL . '/assets/css/backend.css', array(), SUBSCRIPTIO_VERSION); // Scripts wp_enqueue_script('subscriptio-backend-scripts'); // Styles wp_enqueue_style('subscriptio-backend-styles'); // Datepicker wp_enqueue_script('jquery-ui-datepicker'); // Datepicker styles wp_register_style('subscriptio-jquery-ui', SUBSCRIPTIO_PLUGIN_URL . '/assets/jquery-ui/jquery-ui.min.css', array(), SUBSCRIPTIO_VERSION); wp_enqueue_style('subscriptio-jquery-ui'); } /** * Load backend assets unconditionally * * @access public * @return bool */ public function enqueue_backend_assets_all() { // Our own scripts and styles wp_register_script('subscriptio-backend-scripts-all', SUBSCRIPTIO_PLUGIN_URL . '/assets/js/backend-all.js', array('jquery'), SUBSCRIPTIO_VERSION); wp_register_style('subscriptio-backend-styles-all', SUBSCRIPTIO_PLUGIN_URL . '/assets/css/backend-all.css', array(), SUBSCRIPTIO_VERSION); // Localize script wp_localize_script('subscriptio-backend-scripts-all', 'subscriptio_vars', array( 'title_subscription_product' => esc_html__('Subscription product', 'subscriptio'), 'current_text' => esc_html__('Today', 'subscriptio'), 'close_text' => esc_html__('Close', 'subscriptio'), 'date_change_alert' => esc_html__('Error! The selected date is incorrect!', 'subscriptio'), )); // Font awesome (icons) wp_register_style('subscriptio-font-awesome', SUBSCRIPTIO_PLUGIN_URL . '/assets/font-awesome/css/font-awesome.min.css', array(), '4.1'); // Scripts wp_enqueue_script('subscriptio-backend-scripts-all'); // Styles wp_enqueue_style('subscriptio-backend-styles-all'); wp_enqueue_style('subscriptio-font-awesome'); // RTL support if (is_rtl()) { wp_register_style('subscriptio-backend-rtl-styles', SUBSCRIPTIO_PLUGIN_URL . '/assets/css/backend-rtl.css', array(), SUBSCRIPTIO_VERSION); wp_enqueue_style('subscriptio-backend-rtl-styles'); } } /** * Load frontend assets * * @access public * @return bool */ public function enqueue_frontend_assets() { // Frontent styles wp_register_style('subscriptio_frontend', SUBSCRIPTIO_PLUGIN_URL . '/assets/css/frontend.css', array(), SUBSCRIPTIO_VERSION); wp_enqueue_style('subscriptio_frontend'); // Frontent scripts wp_register_script('subscriptio_frontend', SUBSCRIPTIO_PLUGIN_URL . '/assets/js/frontend.js', array('jquery'), SUBSCRIPTIO_VERSION); wp_localize_script('subscriptio_frontend', 'subscriptio_vars', array( 'confirm_pause' => esc_html__('Are you sure you want to pause this subscription?', 'subscriptio'), 'confirm_resume' => esc_html__('Are you sure you want to resume this subscription?', 'subscriptio'), 'confirm_cancel' => esc_html__('Are you sure you want to cancel this subscription?', 'subscriptio'), )); wp_enqueue_script('subscriptio_frontend'); // RTL support if (is_rtl()) { wp_register_style('subscriptio-frontend-rtl-styles', SUBSCRIPTIO_PLUGIN_URL . '/assets/css/frontend-rtl.css', array(), SUBSCRIPTIO_VERSION); wp_enqueue_style('subscriptio-frontend-rtl-styles'); } } /** * Allow no guest checkout * * @access public * @param object $checkout * @return void */ public function enforce_registration($checkout) { // User already registered? if (is_user_logged_in()) { return; } // Only proceed if cart contains subscription if (self::cart_contains_subscription()) { // Enable registration if (!$checkout->enable_signup) { $checkout->enable_signup = true; } // Enforce registration if ($checkout->enable_guest_checkout) { $checkout->enable_guest_checkout = false; $checkout->must_create_account = true; } } } /** * Allow no guest checkout * * @access public * @param bool $enforce * @return bool */ public function enforce_registration_new($enforce) { // Only proceed if cart contains subscription if (self::cart_contains_subscription()) { $enforce = true; } return $enforce; } /** * Enforce create new account option * * @access public * @param array $params * @return void */ public function enforce_createaccount_option() { // User already registered? if (is_user_logged_in()) { return; } // Only proceed if cart contains subscription if (self::cart_contains_subscription()) { $_POST['createaccount'] = 1; } } /** * Allow no guest checkout (Javascript part) * * @access public * @param array $properties * @return array */ public function enforce_registration_js($properties) { // User already registered? if (is_user_logged_in()) { return $properties; } // No subscription in cart? if (!self::cart_contains_subscription()) { return $properties; } $properties['option_guest_checkout'] = 'no'; return $properties; } /** * Check if cart contains subscription product * * @access public * @return bool */ public static function cart_contains_subscription() { global $woocommerce; if (!empty($woocommerce->cart->cart_contents)) { foreach ($woocommerce->cart->cart_contents as $item) { if (Subscriptio_Subscription_Product::is_subscription($item['variation_id'] ? $item['variation_id'] : $item['product_id'])) { return true; } } } return false; } /** * Sanitize float (treats as a string) * * @access public * @param string $input * @return string */ public static function sanitize_float($input) { return preg_replace('/[^0-9\.]/', '', $input); } /** * Sanitize integer (treats as a string) * * @access public * @param string $input * @return string */ public static function sanitize_integer($input) { return preg_replace('/[^0-9]/', '', $input); } /** * Get natural number from anything * * @access public * @param string $input * @return int */ public static function get_natural_number($input) { if (!isset($input)) { return 1; } $input = (int) self::sanitize_integer($input); return $input < 1 ? 1 : $input; } /** * Get floating point number from anything (but return as string) * Returns zero (0) if input variable is not properly defined * * @access public * @param string $input * @return string */ public static function get_float_number_as_string($input) { if (!isset($input)) { return '0'; } return (string) (float) self::sanitize_float($input); } /** * Alias for post_is_active * * @access public * @param string $product_id * @return bool */ public static function product_is_active($product_id) { // WC31: Orders will no longer be posts return RightPress_Helper::post_is_active($product_id); } /** * Get timezone-adjusted formatted date/time string * * @access public * @param int $timestamp * @param string $format * @param string $context * @return string */ public static function get_adjusted_datetime($timestamp, $format = null, $context = null) { // Fix possible issues if (empty($timestamp)) { return false; } // No format passed? Get it from WordPress settings and allow developers to override it if ($format === null) { $date_format = apply_filters('subscriptio_date_format', get_option('date_format'), $context); $time_format = apply_filters('subscriptio_time_format', get_option('time_format'), $context); $format = $date_format . (apply_filters('subscriptio_display_event_time', true) ? ' ' . $time_format : ''); } // Get adjusted datetime return RightPress_Helper::get_adjusted_datetime($timestamp, $format); } /** * Get user full name from database with link to user profile or revert to provided name * * @access public * @param int $user_id * @param string $default * @return string */ public static function get_user_full_name_link($user_id, $default) { // User still exists? if ($user = get_userdata($user_id)) { $first_name = get_the_author_meta('first_name', $user_id); $last_name = get_the_author_meta('last_name', $user_id); if ($first_name || $last_name) { $display_name = join(' ', array($first_name, $last_name)); } else { $display_name = $user->display_name; } return '' . $display_name . ''; } return $default . ' (' . esc_html__('deleted', 'subscriptio') . ')'; } /** * Get formatted shipping address * * @access public * @param array $input * @return string */ public static function get_formatted_shipping_address($input) { if (!is_array($input) || empty($input)) { return ''; } $address = array(); foreach ($input as $key => $value) { $address[str_replace('_shipping_', '', $key)] = $value; } $address = apply_filters('woocommerce_order_formatted_shipping_address', $address); return WC()->countries->get_formatted_address($address); } /** * Get price suffix * * @access public * @return string */ public static function get_wc_price_suffix($price) { // Create empty product to access get_price_suffix method $product = new WC_Product(null); return $product->get_price_suffix($price); } /** * Get formatted price * * @access public * @param float $price * @param string $currency * @param bool $sale_price * @param bool $display_price_suffix * @return string */ public static function get_formatted_price($price, $currency = '', $sale_price = false, $display_price_suffix = true) { // Both prices are only needed on shop/product pages, not for cart and checkout $show_both_prices = (is_cart() || is_checkout()) ? false : true; // Do not show both prices if they match if ($price === $sale_price) { $show_both_prices = false; } // Format price if ($sale_price && $show_both_prices && !defined('DOING_AJAX')) { $formatted_price = '' . sprintf(esc_html__('%1$s requires PHP %2$s or later. Please update PHP on your server to use this plugin.', 'subscriptio'), 'Subscriptio', SUBSCRIPTIO_SUPPORT_PHP) . ' ' . sprintf(esc_html__('If you have any questions, please contact %s.', 'subscriptio'), ('' . esc_html__('RightPress Support', 'subscriptio') . '')) . '
' . sprintf(esc_html__('%1$s requires WordPress version %2$s or later. Please update WordPress to use this plugin.', 'subscriptio'), 'Subscriptio', SUBSCRIPTIO_SUPPORT_WP) . ' ' . sprintf(esc_html__('If you have any questions, please contact %s.', 'subscriptio'), ('' . esc_html__('RightPress Support', 'subscriptio') . '')) . '
' . sprintf(esc_html__('%1$s requires WooCommerce to be active. You can download WooCommerce %2$s.', 'subscriptio'), 'Subscriptio', ('' . esc_html__('here', 'subscriptio') . '')) . ' ' . sprintf(esc_html__('If you have any questions, please contact %s.', 'subscriptio'), ('' . esc_html__('RightPress Support', 'subscriptio') . '')) . '
' . sprintf(esc_html__('%1$s requires WooCommerce version %2$s or later. Please update WooCommerce to use this plugin.', 'subscriptio'), 'Subscriptio', SUBSCRIPTIO_SUPPORT_WC) . ' ' . sprintf(esc_html__('If you have any questions, please contact %s.', 'subscriptio'), ('' . esc_html__('RightPress Support', 'subscriptio') . '')) . '
Action required
'; // Content echo 'Subscriptio Stripe payment gateway extension has been discontinued in favour of the WooCommerce Stripe Payment Gateway extension.'; echo '
It is important that you switch to the new payment gateway extension at your earliest convenience.
'; echo 'You can find more details as well as a migration tool in settings.
'; // Close container echo ''; $notice .= sprintf(esc_html__('%s version 2.3.10 was loaded on your site as this looks like a pre-existing installation.', 'subscriptio'), 'Subscriptio'); $notice .= '
'; $notice .= esc_html__('Version 3.0 is available for use on new sites only. This is to give the brand new version some time to mature before it is used on sites with existing subscriptions.', 'subscriptio'); $notice .= '
'; $notice .= esc_html__('We advise you to try version 3.0 on a test site, familiarize with all the changes, as well as review any customizations or integrations.', 'subscriptio'); $notice .= '
'; $notice .= sprintf(esc_html__('Please read our %s for more information.', 'subscriptio'), ('' . esc_html__('upgrade guide', 'subscriptio') . '')); $notice .= '
'; // Print dismiss link if (!isset($_GET['post_type']) || $_GET['post_type'] !== 'subscription' || !isset($_GET['page']) || $_GET['page'] !== 'subscriptio_settings') { $notice .= ''; $notice .= '' . esc_html__('Hide this notice', 'subscriptio') . ''; $notice .= '
'; } // Print notice echo '