mirror of
https://gitlab.com/ArkHost/WP-WHMCS-Pricing.git
synced 2026-09-19 09:27:31 +02:00
218 lines
6.2 KiB
PHP
218 lines
6.2 KiB
PHP
<?php
|
|
/**
|
|
* Shortcode Handler
|
|
*
|
|
* Registers and processes shortcodes
|
|
*/
|
|
|
|
// Exit if accessed directly
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class WHMCS_Pricing_Shortcodes {
|
|
|
|
/**
|
|
* Single instance
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Translations cache
|
|
*/
|
|
private static $translations = null;
|
|
|
|
/**
|
|
* Get instance
|
|
*/
|
|
public static function get_instance() {
|
|
if (null === self::$instance) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
private function __construct() {
|
|
add_shortcode('whmcs_price', array($this, 'render_price_shortcode'));
|
|
}
|
|
|
|
/**
|
|
* Load translations from JSON file
|
|
*/
|
|
private static function load_translations() {
|
|
if (null !== self::$translations) {
|
|
return self::$translations;
|
|
}
|
|
|
|
$json_file = WHMCS_PRICING_PLUGIN_DIR . 'languages.json';
|
|
|
|
if (file_exists($json_file)) {
|
|
$json_content = file_get_contents($json_file);
|
|
self::$translations = json_decode($json_content, true);
|
|
}
|
|
|
|
if (!is_array(self::$translations)) {
|
|
self::$translations = array();
|
|
}
|
|
|
|
return self::$translations;
|
|
}
|
|
|
|
/**
|
|
* Render price shortcode
|
|
*
|
|
* @param array $atts Shortcode attributes
|
|
* @return string HTML output
|
|
*/
|
|
public function render_price_shortcode($atts) {
|
|
// Parse attributes
|
|
$atts = shortcode_atts(array(
|
|
'product_id' => '',
|
|
'billing_cycle' => 'monthly',
|
|
'currency' => '',
|
|
'format' => 'default',
|
|
'show_cycle' => 'true',
|
|
'class' => '',
|
|
'lang' => 'english',
|
|
'language' => '' // Support both lang and language
|
|
), $atts, 'whmcs_price');
|
|
|
|
// Validate product ID
|
|
if (empty($atts['product_id'])) {
|
|
return $this->render_error(__('Product ID is required', 'whmcs-pricing'));
|
|
}
|
|
|
|
// Sanitize attributes
|
|
$product_id = absint($atts['product_id']);
|
|
$billing_cycle = sanitize_text_field($atts['billing_cycle']);
|
|
$currency = !empty($atts['currency']) ? sanitize_text_field($atts['currency']) : '';
|
|
$format = sanitize_text_field($atts['format']);
|
|
$show_cycle = filter_var($atts['show_cycle'], FILTER_VALIDATE_BOOLEAN);
|
|
$custom_class = sanitize_html_class($atts['class']);
|
|
|
|
// Support both 'lang' and 'language' parameters
|
|
$lang = !empty($atts['language']) ? sanitize_text_field($atts['language']) : sanitize_text_field($atts['lang']);
|
|
|
|
// Get price from API
|
|
$price_data = WHMCS_Pricing_API::get_price($product_id, array(
|
|
'billing_cycle' => $billing_cycle,
|
|
'currency' => $currency,
|
|
'format' => $format
|
|
));
|
|
|
|
// Check for errors
|
|
if (is_wp_error($price_data)) {
|
|
return $this->render_error($price_data->get_error_message());
|
|
}
|
|
|
|
// Render the price
|
|
return $this->render_price_html($price_data, $billing_cycle, $product_id, $show_cycle, $custom_class, $lang);
|
|
}
|
|
|
|
/**
|
|
* Render price HTML
|
|
*
|
|
* @param array $price_data Price data from API
|
|
* @param string $billing_cycle Billing cycle
|
|
* @param int $product_id Product ID
|
|
* @param bool $show_cycle Whether to show billing cycle
|
|
* @param string $custom_class Custom CSS class
|
|
* @param string $lang Language code
|
|
* @return string HTML output
|
|
*/
|
|
private function render_price_html($price_data, $billing_cycle, $product_id, $show_cycle, $custom_class, $lang = 'english') {
|
|
$classes = array('whmcs-price');
|
|
|
|
if (!empty($custom_class)) {
|
|
$classes[] = $custom_class;
|
|
}
|
|
|
|
$cycle_text = $show_cycle ? $this->get_cycle_text($billing_cycle, $lang) : '';
|
|
|
|
$html = sprintf(
|
|
'<span class="%s" data-product-id="%d" data-cycle="%s">',
|
|
esc_attr(implode(' ', $classes)),
|
|
esc_attr($product_id),
|
|
esc_attr($billing_cycle)
|
|
);
|
|
|
|
$html .= sprintf(
|
|
'<span class="currency-symbol">%s</span>',
|
|
esc_html($price_data['symbol'])
|
|
);
|
|
|
|
$html .= sprintf(
|
|
'<span class="price-amount">%s</span>',
|
|
esc_html($price_data['formatted'])
|
|
);
|
|
|
|
if (!empty($cycle_text)) {
|
|
$html .= sprintf(
|
|
'<span class="billing-cycle">%s</span>',
|
|
esc_html($cycle_text)
|
|
);
|
|
}
|
|
|
|
$html .= '</span>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Get billing cycle text
|
|
*
|
|
* @param string $cycle Billing cycle
|
|
* @param string $lang Language code
|
|
* @return string Human-readable cycle text
|
|
*/
|
|
private function get_cycle_text($cycle, $lang = 'english') {
|
|
$cycle = strtolower($cycle);
|
|
|
|
// Load translations
|
|
$translations = self::load_translations();
|
|
|
|
// Check if language exists, fallback to English
|
|
if (!isset($translations[$lang])) {
|
|
$lang = 'english';
|
|
}
|
|
|
|
// Get translated text
|
|
if (isset($translations[$lang][$cycle])) {
|
|
return ' ' . $translations[$lang][$cycle];
|
|
}
|
|
|
|
// Final fallback to English defaults
|
|
$defaults = array(
|
|
'monthly' => 'per month',
|
|
'quarterly' => 'per quarter',
|
|
'semiannually' => 'per 6 months',
|
|
'annually' => 'per year',
|
|
'biennially' => 'per 2 years',
|
|
'triennially' => 'per 3 years'
|
|
);
|
|
|
|
return isset($defaults[$cycle]) ? ' ' . $defaults[$cycle] : '';
|
|
}
|
|
|
|
/**
|
|
* Render error message
|
|
*
|
|
* @param string $message Error message
|
|
* @return string HTML output
|
|
*/
|
|
private function render_error($message) {
|
|
// Only show errors to administrators
|
|
if (!current_user_can('manage_options')) {
|
|
return '<span class="whmcs-price whmcs-price-error" style="display:none;"></span>';
|
|
}
|
|
|
|
return sprintf(
|
|
'<span class="whmcs-price whmcs-price-error" style="color: #dc3232; font-style: italic;">[WHMCS Pricing Error: %s]</span>',
|
|
esc_html($message)
|
|
);
|
|
}
|
|
}
|