+
+ 'page',
+ 'name' => 'license-cart', // Check for the slug
+ 'post_status' => 'publish',
+ 'posts_per_page' => 1,
+ ));
+
+ if ($query->have_posts()) {
+ add_settings_error(
+ 'slm_license_cart_error',
+ 'slm_license_cart_exists',
+ __('The License Cart page already exists.', 'slm-plus'),
+ 'error'
+ );
+ return;
+ }
+
+ // Create the License Cart page
+ $page_id = wp_insert_post(array(
+ 'post_title' => 'License Cart',
+ 'post_content' => '',
+ 'post_status' => 'publish',
+ 'post_name' => 'license-cart', // Set the slug
+ 'post_type' => 'page',
+ 'meta_input' => array('_wp_page_template' => 'page-license-cart.php'), // Assign the custom template
+ ));
+
+ // Check if the page was created successfully
+ if ($page_id && !is_wp_error($page_id)) {
+ // Hide the page from menus and navigation
+ update_post_meta($page_id, '_menu_item_visibility', 'hidden');
+ add_settings_error(
+ 'slm_license_cart_success',
+ 'slm_license_cart_created',
+ __('The License Cart page was successfully created.', 'slm-plus'),
+ 'updated'
+ );
+ } else {
+ add_settings_error(
+ 'slm_license_cart_error',
+ 'slm_license_cart_failed',
+ __('Failed to create the License Cart page. Please try again.', 'slm-plus'),
+ 'error'
+ );
+ }
+}
+
+
+add_action('admin_notices', 'slm_license_cart_admin_notices');
+
+function slm_license_cart_admin_notices() {
+ settings_errors('slm_license_cart_error');
+ settings_errors('slm_license_cart_success');
+}
diff --git a/admin/slm-list-licenses-class.php b/admin/slm-list-licenses-class.php
new file mode 100755
index 0000000..88c2477
--- /dev/null
+++ b/admin/slm-list-licenses-class.php
@@ -0,0 +1,551 @@
+ 'item', //singular name of the listed records
+ 'plural' => 'items', //plural name of the listed records
+ 'ajax' => false //does this table support ajax?
+ ));
+ }
+
+ public function no_items()
+ {
+ esc_html_e('No licenses avaliable.', 'slm-plus');
+ }
+
+ function get_views()
+ {
+
+ $base = admin_url('admin.php?page=slm_overview');
+ $current = isset($_GET['view']) ? $_GET['view'] : '';
+
+ $link_html = '
%s (%s)';
+
+ $views = array(
+ 'all' => sprintf(
+ $link_html,
+ esc_url(remove_query_arg('view', $base)),
+ $current === 'all' || $current == '' ? ' class="current"' : '',
+ esc_html__('All', 'slm-plus'),
+ SLM_Utility::get_total_licenses()
+ ),
+ 'active' => sprintf(
+ $link_html,
+ esc_url(add_query_arg('view', 'active', $base . '&s=active')),
+ $current === 'active' ? ' class="current"' : '',
+ esc_html__('active', 'slm-plus'),
+ SLM_Utility::count_licenses('active')
+ ),
+ 'pending' => sprintf(
+ $link_html,
+ esc_url(add_query_arg('view', 'pending', $base . '&s=pending')),
+ $current === 'pending' ? ' class="current"' : '',
+ esc_html__('pending', 'slm-plus'),
+ SLM_Utility::count_licenses('pending')
+ ),
+ 'expired' => sprintf(
+ $link_html,
+ esc_url(add_query_arg('view', 'expired', $base . '&s=expired')),
+ $current === 'expired' ? ' class="current"' : '',
+ esc_html__('expired', 'slm-plus'),
+ SLM_Utility::count_licenses('expired')
+ ),
+ 'blocked' => sprintf(
+ $link_html,
+ esc_url(add_query_arg('view', 'blocked', $base . '&s=blocked')),
+ $current === 'blocked' ? ' class="current"' : '',
+ esc_html__('blocked', 'slm-plus'),
+ SLM_Utility::count_licenses('blocked')
+ )
+ );
+
+ return $views;
+ }
+
+
+ function get_columns()
+ {
+ $columns = array(
+ 'cb' => '
', //Render a checkbox
+ 'id' => __('ID', 'slm-plus'),
+ 'lic_status' => __('Status', 'slm-plus'),
+ 'license_key' => __('Key', 'slm-plus'),
+ 'item_reference' => __('Item reference', 'slm-plus'),
+ 'lic_type' => __('License type', 'slm-plus'),
+ 'email' => __('Email', 'slm-plus'),
+ 'max_allowed_domains' => __('Domains', 'slm-plus'),
+ 'max_allowed_devices' => __('Devices', 'slm-plus'),
+ 'purchase_id_' => __('Order #', 'slm-plus'),
+ 'date_created' => __('Created on', 'slm-plus'),
+ 'date_renewed' => __('Renewed on', 'slm-plus'),
+ 'date_activated' => __('Activated on', 'slm-plus'),
+ 'date_expiry' => __('Expiration', 'slm-plus'),
+ 'until' => __('Until Ver.', 'slm-plus'),
+ 'current_ver' => __('Current Ver.', 'slm-plus')
+ );
+ return $columns;
+ }
+
+ function column_default($item, $column_name)
+ {
+ switch ($column_name) {
+
+ case 'lic_status':
+ return '
' . $item[$column_name] . ' ';
+ break;
+
+ case 'email':
+ return '
' . $item[$column_name] . ' ';
+ break;
+
+ case 'date_expiry':
+ $expiration = $item[$column_name];
+ $date_today = time();
+
+ if ($expiration == '0000-00-00') {
+ return '
' . __(' Lifetime ', 'slm-plus') . ' ' . '
';
+ }
+
+
+ if ($expiration != '0000-00-00') {
+ if (strtotime($expiration) < time()) {
+ return '
' . $expiration . ' ' . '
' . SLM_Utility::get_days_remaining($expiration) . ' day(s) due ';
+ } else {
+ return '
' . $item[$column_name] . ' ' . '
' . SLM_Utility::get_days_remaining($expiration) . ' day(s) left ';
+ }
+ } else {
+ //return $item[$column_name];
+ return '
not set';
+ }
+ break;
+
+ default:
+ return $item[$column_name];
+ }
+ }
+
+ function column_id($item)
+ {
+ $row_id = $item['id'];
+ $actions = array(
+ 'edit' => sprintf('Edit ', $row_id),
+ 'delete' => sprintf('Delete ', $row_id),
+ );
+ return sprintf(
+ ' %1$s %2$s',
+ /*$1%s*/
+ $item['id'],
+ /*$2%s*/
+ $this->row_actions($actions)
+ );
+ }
+
+ function column_active($item)
+ {
+ if ($item['active'] == 1) {
+ return 'active';
+ } else {
+ return 'inactive';
+ }
+ }
+
+ function column_cb($item)
+ {
+
+ return sprintf(
+ ' ',
+ /*$1%s*/
+ $this->_args['singular'], //Let's simply repurpose the table's singular label
+ /*$2%s*/
+ $item['id'] //The value of the checkbox should be the record's id
+ );
+ }
+
+ function get_sortable_columns()
+ {
+ $sortable_columns = array(
+ 'id' => array('id', true),
+ 'email' => array('email', true),
+ 'lic_type' => array('lic_type', true),
+ 'until' => array('until', true),
+ 'current_ver' => array('current_ver', true),
+ 'lic_status' => array('lic_status', true),
+ 'item_reference' => array('item_reference', true),
+ );
+
+ return $sortable_columns;
+ }
+
+ function get_bulk_actions()
+ {
+ $actions = array(
+ 'delete' => 'Delete',
+ 'blocked' => 'Block',
+ 'expired' => 'Expire',
+ 'active' => 'Activate',
+ // 'reminder' => 'Send Reminder',
+ 'export' => 'Export',
+ );
+ return $actions;
+ }
+
+ function process_bulk_action()
+ {
+ if ('delete' === $this->current_action()) {
+ //Process delete bulk actions
+ if (!isset($_REQUEST['item'])) {
+ $error_msg = '' . __('Error - Please select some records using the checkboxes', 'slm-plus') . '
';
+ echo '' . esc_html($error_msg) . '
';
+ return;
+ } else {
+ $nvp_key = $this->_args['singular'];
+ $records_to_delete = $_GET[$nvp_key];
+
+ foreach ($records_to_delete as $row) {
+ SLM_Utility::delete_license_key_by_row_id($row);
+ }
+
+ echo 'Selected records deleted successfully!
';
+ }
+ }
+
+ if ('blocked' === $this->current_action()) {
+ //Process blocked bulk actions
+ if (!isset($_REQUEST['item'])) {
+ $error_msg = '' . __('Error - Please select some records using the checkboxes', 'slm-plus') . '
';
+ echo '' . esc_html($error_msg) . '
';
+ return;
+ } else {
+ $nvp_key = $this->_args['singular'];
+ $licenses_to_block = $_GET[$nvp_key];
+
+ foreach ($licenses_to_block as $row) {
+ SLM_Utility::block_license_key_by_row_id($row);
+ }
+
+ echo '' . esc_html($row) . ' ' . esc_html__('Selected records blocked successfully!', 'slm-plus') . '
';
+ }
+ }
+
+ if ('expired' === $this->current_action()) {
+ //Process expired bulk actions
+ if (!isset($_REQUEST['item'])) {
+ $error_msg = '' . __('Error - Please select some records using the checkboxes', 'slm-plus') . '
';
+ echo '' . esc_html($error_msg) . '
';
+ return;
+ } else {
+ $nvp_key = $this->_args['singular'];
+ $licenses_to_expire = $_GET[$nvp_key];
+
+ foreach ($licenses_to_expire as $row) {
+ SLM_Utility::expire_license_key_by_row_id($row);
+ }
+
+ echo '' . esc_html($row) . ' ' . esc_html__('Selected records expired successfully!', 'slm-plus') . '
';
+ }
+ }
+
+ if ('active' === $this->current_action()) {
+ //Process activate bulk actions
+ if (!isset($_REQUEST['item'])) {
+ $error_msg = '' . __('Error - Please select some records using the checkboxes', 'slm-plus') . '
';
+ echo '' . esc_html($error_msg) . '
';
+ return;
+ } else {
+ $nvp_key = $this->_args['singular'];
+ $liceses_to_activate = $_GET[$nvp_key];
+
+ foreach ($liceses_to_activate as $row) {
+ SLM_Utility::active_license_key_by_row_id($row);
+ }
+
+ echo '' . esc_html($row) . ' ' . esc_html__('Selected records activated successfully!', 'slm-plus') . '
';
+ }
+ }
+
+ // Export license data
+ if ('export' === $this->current_action()) {
+ if (!isset($_REQUEST['item'])) {
+ $error_msg = '' . __('Error - Please select some records using the checkboxes', 'slm-plus') . '
';
+ echo '' . esc_html($error_msg) . '
';
+ return;
+ } else {
+ $nvp_key = $this->_args['singular'];
+ $licenses_to_export = $_GET[$nvp_key];
+
+ // Call the export function
+ $file_urls = self::export_license_data($licenses_to_export);
+
+ // Display success message with download links for each license
+ echo '';
+ echo '
Export successful! Download the CSV files:
';
+ foreach ($file_urls as $file_url) {
+ echo '
Download CSV File
';
+ }
+ echo '
';
+ }
+ }
+ }
+
+ public static function export_license_data($license_ids)
+ {
+ global $wpdb;
+
+ // Fetch the custom directory path from options (saved with hash)
+ $slm_options = get_option('slm_plugin_options');
+ $custom_dir_hash = isset($slm_options['slm_backup_dir_hash']) ? $slm_options['slm_backup_dir_hash'] : '';
+
+ // Prepare file URLs array
+ $file_urls = [];
+
+ // Get the WordPress upload directory
+ $upload_dir = wp_upload_dir();
+ $custom_dir = $upload_dir['basedir'] . '/' . $custom_dir_hash;
+
+ // Initialize WP_Filesystem for safe file handling
+ if (empty($GLOBALS['wp_filesystem'])) {
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ WP_Filesystem();
+ }
+
+ // Ensure the directory exists using WP_Filesystem methods
+ if (!is_dir($custom_dir)) {
+ $created = $GLOBALS['wp_filesystem']->mkdir($custom_dir, 0755); // Create the directory if it doesn't exist
+ if (!$created) {
+ return new WP_Error('directory_creation_failed', 'Unable to create the directory.');
+ }
+ }
+
+ // Fetch license data for each selected ID
+ foreach ($license_ids as $license_id) {
+ $data = $wpdb->get_row($wpdb->prepare(
+ "SELECT * FROM " . SLM_TBL_LICENSE_KEYS . " WHERE id = %d",
+ $license_id
+ ), ARRAY_A);
+
+ if ($data) {
+ $license_key = $data['license_key'];
+
+ // Prepare file name as "license_key.csv"
+ $file_name = sanitize_file_name($license_key) . '.csv';
+ $file_path = $custom_dir . '/' . $file_name;
+
+ // Open file handle using WP_Filesystem methods
+ $file_handle = $GLOBALS['wp_filesystem']->open($file_path, 'w');
+
+ if (!$file_handle) {
+ return new WP_Error('file_creation_failed', 'Unable to open the file for writing.');
+ }
+
+ // Write CSV headers and license data to the file
+ fputcsv($file_handle, array_keys($data));
+ fputcsv($file_handle, $data);
+
+ // Close the file handle
+ $GLOBALS['wp_filesystem']->close($file_handle);
+
+ // Store the file URL for download
+ $file_urls[] = $upload_dir['baseurl'] . '/' . $custom_dir_hash . '/' . $file_name;
+ }
+ }
+
+ // Return the array of file URLs
+ return $file_urls;
+ }
+
+
+
+ /*
+ * This function will delete the selected license key entries from the DB.
+ */
+ function delete_license_key($key_row_id)
+ {
+ SLM_Utility::delete_license_key_by_row_id($key_row_id);
+ $success_msg = '';
+ $success_msg .= 'The selected entry was deleted successfully!';
+ $success_msg .= '
';
+ echo esc_html($success_msg);
+ }
+
+ function block_license_key($key_row_id)
+ {
+ SLM_Utility::block_license_key_by_row_id($key_row_id);
+ $success_msg = '';
+ $success_msg .= 'The selected entry was blocked successfully!';
+ $success_msg .= '
';
+ echo esc_html($success_msg);
+ }
+
+ private function sort_data($a, $b)
+ {
+ // Set defaults
+ $orderby = 'id';
+ $order = 'desc';
+
+ // Sanitize and unslash input for 'orderby' and 'order'
+ if (!empty($_GET['orderby'])) {
+ $orderby = wp_unslash($_GET['orderby']); // wp_unslash before sanitization
+ $orderby = sanitize_key($orderby); // sanitize for key-based data
+ }
+
+ if (!empty($_GET['order'])) {
+ $order = wp_unslash($_GET['order']); // wp_unslash before sanitization
+ $order = in_array(strtolower($order), ['asc', 'desc']) ? strtolower($order) : 'desc'; // Ensure 'asc' or 'desc' only
+ }
+
+ // Sorting logic
+ if ($orderby == 'id') {
+ if ($a[$orderby] == $b[$orderby]) {
+ $result = 0;
+ } else {
+ $result = ($a[$orderby] < $b[$orderby]) ? -1 : 1;
+ }
+ } else {
+ $result = strcmp($a[$orderby], $b[$orderby]);
+ }
+
+ // Return based on the order (asc or desc)
+ if ($order === 'asc') {
+ return $result;
+ }
+
+ return -$result;
+ }
+
+ function prepare_items()
+ {
+ global $wpdb;
+ $user = get_current_user_id();
+ $screen = get_current_screen();
+ $option = $screen->get_option('per_page', 'option');
+ $per_page = get_user_meta($user, $option, true);
+
+ if (empty($per_page) || $per_page < 1) {
+ $per_page = $screen->get_option('per_page', 'default');
+ }
+
+ $columns = $this->get_columns();
+ $hidden = get_hidden_columns($screen);
+ $sortable = $this->get_sortable_columns();
+ $this->_column_headers = array($columns, $hidden, $sortable);
+
+ $this->process_bulk_action();
+
+ // Ensure the license table constant is used safely
+ $license_table = esc_sql(SLM_TBL_LICENSE_KEYS); // Sanitize the table name
+
+ // Search handling with esc_like for wildcard search
+ $search = isset($_REQUEST['s']) ? sanitize_text_field(wp_unslash($_REQUEST['s'])) : ''; // Use wp_unslash to handle slashes
+ $search_term = wp_strip_all_tags($search); // Using wp_strip_all_tags instead of strip_tags
+ $search_term_esc = addcslashes($search_term, '_%'); // Escapes underscore and percent characters
+
+ // Prepared query with placeholders and escaped search term
+ $do_search = $wpdb->prepare(
+ "SELECT * FROM $license_table
+ WHERE license_key LIKE %s OR email LIKE %s OR lic_status LIKE %s OR first_name LIKE %s OR last_name LIKE %s",
+ '%' . $search_term_esc . '%', // Apply wildcard to the escaped search term
+ '%' . $search_term_esc . '%',
+ '%' . $search_term_esc . '%',
+ '%' . $search_term_esc . '%',
+ '%' . $search_term_esc . '%'
+ );
+
+ // Execute the query and get the results
+ $data = $wpdb->get_results($do_search, ARRAY_A);
+
+ // Sort data
+ usort($data, array(&$this, 'sort_data'));
+
+ // Pagination
+ $current_page = $this->get_pagenum();
+ $total_items = count($data);
+ $data = array_slice($data, (($current_page - 1) * $per_page), $per_page);
+
+ $this->items = $data;
+
+ // Set pagination arguments
+ $this->set_pagination_args(array(
+ 'total_items' => $total_items,
+ 'per_page' => $per_page,
+ 'total_pages' => ceil($total_items / $per_page)
+ ));
+ }
+}
+
+class SLM_Plugin
+{
+ // class instance
+ static $instance;
+
+ // customer WP_List_Table object
+ public $licenses_obj;
+
+ // class constructor
+ public function __construct()
+ {
+ add_filter('set-screen-option', [__CLASS__, 'set_screen'], 10, 3);
+ add_action('admin_menu', [$this, 'slm_add_admin_menu']);
+ }
+
+ public static function set_screen($status, $option, $value)
+ {
+ return $value;
+ }
+
+ public function slm_add_admin_menu()
+ {
+ $icon_svg = SLM_ASSETS_URL . 'images/slm_logo_small.svg';
+ add_menu_page(__('SLM Plus', 'slm-plus'), __('SLM Plus', 'slm-plus'), SLM_MANAGEMENT_PERMISSION, SLM_MAIN_MENU_SLUG, "slm_manage_licenses_menu", $icon_svg);
+ $hook = add_submenu_page(SLM_MAIN_MENU_SLUG, __('Manage Licenses', 'slm-plus'), __('Manage Licenses', 'slm-plus'), SLM_MANAGEMENT_PERMISSION, SLM_MAIN_MENU_SLUG, "slm_manage_licenses_menu");
+ add_submenu_page(SLM_MAIN_MENU_SLUG, __('Create license', 'slm-plus'), __('Create license', 'slm-plus'), SLM_MANAGEMENT_PERMISSION, 'slm_manage_license', "slm_add_licenses_menu");
+ add_submenu_page(SLM_MAIN_MENU_SLUG, __('Subscribers', 'slm-plus'), __('Subscribers', 'slm-plus'), SLM_MANAGEMENT_PERMISSION, 'slm_subscribers', "slm_subscribers_menu");
+ add_submenu_page(SLM_MAIN_MENU_SLUG, __('Tools', 'slm-plus'), __('Tools', 'slm-plus'), SLM_MANAGEMENT_PERMISSION, 'slm_admin_tools', "slm_admin_tools_menu");
+ add_submenu_page(SLM_MAIN_MENU_SLUG, __('Settings', 'slm-plus'), __('Settings', 'slm-plus'), SLM_MANAGEMENT_PERMISSION, 'slm_settings', "slm_settings_menu");
+ add_submenu_page(SLM_MAIN_MENU_SLUG, __('Help', 'slm-plus'), __('Help', 'slm-plus'), SLM_MANAGEMENT_PERMISSION, 'slm_help', "slm_integration_help_menu");
+ add_submenu_page(SLM_MAIN_MENU_SLUG, __('About', 'slm-plus'), __('About', 'slm-plus'), SLM_MANAGEMENT_PERMISSION, 'slm_about', "slm_about_menu");
+ add_action("load-" . $hook, [$this, 'screen_option']);
+ }
+
+ /**
+ * Screen options
+ */
+ public function screen_option()
+ {
+ $option = 'per_page';
+ $args = [
+ 'label' => 'Pagination',
+ 'default' => 16,
+ 'option' => 'licenses_per_page'
+ ];
+ add_screen_option($option, $args);
+ $this->licenses_obj = new SLM_List_Licenses();
+ }
+
+ /** Singleton instance */
+ public static function get_instance()
+ {
+ if (!isset(self::$instance)) {
+ self::$instance = new self();
+ }
+
+ return self::$instance;
+ }
+}
+
+add_action('plugins_loaded', function () {
+ SLM_Plugin::get_instance();
+});
diff --git a/admin/slm-manage-licenses.php b/admin/slm-manage-licenses.php
new file mode 100755
index 0000000..83b8a6e
--- /dev/null
+++ b/admin/slm-manage-licenses.php
@@ -0,0 +1,76 @@
+ false,
+ 'message' => esc_html__('You do not have permission to manage this license.', 'slm-plus'),
+ );
+ echo json_encode($response);
+ die();
+ }
+}
+
+function slm_manage_licenses_menu()
+{
+ //include_once('slm-list-licenses-class.php');
+ $license_list = new SLM_List_Licenses();
+
+ if (isset($_REQUEST['action'])) { //Do list table form row action tasks
+ if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'delete_license') { //Delete link was clicked for a row in list table
+ $license_list->delete_license_key(sanitize_text_field($_REQUEST['id']));
+ }
+ }
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ prepare_items();
+ $license_list->search_box(__('Search', 'slm-plus'), 'search-box-id');
+ $license_list->views();
+ $license_list->display(); ?>
+
+
+
+
+
+
+
+
+
+
+ 'slm_subscriber',
+ 'plural' => 'slm_subscribers',
+ 'ajax' => false
+ ));
+ }
+
+ function column_default($item, $column_name)
+ {
+ switch ($column_name) {
+
+ case 'lic_status':
+ return ' ' . $item[$column_name] . ' ';
+ break;
+
+ default:
+ return $item[$column_name];
+ }
+ }
+
+
+
+ function column_id($item)
+ {
+ $row_id = $item['id'] . '&email=' . $item['email'];
+ $actions = array(
+ 'edit' => sprintf('View ', $row_id),
+ );
+ return sprintf(
+ ' %1$s %2$s',
+ /*$1%s*/
+ $item['id'],
+ /*$2%s*/
+ $this->row_actions($actions)
+ );
+ }
+
+
+ function column_active($item)
+ {
+ if ($item['active'] == 1) {
+ return 'active';
+ } else {
+ return 'inactive';
+ }
+ }
+
+
+
+
+ function column_cb($item)
+ {
+
+ return sprintf(
+ ' ',
+ /*$1%s*/
+ $this->_args['singular'], //Let's simply repurpose the table's singular label
+ /*$2%s*/
+ $item['id'] //The value of the checkbox should be the record's id
+ );
+ }
+
+ function get_columns()
+ {
+ $columns = array(
+ 'cb' => ' ', //Render a checkbox
+ 'id' => __('ID', 'slm-plus'),
+ 'first_name' => __('First Name', 'slm-plus'),
+ 'last_name' => __('Last Name', 'slm-plus'),
+ 'email' => __('Email Address', 'slm-plus')
+ );
+ return $columns;
+ }
+
+
+ function get_sortable_columns()
+ {
+ $sortable_columns = array(
+ 'id' => array('id', true),
+ 'email' => array('email', true),
+ 'first_name' => array('first_name', true),
+ 'last_name' => array('last_name', true)
+ );
+
+ return $sortable_columns;
+ }
+
+ private function sort_data($a, $b)
+ {
+ // Set defaults
+ $orderby = 'id';
+ $order = 'desc';
+ // If orderby is set, use this as the sort column
+ if (!empty($_GET['orderby'])) {
+ $orderby = $_GET['orderby'];
+ }
+ // If order is set use this as the order
+ if (!empty($_GET['order'])) {
+ $order = $_GET['order'];
+ }
+ if ($orderby == 'id') {
+ if ($a[$orderby] == $b[$orderby]) {
+ $result = 0;
+ } else {
+ $result = ($a[$orderby] < $b[$orderby]) ? -1 : 1;
+ }
+ } else {
+ $result = strcmp($a[$orderby], $b[$orderby]);
+ }
+ if ($order === 'asc') {
+ return $result;
+ }
+ return -$result;
+ }
+
+ function prepare_items()
+ {
+ $per_page = 24;
+ $columns = $this->get_columns();
+ $hidden = array();
+ $sortable = $this->get_sortable_columns();
+
+ $this->_column_headers = array($columns, $hidden, $sortable);
+ $this->process_bulk_action();
+
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ // Sanitize the search term and strip all tags
+ $search = isset($_REQUEST['s']) ? sanitize_text_field(wp_unslash($_REQUEST['s'])) : false;
+ $search_term = trim(wp_strip_all_tags($search)); // Using wp_strip_all_tags for better sanitization
+
+ // Escape the search term for SQL and add wildcards manually
+ $escaped_search_term = '%' . $wpdb->esc_like($search_term) . '%'; // esc_like handles escaping the term
+
+ // Prepare the query with placeholders to prevent SQL injection
+ $do_search = $wpdb->prepare(
+ "SELECT * FROM {$license_table}
+ WHERE `email` LIKE %s
+ OR `first_name` LIKE %s
+ OR `last_name` LIKE %s
+ GROUP BY `email`",
+ $escaped_search_term, // Use the escaped search term with wildcards
+ $escaped_search_term,
+ $escaped_search_term
+ );
+
+ // Execute the query safely
+ $data = $wpdb->get_results($do_search, ARRAY_A);
+
+ usort($data, array(&$this, 'sort_data'));
+
+ // Pagination logic
+ $current_page = $this->get_pagenum();
+ $total_items = count($data);
+ $data = array_slice($data, (($current_page - 1) * $per_page), $per_page);
+ $this->items = $data;
+
+ // Set pagination arguments
+ $this->set_pagination_args(array(
+ 'total_items' => $total_items,
+ 'per_page' => $per_page,
+ 'total_pages' => ceil($total_items / $per_page)
+ ));
+ }
+}
+
+function slm_subscribers_menu()
+{
+ $subscribers_list = new Subscribers_List_Table();
+ $slm_subscriber_edit = isset($_REQUEST['slm_subscriber_edit']) ? sanitize_text_field($_REQUEST['slm_subscriber_edit']) : '';
+ if ($slm_subscriber_edit === 'true') : ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ prepare_items();
+ $subscribers_list->search_box(__('Search', 'slm-plus'), 'search-box-id');
+ $subscribers_list->views();
+ $subscribers_list->display(); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+Choose this date to set when the license should renew or expire. "
+" Format: %s (input: YYYY-MM-DD)."
+msgstr ""
+
+#: admin/slm-add-licenses.php:538
+msgid "Renewal"
+msgstr ""
+
+#: admin/slm-add-licenses.php:542 admin/slm-lic-settings.php:167
+msgid "Billing Length"
+msgstr ""
+
+#: admin/slm-add-licenses.php:545
+msgid ""
+"Sets how often the license renews. E.g., a length of 2 with a term of years "
+"means the license renews every 2 years."
+msgstr ""
+
+#: admin/slm-add-licenses.php:550 admin/slm-lic-settings.php:173
+#: woocommerce/includes/slm-meta-boxes.php:207
+msgid "Expiration Term"
+msgstr ""
+
+#: admin/slm-add-licenses.php:552 admin/slm-lic-settings.php:176
+#: woocommerce/includes/slm-meta-boxes.php:211
+msgid "Day(s)"
+msgstr ""
+
+#: admin/slm-add-licenses.php:553 admin/slm-lic-settings.php:177
+#: woocommerce/includes/slm-meta-boxes.php:212
+msgid "Month(s)"
+msgstr ""
+
+#: admin/slm-add-licenses.php:554 admin/slm-lic-settings.php:178
+#: woocommerce/includes/slm-meta-boxes.php:213
+msgid "Year(s)"
+msgstr ""
+
+#: admin/slm-add-licenses.php:557
+msgid "Choose the renewal period: days, months, or years."
+msgstr ""
+
+#: admin/slm-add-licenses.php:564
+msgid "Subscriber ID"
+msgstr ""
+
+#: admin/slm-add-licenses.php:568
+#: woocommerce/includes/wc_licenses_class.php:205
+msgid "Date Renewed"
+msgstr ""
+
+#: admin/slm-add-licenses.php:579
+#: woocommerce/includes/wc_licenses_class.php:204
+msgid "Date Activated"
+msgstr ""
+
+#: admin/slm-add-licenses.php:593
+msgid "Transaction Information"
+msgstr ""
+
+#: admin/slm-add-licenses.php:599 woocommerce/includes/slm-meta-boxes.php:174
+msgid "Item Reference"
+msgstr ""
+
+#: admin/slm-add-licenses.php:604
+msgid "Transaction ID"
+msgstr ""
+
+#: admin/slm-add-licenses.php:609
+msgid "Purchase ID"
+msgstr ""
+
+#: admin/slm-add-licenses.php:614
+#: woocommerce/includes/wc_licenses_class.php:207
+msgid "Product Reference"
+msgstr ""
+
+#: admin/slm-add-licenses.php:622
+msgid "Other"
+msgstr ""
+
+#: admin/slm-add-licenses.php:627
+msgid "Until"
+msgstr ""
+
+#: admin/slm-add-licenses.php:631 admin/slm-lic-settings.php:155
+#: woocommerce/includes/slm-meta-boxes.php:224
+msgid "Current Version"
+msgstr ""
+
+#: admin/slm-add-licenses.php:635
+msgid "Reminder Sent"
+msgstr ""
+
+#: admin/slm-add-licenses.php:639
+msgid "Reminder Sent Date"
+msgstr ""
+
+#: admin/slm-add-licenses.php:651
+msgid "Manual Reset Count"
+msgstr ""
+
+#: admin/slm-add-licenses.php:659
+msgid "Update License"
+msgstr ""
+
+#: admin/slm-add-licenses.php:661 woocommerce/includes/slm-meta-boxes.php:395
+#: woocommerce/includes/slm-meta-boxes.php:399
+msgid "Create License"
+msgstr ""
+
+#: admin/slm-admin-functions.php:14
+msgid "SLM Plus - Tools"
+msgstr ""
+
+#: admin/slm-admin-functions.php:30
+msgid "Success message returned from the remote host."
+msgstr ""
+
+#: admin/slm-admin-functions.php:33
+msgid "Request sent to the specified URL!"
+msgstr ""
+
+#: admin/slm-admin-functions.php:45
+msgid "Log was cleared successfully!"
+msgstr ""
+
+#: admin/slm-admin-functions.php:51
+msgid "Send Deactivation Message for a License"
+msgstr ""
+
+#: admin/slm-admin-functions.php:56
+msgid "Send Request"
+msgstr ""
+
+#: admin/slm-admin-functions.php:63
+msgid "Clean Activity Log"
+msgstr ""
+
+#: admin/slm-admin-functions.php:65
+msgid "This will clear/reset license keys activities"
+msgstr ""
+
+#: admin/slm-admin-functions.php:68
+msgid "Clear Log"
+msgstr ""
+
+#: admin/slm-admin-functions.php:75
+msgid "Backup Database"
+msgstr ""
+
+#: admin/slm-admin-functions.php:77
+msgid ""
+"This will create a backup of the database tables related to this plugin and "
+"save it to the uploads directory."
+msgstr ""
+
+#: admin/slm-admin-functions.php:80
+msgid "Create Backup"
+msgstr ""
+
+#: admin/slm-admin-functions.php:90
+msgid "Last backup created on: "
+msgstr ""
+
+#: admin/slm-admin-functions.php:90
+msgid "Download Backup"
+msgstr ""
+
+#: admin/slm-admin-functions.php:97
+msgid "Generate License for WooCommerce Orders"
+msgstr ""
+
+#: admin/slm-admin-functions.php:100 admin/slm-lic-settings.php:249
+msgid ""
+"This tool generates bulk licenses for WooCommerce orders placed before the "
+"plugin was activated or for orders that lack existing licenses."
+msgstr ""
+
+#: admin/slm-admin-functions.php:101 admin/slm-lic-settings.php:250
+msgid "Warning:"
+msgstr ""
+
+#: admin/slm-admin-functions.php:102 admin/slm-lic-settings.php:251
+msgid ""
+"This action cannot be undone. Please back up your database before proceeding."
+msgstr ""
+
+#: admin/slm-admin-functions.php:112
+msgid "Product ID"
+msgstr ""
+
+#: admin/slm-admin-functions.php:114
+msgid "Enter Product ID"
+msgstr ""
+
+#: admin/slm-admin-functions.php:115
+msgid "Specify the default product ID for license generation."
+msgstr ""
+
+#: admin/slm-admin-functions.php:120
+msgid "Subscription Type"
+msgstr ""
+
+#: admin/slm-admin-functions.php:126
+msgid "Select the type of license for the order."
+msgstr ""
+
+#: admin/slm-admin-functions.php:133
+msgid "Generate Licenses"
+msgstr ""
+
+#: admin/slm-admin-functions.php:137
+msgid ""
+"Please enable the WooCommerce License Generator option to activate the "
+"Generate Licenses tool."
+msgstr ""
+
+#: admin/slm-admin-functions.php:147
+msgid "License Generation Results:"
+msgstr ""
+
+#: admin/slm-admin-functions.php:165
+msgid "Product ID cannot be empty."
+msgstr ""
+
+#: admin/slm-admin-functions.php:166
+msgid "Product ID is required."
+msgstr ""
+
+#: admin/slm-admin-functions.php:170
+msgid "Subscription Type cannot be empty."
+msgstr ""
+
+#: admin/slm-admin-functions.php:171
+msgid "Subscription Type is required."
+msgstr ""
+
+#: admin/slm-admin-functions.php:193
+msgid "Licenses generated successfully!"
+msgstr ""
+
+#: admin/slm-admin-functions.php:196
+msgid "Some licenses failed to generate. Check the response for details."
+msgstr ""
+
+#: admin/slm-admin-functions.php:200
+msgid "There was an error processing the request. Please try again."
+msgstr ""
+
+#: admin/slm-admin-functions.php:201
+msgid "There was an error processing the request."
+msgstr ""
+
+#: admin/slm-admin-functions.php:283
+msgid "Backup created successfully! Download from: "
+msgstr ""
+
+#: admin/slm-admin-functions.php:285
+msgid "Error: Failed to create the backup file."
+msgstr ""
+
+#. Plugin Name of the plugin/theme
+#: admin/slm-dashboard-widgets.php:30 admin/slm-list-licenses-class.php:466
+msgid "SLM Plus"
+msgstr ""
+
+#: admin/slm-dashboard-widgets.php:33
+msgid "slm-plus"
+msgstr ""
+
+#: admin/slm-dashboard-widgets.php:42
+msgid "Overview"
+msgstr ""
+
+#: admin/slm-dashboard-widgets.php:52
+msgid "Add new license"
+msgstr ""
+
+#: admin/slm-dashboard-widgets.php:62 admin/slm-list-licenses-class.php:471
+#: slm-plus.php:69
+msgid "Settings"
+msgstr ""
+
+#: admin/slm-dashboard-widgets.php:79
+msgid "Manage licenses"
+msgstr ""
+
+#: admin/slm-dashboard-widgets.php:80
+msgid "Total active licenses"
+msgstr ""
+
+#: admin/slm-dashboard-widgets.php:120
+msgid "Recent Licenses"
+msgstr ""
+
+#: admin/slm-dashboard-widgets.php:121
+msgid "View All"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:14
+msgid "SLM Plus - Integration Help"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:15
+msgid "Version:"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:21
+msgid "API Settings"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:29
+msgid "License API Query POST URL for Your Installation"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:32
+msgid "License Activation/Deactivation API Secret Key"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:35
+msgid "License Creation API Secret Key"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:41
+msgid "Documentation and Guides"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:43
+msgid "Need more help? Check out the documentation:"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:45
+msgid "Postman API Demos"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:52
+msgid "Error Codes and Descriptions"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:57
+msgid "Constant"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:58
+msgid "Error Code"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:59
+msgid "Description"
+msgstr ""
+
+#: admin/slm-integration-help-page.php:65
+msgid "The license creation failed due to an unknown error."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:66
+msgid "The license key provided during creation is invalid."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:67
+msgid "The domain associated with this license is already inactive."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:68
+msgid "The domain information is missing in the request."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:69
+msgid "The license key has been canceled."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:70
+msgid "Failed to cancel the license key."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:71
+msgid "Successfully deactivated the license key for the specified domain."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:72
+msgid "The license key was successfully deactivated."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:73
+msgid "Failed to delete the license key."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:74
+msgid "The license key was successfully deleted."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:75
+msgid "The license key has been deleted."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:76
+msgid "Failed to update the license key details."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:77
+msgid "The license key was successfully updated."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:78
+msgid "The license key was successfully activated."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:79
+msgid "The license key has been blocked from further use."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:80
+msgid "The license key was successfully created."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:81
+msgid "The license key already exists in the system."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:82
+msgid "The license key has expired."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:83
+msgid "The license key is already in use on another domain or device."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:84
+msgid "The license key is invalid."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:85
+msgid "Failed to delete the license key because it was not found."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:86
+msgid "Failed to update the license key because it was not found."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:87
+msgid "The license key has reached its maximum allowable devices."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:88
+msgid "The license key has reached its maximum allowable domains."
+msgstr ""
+
+#: admin/slm-integration-help-page.php:89
+msgid "The key verification failed due to an invalid key."
+msgstr ""
+
+#: admin/slm-lic-settings.php:72
+msgid "Options updated!"
+msgstr ""
+
+#: admin/slm-lic-settings.php:85
+msgid "SLM Plus - Settings"
+msgstr ""
+
+#: admin/slm-lic-settings.php:91
+msgid "General"
+msgstr ""
+
+#: admin/slm-lic-settings.php:95
+msgid "Integrations"
+msgstr ""
+
+#: admin/slm-lic-settings.php:99
+msgid "Debugging"
+msgstr ""
+
+#: admin/slm-lic-settings.php:103
+msgid "Emails"
+msgstr ""
+
+#: admin/slm-lic-settings.php:115
+msgid "Secret Key for License Creation"
+msgstr ""
+
+#: admin/slm-lic-settings.php:118
+msgid ""
+"This secret key will be used to authenticate any license creation request. "
+"You can change it with something random."
+msgstr ""
+
+#: admin/slm-lic-settings.php:122
+msgid "Secret Key for License Verification Requests"
+msgstr ""
+
+#: admin/slm-lic-settings.php:124
+msgid ""
+"This secret key will be used to authenticate any license verification "
+"request from customer's site. Important! Do not change this value once your "
+"customers start to use your product(s)!"
+msgstr ""
+
+#: admin/slm-lic-settings.php:128
+msgid "License Key Prefix"
+msgstr ""
+
+#: admin/slm-lic-settings.php:130
+msgid ""
+"You can optionaly specify a prefix for the license keys. This prefix will be "
+"added to the uniquely generated license keys."
+msgstr ""
+
+#: admin/slm-lic-settings.php:134
+msgid "Maximum Allowed Devices"
+msgstr ""
+
+#: admin/slm-lic-settings.php:136
+msgid ""
+"Maximum number of devices which each license is valid for (default value)."
+msgstr ""
+
+#: admin/slm-lic-settings.php:141
+msgid "Maximum Allowed Domains"
+msgstr ""
+
+#: admin/slm-lic-settings.php:143
+msgid ""
+"Maximum number of domains which each license is valid for (default value)."
+msgstr ""
+
+#: admin/slm-lic-settings.php:148
+msgid "Support Until Ver."
+msgstr ""
+
+#: admin/slm-lic-settings.php:150
+msgid ""
+"This is used to enable bulk license generation for WooCommerce orders placed "
+"before the plugin was active or for orders that do not already contain "
+"licenses (default setting)."
+msgstr ""
+
+#: admin/slm-lic-settings.php:157 admin/slm-lic-settings.php:169
+#: admin/slm-lic-settings.php:181
+msgid ""
+"This is used to enable bulk license generation for WooCommerce orders placed "
+"before the plugin was active or for orders that do not already contain "
+"licenses (default setting:)."
+msgstr ""
+
+#: admin/slm-lic-settings.php:180
+msgid "Frequency period: in days, months, or years"
+msgstr ""
+
+#: admin/slm-lic-settings.php:187
+msgid "Auto Expire License Keys"
+msgstr ""
+
+#: admin/slm-lic-settings.php:189
+msgid "Enable auto expiration "
+msgstr ""
+
+#: admin/slm-lic-settings.php:190
+msgid ""
+" When enabled, it will automatically set the status of a license key to "
+"\"Expired\" when the expiry date value of the key is reached. It doesn't "
+"remotely deactivate a key. It simply changes the status of the key in your "
+"database to expired."
+msgstr ""
+
+#: admin/slm-lic-settings.php:194
+msgid "General settings"
+msgstr ""
+
+#: admin/slm-lic-settings.php:197
+msgid "Enable stats in licenses overview page."
+msgstr ""
+
+#: admin/slm-lic-settings.php:205
+msgid "Enable admin bar shortcut link"
+msgstr ""
+
+#: admin/slm-lic-settings.php:210
+msgid "Multiple items validation"
+msgstr ""
+
+#: admin/slm-lic-settings.php:213
+msgid "Enable verification of Item reference."
+msgstr ""
+
+#: admin/slm-lic-settings.php:214
+msgid ""
+"When enabled, there will be another field in Licenced product - Item "
+"reference. This field should correspond to the API parameter item_reference "
+"of your software."
+msgstr ""
+
+#: admin/slm-lic-settings.php:219
+msgid "User permissions"
+msgstr ""
+
+#: admin/slm-lic-settings.php:222
+msgid "Allow users to remove domains/devices in My account."
+msgstr ""
+
+#: admin/slm-lic-settings.php:223
+msgid ""
+"When enabled, users will be able to remove registered domains or devices in "
+"their account."
+msgstr ""
+
+#: admin/slm-lic-settings.php:232
+msgid "WooCommerce Settings"
+msgstr ""
+
+#: admin/slm-lic-settings.php:236
+msgid "WooCommerce"
+msgstr ""
+
+#: admin/slm-lic-settings.php:239
+msgid ""
+"Enable WooCommerce Support (A fully customizable, open source eCommerce "
+"platform built for WordPress.)"
+msgstr ""
+
+#: admin/slm-lic-settings.php:247
+msgid "Enable WooCommerce Order License Generator"
+msgstr ""
+
+#: admin/slm-lic-settings.php:260
+msgid ""
+"Disable WooCommerce download page. Process downloads though license order "
+"info page."
+msgstr ""
+
+#: admin/slm-lic-settings.php:267
+msgid ""
+"Enable WooCommerce downloads expiration. Downloads will expire together with "
+"corresponding license."
+msgstr ""
+
+#: admin/slm-lic-settings.php:272 admin/slm-lic-settings.php:275
+msgid "WP eStores"
+msgstr ""
+
+#: admin/slm-lic-settings.php:278
+msgid "Enable WordPress eStore Plugin Support."
+msgstr ""
+
+#: admin/slm-lic-settings.php:289
+msgid "Enable Debug Logging"
+msgstr ""
+
+#: admin/slm-lic-settings.php:292
+msgid "If checked, debug output will be written to log files."
+msgstr ""
+
+#: admin/slm-lic-settings.php:297
+msgid "SLM Plus Version"
+msgstr ""
+
+#: admin/slm-lic-settings.php:304
+msgid "SLM Databse Version"
+msgstr ""
+
+#: admin/slm-lic-settings.php:311
+msgid "SLM Rewrite Version"
+msgstr ""
+
+#: admin/slm-lic-settings.php:326
+msgid "Expiration reminder"
+msgstr ""
+
+#: admin/slm-lic-settings.php:336
+msgid "Update Options"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:27
+msgid "No licenses avaliable."
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:43
+msgid "All"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:50
+msgid "active"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:57
+msgid "pending"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:64
+msgid "expired"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:71
+msgid "blocked"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:85 admin/slm-subscribers.php:189
+#: woocommerce/includes/wc_licenses_class.php:114
+#: woocommerce/includes/wc_licenses_class.php:200
+msgid "Status"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:86
+msgid "Key"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:87
+msgid "Item reference"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:88
+msgid "License type"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:90
+msgid "Domains"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:91
+msgid "Devices"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:92
+msgid "Order #"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:93
+msgid "Created on"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:94
+msgid "Renewed on"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:95
+msgid "Activated on"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:96
+msgid "Expiration"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:97
+msgid "Until Ver."
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:98
+msgid "Current Ver."
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:120
+msgid " Lifetime "
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:213 admin/slm-list-licenses-class.php:231
+#: admin/slm-list-licenses-class.php:249 admin/slm-list-licenses-class.php:267
+#: admin/slm-list-licenses-class.php:285
+msgid "Error - Please select some records using the checkboxes"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:467
+msgid "Manage Licenses"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:468
+msgid "Create license"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:469
+msgid "Subscribers"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:470
+msgid "Tools"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:472
+msgid "Help"
+msgstr ""
+
+#: admin/slm-list-licenses-class.php:473
+msgid "About"
+msgstr ""
+
+#: admin/slm-manage-licenses.php:15
+msgid "You do not have permission to manage this license."
+msgstr ""
+
+#: admin/slm-manage-licenses.php:36
+msgid "SLM Plus - Manage Licenses"
+msgstr ""
+
+#: admin/slm-manage-licenses.php:38
+msgid "Add New"
+msgstr ""
+
+#: admin/slm-manage-licenses.php:62 admin/slm-subscribers.php:217
+msgid "Search"
+msgstr ""
+
+#: admin/slm-subscribers.php:88
+msgid "Email Address"
+msgstr ""
+
+#: admin/slm-subscribers.php:176
+msgid "Overview - Manage Subscribers"
+msgstr ""
+
+#: admin/slm-subscribers.php:178
+msgid "View all"
+msgstr ""
+
+#: admin/slm-subscribers.php:188
+msgid "License key"
+msgstr ""
+
+#: admin/slm-subscribers.php:206
+msgid "Overview - All Subscribers"
+msgstr ""
+
+#: includes/class-slm-installer.php:41
+msgid "Pending"
+msgstr ""
+
+#: includes/class-slm-installer.php:42
+msgid "Active"
+msgstr ""
+
+#: includes/class-slm-installer.php:43
+msgid "Blocked"
+msgstr ""
+
+#: includes/class-slm-installer.php:44
+msgid "Expired"
+msgstr ""
+
+#: includes/slm-utility.php:421 includes/slm-utility.php:437
+msgid "0 days remaining"
+msgstr ""
+
+#: includes/slm-utility.php:430
+#, php-format
+msgid "%s days remaining until %s"
+msgstr ""
+
+#: includes/slm-utility.php:482
+msgid "License key not found or invalid email."
+msgstr ""
+
+#: includes/slm-utility.php:882
+msgid " view"
+msgstr ""
+
+#: includes/slm-utility.php:894
+msgid "Request"
+msgstr ""
+
+#: includes/slm-utility.php:902
+msgid "Source:"
+msgstr ""
+
+#: includes/slm-utility.php:903
+msgid "Time:"
+msgstr ""
+
+#: includes/slm-utility.php:949
+msgid "Not registered yet"
+msgstr ""
+
+#: includes/slm-utility.php:967 includes/slm-utility.php:979
+msgid "License information"
+msgstr ""
+
+#: includes/slm-utility.php:980
+msgid "License type: "
+msgstr ""
+
+#: includes/slm-utility.php:981
+msgid "Domains allowed: "
+msgstr ""
+
+#: includes/slm-utility.php:982
+msgid "Devices allowed: "
+msgstr ""
+
+#: includes/slm-utility.php:983
+msgid "Renews every "
+msgstr ""
+
+#: woocommerce/includes/create-license-orders.php:42
+msgid "Product ID is missing in the request."
+msgstr ""
+
+#: woocommerce/includes/create-license-orders.php:58
+msgid ""
+"The provided Product ID does not correspond to a valid WooCommerce product. "
+"Please check the ID and try again."
+msgstr ""
+
+#: woocommerce/includes/create-license-orders.php:190
+#: woocommerce/includes/create-license-orders.php:239
+#: woocommerce/includes/slm-meta-boxes.php:530
+#, php-format
+msgid "License Key generated: %s"
+msgstr ""
+
+#: woocommerce/includes/create-license-orders.php:260
+#, php-format
+msgid "%d orders were skipped:"
+msgstr ""
+
+#: woocommerce/includes/create-license-orders.php:264
+#, php-format
+msgid ""
+"Order ID %d was skipped due to: %s. View "
+"Order "
+msgstr ""
+
+#: woocommerce/includes/create-license-orders.php:273
+#, php-format
+msgid "%d licenses generated successfully:"
+msgstr ""
+
+#: woocommerce/includes/create-license-orders.php:276
+#, php-format
+msgid ""
+"License Key: %s for Order ID %d - View "
+"Order "
+msgstr ""
+
+#: woocommerce/includes/create-license-orders.php:282
+#, php-format
+msgid "%d licenses failed to generate."
+msgstr ""
+
+#: woocommerce/includes/purchase.php:90
+msgid "License no longer exists"
+msgstr ""
+
+#: woocommerce/includes/purchase.php:95
+#: woocommerce/includes/slm-meta-boxes.php:381
+msgid "License Key:"
+msgstr ""
+
+#: woocommerce/includes/purchase.php:193
+msgid "License could not be created: Invalid sites allowed number."
+msgstr ""
+
+#: woocommerce/includes/purchase.php:344
+msgid "License Key(s) generated:"
+msgstr ""
+
+#: woocommerce/includes/purchase.php:373
+msgid "License Key(s) could not be created."
+msgstr ""
+
+#: woocommerce/includes/purchase.php:627
+#, php-format
+msgid "Order confirmation email sent to: %s "
+msgstr ""
+
+#: woocommerce/includes/purchase.php:675
+#: woocommerce/includes/wc_licenses_class.php:215
+msgid "License Details"
+msgstr ""
+
+#: woocommerce/includes/purchase.php:690
+msgid "View My Licenses"
+msgstr ""
+
+#: woocommerce/includes/purchase.php:748
+msgid "License Keys"
+msgstr ""
+
+#: woocommerce/includes/purchase.php:753
+msgid "Product"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:51
+msgid "License product"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:68
+msgid "License Manager"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:70
+msgid "Enables the license creation API."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:120
+msgid "License Info"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:146
+msgid "Domain Licenses"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:152
+msgid "Enter the allowed number of domains this license can have (websites)."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:161
+msgid "Devices Licenses"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:167
+msgid ""
+"Enter the allowed number of devices this license can have (computers, "
+"mobile, etc)."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:175
+msgid "Software's item reference"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:177
+msgid ""
+"Enter the item reference of your application, theme, or plug-in. The license "
+"will be then bound to this exact software."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:186
+msgid "Type of license: subscription base or lifetime"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:188
+msgid "Select one"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:197
+msgid "Renewal Period Length"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:198
+msgid "XX Amount of days, months, or years."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:209
+msgid "Choose between days, months, or years"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:214
+msgid "One Time"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:227
+msgid "Enter the current version of your application, theme, or plug-in"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:233
+msgid "Until Version"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:236
+msgid "Enter the version until support expires."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:361
+msgid "SLM Properties"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:382
+#: woocommerce/includes/slm-meta-boxes.php:389
+msgid "License Type:"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:383
+msgid "A license key is already assigned to this order."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:398
+msgid "Order must be completed or processing to create a license."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:421
+msgid ""
+"Warning: The order lacks user information like last name or email. Do you "
+"still wish to create the license?"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:425
+msgid "Are you sure you want to create a license for this order?"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:435
+msgid "License creation failed. Please check the logs."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:441
+msgid "Unable to verify order details. Please try again."
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:460
+#: woocommerce/includes/slm-meta-boxes.php:545
+msgid "Invalid order ID"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:465
+msgid "Order must be completed or processing to create a license"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:518
+msgid "API request failed"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:533
+msgid "License created successfully"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:535
+msgid "License creation failed"
+msgstr ""
+
+#: woocommerce/includes/slm-meta-boxes.php:554
+msgid "Order not found"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:59
+msgid "My Licenses"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:84
+#: woocommerce/includes/wc_licenses_class.php:188
+msgid "Invalid license or access denied."
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:112
+#: woocommerce/includes/wc_licenses_class.php:202
+msgid "Order ID"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:132
+msgid "Manual"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:140
+msgid "View"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:195
+msgid "Back to My Licenses"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:206
+msgid "Date Expiry"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:208
+msgid "Subscription ID"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:231
+msgid "No Order Information Available"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:247
+msgid "Product Not Found"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:250
+msgid "No Product Information Available"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:256
+msgid "Not activated yet"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:256
+msgid "Not renewed yet"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:289
+msgid "No activations found."
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:305
+msgid "Delete"
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:327
+msgid "Activation successfully deleted. Reload Page."
+msgstr ""
+
+#: woocommerce/includes/wc_licenses_class.php:329
+msgid "Failed to delete activation. Please try again."
+msgstr ""
+
+#. Plugin URI of the plugin/theme
+msgid "https://github.com/michelve/software-license-manager/"
+msgstr ""
+
+#. Description of the plugin/theme
+msgid ""
+"A comprehensive software license management solution for web applications "
+"including WordPress plugins, themes, and PHP-based software. Seamlessly "
+"integrates with WooCommerce to offer license key generation, management, and "
+"validation. Ideal for developers managing software licenses across multiple "
+"platforms with built-in multilingual support and performance optimization."
+msgstr ""
+
+#. Author of the plugin/theme
+msgid "Michel Velis"
+msgstr ""
+
+#. Author URI of the plugin/theme
+msgid "https://github.com/michelve/"
+msgstr ""
diff --git a/includes/class-slm-activator.php b/includes/class-slm-activator.php
new file mode 100755
index 0000000..4989f11
--- /dev/null
+++ b/includes/class-slm-activator.php
@@ -0,0 +1,48 @@
+get_charset_collate();
+
+$used_db_version = get_option('slm_db_version', '5.0.0');
+
+// Check the current database version
+$new_db_version = SLM_DB_VERSION;
+
+// Table definitions
+$lic_key_table = SLM_TBL_LICENSE_KEYS;
+
+// Ensure backward compatibility updates are applied
+if (version_compare($used_db_version, $new_db_version, '<')) {
+ error_log("SLM: Starting database updates from version $used_db_version to $new_db_version.");
+
+ // Check if the 'associated_orders' column exists
+ $column_exists = $wpdb->get_results("SHOW COLUMNS FROM $lic_key_table LIKE 'associated_orders'");
+
+ // Ensure the 'time' column is DATETIME
+ $check_time_column = $wpdb->get_results("SHOW COLUMNS FROM $lic_log_tbl LIKE 'time'");
+ if (!empty($check_time_column)) {
+ $time_column_info = $wpdb->get_row("SHOW COLUMNS FROM $lic_log_tbl WHERE Field = 'time'");
+ if ($time_column_info->Type !== 'datetime') {
+ error_log("SLM: Updating 'time' column to DATETIME in $lic_log_tbl.");
+ $update_time_column_query = "
+ ALTER TABLE $lic_log_tbl
+ MODIFY COLUMN time DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';
+ ";
+ $update_time_column_result = $wpdb->query($update_time_column_query);
+ if ($update_time_column_result === false) {
+ error_log("SLM: Error updating 'time' column - " . $wpdb->last_error);
+ } else {
+ error_log("SLM: 'time' column updated successfully to DATETIME.");
+ }
+ } else {
+ error_log("SLM: 'time' column is already DATETIME.");
+ }
+ } else {
+ error_log("SLM: 'time' column does not exist in $lic_log_tbl. Skipping update.");
+ }
+
+ // Add the 'time_only' column if it doesn't exist
+ $check_time_only_column = $wpdb->get_results("SHOW COLUMNS FROM $lic_log_tbl LIKE 'time_only'");
+ if (empty($check_time_only_column)) {
+ error_log("SLM: Adding missing column 'time_only' to $lic_log_tbl.");
+ $add_time_only_column_query = "
+ ALTER TABLE $lic_log_tbl
+ ADD COLUMN time_only TIME NOT NULL DEFAULT '00:00:00';
+ ";
+ $add_time_only_column_result = $wpdb->query($add_time_only_column_query);
+ if ($add_time_only_column_result === false) {
+ error_log("SLM: Error adding 'time_only' column - " . $wpdb->last_error);
+ } else {
+ error_log("SLM: 'time_only' column added successfully.");
+ }
+ } else {
+ error_log("SLM: Column 'time_only' already exists in $lic_log_tbl.");
+ }
+
+
+ if (empty($column_exists)) {
+ error_log("SLM: Adding missing column 'associated_orders' to $lic_key_table.");
+
+ // Add missing columns to the license keys table
+ $lk_tbl_sql_mod = "
+ ALTER TABLE $lic_key_table
+ ADD COLUMN associated_orders TEXT DEFAULT NULL;
+ ";
+
+ $result = $wpdb->query($lk_tbl_sql_mod);
+
+ if ($result === false) {
+ error_log("SLM: Error adding 'associated_orders' column - " . $wpdb->last_error);
+ } else {
+ error_log("SLM: 'associated_orders' column added successfully.");
+ }
+ } else {
+ error_log("SLM: Column 'associated_orders' already exists in $lic_key_table.");
+ }
+
+ // Add other missing columns (if required)
+ $other_columns = array(
+ 'item_reference' => "VARCHAR(255) NOT NULL",
+ 'slm_billing_length' => "VARCHAR(255) NOT NULL",
+ 'slm_billing_interval' => "ENUM('days', 'months', 'years', 'onetime') NOT NULL DEFAULT 'days'",
+ 'wc_order_id' => "INT DEFAULT NULL",
+ 'payment_status' => "ENUM('pending', 'completed', 'failed') DEFAULT 'pending'",
+ 'renewal_attempts' => "INT DEFAULT 0",
+ 'lic_status' => "ENUM('pending', 'active', 'expired', 'suspended', 'blocked', 'trial') NOT NULL DEFAULT 'pending'"
+ );
+
+ foreach ($other_columns as $column => $definition) {
+ $column_exists = $wpdb->get_results("SHOW COLUMNS FROM $lic_key_table LIKE '$column'");
+ if (empty($column_exists)) {
+ // Add missing column
+ $alter_query = "ALTER TABLE $lic_key_table ADD COLUMN $column $definition;";
+ error_log("SLM: Adding missing column '$column' to $lic_key_table.");
+ $result = $wpdb->query($alter_query);
+
+ if ($result === false) {
+ error_log("SLM: Error adding column '$column' - " . $wpdb->last_error);
+ } else {
+ error_log("SLM: Column '$column' added successfully.");
+ }
+ } else {
+ // Check if the column definition needs to be updated (for example, updating lic_status ENUM values)
+ $column_info = $wpdb->get_row("SHOW COLUMNS FROM $lic_key_table LIKE '$column'");
+ if ($column === 'lic_status' && strpos($column_info->Type, "'trial'") === false) {
+ // Update lic_status to include the new ENUM values
+ $alter_query = "ALTER TABLE $lic_key_table MODIFY COLUMN $column $definition;";
+ error_log("SLM: Updating column '$column' in $lic_key_table.");
+ $result = $wpdb->query($alter_query);
+
+ if ($result === false) {
+ error_log("SLM: Error updating column '$column' - " . $wpdb->last_error);
+ } else {
+ error_log("SLM: Column '$column' updated successfully.");
+ }
+ } else {
+ error_log("SLM: Column '$column' already exists and does not need updates.");
+ }
+ }
+ }
+
+ // Update the database version
+ update_option("slm_db_version", $new_db_version);
+ error_log("SLM database updated from version $used_db_version to $new_db_version.");
+} else {
+ error_log("SLM: No updates needed for backward compatibility. Current version: $used_db_version.");
+}
+
+
+// Create license statuses table if it doesn't exist
+$status_table_sql = "CREATE TABLE IF NOT EXISTS " . $lic_status_table . " (
+ id INT(11) NOT NULL AUTO_INCREMENT,
+ status_key VARCHAR(255) NOT NULL,
+ status_label VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id),
+ UNIQUE KEY unique_status_key (status_key)
+) " . $charset_collate . ";";
+dbDelta($status_table_sql);
+
+
+// Insert default statuses if table is empty
+$status_count = $wpdb->get_var("SELECT COUNT(*) FROM $lic_status_table");
+if ($status_count == 0) {
+ $default_statuses = array(
+ array('status_key' => 'pending', 'status_label' => __('Pending', 'slm-plus')),
+ array('status_key' => 'active', 'status_label' => __('Active', 'slm-plus')),
+ array('status_key' => 'blocked', 'status_label' => __('Blocked', 'slm-plus')),
+ array('status_key' => 'trial', 'status_label' => __('Trial', 'slm-plus')),
+ array('status_key' => 'expired', 'status_label' => __('Expired', 'slm-plus'))
+ );
+
+ foreach ($default_statuses as $status) {
+ $wpdb->insert($lic_status_table, $status);
+ }
+}
+
+// Create or update the license keys table structure
+$lk_tbl_sql = "CREATE TABLE IF NOT EXISTS " . $lic_key_table . " (
+ id INT(12) NOT NULL AUTO_INCREMENT,
+ license_key VARCHAR(255) NOT NULL,
+ item_reference VARCHAR(255) NOT NULL,
+ product_ref VARCHAR(255) NOT NULL DEFAULT '',
+ subscr_id VARCHAR(128) NOT NULL DEFAULT '',
+ txn_id VARCHAR(64) NOT NULL DEFAULT '',
+ purchase_id_ VARCHAR(255) NOT NULL DEFAULT '',
+ wc_order_id INT DEFAULT NULL,
+ associated_orders TEXT DEFAULT NULL,
+ first_name VARCHAR(32) NOT NULL DEFAULT '',
+ last_name VARCHAR(32) NOT NULL DEFAULT '',
+ email VARCHAR(64) NOT NULL,
+ company_name VARCHAR(100) NOT NULL DEFAULT '',
+ lic_status ENUM('pending', 'active', 'expired', 'suspended', 'blocked', 'trial') NOT NULL DEFAULT 'pending',
+ lic_type ENUM('none', 'subscription', 'lifetime') NOT NULL DEFAULT 'subscription',
+ max_allowed_domains INT NOT NULL,
+ max_allowed_devices INT NOT NULL,
+ manual_reset_count VARCHAR(128) NOT NULL DEFAULT '',
+ current_ver VARCHAR(255) NOT NULL DEFAULT '',
+ until VARCHAR(255) NOT NULL DEFAULT '',
+ slm_billing_length VARCHAR(255) NOT NULL,
+ slm_billing_interval ENUM('days', 'months', 'years', 'onetime') NOT NULL DEFAULT 'days',
+ payment_status ENUM('pending', 'completed', 'failed') DEFAULT 'pending',
+ renewal_attempts INT DEFAULT 0,
+ date_created DATE NOT NULL DEFAULT '0000-00-00',
+ date_activated DATE NOT NULL DEFAULT '0000-00-00',
+ date_renewed DATE NOT NULL DEFAULT '0000-00-00',
+ date_expiry DATE NOT NULL DEFAULT '0000-00-00',
+ reminder_sent_date DATE NOT NULL DEFAULT '0000-00-00',
+ reminder_sent VARCHAR(255) NOT NULL DEFAULT '0',
+ PRIMARY KEY (id)
+) " . $charset_collate . ";";
+
+
+dbDelta($lk_tbl_sql);
+
+// Create domains table if not exists
+$ld_tbl_sql = "CREATE TABLE IF NOT EXISTS " . $lic_domain_table . " (
+ id INT NOT NULL AUTO_INCREMENT,
+ lic_key_id INT NOT NULL,
+ lic_key varchar(255) NOT NULL,
+ registered_domain text NOT NULL,
+ registered_devices text NOT NULL,
+ item_reference varchar(255) NOT NULL,
+ PRIMARY KEY (id)
+)" . $charset_collate . ";";
+dbDelta($ld_tbl_sql);
+
+// Create emails table if not exists
+$slm_emails_tbl = "CREATE TABLE IF NOT EXISTS " . $lic_emails_table . " (
+ id INT NOT NULL AUTO_INCREMENT,
+ lic_key varchar(255) NOT NULL,
+ sent_to varchar(255) NOT NULL,
+ status varchar(255) NOT NULL,
+ sent text NOT NULL,
+ date_sent date NOT NULL DEFAULT '0000-00-00',
+ disable_notifications text NOT NULL,
+ PRIMARY KEY (id)
+)" . $charset_collate . ";";
+dbDelta($slm_emails_tbl);
+
+// Create log table if not exists
+$log_tbl_sql = "CREATE TABLE IF NOT EXISTS" . $lic_log_tbl . " (
+ id INT NOT NULL AUTO_INCREMENT,
+ license_key VARCHAR(255) NOT NULL,
+ slm_action VARCHAR(255) NOT NULL,
+ time DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', -- Store combined date and time
+ time_only TIME NOT NULL DEFAULT '00:00:00', -- Store time only
+ source VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id)
+) $charset_collate;";
+dbDelta($log_tbl_sql);
+
+
+// Create devices table if not exists
+$ldv_tbl_sql = "CREATE TABLE IF NOT EXISTS " . $lic_devices_table . " (
+ id INT NOT NULL AUTO_INCREMENT,
+ lic_key_id INT NOT NULL,
+ lic_key varchar(255) NOT NULL,
+ registered_devices text NOT NULL,
+ registered_domain text NOT NULL,
+ item_reference varchar(255) NOT NULL,
+ PRIMARY KEY (id)
+)" . $charset_collate . ";";
+dbDelta($ldv_tbl_sql);
+
+// Add new options if they don't exist and preserve old settings
+$new_options = array(
+ 'lic_creation_secret' => SLM_Utility::create_secret_keys(),
+ 'lic_verification_secret' => SLM_Utility::create_secret_keys(),
+ 'lic_prefix' => 'SLM-',
+ 'default_max_domains' => '2',
+ 'default_max_devices' => '2',
+ 'enable_debug' => '',
+ 'slm_woo' => '1',
+ 'license_current_version' => '1.0.0',
+ 'license_until_version' => '2.1.0',
+ 'slm_wc_lic_generator' => '1',
+ 'slm_woo_downloads' => '',
+ 'slm_woo_affect_downloads' => '1',
+ 'slm_wpestores' => '',
+ 'slm_stats' => '1',
+ 'slm_billing_length' => '1',
+ 'slm_billing_interval' => 'years',
+ 'slm_adminbar' => '1',
+ 'slm_multiple_items' => '',
+ 'slm_conflictmode' => '1',
+ 'slm_front_conflictmode' => '1',
+ 'enable_auto_key_expiration' => '1',
+ 'slm_backup_dir_hash' => '/slm-plus-' . wp_generate_password(8, false, false),
+ 'slm_dl_manager' => '',
+ 'allow_user_activation_removal' => '1',
+ 'expiration_reminder_text' => 'Your account has reverted to Basic with limited functionality. You can renew today to keep using it on all your devices and enjoy the valuable features. It is a smart investment.'
+);
+
+// Retrieve existing options to merge them with the new ones
+$existing_options = get_option('slm_plugin_options', []);
+$merged_options = array_merge($new_options, $existing_options);
+
+// Update options with merged settings
+update_option('slm_plugin_options', $merged_options);
+
+// Create the backup directory if it doesn't already exist
+$upload_dir = wp_upload_dir(); // Get the WordPress upload directory
+$backup_dir_path = $upload_dir['basedir'] . $merged_options['slm_backup_dir_hash'];
+
+// Check if the directory exists, and if not, create it
+if (!file_exists($backup_dir_path)) {
+ wp_mkdir_p($backup_dir_path);
+}
+
diff --git a/software-license-manager/includes/index.html b/includes/index.php
old mode 100644
new mode 100755
similarity index 100%
rename from software-license-manager/includes/index.html
rename to includes/index.php
diff --git a/includes/mails/expired.php b/includes/mails/expired.php
new file mode 100644
index 0000000..5a2fec3
--- /dev/null
+++ b/includes/mails/expired.php
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Hello there, '. $first_name . '!
+
+
+
+
+
+
+
+
Your license key has
+ expired!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '. $expiration_reminder_text .'
+
+
+
+ License info:
+ License key: ' . $license_key . '
+ Expiration: ' . $date_expiry . '
+
+
Go to My account
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+';
\ No newline at end of file
diff --git a/includes/slm-api-listener.php b/includes/slm-api-listener.php
new file mode 100755
index 0000000..b7c868b
--- /dev/null
+++ b/includes/slm-api-listener.php
@@ -0,0 +1,859 @@
+renew_api_listener();
+ break;
+ case 'slm_create_new':
+ $this->creation_api_listener();
+ break;
+ case 'slm_activate':
+ $this->activation_api_listener();
+ break;
+ case 'slm_deactivate':
+ $this->deactivation_api_listener();
+ break;
+ case 'slm_update':
+ $this->update_api_listener();
+ break;
+ case 'slm_check':
+ $this->check_api_listener();
+ break;
+ case 'slm_info':
+ $this->check_api_info();
+ break;
+ }
+ }
+ }
+
+
+ function creation_api_listener()
+ {
+ if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) === 'slm_create_new') {
+ global $slm_debug_logger, $wpdb;
+ $slm_lic_table = SLM_TBL_LICENSE_KEYS;
+ $options = get_option('slm_plugin_options');
+ $lic_key_prefix = $options['lic_prefix'] ?? 'SLM-'; // Use default prefix if missing
+
+ // Security check: Verify secret key
+ SLM_API_Utility::verify_secret_key_for_creation();
+
+ // Logging for debugging
+ $slm_debug_logger->log_debug("API - license creation (slm_create_new) request received.");
+
+ // Trigger action hook for external integrations
+ do_action('slm_api_listener_slm_create_new');
+
+ // Initialize fields array
+ $fields = [];
+
+ // License key handling
+ if (!empty($_REQUEST['license_key'])) {
+ $fields['license_key'] = sanitize_text_field($_REQUEST['license_key']);
+ } else {
+ $fields['license_key'] = slm_get_license($lic_key_prefix); // Generate if not provided
+ }
+
+ // Sanitize and prepare other fields
+ $fields['lic_status'] = !empty($_REQUEST['lic_status']) ? sanitize_text_field($_REQUEST['lic_status']) : 'pending';
+ $fields['first_name'] = sanitize_text_field($_REQUEST['first_name']);
+ $fields['last_name'] = sanitize_text_field($_REQUEST['last_name']);
+ $fields['purchase_id_'] = sanitize_text_field($_REQUEST['purchase_id_']);
+ $fields['email'] = sanitize_email($_REQUEST['email']);
+ $fields['company_name'] = !empty($_REQUEST['company_name']) ? sanitize_text_field($_REQUEST['company_name']) : '';
+ $fields['txn_id'] = sanitize_text_field($_REQUEST['txn_id']);
+ $fields['max_allowed_domains'] = !empty($_REQUEST['max_allowed_domains']) ? intval($_REQUEST['max_allowed_domains']) : intval($options['default_max_domains']);
+ $fields['max_allowed_devices'] = !empty($_REQUEST['max_allowed_devices']) ? intval($_REQUEST['max_allowed_devices']) : intval($options['default_max_devices']);
+ $fields['date_created'] = isset($_REQUEST['date_created']) ? sanitize_text_field($_REQUEST['date_created']) : wp_date('Y-m-d');
+ $fields['date_expiry'] = !empty($_REQUEST['date_expiry']) ? sanitize_text_field($_REQUEST['date_expiry']) : null;
+ $fields['product_ref'] = !empty($_REQUEST['product_ref']) ? sanitize_text_field($_REQUEST['product_ref']) : '';
+ $fields['until'] = !empty($_REQUEST['until']) ? sanitize_text_field($_REQUEST['until']) : '';
+ $fields['current_ver'] = !empty($_REQUEST['current_ver']) ? sanitize_text_field($_REQUEST['current_ver']) : '';
+ $fields['subscr_id'] = !empty($_REQUEST['subscr_id']) ? sanitize_text_field($_REQUEST['subscr_id']) : '';
+ $fields['item_reference'] = !empty($_REQUEST['item_reference']) ? sanitize_text_field($_REQUEST['item_reference']) : '';
+ $fields['lic_type'] = !empty($_REQUEST['lic_type']) ? sanitize_text_field($_REQUEST['lic_type']) : '';
+ $fields['slm_billing_length'] = !empty($_REQUEST['slm_billing_length']) ? sanitize_text_field($_REQUEST['slm_billing_length']) : '';
+ $fields['slm_billing_interval'] = !empty($_REQUEST['slm_billing_interval']) ? sanitize_text_field($_REQUEST['slm_billing_interval']) : '';
+
+ // Validation for subscription-type licenses
+ if ($fields['lic_type'] === 'subscription') {
+ if (empty($fields['slm_billing_length'])) {
+ SLM_API_Utility::output_api_response([
+ 'result' => 'error',
+ 'message' => 'License creation failed. Specify "slm_billing_length".',
+ 'error_code' => SLM_Error_Codes::CREATE_FAILED
+ ]);
+ }
+ if (empty($fields['slm_billing_interval'])) {
+ SLM_API_Utility::output_api_response([
+ 'result' => 'error',
+ 'message' => 'License creation failed. Specify "slm_billing_interval".',
+ 'error_code' => SLM_Error_Codes::CREATE_FAILED
+ ]);
+ }
+ }
+
+ // Insert the license into the database
+ $result = $wpdb->insert($slm_lic_table, $fields);
+
+ // Error handling for database insertion
+ if ($result === false) {
+ SLM_API_Utility::output_api_response([
+ 'result' => 'error',
+ 'message' => 'License creation failed',
+ 'error_code' => SLM_Error_Codes::CREATE_FAILED
+ ]);
+ } else {
+ // Success: License created
+ $response_args = [
+ 'result' => 'success',
+ 'message' => 'License successfully created',
+ 'key' => $fields['license_key'],
+ 'code' => SLM_Error_Codes::LICENSE_CREATED
+ ];
+
+ // Log license creation
+ SLM_Utility::create_log($fields['license_key'], 'slm_create_new');
+
+ // Output API response
+ SLM_API_Utility::output_api_response($response_args);
+ }
+ }
+ }
+
+ function activation_api_listener()
+ {
+ if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) === 'slm_activate') {
+ global $slm_debug_logger, $wpdb;
+ $sql_prep1 = "";
+ $options = get_option('slm_plugin_options');
+
+ // Verify secret key first for security
+ SLM_API_Utility::verify_secret_key();
+
+ // Trigger action hook for external integrations
+ do_action('slm_api_listener_slm_activate');
+
+ // Initialize fields
+ $fields = [];
+ $fields['lic_key'] = sanitize_text_field($_REQUEST['license_key']);
+ $registered_domain = isset($_REQUEST['registered_domain']) ? sanitize_text_field($_REQUEST['registered_domain']) : '';
+ $registered_devices = isset($_REQUEST['registered_devices']) ? sanitize_text_field($_REQUEST['registered_devices']) : '';
+ $item_reference = isset($_REQUEST['item_reference']) ? sanitize_text_field($_REQUEST['item_reference']) : '';
+
+
+ // Table names
+ $slm_lic_table = SLM_TBL_LICENSE_KEYS;
+ $reg_domain_table = SLM_TBL_LIC_DOMAIN;
+ $reg_table_devices = SLM_TBL_LIC_DEVICES;
+
+ // Check if multiple items need verification
+ if (!empty($item_reference) && $options['slm_multiple_items'] == 1) {
+ $sql_prep1 = $wpdb->prepare("SELECT * FROM $slm_lic_table WHERE license_key = %s AND item_reference = %s", $fields['lic_key'], $item_reference);
+ } else {
+ $sql_prep1 = $wpdb->prepare("SELECT * FROM $slm_lic_table WHERE license_key = %s", $fields['lic_key']);
+ }
+
+ // Get the license details from the database
+ $retLic = $wpdb->get_row($sql_prep1, OBJECT);
+
+ SLM_Helper_Class::write_log('User ID (subscr_id): ' . $sql_prep1);
+
+
+ if (!$retLic) {
+ $args = ['result' => 'error', 'message' => 'Invalid license key, key was not found.', 'error_code' => SLM_Error_Codes::LICENSE_INVALID];
+ SLM_API_Utility::output_api_response($args);
+ }
+
+ // Check if the license is blocked or expired
+ if ($retLic->lic_status === 'blocked') {
+ do_action('slm_api_listener_slm_activate_key_blocked', $fields['lic_key']);
+ $args = ['result' => 'error', 'message' => 'Your license key is blocked', 'error_code' => SLM_Error_Codes::LICENSE_BLOCKED];
+ SLM_API_Utility::output_api_response($args);
+ }
+
+ if ($retLic->lic_status === 'expired') {
+ do_action('slm_api_listener_slm_activate_key_expired', $fields['lic_key']);
+ $args = ['result' => 'error', 'message' => 'Your license key has expired', 'error_code' => SLM_Error_Codes::LICENSE_EXPIRED];
+ SLM_API_Utility::output_api_response($args);
+ }
+
+ // Handling registered domains
+ if (!empty($registered_domain)) {
+ $sql_prep2 = $wpdb->prepare("SELECT * FROM $reg_domain_table WHERE lic_key = %s", $fields['lic_key']);
+ $reg_domains = $wpdb->get_results($sql_prep2, OBJECT);
+
+ if (count($reg_domains) < intval($retLic->max_allowed_domains)) {
+ foreach ($reg_domains as $reg_domain) {
+
+ // Handle domain migration
+ if (!empty($_REQUEST['migrate_from']) && $reg_domain->registered_domain === sanitize_text_field($_REQUEST['migrate_from'])) {
+ $wpdb->update($reg_domain_table, ['registered_domain' => $registered_domain], ['registered_domain' => sanitize_text_field($_REQUEST['migrate_from'])]);
+ $args = ['result' => 'success', 'message' => 'Registered domain has been updated'];
+ SLM_API_Utility::output_api_response($args);
+ }
+
+ // Check if the domain is already in use
+ if ($reg_domain->registered_domain === $registered_domain) {
+ $args = [
+ 'result' => 'error',
+ 'icon_url' => SLM_Utility::slm_get_icon_url('1x', 'f-remove.png'),
+ 'message' => 'License key already in use on ' . $registered_domain,
+ 'error_code' => SLM_Error_Codes::LICENSE_IN_USE,
+ 'registered_domain' => $reg_domain->registered_domain,
+ 'item_reference' => $item_reference
+ ];
+ SLM_API_Utility::output_api_response($args);
+ }
+ }
+
+ // Register new domain
+ // If the registered domain is provided, add it to the fields
+ $fields['registered_domain'] = $registered_domain;
+
+ // Assuming $retLic->id contains the license key ID, add it to the fields
+ $fields['lic_key_id'] = $retLic->id;
+
+ // Insert into the registered domain table
+ $wpdb->insert($reg_domain_table, $fields);
+
+ // Update license status to active
+ $current_date = wp_date('Y-m-d');
+ $wpdb->update($slm_lic_table, ['lic_status' => 'active', 'date_activated' => $current_date], ['id' => $retLic->id]);
+
+ //SLM_Helper_Class::write_log('LOG: ' . $url);
+
+ // Send activation email
+ $lic_email = SLM_Utility::slm_get_lic_email($fields['lic_key']);
+ $subject = 'Your license key was activated';
+ $message = 'Your license key: ' . $fields['lic_key'] . ' was activated successfully on ' . wp_date("F j, Y, g:i a") . '.';
+ SLM_Utility::slm_send_mail($lic_email, $subject, $message, 'success');
+
+ // Return success response
+ $args = [
+ 'result' => 'success',
+ 'icon_url' => SLM_Utility::slm_get_icon_url('1x', 'verified.png'),
+ 'message' => 'License key activated.',
+ 'registered_domain' => $registered_domain,
+ 'code' => SLM_Error_Codes::LICENSE_VALID,
+ 'item_reference' => $item_reference
+ ];
+ SLM_Utility::create_log($fields['lic_key'], 'License key activated for domain ' . $registered_domain);
+ SLM_API_Utility::output_api_response($args);
+ } else {
+ $args = [
+ 'result' => 'error',
+ 'message' => 'Reached maximum allowable domains',
+ 'error_code' => SLM_Error_Codes::REACHED_MAX_DOMAINS
+ ];
+ SLM_Utility::create_log($fields['lic_key'], 'Reached maximum allowable domains');
+ SLM_API_Utility::output_api_response($args);
+ }
+ }
+
+ // Handling registered devices
+ if (!empty($registered_devices)) {
+ $sql_prep3 = $wpdb->prepare("SELECT * FROM $reg_table_devices WHERE lic_key = %s", $fields['lic_key']);
+ $reg_devices = $wpdb->get_results($sql_prep3, OBJECT);
+
+ if (count($reg_devices) < intval($retLic->max_allowed_devices)) {
+ foreach ($reg_devices as $reg_device) {
+ if (!empty($_REQUEST['migrate_from']) && $reg_device->registered_devices === sanitize_text_field($_REQUEST['migrate_from'])) {
+ $wpdb->update($reg_table_devices, ['registered_devices' => $registered_devices], ['registered_devices' => sanitize_text_field($_REQUEST['migrate_from'])]);
+ $args = ['result' => 'success', 'message' => 'Registered device has been updated'];
+ SLM_API_Utility::output_api_response($args);
+ }
+ if ($reg_device->registered_devices === $registered_devices) {
+ $args = [
+ 'result' => 'error',
+ 'icon_url' => SLM_Utility::slm_get_icon_url('1x', 'f-remove.png'),
+ 'message' => 'License key already in use on ' . $registered_devices,
+ 'error_code' => SLM_Error_Codes::LICENSE_IN_USE,
+ 'device' => $reg_device->registered_devices
+ ];
+ SLM_API_Utility::output_api_response($args);
+ }
+ }
+
+ // Register new device
+ // If the registered device is provided, add it to the fields
+ $fields['registered_devices'] = $registered_devices;
+
+ // Assuming $retLic->id contains the license key ID, add it to the fields
+ $fields['lic_key_id'] = $retLic->id;
+
+ // Insert into the registered device table
+ $wpdb->insert($reg_table_devices, $fields);
+
+ // Update license status
+ $current_date = wp_date('Y-m-d');
+ $wpdb->update($slm_lic_table, ['lic_status' => 'active', 'date_activated' => $current_date], ['id' => $retLic->id]);
+
+ // Send activation email
+ $lic_email = SLM_Utility::slm_get_lic_email($fields['lic_key']);
+ $subject = 'Your license key was activated';
+ $message = 'Your license key: ' . $fields['lic_key'] . ' was activated successfully on ' . wp_date("F j, Y, g:i a") . '.';
+ SLM_Utility::slm_send_mail($lic_email, $subject, $message, 'success');
+
+ // Return success response
+ $args = [
+ 'result' => 'success',
+ 'registered_device' => $registered_devices,
+ 'code' => SLM_Error_Codes::LICENSE_ACTIVATED,
+ 'icon_url' => SLM_Utility::slm_get_icon_url('1x', 'verified.png'),
+ 'message' => 'License key activated for device.',
+ ];
+ SLM_Utility::create_log($fields['lic_key'], 'License key activated for device ' . $registered_devices);
+ SLM_API_Utility::output_api_response($args);
+ } else {
+ $args = [
+ 'result' => 'error',
+ 'icon_url' => SLM_Utility::slm_get_icon_url('1x', 'f-remove.png'),
+ 'message' => 'Reached maximum allowable devices for this license. Please upgrade.',
+ 'error_code' => SLM_Error_Codes::REACHED_MAX_DEVICES
+ ];
+ SLM_Utility::create_log($fields['lic_key'], 'Reached maximum allowable devices');
+ SLM_API_Utility::output_api_response($args);
+ }
+ }
+ }
+ }
+
+ function deactivation_api_listener()
+ {
+ if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) === 'slm_deactivate') {
+ global $slm_debug_logger, $wpdb;
+
+ // Verify the secret key for security
+ SLM_API_Utility::verify_secret_key();
+ $slm_debug_logger->log_debug("API - license deactivation (slm_deactivate) request received.");
+
+ // Trigger deactivation hook for other integrations
+ do_action('slm_api_listener_slm_deactivate');
+
+ // Sanitize inputs
+ $license_key = sanitize_text_field($_REQUEST['license_key']);
+ $registered_domain = isset($_REQUEST['registered_domain']) ? sanitize_text_field($_REQUEST['registered_domain']) : '';
+ $registered_devices = isset($_REQUEST['registered_devices']) ? sanitize_text_field($_REQUEST['registered_devices']) : '';
+
+
+ // Handle domain deactivation if domain info is provided
+ if (!empty($registered_domain)) {
+ $registered_dom_table = SLM_TBL_LIC_DOMAIN;
+
+ // Prepare SQL query for domain deactivation
+ $sql_prep = $wpdb->prepare("DELETE FROM $registered_dom_table WHERE lic_key = %s AND registered_domain = %s", $license_key, $registered_domain);
+ $delete = $wpdb->query($sql_prep);
+
+ // Check result of the deletion query
+ if ($delete === false) {
+ $slm_debug_logger->log_debug("Error - failed to delete the registered domain from the database.");
+ $args = ['result' => 'error', 'message' => 'Failed to delete the registered domain.', 'error_code' => SLM_Error_Codes::DOMAIN_MISSING];
+ SLM_API_Utility::output_api_response($args);
+ } elseif ($delete === 0) {
+ $args = [
+ 'result' => 'error',
+ 'message' => 'The license key on this domain is already inactive',
+ 'error_code' => SLM_Error_Codes::DOMAIN_ALREADY_INACTIVE,
+ ];
+ SLM_Utility::create_log($license_key, 'Domain license deactivation failed - already inactive.');
+ SLM_API_Utility::output_api_response($args);
+ } else {
+ // Successful deactivation of the domain
+ $args = [
+ 'result' => 'success',
+ 'message' => 'The license key has been deactivated for this domain.',
+ 'error_code' => SLM_Error_Codes::KEY_DEACTIVATE_DOMAIN_SUCCESS,
+ ];
+ SLM_Utility::create_log($license_key, 'Domain license deactivated successfully.');
+ SLM_API_Utility::output_api_response($args);
+ }
+ }
+
+ // Handle device deactivation if device info is provided
+ if (!empty($registered_devices)) {
+ $registered_device_table = SLM_TBL_LIC_DEVICES;
+
+ // Prepare SQL query for device deactivation
+ $sql_prep2 = $wpdb->prepare("DELETE FROM $registered_device_table WHERE lic_key = %s AND registered_devices = %s", $license_key, $registered_devices);
+ $delete2 = $wpdb->query($sql_prep2);
+
+ // Check result of the deletion query
+ if ($delete2 === false) {
+ $slm_debug_logger->log_debug("Error - failed to delete the registered device from the database.");
+ $args = ['result' => 'error', 'message' => 'Failed to delete the registered device.', 'error_code' => SLM_Error_Codes::DOMAIN_MISSING];
+ SLM_API_Utility::output_api_response($args);
+ } elseif ($delete2 === 0) {
+ $args = [
+ 'result' => 'error',
+ 'message' => 'The license key on this device is already inactive',
+ 'error_code' => SLM_Error_Codes::DOMAIN_ALREADY_INACTIVE,
+ ];
+ SLM_Utility::create_log($license_key, 'Device license deactivation failed - already inactive.');
+ SLM_API_Utility::output_api_response($args);
+ } else {
+ // Successful deactivation of the device
+ $args = [
+ 'result' => 'success',
+ 'message' => 'The license key has been deactivated for this device.',
+ 'error_code' => SLM_Error_Codes::KEY_DEACTIVATE_SUCCESS,
+ ];
+ SLM_Utility::create_log($license_key, 'Device license deactivated successfully.');
+ SLM_API_Utility::output_api_response($args);
+ }
+ }
+
+ // If neither domain nor device info is provided, return an error response
+ if (empty($registered_domain) && empty($registered_devices)) {
+ $args = ['result' => 'error', 'message' => 'No deactivation target specified. Either a domain or device must be provided.', 'error_code' => SLM_Error_Codes::DOMAIN_MISSING];
+ SLM_API_Utility::output_api_response($args);
+ }
+ }
+ }
+
+ function update_api_listener()
+ {
+ if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) === 'slm_update') {
+ global $slm_debug_logger, $wpdb;
+
+ // Verify secret key for security
+ SLM_API_Utility::verify_secret_key_for_creation();
+ $slm_debug_logger->log_debug("API - license update (slm_update) request received.");
+
+ // Trigger update hook for integrations
+ do_action('slm_api_listener_slm_update');
+
+ // Sanitize inputs and build the update fields array
+ $fields = array(
+ 'license_key' => sanitize_text_field($_REQUEST['license_key']),
+ 'date_expiry' => isset($_REQUEST['date_expiry']) ? sanitize_text_field($_REQUEST['date_expiry']) : '',
+ 'product_ref' => isset($_REQUEST['product_ref']) ? sanitize_text_field($_REQUEST['product_ref']) : '',
+ 'max_allowed_devices' => isset($_REQUEST['max_allowed_devices']) ? sanitize_text_field($_REQUEST['max_allowed_devices']) : '',
+ 'max_allowed_domains' => isset($_REQUEST['max_allowed_domains']) ? sanitize_text_field($_REQUEST['max_allowed_domains']) : '',
+ 'txn_id' => isset($_REQUEST['txn_id']) ? sanitize_text_field($_REQUEST['txn_id']) : '',
+ 'lic_type' => isset($_REQUEST['lic_type']) ? sanitize_text_field($_REQUEST['lic_type']) : 'subscription',
+ 'lic_status' => isset($_REQUEST['lic_status']) ? sanitize_text_field($_REQUEST['lic_status']) : 'active',
+ 'item_reference' => isset($_REQUEST['item_reference']) ? sanitize_text_field($_REQUEST['item_reference']) : '',
+ );
+
+ // Validate that the license key is provided
+ if (empty($fields['license_key'])) {
+ $args = array(
+ 'result' => 'error',
+ 'message' => 'Cannot update license, license key not provided.',
+ 'error_code' => SLM_Error_Codes::MISSING_KEY_UPDATE_FAILED
+ );
+ $slm_debug_logger->log_debug("API - License update failed: Missing license key.");
+ SLM_API_Utility::output_api_response($args);
+ return;
+ }
+
+ // Update the license in the database
+ $slm_lic_table = SLM_TBL_LICENSE_KEYS;
+ $where_clause = array('license_key' => $fields['license_key']);
+ $update_result = $wpdb->update($slm_lic_table, $fields, $where_clause);
+
+ // Handle update result
+ if ($update_result === false) {
+ $args = array(
+ 'result' => 'error',
+ 'message' => 'License update failed.',
+ 'error_code' => SLM_Error_Codes::KEY_UPDATE_FAILED
+ );
+ SLM_Utility::create_log($fields['license_key'], 'License update failed');
+ SLM_API_Utility::output_api_response($args);
+ } else {
+ $args = array(
+ 'result' => 'success',
+ 'message' => 'License successfully updated.',
+ 'key' => $fields['license_key'],
+ 'error_code' => SLM_Error_Codes::KEY_UPDATE_SUCCESS
+ );
+ SLM_Utility::create_log($fields['license_key'], 'License successfully updated');
+ SLM_API_Utility::output_api_response($args);
+ }
+ } else {
+ // Handle missing or incorrect action parameter
+ $args = array(
+ 'result' => 'error',
+ 'message' => 'Cannot update license, license key not found or invalid action.',
+ 'error_code' => SLM_Error_Codes::MISSING_KEY_UPDATE_FAILED
+ );
+ SLM_Utility::create_log($_REQUEST['license_key'], 'License update failed: action parameter incorrect or missing.');
+ SLM_API_Utility::output_api_response($args);
+ }
+ }
+
+ function check_api_listener()
+ {
+ if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) === 'slm_check') {
+ global $slm_debug_logger, $wpdb;
+
+ // Verify secret key for security
+ SLM_API_Utility::verify_secret_key();
+
+ $slm_debug_logger->log_debug("API - license check (slm_check) request received.");
+
+ // Sanitize input
+ $license_key = sanitize_text_field($_REQUEST['license_key']);
+ $slm_debug_logger->log_debug("Checking license key: " . $license_key);
+
+ // Action hook for additional integrations
+ do_action('slm_api_listener_slm_check');
+
+ // Query license key details
+ $slm_lic_table = SLM_TBL_LICENSE_KEYS;
+ $reg_domain_table = SLM_TBL_LIC_DOMAIN;
+ $reg_table_devices = SLM_TBL_LIC_DEVICES;
+
+ // Retrieve the license key details from the database
+ $license_query = $wpdb->prepare("SELECT * FROM $slm_lic_table WHERE license_key = %s", $license_key);
+ $retLic = $wpdb->get_row($license_query, OBJECT);
+
+ if ($retLic) {
+ // If the license exists, retrieve domain and device information
+ $domain_query = $wpdb->prepare("SELECT * FROM $reg_domain_table WHERE lic_key = %s", $license_key);
+ $device_query = $wpdb->prepare("SELECT * FROM $reg_table_devices WHERE lic_key = %s", $license_key);
+
+ $registered_domains = $wpdb->get_results($domain_query, OBJECT);
+ $registered_devices = $wpdb->get_results($device_query, OBJECT);
+
+ // Prepare response with license and registration data
+ $response_args = apply_filters('slm_check_response_args', array(
+ 'result' => 'success',
+ 'code' => SLM_Error_Codes::LICENSE_EXIST,
+ 'message' => 'License key details retrieved.',
+ 'status' => $retLic->lic_status,
+ 'subscr_id' => $retLic->subscr_id,
+ 'first_name' => $retLic->first_name,
+ 'last_name' => $retLic->last_name,
+ 'company_name' => $retLic->company_name,
+ 'email' => $retLic->email,
+ 'license_key' => $retLic->license_key,
+ 'lic_type' => $retLic->lic_type,
+ 'max_allowed_domains' => $retLic->max_allowed_domains,
+ 'max_allowed_devices' => $retLic->max_allowed_devices,
+ 'item_reference' => $retLic->item_reference,
+ 'registered_domains' => $registered_domains,
+ 'registered_devices' => $registered_devices,
+ 'date_created' => $retLic->date_created,
+ 'date_renewed' => $retLic->date_renewed,
+ 'date_expiry' => $retLic->date_expiry,
+ 'product_ref' => $retLic->product_ref,
+ 'txn_id' => $retLic->txn_id,
+ 'until' => $retLic->until,
+ 'current_ver' => $retLic->current_ver,
+ ));
+
+ // Log and send the response
+ SLM_Utility::create_log($license_key, 'License check successful');
+ SLM_API_Utility::output_api_response($response_args);
+ } else {
+ // Invalid license key case
+ $error_args = array(
+ 'result' => 'error',
+ 'message' => 'Invalid license key',
+ 'error_code' => SLM_Error_Codes::LICENSE_INVALID
+ );
+
+ // Log the error and respond
+ SLM_Utility::create_log($license_key, 'License check failed: Invalid license key');
+ SLM_API_Utility::output_api_response($error_args);
+ }
+ }
+ }
+
+ function check_api_info()
+ {
+ if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) === 'slm_info') {
+ global $slm_debug_logger, $wpdb;
+
+ // Verify secret key for security
+ SLM_API_Utility::verify_secret_key();
+
+ // Log the API request
+ $slm_debug_logger->log_debug("API - license info (slm_info) request received.");
+
+ // Sanitize input data
+ $license_key = sanitize_text_field($_REQUEST['license_key']);
+ $slm_debug_logger->log_debug("License key: " . $license_key);
+
+ // Action hook for additional integrations
+ do_action('slm_api_listener_slm_info');
+
+ // Fetch license details from the database
+ $slm_lic_table = SLM_TBL_LICENSE_KEYS;
+ $reg_domain_table = SLM_TBL_LIC_DOMAIN;
+ $reg_table_devices = SLM_TBL_LIC_DEVICES;
+
+ $license_query = $wpdb->prepare("SELECT * FROM $slm_lic_table WHERE license_key = %s", $license_key);
+ $retLic = $wpdb->get_row($license_query, OBJECT);
+
+ if ($retLic) {
+ // If the license exists, fetch associated domains and devices
+ $domain_query = $wpdb->prepare("SELECT * FROM $reg_domain_table WHERE lic_key = %s", $license_key);
+ $device_query = $wpdb->prepare("SELECT * FROM $reg_table_devices WHERE lic_key = %s", $license_key);
+
+ $registered_domains = $wpdb->get_results($domain_query, OBJECT);
+ $registered_devices = $wpdb->get_results($device_query, OBJECT);
+
+ // Prepare the response with the license and registration data
+ $response_args = apply_filters('slm_info_response_args', array(
+ 'result' => 'success',
+ 'message' => 'License key details retrieved.',
+ 'code' => SLM_Error_Codes::LICENSE_EXIST,
+ 'status' => $retLic->lic_status,
+ 'subscr_id' => $retLic->subscr_id,
+ 'first_name' => $retLic->first_name,
+ 'last_name' => $retLic->last_name,
+ 'company_name' => $retLic->company_name,
+ 'email' => $retLic->email,
+ 'license_key' => $retLic->license_key,
+ 'lic_type' => $retLic->lic_type,
+ 'max_allowed_domains' => $retLic->max_allowed_domains,
+ 'item_reference' => $retLic->item_reference,
+ 'max_allowed_devices' => $retLic->max_allowed_devices,
+ 'date_created' => $retLic->date_created,
+ 'date_renewed' => $retLic->date_renewed,
+ 'date_expiry' => $retLic->date_expiry,
+ 'product_ref' => $retLic->product_ref,
+ 'txn_id' => $retLic->txn_id,
+ 'until' => $retLic->until,
+ 'current_ver' => $retLic->current_ver,
+ ));
+
+ // Log the successful check
+ SLM_Utility::create_log($license_key, 'info: valid license key');
+ SLM_API_Utility::output_api_response($response_args);
+ } else {
+ // Handle invalid license case
+ $error_args = array(
+ 'result' => 'error',
+ 'message' => 'Invalid license key',
+ 'error_code' => SLM_Error_Codes::LICENSE_INVALID
+ );
+
+ // Log the error
+ SLM_Utility::create_log($license_key, 'info: invalid license key');
+ SLM_API_Utility::output_api_response($error_args);
+ }
+ }
+ }
+
+ function wc_slm_handle_license_renewal($order_id, $license_key)
+ {
+ // Log the renewal action for debugging
+ SLM_Helper_Class::write_log("Processing license renewal for Order ID: $order_id, License Key: $license_key");
+
+ // Retrieve the license data
+ $license_data = SLM_Utility::get_licence_by_key($license_key);
+ if (!$license_data) {
+ SLM_Helper_Class::write_log("License key $license_key not found.");
+ return; // Stop if the license is not found
+ }
+
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ // Calculate the new expiration date
+ $renewal_period = intval($license_data['slm_billing_length']);
+ $renewal_term = sanitize_text_field($license_data['slm_billing_interval']);
+ $new_expiry_date = date('Y-m-d', strtotime('+' . $renewal_period . ' ' . $renewal_term));
+
+ // Update the license expiry date in the database
+ $update_result = $wpdb->update(
+ $license_table,
+ ['date_expiry' => $new_expiry_date, 'lic_status' => 'active'],
+ ['license_key' => $license_key]
+ );
+
+ if ($update_result !== false) {
+ SLM_Helper_Class::write_log("License $license_key renewed successfully. New expiry date: $new_expiry_date.");
+ } else {
+ SLM_Helper_Class::write_log("Failed to renew license $license_key.");
+ }
+
+ // Add order note for renewal confirmation
+ $order = wc_get_order($order_id);
+ if ($order) {
+ $order->add_order_note(sprintf(
+ __('License Key %s renewed. New expiry date: %s', 'slm-plus'),
+ $license_key,
+ $new_expiry_date
+ ));
+ $order->save();
+ }
+
+ // Optional: Notify the user about the renewal
+ wc_slm_notify_user_about_renewal($order, $license_key);
+ }
+
+
+ function renew_api_listener() {
+ if (isset($_POST['slm_action']) && trim($_POST['slm_action']) === 'renew_license') {
+ global $wpdb;
+
+ // Verify the secret key for security
+ SLM_API_Utility::verify_secret_key();
+
+ // Get and sanitize the license key and WooCommerce order ID
+ $license_key = sanitize_text_field($_POST['license_key']);
+ $wc_order_id = intval($_POST['wc_order_id']);
+
+ // Check if license key and order ID are provided
+ if (empty($license_key) || empty($wc_order_id)) {
+ SLM_API_Utility::output_api_response([
+ 'result' => 'error',
+ 'message' => 'License key or WooCommerce order ID is missing.',
+ 'error_code' => SLM_Error_Codes::MISSING_PARAMETERS,
+ 'status_code' => 400,
+ ]);
+ return;
+ }
+
+ // Fetch the WooCommerce order
+ $order = wc_get_order($wc_order_id);
+ if (!$order) {
+ SLM_API_Utility::output_api_response([
+ 'result' => 'error',
+ 'message' => 'Invalid WooCommerce order ID.',
+ 'error_code' => SLM_Error_Codes::ORDER_NOT_FOUND,
+ 'status_code' => 404,
+ ]);
+ return;
+ }
+
+ // Fetch license details from the database
+ $license = SLM_Utility::get_license_by_key($license_key);
+ if (!$license) {
+ SLM_API_Utility::output_api_response([
+ 'result' => 'error',
+ 'message' => 'License not found.',
+ 'error_code' => SLM_Error_Codes::LICENSE_INVALID,
+ 'status_code' => 404,
+ ]);
+ return;
+ }
+
+ // Verify the order ID matches the one associated with the license (if applicable)
+ if (!empty($license->wc_order_id) && $license->wc_order_id != $wc_order_id) {
+ SLM_API_Utility::output_api_response([
+ 'result' => 'error',
+ 'message' => 'The provided order ID does not match the one associated with this license.',
+ 'error_code' => SLM_Error_Codes::ORDER_ID_MISMATCH,
+ 'status_code' => 400,
+ ]);
+ return;
+ }
+
+ // Check the WooCommerce order status
+ if ($order->get_status() !== 'completed') {
+ SLM_API_Utility::output_api_response([
+ 'result' => 'error',
+ 'message' => 'The WooCommerce order has not been completed.',
+ 'error_code' => SLM_Error_Codes::ORDER_NOT_COMPLETED,
+ 'status_code' => 400,
+ ]);
+ return;
+ }
+
+ // Handle license renewal process
+ $this->handle_license_renewal($wc_order_id, $license_key);
+
+ // Return a success response
+ SLM_API_Utility::output_api_response([
+ 'result' => 'success',
+ 'message' => 'License renewed successfully.',
+ 'license_key' => $license_key,
+ 'renewal_date' => current_time('mysql'),
+ 'status_code' => 200,
+ ]);
+ }
+ }
+
+ private function handle_license_renewal($order_id, $license_key) {
+ // Log the renewal action for debugging
+ SLM_Helper_Class::write_log("Processing license renewal for Order ID: $order_id, License Key: $license_key");
+
+ // Retrieve the license data
+ $license_data = SLM_Utility::get_license_by_key($license_key);
+ if (!$license_data) {
+ SLM_Helper_Class::write_log("License key $license_key not found.");
+ return; // Stop if the license is not found
+ }
+
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ // Calculate the new expiration date
+ $renewal_period = intval($license_data->slm_billing_length);
+ $renewal_term = sanitize_text_field($license_data->slm_billing_interval);
+ $new_expiry_date = date('Y-m-d', strtotime('+' . $renewal_period . ' ' . $renewal_term));
+
+ // Update the license expiry date in the database
+ $update_result = $wpdb->update(
+ $license_table,
+ ['date_expiry' => $new_expiry_date, 'lic_status' => 'active'],
+ ['license_key' => $license_key]
+ );
+
+ if ($update_result !== false) {
+ SLM_Helper_Class::write_log("License $license_key renewed successfully. New expiry date: $new_expiry_date.");
+ } else {
+ SLM_Helper_Class::write_log("Failed to renew license $license_key.");
+ }
+
+ // Add order note for renewal confirmation
+ $order = wc_get_order($order_id);
+ if ($order) {
+ $order->add_order_note(sprintf(
+ __('License Key %s renewed. New expiry date: %s', 'slm-plus'),
+ $license_key,
+ $new_expiry_date
+ ));
+ $order->save();
+ }
+
+ // Notify the user about the renewal
+ wc_slm_notify_user_about_renewal($order, $license_key);
+ }
+}
diff --git a/includes/slm-blocks.php b/includes/slm-blocks.php
new file mode 100644
index 0000000..5216ec1
--- /dev/null
+++ b/includes/slm-blocks.php
@@ -0,0 +1,25 @@
+log_debug("Some debug message");
+ *
+ * OR
+ *
+ * - SLM_Debug_Logger::log_debug_st("Some debug message");
+ */
+
+class SLM_Debug_Logger {
+ var $log_folder_path;
+ var $default_log_file = 'log.txt';
+ var $default_log_file_cron = 'log-cron-job.txt';
+ var $debug_enabled = false;
+ var $debug_status = array('SUCCESS', 'STATUS', 'NOTICE', 'WARNING', 'FAILURE', 'CRITICAL');
+ var $section_break_marker = "\n----------------------------------------------------------\n\n";
+ var $log_reset_marker = "-------- Log File Reset --------\n";
+
+ /**
+ * Constructor
+ * Initializes the logger by setting the log folder path and enabling debugging based on plugin settings.
+ */
+ function __construct() {
+ $this->log_folder_path = SLM_PATH . '/logs';
+
+ // Check plugin options to see if debugging is enabled
+ $options = get_option('slm_plugin_options');
+ if (!empty($options['enable_debug'])) {
+ $this->debug_enabled = true;
+ }
+ }
+
+ /**
+ * Get the current timestamp for the log entry
+ *
+ * @return string Timestamp in the format [m/d/Y g:i A]
+ */
+ function get_debug_timestamp() {
+ return '[' . wp_date('m/d/Y g:i A') . '] - ';
+ }
+
+ /**
+ * Get the debug status label based on the level
+ *
+ * @param int $level The severity level of the log message (0-5)
+ * @return string The corresponding status label (e.g., 'SUCCESS', 'FAILURE')
+ */
+ function get_debug_status($level) {
+ $size = count($this->debug_status);
+ return ($level >= $size) ? 'UNKNOWN' : $this->debug_status[$level];
+ }
+
+ /**
+ * Return a section break marker if required
+ *
+ * @param bool $section_break Whether to include a section break
+ * @return string Section break marker or empty string
+ */
+ function get_section_break($section_break) {
+ return $section_break ? $this->section_break_marker : "";
+ }
+
+ /**
+ * Reset the log file by clearing its contents and adding a reset marker
+ *
+ * @param string $file_name Optional file name to reset, defaults to main log file
+ */
+ function reset_log_file($file_name = '') {
+ if (empty($file_name)) {
+ $file_name = $this->default_log_file;
+ }
+ $debug_log_file = $this->log_folder_path . '/' . $file_name;
+ $content = $this->get_debug_timestamp() . $this->log_reset_marker;
+ $fp = fopen($debug_log_file, 'w');
+ fwrite($fp, $content);
+ fclose($fp);
+ }
+
+ /**
+ * Append content to the specified log file
+ *
+ * @param string $content The content to log
+ * @param string $file_name The file to which content will be appended
+ */
+ function append_to_file($content, $file_name) {
+ if (empty($file_name)) $file_name = $this->default_log_file;
+ $debug_log_file = $this->log_folder_path . '/' . $file_name;
+ $fp = fopen($debug_log_file, 'a');
+ fwrite($fp, $content);
+ fclose($fp);
+ }
+
+ /**
+ * Log a debug message
+ *
+ * @param string $message The debug message to log
+ * @param int $level The debug level (default 0 - SUCCESS)
+ * @param bool $section_break Whether to include a section break after the message
+ * @param string $file_name Optional log file name
+ */
+ function log_debug($message, $level = 0, $section_break = false, $file_name = '') {
+ if (!$this->debug_enabled) return;
+
+ // Build the log content
+ $content = $this->get_debug_timestamp(); // Add timestamp
+ $content .= $this->get_debug_status($level); // Add status level
+ $content .= ' : ' . $message . "\n"; // Add message
+ $content .= $this->get_section_break($section_break); // Add section break if needed
+
+ $this->append_to_file($content, $file_name); // Append to log file
+ }
+
+ /**
+ * Log a debug message specifically for cron jobs
+ *
+ * @param string $message The debug message to log for cron jobs
+ * @param int $level The debug level (default 0 - SUCCESS)
+ * @param bool $section_break Whether to include a section break after the message
+ */
+ function log_debug_cron($message, $level = 0, $section_break = false) {
+ if (!$this->debug_enabled) return;
+
+ // Build the log content for cron jobs
+ $content = $this->get_debug_timestamp();
+ $content .= $this->get_debug_status($level);
+ $content .= ' : ' . $message . "\n";
+ $content .= $this->get_section_break($section_break);
+
+ // Log to the cron-specific log file
+ $this->append_to_file($content, $this->default_log_file_cron);
+ }
+
+ /**
+ * Static method to log debug messages from a static context
+ *
+ * @param string $message The debug message to log
+ * @param int $level The debug level (default 0 - SUCCESS)
+ * @param bool $section_break Whether to include a section break after the message
+ * @param string $file_name Optional log file name
+ */
+ static function log_debug_st($message, $level = 0, $section_break = false, $file_name = '') {
+ $options = get_option('slm_plugin_options');
+ if (empty($options['enable_debug'])) {
+ return; // Debugging is disabled
+ }
+
+ // Build the log content
+ $content = '[' . wp_date('m/d/Y g:i A') . '] - STATUS : ' . $message . "\n";
+ $debug_log_file = SLM_PUBLIC . '/logs/log.txt';
+
+ // Append the log content to the file
+ $fp = fopen($debug_log_file, 'a');
+ fwrite($fp, $content);
+ fclose($fp);
+ }
+}
diff --git a/includes/slm-error-codes.php b/includes/slm-error-codes.php
new file mode 100755
index 0000000..5af3210
--- /dev/null
+++ b/includes/slm-error-codes.php
@@ -0,0 +1,67 @@
+load_scripts();
+ // Add other init time operations here
+ add_action('slm_daily_cron_event', array($this, 'slm_daily_cron_event_handler'));
+}
+
+// Load common and admin-specific scripts and styles
+public function load_scripts() {
+ $plugin_version = '1.0.0'; // Replace with your plugin version if available
+
+ wp_enqueue_script('jquery'); // Common scripts
+
+ if (is_admin()) {
+ wp_enqueue_script('jquery-ui-datepicker');
+ // Enqueue admin-specific JS and add version and load in footer
+ wp_enqueue_script('wplm-custom-admin-js', SLM_ASSETS_URL . 'js/wplm-custom-admin.js', array('jquery-ui-dialog'), $plugin_version, true); // true loads in footer
+ if (isset($_GET['page']) && $_GET['page'] == 'slm_manage_license') { // Only include if in license management interface
+ wp_enqueue_style('jquery-ui-style', SLM_ASSETS_URL . 'css/jquery-ui.css', array(), $plugin_version); // Add version for caching
+ }
+ }
+}
+
+// Daily cron event handler
+public function slm_daily_cron_event_handler() {
+ $options = get_option('slm_plugin_options');
+ do_action('slm_daily_cron_event_triggered');
+
+ if (isset($options['enable_auto_key_expiry']) && $options['enable_auto_key_expiry'] == '1') {
+ // Perform auto key expiry task
+ SLM_Debug_Logger::log_debug_st("SLM daily cronjob - auto expiry of license key is enabled.");
+ SLM_Utility::do_auto_key_expiry();
+ }
+}
+}
diff --git a/includes/slm-plugin-core.php b/includes/slm-plugin-core.php
new file mode 100755
index 0000000..b0d36f1
--- /dev/null
+++ b/includes/slm-plugin-core.php
@@ -0,0 +1,264 @@
+activate();
+}
+
+function deactivate_slm_plus()
+{
+ require_once SLM_LIB . 'class-slm-deactivator.php';
+ $slm_deactivator->deactivate();
+}
+
+register_activation_hook(__FILE__, 'activate_slm_plus');
+register_deactivation_hook(__FILE__, 'deactivate_slm_plus');
+
+// Improved and Shortened License Key Generator Function
+function slm_get_license($lic_key_prefix = '')
+{
+ global $wpdb;
+ $max_retries = 5; // Set the maximum number of retries
+ $retry_count = 0;
+ $license_key = '';
+
+ // Use the constant to define the license table
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ // Generate a unique license key
+ while ($retry_count < $max_retries) {
+ // Generate a strong, random base using random_int() and uniqid
+ $random_base = uniqid(random_int(1000, 9999), true);
+
+ // Combine random base with the current GMT date and time and the Unix timestamp for additional uniqueness
+ $combined_string = $random_base . gmdate('Y-m-d H:i:s') . time();
+
+ // Create a sha256 hash of the combined string
+ $hashed_string = substr(hash('sha256', $combined_string), 0, 32); // Take first 32 characters of the sha256 hash
+
+ // Ensure the prefix is added correctly
+ $license_key = strtoupper($hashed_string);
+
+ // Add dashes every 4 characters
+ $license_key_with_dashes = implode('-', str_split($license_key, 4));
+
+ // Add the prefix to the formatted key
+ $license_key_with_prefix = $lic_key_prefix . $license_key_with_dashes;
+
+ // Check if the generated license key already exists in the database
+ $existing_license = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $license_table WHERE license_key = %s", $license_key_with_prefix));
+
+ // If the license doesn't exist, break out of the loop and return the key
+ if ($existing_license == 0) {
+ return $license_key_with_prefix;
+ }
+
+ // If the license already exists, increment the retry count and try again
+ $retry_count++;
+ }
+
+ // If we exceed the retry limit, return false or handle the error as needed
+ error_log('Failed to generate a unique license key after ' . $max_retries . ' attempts.');
+ return false;
+}
+
+
+// Example hyphenate function (assuming hyphenates every 4 characters)
+function hyphenate($string)
+{
+ return implode('-', str_split($string, 4)); // This splits the string into chunks of 4 characters and adds hyphens
+}
+
+// Action hooks
+add_action('init', 'slmplus_init_handler');
+add_action('plugins_loaded', 'slmplus_plugins_loaded_handler');
+add_action('wp_ajax_del_registered_devices', 'slmplus_del_registered_devices');
+add_action('wp_ajax_del_registered_domain', 'slmplus_del_registered_domain');
+add_action('wp_ajax_del_activation', 'slmplus_remove_activation');
+// Initialize plugin on plugins_loaded action
+add_action('plugins_loaded', array('SLM_Tabbed_Plugin', 'get_object'));
+
+// Initialize debug logger
+$slm_debug_logger = new SLM_Debug_Logger();
+
+// Init-time tasks
+function slmplus_init_handler()
+{
+ $init_task = new SLM_Init_Time_Tasks();
+ $api_listener = new SLM_API_Listener();
+}
+
+// Plugins loaded tasks
+function slmplus_plugins_loaded_handler()
+{
+ if (is_admin() && get_option('slm_db_version') != SLM_DB_VERSION) {
+ require_once SLM_LIB . 'class-slm-installer.php';
+ // TODO - Implement DB update logic here
+ }
+}
+
+// Singleton pattern for the plugin
+class SLM_Tabbed_Plugin
+{
+ private static $classobj = NULL;
+
+ public static function get_object()
+ {
+ if (self::$classobj === NULL) {
+ self::$classobj = new self();
+ }
+ return self::$classobj;
+ }
+
+ private function __construct() {}
+}
+
+// AJAX handlers
+function slmplus_del_registered_domain()
+{
+ global $wpdb;
+ $id = strip_tags($_GET['id']);
+ $ret = $wpdb->query($wpdb->prepare("DELETE FROM " . SLM_TBL_LIC_DOMAIN . " WHERE id = %d", $id));
+ echo ($ret) ? 'success' : 'failed';
+ exit;
+}
+
+function slmplus_del_registered_devices()
+{
+ global $wpdb;
+ $id = strip_tags($_GET['id']);
+ $ret = $wpdb->query($wpdb->prepare("DELETE FROM " . SLM_TBL_LIC_DEVICES . " WHERE id = %d", $id));
+ echo ($ret) ? 'success' : 'failed';
+ exit;
+}
+
+function slmplus_remove_activation()
+{
+ global $wpdb;
+ $id = strip_tags($_GET['id']);
+ $activation_type = strip_tags($_GET['activation_type']);
+
+ $table = ($activation_type == 'Devices') ? SLM_TBL_LIC_DEVICES : SLM_TBL_LIC_DOMAIN;
+ $ret = $wpdb->query($wpdb->prepare("DELETE FROM {$table} WHERE id = %d", $id));
+ echo ($ret) ? 'success' : 'failed';
+ exit;
+}
+
+// Debugging functions
+function wc_print_pretty($args)
+{
+ echo '';
+ print_r($args);
+ echo ' ';
+}
+
+function wc_log($msg)
+{
+ $log = ABSPATH . DIRECTORY_SEPARATOR . 'slm_log.txt';
+ file_put_contents($log, $msg . '', FILE_APPEND);
+}
+
+// WooCommerce integration
+if (SLM_Helper_Class::slm_get_option('slm_woo') == 1 && is_plugin_active('woocommerce/woocommerce.php')) {
+ require_once SLM_WOO . 'includes/wc_licenses_class.php';
+ require_once SLM_WOO . 'includes/slm-meta-boxes.php';
+ require_once SLM_WOO . 'includes/register-template.php';
+ require_once SLM_WOO . 'includes/purchase.php';
+ require_once SLM_WOO . 'includes/create-license-orders.php';
+ require_once SLM_WOO . 'includes/hooks/license-checkout-hooks.php';
+ // Build WooCommerce tabs
+ SLM_Utility::slm_woo_build_tab();
+}
+
+add_action('wp_ajax_slm_user_search', 'slm_user_search');
+function slm_user_search()
+{
+ global $wpdb;
+
+ $value = sanitize_text_field($_POST['value']);
+
+ // Direct SQL Query to improve performance
+ $query = $wpdb->prepare(
+ "
+ SELECT u.ID, u.display_name, u.user_email,
+ IFNULL(um_first_name.meta_value, um_billing_first_name.meta_value) AS first_name,
+ IFNULL(um_last_name.meta_value, um_billing_last_name.meta_value) AS last_name
+ FROM {$wpdb->users} u
+ LEFT JOIN {$wpdb->prefix}usermeta um_first_name ON um_first_name.user_id = u.ID AND um_first_name.meta_key = 'first_name'
+ LEFT JOIN {$wpdb->prefix}usermeta um_last_name ON um_last_name.user_id = u.ID AND um_last_name.meta_key = 'last_name'
+ LEFT JOIN {$wpdb->prefix}usermeta um_billing_first_name ON um_billing_first_name.user_id = u.ID AND um_billing_first_name.meta_key = 'billing_first_name'
+ LEFT JOIN {$wpdb->prefix}usermeta um_billing_last_name ON um_billing_last_name.user_id = u.ID AND um_billing_last_name.meta_key = 'billing_last_name'
+ WHERE (um_first_name.meta_value LIKE %s OR um_last_name.meta_value LIKE %s OR um_billing_first_name.meta_value LIKE %s OR um_billing_last_name.meta_value LIKE %s)
+ LIMIT 10
+ ",
+ '%' . $wpdb->esc_like($value) . '%',
+ '%' . $wpdb->esc_like($value) . '%',
+ '%' . $wpdb->esc_like($value) . '%',
+ '%' . $wpdb->esc_like($value) . '%'
+ );
+
+ $users = $wpdb->get_results($query);
+ $results = [];
+
+ foreach ($users as $user) {
+ $results[] = [
+ 'ID' => $user->ID,
+ 'display_name' => $user->display_name ?: "{$user->first_name} {$user->last_name}",
+ 'first_name' => $user->first_name,
+ 'last_name' => $user->last_name,
+ 'email' => $user->user_email,
+ 'company_name' => get_user_meta($user->ID, 'company_name', true),
+ 'subscr_id' => $user->ID, // Pass user ID as the subscription ID
+ ];
+ }
+
+ wp_send_json_success($results);
+}
diff --git a/includes/slm-scripts.php b/includes/slm-scripts.php
new file mode 100644
index 0000000..7d0ec56
--- /dev/null
+++ b/includes/slm-scripts.php
@@ -0,0 +1,13 @@
+options} WHERE option_name LIKE '_transient_$like_pattern' OR option_name LIKE '_transient_timeout_$like_pattern'";
+ $wpdb->query($sql);
+
+ add_action('admin_notices', function () {
+ echo 'All rate-limiting transients have been cleared.
';
+ });
+ }
+});
+
+
+// Custom Hooks
+// Hooks added to customize the text or logic:
+
+// slm_invalid_email_message: Customize the invalid email message.
+// slm_success_message: Customize the success message.
+// slm_no_license_message: Customize the "no license found" message.
+// slm_license_email_message: Modify the email message body.
+// slm_license_email_subject: Modify the email subject.
+// slm_form_label: Change the form label text.
+// slm_form_button_text: Change the form button text.
+
+class SLM_Forgot_License {
+ /**
+ * Initialize the class and hooks.
+ */
+ public function __construct() {
+ // Register shortcode.
+ add_shortcode('slm_forgot_license', [$this, 'render_shortcode']);
+ }
+
+ /**
+ * Render the shortcode.
+ *
+ * @return string
+ */
+ public function render_shortcode() {
+ // Check if form is submitted.
+ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['slm_forgot_license_nonce'])) {
+ return $this->handle_form_submission();
+ }
+
+ // Output the form.
+ return $this->render_form();
+ }
+
+ /**
+ * Handle form submission.
+ *
+ * @return string
+ */
+ protected function handle_form_submission() {
+ // Verify nonce for security.
+ if (!isset($_POST['slm_forgot_license_nonce']) ||
+ !wp_verify_nonce($_POST['slm_forgot_license_nonce'], 'slm_forgot_license_action')) {
+ return 'Invalid request. Please try again.
';
+ }
+
+ // Sanitize and validate email.
+ $email = sanitize_email($_POST['slm_forgot_license_email']);
+ if (!is_email($email)) {
+ return apply_filters('slm_invalid_email_message', 'Invalid email address.
');
+ }
+
+ // Rate limiting: prevent repeated submissions from the same IP.
+ $ip = $_SERVER['REMOTE_ADDR'];
+ if ($this->is_rate_limited($ip)) {
+ return 'You are submitting requests too quickly. Please try again later.
';
+ }
+
+ // Retrieve licenses.
+ $licenses = SLM_Utility::get_licenses_by_email($email);
+
+ if (!empty($licenses)) {
+ // Prepare and send the email.
+ $message = apply_filters('slm_license_email_message', $this->generate_email_message($licenses), $licenses);
+ wp_mail($email, apply_filters('slm_license_email_subject', 'Your Licenses'), $message);
+
+ return apply_filters('slm_success_message', 'Your licenses have been sent to your email.
');
+ }
+
+ return apply_filters('slm_no_license_message', 'No licenses found for the provided email.
');
+ }
+
+ /**
+ * Check if the IP is rate-limited.
+ *
+ * @param string $ip
+ * @return bool
+ */
+ protected function is_rate_limited($ip) {
+ // Allow administrators to bypass rate limiting and clear transients.
+ if (is_user_logged_in() && current_user_can('manage_options')) {
+ $this->clear_transients();
+ return false; // Admins are not rate-limited.
+ }
+
+ $key = 'slm_rate_limit_' . $ip;
+ $limit = 3; // Max submissions allowed per hour.
+ $time_frame = HOUR_IN_SECONDS;
+
+ $attempts = get_transient($key);
+
+ if ($attempts === false) {
+ set_transient($key, 1, $time_frame);
+ return false;
+ }
+
+ if ($attempts >= $limit) {
+ return true;
+ }
+
+ set_transient($key, $attempts + 1, $time_frame);
+ return false;
+ }
+
+ /**
+ * Clear all relevant transients.
+ */
+ protected function clear_transients() {
+ global $wpdb;
+
+ // Search and delete all transients related to rate limiting.
+ $like_pattern = '%slm_rate_limit_%';
+ $sql = "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_$like_pattern' OR option_name LIKE '_transient_timeout_$like_pattern'";
+ $wpdb->query($sql);
+ }
+
+
+
+
+ /**
+ * Generate the email message.
+ *
+ * @param array $licenses
+ * @return string
+ */
+ protected function generate_email_message($licenses) {
+ $message = "Here are your licenses:\n\n";
+
+ foreach ($licenses as $license) {
+ $message .= "License Key: {$license['license_key']}\n";
+ // $message .= "Product: {$license['product_ref']}\n";
+ $message .= "Status: {$license['lic_status']}\n\n";
+ }
+
+ return $message;
+ }
+
+ /**
+ * Render the form HTML.
+ *
+ * @return string
+ */
+ protected function render_form() {
+ ob_start();
+ ?>
+
+
+
+
+
+
+ ' . __('You must be logged in to view your licenses.', 'slm-plus') . '';
+ }
+
+ // Get the current user's email.
+ $current_user = wp_get_current_user();
+ $email = $current_user->user_email;
+
+ // Retrieve licenses for the user.
+ $licenses = $this->get_licenses_by_email($email);
+
+ // Render the licenses table or a message if none are found.
+ if (empty($licenses)) {
+ return apply_filters('slm_no_license_message', '' . __('No licenses found for your account.', 'slm-plus') . '
');
+ }
+
+ return $this->render_licenses_table($licenses);
+ }
+
+ /**
+ * Retrieve licenses by email from the database.
+ *
+ * @param string $email
+ * @return array
+ */
+ protected function get_licenses_by_email($email) {
+ global $wpdb;
+
+ $table_name = $wpdb->prefix . 'lic_key_tbl'; // Update to match your actual table name.
+ $query = $wpdb->prepare(
+ "SELECT license_key, product_ref, lic_status, date_expiry, date_activated, max_allowed_domains, max_allowed_devices
+ FROM $table_name WHERE email = %s",
+ $email
+ );
+
+ return $wpdb->get_results($query, ARRAY_A);
+ }
+
+ /**
+ * Render the licenses table HTML.
+ *
+ * @param array $licenses
+ * @return string
+ */
+ protected function render_licenses_table($licenses) {
+ ob_start();
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get_error_messages(), true));
+ }
+}
+add_action('wp_mail_failed', 'action_wp_mail_failed', 10, 1);
+
+
+class SLM_Helper_Class
+{
+
+ public static function slm_get_option($option)
+ {
+ $slm_opts = get_option('slm_plugin_options');
+ if (is_array($slm_opts) && array_key_exists($option, $slm_opts)) {
+ return $slm_opts[$option];
+ }
+ return '';
+ }
+
+ public static function write_log($log)
+ {
+ if (defined('WP_DEBUG') && WP_DEBUG === true) {
+ if (is_array($log) || is_object($log)) {
+ error_log(print_r($log, true));
+ } else {
+ error_log($log);
+ }
+ }
+ }
+ public static function get_license_logs($license_key)
+ {
+ global $wpdb;
+ $table_name = SLM_TBL_LIC_LOG;
+
+ // Use a prepared statement for security
+ $query = $wpdb->prepare(
+ "SELECT * FROM $table_name WHERE license_key = %s ORDER BY time DESC",
+ $license_key
+ );
+
+ // Fetch results as an associative array
+ return $wpdb->get_results($query, ARRAY_A);
+ }
+
+ /**
+ * PHP Logger
+ */
+
+ static function console($data)
+ {
+ $output = $data;
+ if (is_array($output))
+ $output = implode(',', $output);
+
+ // print the result into the JavaScript console
+ echo "";
+ }
+}
+
+$slm_helper = new SLM_Helper_Class();
+
+
+class SLM_API_Utility
+{
+
+ /*
+ * The args array can contain the following:
+ * result (success or error)
+ * message (a message describing the outcome of the action
+ */
+
+ public static function output_api_response($args)
+ {
+ // Log to debug file (if enabled)
+ global $slm_debug_logger;
+ if (isset($slm_debug_logger)) {
+ $slm_debug_logger->log_debug('API Response - Result: ' . esc_html($args['result']) . ' Message: ' . esc_html($args['message']));
+ }
+
+ // Send response
+ $args = apply_filters('slm_ap_response_args', $args);
+ $args = apply_filters('slm_api_response_args', $args);
+
+ header('Content-Type: application/json');
+ echo json_encode($args);
+ exit;
+ }
+
+ /**
+ * Validate date format to ensure it's in 'YYYY-MM-DD' format.
+ * Returns the sanitized date or an empty string if invalid.
+ */
+ public static function slm_validate_date($date)
+ {
+ $date = sanitize_text_field($date);
+ $timestamp = strtotime($date);
+ if ($timestamp && date('Y-m-d', $timestamp) === $date) {
+ return $date;
+ }
+ return ''; // Return an empty string if the date is invalid
+ }
+
+ public static function verify_secret_key()
+ {
+ $slm_options = get_option('slm_plugin_options');
+ $right_secret_key = $slm_options['lic_verification_secret'] ?? '';
+ $received_secret_key = sanitize_text_field($_REQUEST['secret_key'] ?? '');
+ $slm_action = sanitize_text_field($_REQUEST['slm_action'] ?? '');
+
+ // Case-sensitive comparison for the secret keys
+ if ($received_secret_key !== $right_secret_key) {
+ // Prepare the error response with case-sensitivity note
+ $args = array(
+ 'result' => 'error',
+ 'message' => 'Verification API secret key is invalid. Note: The key is case-sensitive.',
+ 'slm_action' => $slm_action,
+ 'received_secret_key' => $received_secret_key,
+ 'error_code' => SLM_Error_Codes::VERIFY_KEY_INVALID
+ );
+ // Output the API response with the error
+ self::output_api_response($args);
+ SLM_Helper_Class::write_log('Verification API secret key is invalid. Note: The key is case-sensitive. ' . $slm_action);
+ }
+ }
+
+ public static function get_slm_option($option)
+ {
+ // Retrieve the option value from the database
+ $slm_options_func = get_option('slm_plugin_options', []);
+
+ // Check if the option exists; if not, return an empty string
+ if (!isset($slm_options_func[$option])) {
+ return '';
+ }
+
+ // Get the option value and unslash it (removes slashes from the option value)
+ $option_value = wp_unslash($slm_options_func[$option]);
+
+ // Sanitize the option value (text field sanitization)
+ $sanitized_option = sanitize_text_field($option_value);
+
+ // Return the sanitized and unslashed option value
+ return $sanitized_option;
+ }
+
+
+ public static function verify_secret_key_for_creation()
+ {
+ // Get the stored secret key from plugin options
+ $slm_options = get_option('slm_plugin_options');
+ $right_secret_key = $slm_options['lic_creation_secret'] ?? '';
+
+ // Sanitize and retrieve the received secret key
+ $received_secret_key = sanitize_text_field($_REQUEST['secret_key'] ?? '');
+
+ // Case-sensitive comparison for the secret keys
+ if ($received_secret_key !== $right_secret_key) {
+ // Prepare the error response with case-sensitivity note
+ $args = array(
+ 'result' => 'error',
+ 'message' => 'Invalid License Creation API Secret Key provided. Note: The key comparison is case-sensitive.',
+ 'error_code' => SLM_Error_Codes::CREATE_KEY_INVALID
+ );
+ // Output the API response with the error
+ self::output_api_response($args);
+ }
+ }
+
+ public static function insert_license_data_internal($fields)
+ {
+ global $wpdb;
+ $slm_lic_table = SLM_TBL_LICENSE_KEYS;
+ $fields = array_filter($fields); // Remove any null values.
+
+ $wpdb->insert($slm_lic_table, $fields);
+ }
+}
+
+
+class SLM_Utility
+{
+ public static function get_licenses_by_email($email) {
+ global $wpdb;
+
+ // Query the licenses table for entries matching the email.
+ $table_name = SLM_TBL_LICENSE_KEYS; // Adjust table name if needed.
+ $query = $wpdb->prepare(
+ "SELECT license_key, product_ref, lic_status FROM $table_name WHERE email = %s",
+ $email
+ );
+
+ return $wpdb->get_results($query, ARRAY_A);
+ }
+
+ /**
+ * Saves a backup of the plugin's database tables in a secure folder.
+ */
+ public static function renew_license($license_key, $order_id) {
+ global $wpdb;
+ $wpdb->update(SLM_TBL_LICENSE_KEYS, [
+ 'wc_order_id' => $order_id,
+ 'payment_status' => 'pending'
+ ], ['license_key' => $license_key]);
+ }
+
+ public static function slm_save_backup_to_uploads()
+ {
+ global $wpdb;
+
+ // Get the upload directory
+ $upload_dir = wp_upload_dir();
+ $unique_hash = slm_get_unique_hash(); // Generate or retrieve the unique hash
+ $slm_backup_dir = $upload_dir['basedir'] . $unique_hash;
+
+ // Create the slm-plus folder with hash if it doesn't exist
+ if (!file_exists($slm_backup_dir)) {
+ wp_mkdir_p($slm_backup_dir);
+ }
+
+ // Set backup file name and path
+ $backup_file = $slm_backup_dir . '/slm_plugin_backup_' . gmdate('Y-m-d H:i:s') . '.sql';
+
+ // Get plugin tables
+ $backup_tables = [
+ SLM_TBL_LICENSE_KEYS,
+ SLM_TBL_LIC_DOMAIN,
+ SLM_TBL_LIC_DEVICES,
+ SLM_TBL_LIC_LOG,
+ SLM_TBL_EMAILS,
+ SLM_TBL_LICENSE_STATUS
+ ];
+
+ $sql = "";
+ foreach ($backup_tables as $table) {
+ // Get table structure
+ $create_table_query = $wpdb->get_results("SHOW CREATE TABLE $table", ARRAY_N);
+ $sql .= "\n\n" . $create_table_query[0][1] . ";\n\n";
+
+ // Get table data
+ $rows = $wpdb->get_results("SELECT * FROM $table", ARRAY_A);
+ foreach ($rows as $row) {
+ $values = array_map('esc_sql', array_values($row)); // Use esc_sql to escape the values
+ $values = "'" . implode("','", $values) . "'";
+ $sql .= "INSERT INTO $table VALUES ($values);\n";
+ }
+ }
+
+ // Include the WordPress Filesystem API
+ if (! function_exists('request_filesystem_credentials')) {
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ }
+
+ // Ensure the filesystem is ready
+ if (! WP_Filesystem()) {
+ request_filesystem_credentials(admin_url());
+ }
+
+ global $wp_filesystem;
+
+ // Define the backup file path
+ $backup_path = $upload_dir['basedir'] . '/' . $unique_hash . '/' . basename($backup_file);
+
+ // Create the backup directory if it doesn't exist
+ if (! is_dir(dirname($backup_path))) {
+ $wp_filesystem->mkdir(dirname($backup_path));
+ }
+
+ // Save the SQL to the backup file using the WP Filesystem
+ if ($wp_filesystem->put_contents($backup_path, $sql)) {
+ $backup_url = $upload_dir['baseurl'] . '/' . $unique_hash . '/' . basename($backup_file);
+
+ // Save backup info in plugin options
+ $backup_info = [
+ 'url' => $backup_url,
+ 'date' => gmdate('Y-m-d H:i:s'),
+ ];
+ slm_update_option('slm_last_backup_info', $backup_info);
+
+ echo '';
+ } else {
+ echo '' . esc_html__('Error: Failed to create the backup file.', 'slm-plus') . '
';
+ }
+ }
+
+ // Function to export a single license as a JSON file
+ public static function export_license_to_json($license_id_or_key)
+ {
+ global $wpdb;
+
+ // Fetch the custom directory path from options (saved with hash)
+ $slm_options = get_option('slm_plugin_options');
+ $custom_dir_hash = isset($slm_options['slm_backup_dir_hash']) ? $slm_options['slm_backup_dir_hash'] : '';
+
+ // Get the WordPress upload directory
+ $upload_dir = wp_upload_dir();
+ $custom_dir = $upload_dir['basedir'] . $custom_dir_hash;
+
+ // Ensure the directory exists
+ if (!file_exists($custom_dir)) {
+ wp_mkdir_p($custom_dir); // Create the directory if it doesn't exist
+ }
+
+ // Check if the input is a license ID or license key and fetch the license data accordingly
+ if (is_numeric($license_id_or_key)) {
+ // Fetch license by ID
+ $data = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . SLM_TBL_LICENSE_KEYS . " WHERE id = %d", $license_id_or_key), ARRAY_A);
+ } else {
+ // Fetch license by key
+ $data = $wpdb->get_row($wpdb->prepare("SELECT * FROM " . SLM_TBL_LICENSE_KEYS . " WHERE license_key = %s", $license_id_or_key), ARRAY_A);
+ }
+
+ if ($data) {
+ $license_key = $data['license_key'];
+
+ // Prepare the file name as "license_key.json"
+ $file_name = sanitize_file_name($license_key) . '.json';
+ $file_path = $custom_dir . '/' . $file_name;
+
+ // Encode the license data to JSON format
+ $json_data = wp_json_encode($data, JSON_PRETTY_PRINT);
+
+ // Save the JSON data to a file in the custom directory
+ if (file_put_contents($file_path, $json_data)) {
+ $file_url = $upload_dir['baseurl'] . $custom_dir_hash . '/' . $file_name;
+
+ // Return the file URL for download
+ return $file_url;
+ } else {
+ return false; // Return false if the file couldn't be saved
+ }
+ }
+
+ return false; // Return false if no data was found
+ }
+
+ public static function check_for_expired_lic($lic_key = '')
+ {
+ global $wpdb;
+
+ // Set up email headers and subject line
+ $headers = array('Content-Type: text/html; charset=UTF-8');
+ $subject = get_bloginfo('name') . ' - Your license has expired';
+ $expiration_reminder_text = SLM_Helper_Class::slm_get_option('expiration_reminder_text');
+ $expired_licenses_list = [];
+ $reinstated_licenses_list = [];
+
+ // Query licenses marked as expired but with future expiration dates to correct their status
+ $incorrectly_expired_query = $wpdb->prepare(
+ "SELECT * FROM " . SLM_TBL_LICENSE_KEYS . " WHERE lic_status = %s AND date_expiry > NOW()",
+ 'expired'
+ );
+ $incorrectly_expired_licenses = $wpdb->get_results($incorrectly_expired_query, ARRAY_A);
+
+ // Reinstate incorrectly expired licenses
+ foreach ($incorrectly_expired_licenses as $license) {
+ $license_key = sanitize_text_field($license['license_key']);
+ $id = intval($license['id']);
+
+ // Update license status to 'active'
+ $wpdb->update(
+ SLM_TBL_LICENSE_KEYS,
+ ['lic_status' => 'active'],
+ ['id' => $id]
+ );
+
+ self::create_log($license_key, 'status corrected to active');
+ $reinstated_licenses_list[] = $license_key;
+ }
+
+ // Log reinstated licenses
+ if (!empty($reinstated_licenses_list)) {
+ SLM_Helper_Class::write_log('Reinstated licenses set to active: ' . implode(', ', $reinstated_licenses_list));
+ }
+
+ // Query expired licenses
+ $expired_query = $wpdb->prepare(
+ "SELECT * FROM " . SLM_TBL_LICENSE_KEYS . " WHERE date_expiry < NOW() AND date_expiry != %s ORDER BY date_expiry ASC;",
+ '00000000'
+ );
+ $expired_licenses = $wpdb->get_results($expired_query, ARRAY_A);
+
+ // Check if any expired licenses were found
+ if (empty($expired_licenses)) {
+ SLM_Helper_Class::write_log('No expired licenses found');
+ return []; // Return an empty array if no licenses found
+ }
+
+ // Process each expired license
+ foreach ($expired_licenses as $license) {
+ $id = intval($license['id']);
+ $license_key = sanitize_text_field($license['license_key']);
+ // $first_name = sanitize_text_field($license['first_name']);
+ // $last_name = sanitize_text_field($license['last_name']);
+ $email = sanitize_email($license['email']);
+ $date_expiry = sanitize_text_field($license['date_expiry']);
+
+ // Include email template and generate the email body
+ ob_start();
+ include SLM_LIB . 'mails/expired.php';
+ $body = ob_get_clean();
+
+ // Check if auto-expiration is enabled and update the license status
+ if (SLM_Helper_Class::slm_get_option('enable_auto_key_expiration') == 1) {
+ $update_data = ['lic_status' => 'expired'];
+ $where_clause = ['id' => $id];
+ $wpdb->update(SLM_TBL_LICENSE_KEYS, $update_data, $where_clause);
+
+ // Log and send expiration notification
+ self::create_log($license_key, 'set to expired');
+ $email_result = self::slm_check_sent_emails($license_key, $email, $subject, $body, $headers);
+ if ($email_result === '200') {
+ self::create_log($license_key, 'sent expiration email notification');
+ }
+ }
+
+ // Add license to the expired list
+ $expired_licenses_list[] = $license_key;
+ }
+
+ // Log the total count of expired licenses
+ SLM_Helper_Class::write_log('Expired licenses found and processed: ' . implode(', ', $expired_licenses_list));
+
+ return [
+ 'expired_licenses' => $expired_licenses_list,
+ 'reinstated_licenses' => $reinstated_licenses_list
+ ]; // Return both expired and reinstated licenses
+ }
+
+
+ // Define return codes for clarity
+ const EMAIL_SENT_FIRST_TIME = '200';
+ const EMAIL_ALREADY_SENT = '400';
+ const EMAIL_SENT_RECORD_NOT_FOUND = '300';
+
+ public static function slm_check_sent_emails($license_key, $email, $subject, $body, $headers)
+ {
+ global $wpdb;
+
+ // Check if an email has already been sent for this license key
+ $query = $wpdb->prepare(
+ 'SELECT COUNT(*) FROM ' . SLM_TBL_EMAILS . ' WHERE lic_key = %s',
+ $license_key
+ );
+ $email_already_sent = $wpdb->get_var($query) > 0;
+
+ // If email already sent, return status code without resending
+ if ($email_already_sent) {
+ return self::EMAIL_ALREADY_SENT;
+ }
+
+ // Send the email if it hasn't been sent before
+ $mail_sent = wp_mail($email, $subject, $body, $headers);
+
+ // Log the email status
+ if ($mail_sent) {
+ self::create_email_log($license_key, $email, 'success', 'yes', current_time('mysql'));
+ return self::EMAIL_SENT_FIRST_TIME;
+ } else {
+ self::create_email_log($license_key, $email, 'failure', 'no', current_time('mysql'));
+ return self::EMAIL_SENT_RECORD_NOT_FOUND;
+ }
+ }
+
+
+ public static function do_auto_key_expiry()
+ {
+ global $wpdb;
+ $current_date = current_time('Y-m-d');
+ $slm_lic_table = SLM_TBL_LICENSE_KEYS;
+
+ // Query for active (non-expired) licenses
+ $licenses = $wpdb->get_results(
+ $wpdb->prepare("SELECT * FROM $slm_lic_table WHERE lic_status != %s", 'expired'),
+ OBJECT
+ );
+
+ // Log and return if no licenses are found
+ if (empty($licenses)) {
+ SLM_Debug_Logger::log_debug_st("do_auto_key_expiry() - No active license keys found.");
+ return false;
+ }
+
+ $today_dt = new DateTime($current_date);
+
+ foreach ($licenses as $license) {
+ $license_key = sanitize_text_field($license->license_key);
+ $expiry_date = sanitize_text_field($license->date_expiry);
+
+ // Skip if expiration date is invalid or empty
+ if (empty($expiry_date) || in_array($expiry_date, ['0000-00-00', '00000000'])) {
+ SLM_Debug_Logger::log_debug_st("License key ($license_key) has no valid expiration date set. Skipping expiry check.");
+ continue;
+ }
+
+ // Check if the license has expired
+ $expire_dt = new DateTime($expiry_date);
+ if ($today_dt > $expire_dt) {
+ // Update license status to 'expired'
+ $data = ['lic_status' => 'expired'];
+ $where = ['id' => intval($license->id)];
+ $updated = $wpdb->update($slm_lic_table, $data, $where);
+
+ // Log the expiry and trigger action if successfully updated
+ if ($updated) {
+ SLM_Debug_Logger::log_debug_st("License key ($license_key) expired on $expiry_date. Status set to 'expired'.");
+ do_action('slm_license_key_expired', $license->id);
+
+ // Optional: Send expiry reminder email
+ self::check_for_expired_lic($license_key);
+ } else {
+ SLM_Debug_Logger::log_debug_st("Failed to update status for expired license key ($license_key).");
+ }
+ }
+ }
+
+ return true;
+ }
+
+
+
+ public static function get_user_info($by, $value)
+ {
+ // Sanitize the input parameters
+ $by = sanitize_key($by);
+ $value = sanitize_text_field($value);
+
+ // Get the user by specified criteria
+ $user = get_user_by($by, $value);
+ return $user;
+ }
+
+ public static function get_days_remaining($date1)
+ {
+ // Validate and sanitize the date input
+ $date1 = sanitize_text_field($date1);
+
+ // Retrieve the date format setting from WordPress settings
+ $date_format = get_option('date_format');
+
+ try {
+ // Create DateTime objects for future and current dates
+ $future_date = new DateTime($date1);
+ $current_date = new DateTime();
+
+ // Check if the future date is valid and in the future
+ if ($future_date < $current_date) {
+ return __('0 days remaining', 'slm-plus');
+ }
+
+ // Calculate the difference in days
+ $interval = $current_date->diff($future_date);
+ $days_remaining = (int) $interval->days;
+
+ // Format and return the result
+ return sprintf(
+ // Translators: %1$s is the number of days remaining, %2$s is the formatted future date
+ __('%1$s days remaining until %2$s', 'slm-plus'),
+ $days_remaining,
+ date_i18n($date_format, $future_date->getTimestamp())
+ );
+ } catch (Exception $e) {
+ // Return 0 days remaining if date parsing fails
+ return __('0 days remaining', 'slm-plus');
+ }
+ }
+
+
+ public static function delete_license_key_by_row_id($key_row_id)
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ // Sanitize the input
+ $key_row_id = intval($key_row_id);
+
+ // Retrieve the license key associated with this row id
+ $license_key = $wpdb->get_var($wpdb->prepare("SELECT license_key FROM $license_table WHERE id = %d", $key_row_id));
+
+ // Debug: Log the retrieved license key
+ SLM_Helper_Class::write_log("License key retrieved: " . $license_key);
+
+ // First, delete the registered domains entry of this key (if any)
+ SLM_Utility::delete_registered_domains_of_key($key_row_id);
+ SLM_Helper_Class::write_log("Registered domains for key $license_key deleted.");
+
+ // Now, delete the key from the licenses table
+ $wpdb->delete($license_table, array('id' => $key_row_id));
+ SLM_Helper_Class::write_log("License with row ID $key_row_id deleted from the license table.");
+
+ if ($license_key) {
+
+ // Query to get WooCommerce orders using a custom WP_Query with meta_query
+ $args = array(
+ 'post_type' => 'shop_order',
+ 'posts_per_page' => -1,
+ 'meta_query' => array(
+ 'relation' => 'OR',
+ array(
+ 'key' => 'License Key', // License Key meta field
+ 'value' => $license_key,
+ 'compare' => '='
+ ),
+ array(
+ 'key' => '_slm_lic_key', // Fallback License Key meta field
+ 'value' => $license_key,
+ 'compare' => '='
+ )
+ )
+ );
+
+ $order_query = new WP_Query($args);
+
+ if ($order_query->have_posts()) {
+ while ($order_query->have_posts()) {
+ $order_query->the_post();
+ $order_id = get_the_ID();
+
+ // Get order object
+ $order = wc_get_order($order_id);
+
+ // Debugging: Log the order ID
+ SLM_Helper_Class::write_log("Processing order ID: " . $order_id);
+
+ // Meta keys to be removed
+ $meta_keys = [
+ 'License Key',
+ 'License Type',
+ 'Current Version',
+ 'Until Version',
+ 'Max Devices',
+ 'Max Domains'
+ ];
+
+ // Remove order-level metadata
+ foreach ($meta_keys as $meta_key) {
+ $meta_value = $order->get_meta($meta_key, true); // Retrieve the metadata value
+ if ($meta_value) {
+ SLM_Helper_Class::write_log("Found meta key $meta_key with value: $meta_value. Deleting...");
+ $order->delete_meta_data($meta_key); // Remove meta data from the order
+ }
+ }
+
+ // Add a note to the order
+ $note_content = sprintf(__('License key %s was deleted on %s', 'slm-plus'), $license_key, date_i18n('F j, Y'));
+ $order->add_order_note($note_content);
+
+ // Process and reset license-related metadata from order items
+ foreach ($order->get_items() as $item_id => $item) {
+ // Remove item-level metadata for the specified keys
+ foreach ($meta_keys as $meta_key) {
+ $meta_value = $item->get_meta($meta_key, true); // Retrieve the metadata value
+ if ($meta_value) {
+ SLM_Helper_Class::write_log("Found meta key $meta_key in order item $item_id with value: $meta_value. Deleting...");
+ $item->delete_meta_data($meta_key); // Remove meta data from the order item
+ }
+ }
+
+ // Save the updated order item
+ $item->save();
+ }
+
+ // Save the updated order
+ $order->save();
+ }
+
+ wp_reset_postdata(); // Reset the post data after custom query
+ } else {
+ // Debugging: Log if no orders were found
+ SLM_Helper_Class::write_log("No orders found for the license key: " . $license_key);
+ }
+ }
+ }
+
+ /**
+ * Get license key by WooCommerce Order ID.
+ *
+ * @param int $order_id WooCommerce order ID.
+ * @return string|null License key associated with the order ID, or null if not found.
+ */
+ public static function slm_get_license_by_order_id($order_id) {
+ global $wpdb;
+ $lic_key_table = SLM_TBL_LICENSE_KEYS;
+
+ // Query to fetch the license key by order ID
+ $query = $wpdb->prepare("SELECT license_key FROM $lic_key_table WHERE wc_order_id = %d", $order_id);
+ $license_key = $wpdb->get_var($query);
+
+ return $license_key ? sanitize_text_field($license_key) : null;
+ }
+
+
+
+ /**
+ * Get associated orders for a license.
+ *
+ * @param mixed $identifier The license key (string) or license ID (integer).
+ * @return array|null List of associated orders or null if none found.
+ */
+ public static function slm_get_associated_orders($identifier) {
+ global $wpdb;
+ $lic_key_table = SLM_TBL_LICENSE_KEYS;
+
+ // Ensure identifier is valid
+ if (empty($identifier)) {
+ SLM_Helper_Class::write_log('Invalid identifier passed to slm_get_associated_orders: ' . print_r($identifier, true));
+ return [];
+ }
+
+ // Prepare the query based on identifier type
+ if (is_numeric($identifier)) {
+ $query = $wpdb->prepare("SELECT associated_orders FROM $lic_key_table WHERE id = %d", $identifier);
+ } else {
+ $query = $wpdb->prepare("SELECT associated_orders FROM $lic_key_table WHERE license_key = %s", $identifier);
+ }
+
+ // Log the query
+ SLM_Helper_Class::write_log('SQL Query: ' . $query);
+
+ // Execute the query
+ $result = $wpdb->get_var($query);
+
+ // Debug the raw result
+ SLM_Helper_Class::write_log('Raw associated_orders value: ' . print_r($result, true));
+
+ // Process the result if not empty
+ if (!empty($result)) {
+ $orders = maybe_unserialize($result);
+ SLM_Helper_Class::write_log('Unserialized associated_orders value: ' . print_r($orders, true));
+
+ if (is_array($orders)) {
+ return array_values(array_unique(array_map('intval', $orders)));
+ }
+ }
+
+ // Return empty array if no valid data found
+ return [];
+ }
+
+
+
+
+ /**
+ * Add an order to the associated orders of a license.
+ *
+ * @param mixed $identifier The license key (string) or license ID (integer).
+ * @param int $order_id The WooCommerce order ID to associate with the license.
+ * @return bool True if the operation was successful, false otherwise.
+ */
+ public static function slm_add_associated_order($identifier, $order_id) {
+ global $wpdb;
+ $lic_key_table = SLM_TBL_LICENSE_KEYS;
+
+ // Validate $order_id
+ if (!is_numeric($order_id) || $order_id <= 0) {
+ error_log("SLM: Invalid order ID provided: $order_id");
+ return false;
+ }
+
+ // Fetch current license data
+ if (is_numeric($identifier)) {
+ // Identifier is a license ID
+ $license_data = $wpdb->get_row(
+ $wpdb->prepare("SELECT associated_orders, wc_order_id FROM $lic_key_table WHERE id = %d", $identifier),
+ ARRAY_A
+ );
+ } else {
+ // Identifier is a license key
+ $license_data = $wpdb->get_row(
+ $wpdb->prepare("SELECT associated_orders, wc_order_id FROM $lic_key_table WHERE license_key = %s", $identifier),
+ ARRAY_A
+ );
+ }
+
+ if (!$license_data) {
+ error_log("SLM: License not found for identifier: $identifier");
+ return false;
+ }
+
+ // Extract current associated orders and wc_order_id
+ $associated_orders = maybe_unserialize($license_data['associated_orders']);
+ $current_wc_order_id = $license_data['wc_order_id'];
+
+ // Ensure $associated_orders is a valid array
+ if (!is_array($associated_orders)) {
+ $associated_orders = [];
+ }
+
+ // Add the old wc_order_id to the associated_orders array if it's valid
+ if (!empty($current_wc_order_id) && !in_array($current_wc_order_id, $associated_orders, true)) {
+ $associated_orders[] = $current_wc_order_id;
+ }
+
+ // Add the new order_id to the associated_orders array if not already present
+ if (!in_array($order_id, $associated_orders, true)) {
+ $associated_orders[] = $order_id;
+ }
+
+ // Serialize the updated orders for storage
+ $updated_orders = maybe_serialize($associated_orders);
+
+ // Prepare the query to update the database
+ if (is_numeric($identifier)) {
+ // Update based on license ID
+ $query = $wpdb->prepare(
+ "UPDATE $lic_key_table SET associated_orders = %s, wc_order_id = %d WHERE id = %d",
+ $updated_orders,
+ $order_id,
+ $identifier
+ );
+ } else {
+ // Update based on license key
+ $query = $wpdb->prepare(
+ "UPDATE $lic_key_table SET associated_orders = %s, wc_order_id = %d WHERE license_key = %s",
+ $updated_orders,
+ $order_id,
+ $identifier
+ );
+ }
+
+ // Execute the query
+ $result = $wpdb->query($query);
+
+ // Handle and log errors
+ if ($result === false) {
+ error_log("SLM: Failed to update associated orders for identifier: $identifier. Error: " . $wpdb->last_error);
+ return false;
+ }
+
+ // Log success
+ error_log("SLM: Successfully updated associated orders for identifier: $identifier with Order ID: $order_id");
+ return true;
+ }
+
+
+
+ /*
+ * Retrieves the email associated with a license key
+ */
+ public static function slm_get_lic_email($license)
+ {
+ global $wpdb;
+ $lic_key_table = SLM_TBL_LICENSE_KEYS;
+
+ // Sanitize the input
+ $license = sanitize_text_field($license);
+
+ // Prepare and execute the query to fetch the email
+ $email = $wpdb->get_var(
+ $wpdb->prepare("SELECT email FROM $lic_key_table WHERE license_key = %s", $license)
+ );
+
+ // Check if an email was found and is valid
+ if ($email && is_email($email)) {
+ return $email;
+ } else {
+ // Return a WP_Error if the email was not found or invalid
+ return new WP_Error('license_not_found', __('License key not found or invalid email.', 'slm-plus'));
+ }
+ }
+
+
+ /*
+ * Sends an email with the specified parameters
+ */
+ public static function slm_send_mail($to, $subject, $message, $bgcolor)
+ {
+ // Sanitize inputs
+ $to = sanitize_email($to);
+ $subject = sanitize_text_field($subject);
+ $message = sanitize_textarea_field($message);
+
+ // Prepare headers
+ $headers = array(
+ 'From: ' . get_bloginfo('name') . ' <' . get_bloginfo('admin_email') . '>',
+ 'Content-Type: text/html; charset=UTF-8'
+ );
+
+ // Prepare the email body
+ $body = self::slm_email_template($message, $bgcolor);
+
+ // Send the email
+ wp_mail($to, $subject, $body, $headers);
+ }
+
+
+ public static function slm_email_template($message, $bgcolor = '')
+ {
+ switch ($bgcolor) {
+ case 'success':
+ $color = '#eceff0';
+ break;
+ case 'error':
+ $color = '#e23b2f';
+ break;
+ default:
+ $color = '#eceff0';
+ break;
+ }
+
+ $template = '
+
+
+
+ ' . esc_html(get_bloginfo('name')) . '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
License key was activated successfully!
+
' . wp_kses_post($message) . '
+
Regards,
+
+
+
+
+
The content of this email is confidential and intended for the recipient specified in message only. It is strictly forbidden to share any part of this message with any third party, without a written consent of the sender. If you received this message by mistake, please reply to this message and follow with its deletion, so that we can ensure such a mistake does not occur in the future.
+
Questions? We are always here to help. Contact ' . esc_html(get_bloginfo('admin_email')) . ' or simply reply to this email.
+
+
+
+
+
+
+
+
+
+
+
+ ';
+
+ return $template;
+ }
+
+ public static function count_licenses($status)
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ // Sanitize input
+ $status = sanitize_text_field($status);
+
+ // Prepare the SQL statement
+ $query = $wpdb->prepare("SELECT COUNT(*) FROM $license_table WHERE lic_status = %s", $status);
+ $get_lic_status = $wpdb->get_var($query);
+
+ return $get_lic_status;
+ }
+
+ public static function slm_get_icon_url($size, $filename)
+ {
+ // Sanitize inputs
+ $size = sanitize_text_field($size);
+ $filename = sanitize_file_name($filename);
+
+ return SLM_ASSETS_URL . 'icons/' . $size . '/' . $filename;
+ }
+
+ public static function count_logrequest()
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_LIC_LOG;
+
+ $getlogs = $wpdb->get_var("SELECT COUNT(*) FROM $license_table");
+ return $getlogs;
+ }
+
+ public static function count_emailsent()
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_EMAILS;
+
+ $getlogs = $wpdb->get_var("SELECT COUNT(*) FROM $license_table");
+ return $getlogs;
+ }
+
+ public static function getstats_licenses($date_created, $interval)
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ // Sanitize inputs
+ $date_created = sanitize_text_field($date_created);
+ $interval = intval($interval);
+
+ $query = $wpdb->prepare(
+ "SELECT COUNT(*) FROM $license_table WHERE $date_created >= DATE_ADD(CURDATE(), INTERVAL -%d DAY)",
+ $interval
+ );
+
+ return $wpdb->get_var($query);
+ }
+
+ public static function get_total_licenses()
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ $license_count = $wpdb->get_var("SELECT COUNT(*) FROM $license_table");
+ return $license_count;
+ }
+
+ public static function get_lic_expiringsoon()
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ $license_count = $wpdb->get_var(
+ "SELECT COUNT(*) FROM $license_table WHERE date_expiry BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 MONTH) AND CURDATE()"
+ );
+
+ return $license_count;
+ }
+
+ public static function block_license_key_by_row_id($key_row_id)
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ // Sanitize input
+ $key_row_id = intval($key_row_id);
+
+ $wpdb->update($license_table, array('lic_status' => 'blocked'), array('id' => $key_row_id));
+ }
+
+ public static function expire_license_key_by_row_id($key_row_id)
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+
+ // Sanitize input
+ $key_row_id = intval($key_row_id);
+
+ $wpdb->update($license_table, array('lic_status' => 'expired'), array('id' => $key_row_id));
+ }
+
+ public static function active_license_key_by_row_id($key_row_id)
+ {
+ global $wpdb;
+ $license_table = SLM_TBL_LICENSE_KEYS;
+ $current_date = current_time('Y-m-d');
+
+ // Sanitize input
+ $key_row_id = intval($key_row_id);
+
+ $wpdb->update($license_table, array('lic_status' => 'active'), array('id' => $key_row_id));
+ $wpdb->update($license_table, array('date_activated' => $current_date), array('id' => $key_row_id));
+ }
+
+ /*
+ * Deletes any registered domains and related entries for the given license key's row id.
+ */
+ static function delete_registered_domains_of_key($key_row_id)
+ {
+ global $slm_debug_logger;
+ global $wpdb;
+
+ // Table constants
+ $reg_domain_table = SLM_TBL_LIC_DOMAIN;
+ $device_table = SLM_TBL_LIC_DEVICES;
+ $log_table = SLM_TBL_LIC_LOG;
+ $email_table = SLM_TBL_EMAILS;
+
+ // Retrieve the license key associated with this row id
+ $license_key = $wpdb->get_var($wpdb->prepare("SELECT license_key FROM " . SLM_TBL_LICENSE_KEYS . " WHERE id = %d", $key_row_id));
+
+ if ($license_key) {
+ // Step 1: Delete from registered domains table
+ $reg_domains = $wpdb->get_results($wpdb->prepare("SELECT id FROM $reg_domain_table WHERE lic_key_id = %d", $key_row_id));
+ foreach ($reg_domains as $domain) {
+ $wpdb->delete($reg_domain_table, array('id' => $domain->id));
+ $slm_debug_logger->log_debug("Registered domain with row id (" . $domain->id . ") deleted.");
+ }
+
+ // Step 2: Delete from devices table
+ $deleted_devices = $wpdb->delete($device_table, array('lic_key' => $license_key), array('%s'));
+ $slm_debug_logger->log_debug("$deleted_devices entries deleted from devices table for license key ($license_key).");
+
+ // Step 3: Delete from log table
+ $deleted_logs = $wpdb->delete($log_table, array('license_key' => $license_key), array('%s'));
+ $slm_debug_logger->log_debug("$deleted_logs entries deleted from log table for license key ($license_key).");
+
+ // Step 4: Delete from emails table
+ $deleted_emails = $wpdb->delete($email_table, array('lic_key' => $license_key), array('%s'));
+ $slm_debug_logger->log_debug("$deleted_emails entries deleted from emails table for license key ($license_key).");
+ } else {
+ $slm_debug_logger->log_debug("No license key found for row id ($key_row_id). Deletion aborted.");
+ }
+ }
+
+
+ static function create_secret_keys()
+ {
+ // Generate secure random bytes (32 bytes = 256 bits)
+ $random_bytes = openssl_random_pseudo_bytes(32); // 32 bytes (256 bits)
+
+ // Convert the random bytes into a hexadecimal string (64 chars)
+ $random_string = bin2hex($random_bytes);
+
+ // Make the entire string uppercase
+ $key = strtoupper($random_string);
+
+ return $key;
+ }
+
+ public static function create_log($license_key, $action)
+ {
+ global $wpdb;
+ $slm_log_table = SLM_TBL_LIC_LOG;
+
+ // Sanitize inputs
+ $license_key = sanitize_text_field($license_key);
+ $action = sanitize_text_field($action);
+
+ // Determine the request origin
+ $origin = '';
+ if (!empty($_SERVER['HTTP_ORIGIN'])) {
+ $origin = sanitize_text_field($_SERVER['HTTP_ORIGIN']);
+ } elseif (!empty($_SERVER['HTTP_REFERER'])) {
+ $origin = sanitize_text_field($_SERVER['HTTP_REFERER']);
+ } elseif (!empty($_SERVER['REMOTE_ADDR'])) {
+ $origin = sanitize_text_field($_SERVER['REMOTE_ADDR']);
+ }
+
+ // Get current date and time
+ $current_date_time = current_time('mysql'); // Returns 'Y-m-d H:i:s' in WordPress timezone
+ $current_time_only = date('H:i:s', strtotime($current_date_time)); // Extract time portion
+
+ // Prepare log data
+ $log_data = [
+ 'license_key' => $license_key,
+ 'slm_action' => $action,
+ 'time' => $current_date_time, // Combined date and time
+ 'time_only' => $current_time_only, // Time only
+ 'source' => $origin,
+ ];
+
+ // Insert log data into the database
+ $inserted = $wpdb->insert($slm_log_table, $log_data);
+
+ // Check for insertion errors
+ if ($inserted === false) {
+ error_log("Failed to insert log for license key: $license_key, action: $action. Error: " . $wpdb->last_error);
+ } else {
+ error_log("Log inserted successfully for license key: $license_key, action: $action.");
+ }
+ }
+
+
+
+
+
+ public static function create_email_log($lic_key, $sent_to, $status, $sent, $date_sent = null)
+ {
+ global $wpdb;
+ $slm_email_table = SLM_TBL_EMAILS;
+
+ // Sanitize inputs
+ $lic_key = sanitize_text_field($lic_key);
+ $sent_to = sanitize_email($sent_to);
+ $status = sanitize_text_field($status);
+ $sent = sanitize_text_field($sent);
+ $date_sent = $date_sent ? sanitize_text_field($date_sent) : current_time('mysql');
+
+ // Prepare log data
+ $log_data = array(
+ 'lic_key' => $lic_key,
+ 'sent_to' => $sent_to,
+ 'status' => $status,
+ 'sent' => $sent,
+ 'date_sent' => $date_sent,
+ );
+
+ // Insert log data into the database
+ $inserted = $wpdb->insert($slm_email_table, $log_data);
+
+ // Check for insertion success and log accordingly
+ if ($inserted !== false) {
+ SLM_Helper_Class::write_log("Email log created for license key: $lic_key");
+ } else {
+ error_log("Failed to create email log for license key: $lic_key. Error: " . $wpdb->last_error);
+ }
+ }
+
+ static function slm_wp_dashboards_stats($amount)
+ {
+ global $wpdb;
+ $slm_log_table = SLM_TBL_LICENSE_KEYS;
+
+ $result = $wpdb->get_results(" SELECT * FROM $slm_log_table ORDER BY id DESC LIMIT $amount");
+
+ foreach ($result as $license) {
+ echo '
+
+ ' . esc_html($license->first_name) . ' ' . esc_html($license->last_name) . '
+ ' . esc_html($license->license_key) . '
+
+ ';
+ }
+ }
+
+ static function slm_get_licinfo($api_action, $license_key)
+ {
+ $api_url = get_site_url() . '/?secret_key=' . SLM_Helper_Class::slm_get_option('lic_verification_secret') . '&slm_action=' . $api_action . '&license_key=' . $license_key;
+ $curl = curl_init();
+ curl_setopt_array($curl, array(
+ CURLOPT_URL => $api_url,
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_ENCODING => "",
+ CURLOPT_MAXREDIRS => 10,
+ CURLOPT_TIMEOUT => 0,
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
+ CURLOPT_CUSTOMREQUEST => "GET",
+ ));
+ $response = curl_exec($curl);
+ curl_close($curl);
+ $json = json_decode($response);
+ return $json;
+ }
+
+ static function get_subscriber_licenses()
+ {
+ global $wpdb;
+ $email = $_GET['email'];
+ $manage_subscriber = $_GET['manage_subscriber'];
+
+ if (isset($email) && isset($manage_subscriber) && current_user_can('edit_pages')) {
+
+ echo 'Listing all licenses related to ' . esc_html($email) . ' ';
+
+ $result_array = $wpdb->get_results(
+ $wpdb->prepare(
+ "SELECT * FROM " . SLM_TBL_LICENSE_KEYS . " WHERE email LIKE %s ORDER BY `email` DESC LIMIT 0,1000",
+ '%' . $wpdb->esc_like($email) . '%'
+ ),
+ ARRAY_A
+ );
+
+
+ foreach ($result_array as $slm_user) {
+ echo '
+ ' . esc_html($slm_user["id"]) . '
+ ' . esc_html($slm_user["license_key"]) . '
+ ' . esc_html($slm_user["lic_status"]) . '
+ ' . esc_html__('View', 'slm-plus') . '
+ ';
+ }
+ }
+ }
+
+ static function get_lic_activity($license_key)
+ {
+ global $wpdb;
+ $slm_log_table = SLM_TBL_LIC_LOG;
+
+ echo '
+
+
+
+
+ ' . esc_html__('ID', 'slm-plus') . '
+ ' . esc_html__('Request', 'slm-plus') . '
+
+
+
+ ';
+ $activity = $wpdb->get_results("SELECT * FROM " . $slm_log_table . " WHERE license_key='" . $license_key . "';");
+ foreach ($activity as $log) {
+ echo '
+ ' .
+ '' . esc_html($log->id) . ' ' .
+ ' ' . esc_html($log->slm_action) . ' ' .
+ ' ' . esc_html__('Source:', 'slm-plus') . ' ' . esc_html($log->source) .
+ '
' . esc_html__('Time:', 'slm-plus') . ' ' . esc_html($log->time) . '
+ ';
+ }
+ echo '
+
+
+
';
+ }
+
+ static function get_license_activation($license_key, $tablename, $item_name, $activation_type, $allow_removal = true)
+ {
+?>
+
+
+ prepare("SELECT * FROM $tablename WHERE lic_key = %s", $license_key);
+ $activations = $wpdb->get_results($sql_prep, OBJECT);
+
+ if (count($activations) > 0) : ?>
+
+
+
+
+
+ registered_devices) . '" aria-label="' . esc_attr($activation->registered_devices) . '" aria-describedby="' . esc_attr($activation->registered_devices) . '" value="' . esc_attr($activation->registered_devices) . '" readonly>';
+ } else {
+ echo '
';
+ }
+ ?>
+
+
+ Remove
+
+
+
+
+
+
+
+
+
+ ' . esc_html__('Not registered yet', 'slm-plus') . '
'; ?>
+
+
+is_type('slm_license')) {
+ $tabs['shipping'] = array(
+ 'title' => __('License information', 'slm-plus'),
+ 'priority' => 50,
+ 'callback' => 'slm_woo_tab_lic_info'
+ );
+ }
+ return $tabs;
+ }
+
+ function slm_woo_tab_lic_info()
+ {
+ global $product;
+ // The new tab content
+ echo '')
+ .addClass('suggestion-item')
+ .text(`${user.first_name} ${user.last_name} (${user.email})`);
+ suggestion.data('user', user);
+ suggestionsBox.append(suggestion);
+ });
+ suggestionsBox.show(); // Show suggestions box if results are found
+ } else {
+ suggestionsBox.hide(); // Hide suggestions box if no results
+ }
+
+ // Handle suggestion click
+ $('.suggestion-item').on('click', function() {
+ const user = $(this).data('user');
+ $('#user_id').val(user.ID);
+ $('#first_name').val(user.first_name);
+ $('#last_name').val(user.last_name);
+ $('#email').val(user.email);
+ $('#subscr_id').val(user.subscr_id); // Populate the subscr_id field
+
+ // Populate company_name if available
+ if (user.company_name) {
+ $('#company_name').val(user.company_name);
+ } else {
+ $('#company_name').val(''); // Clear if no company name is available
+ }
+
+ suggestionsBox.hide(); // Hide suggestions after selection
+ });
+ },
+ });
+ } else {
+ suggestionsBox.hide(); // Hide suggestions if input length < 2
+ }
+ });
+
+ // Hide suggestions if clicking outside of them
+ $(document).on('click', function(e) {
+ if (!$(e.target).closest('.user-search-input, .user-search-suggestions').length) {
+ $('.user-search-suggestions').hide();
+ }
+ });
+});
+
+
+jQuery(document).ready(function($) {
+ let userSelectedDay = null; // Store manually set day of the month
+
+ // Helper to calculate expiry date based on length, interval, and stored day
+ function calculateExpiryDate() {
+ // Exit if lifetime is selected
+ if ($('#lic_type').val() === 'lifetime') return;
+
+ const dateCreated = new Date($('#date_created').val());
+ const billingLength = parseInt($('#slm_billing_length').val()) || 0;
+ const billingInterval = $('#slm_billing_interval').val();
+
+ // Use user-selected day if it exists, otherwise default to the day in `dateCreated`
+ const dayToPreserve = userSelectedDay || dateCreated.getDate();
+
+ // Adjust expiry date based on interval and preserved day
+ let expiryDate = new Date(dateCreated);
+ if (billingInterval === 'years') {
+ expiryDate.setFullYear(dateCreated.getFullYear() + billingLength);
+ } else if (billingInterval === 'months') {
+ expiryDate.setMonth(dateCreated.getMonth() + billingLength);
+ } else if (billingInterval === 'days') {
+ expiryDate.setDate(dateCreated.getDate() + billingLength);
+ }
+
+ // Set the day to the preserved day, adjusting for month-end overflow
+ expiryDate.setDate(Math.min(dayToPreserve, daysInMonth(expiryDate)));
+
+ // Format and set expiry date
+ $('#date_expiry').val(expiryDate.toISOString().split('T')[0]);
+ }
+
+ // Helper to calculate the number of days in a given month/year
+ function daysInMonth(date) {
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
+ }
+
+ // Calculate interval and length based on expiry date
+ function calculateIntervalAndLengthFromExpiry() {
+ if ($('#lic_type').val() === 'lifetime') return; // Skip if lifetime
+
+ const dateCreated = new Date($('#date_created').val());
+ const dateExpiry = new Date($('#date_expiry').val());
+
+ if (dateExpiry < dateCreated) {
+ alert('Expiration date cannot be before the creation date.');
+ $('#date_expiry').val($('#date_created').val()); // Reset to creation date
+ return;
+ }
+
+ const diffTime = dateExpiry - dateCreated;
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
+ const diffMonths = Math.ceil(diffDays / 30);
+ const diffYears = Math.ceil(diffMonths / 12);
+
+ if (diffYears >= 1) {
+ $('#slm_billing_interval').val('years');
+ $('#slm_billing_length').val(diffYears);
+ } else if (diffMonths >= 1) {
+ $('#slm_billing_interval').val('months');
+ $('#slm_billing_length').val(diffMonths);
+ } else {
+ $('#slm_billing_interval').val('days');
+ $('#slm_billing_length').val(diffDays);
+ }
+ }
+
+ // Adjust fields based on license type
+ function adjustFieldsBasedOnType() {
+ const licType = $('#lic_type').val();
+ const isLifetime = licType === 'lifetime';
+
+ if (isLifetime) {
+ // Set expiration far in the future for lifetime licenses
+ const expiryDate = new Date();
+ expiryDate.setFullYear(expiryDate.getFullYear() + 200);
+ $('#date_expiry').val(expiryDate.toISOString().split('T')[0]);
+ userSelectedDay = null; // Clear any selected day
+ }
+
+ // Disable or enable fields based on license type
+ $('#date_expiry, #slm_billing_length, #slm_billing_interval, #date_renewed')
+ .prop('disabled', isLifetime)
+ .closest('tr').toggle(!isLifetime);
+ }
+
+ // Track user-selected day when the expiration date is set manually
+ $('#date_expiry').on('change', function() {
+ const selectedDate = new Date($(this).val());
+ userSelectedDay = selectedDate.getDate(); // Store selected day (e.g., 15)
+ calculateIntervalAndLengthFromExpiry(); // Update interval and length if needed
+ });
+
+ // Set today's date for date_created if new record and disable the field
+ const isEditRecord = window.location.search.includes('edit_record') || window.location.search.includes('slm_save_license');
+ if (!isEditRecord) {
+ const today = new Date().toISOString().split('T')[0];
+ $('#date_created').val(today).prop('disabled', true);
+ }
+
+ // Recalculate expiry date when billing length or interval changes
+ $('#slm_billing_length, #slm_billing_interval').on('change', function() {
+ if ($('#lic_type').val() !== 'lifetime') {
+ calculateExpiryDate();
+ }
+ });
+
+ // Attach change event to license type and initialize on page load
+ $('#lic_type').on('change', adjustFieldsBasedOnType);
+ adjustFieldsBasedOnType(); // Initialize
+
+ // Calculate initial expiry date on page load for new records
+ calculateExpiryDate();
+});
diff --git a/software-license-manager/js/wplm-custom-admin.js b/public/assets/js/wplm-custom-admin.js
old mode 100644
new mode 100755
similarity index 58%
rename from software-license-manager/js/wplm-custom-admin.js
rename to public/assets/js/wplm-custom-admin.js
index fb6639a..ad40813
--- a/software-license-manager/js/wplm-custom-admin.js
+++ b/public/assets/js/wplm-custom-admin.js
@@ -1,11 +1,10 @@
-jQuery(document).ready(function($){
- //Add date picker listener on date fields
- if ($.fn.datepicker){
- $('.wplm_pick_date').datepicker({
- dateFormat : 'yy-mm-dd'
- });
- }
-
- //Add other admin side only jquery code below
-
-});
\ No newline at end of file
+jQuery(document).ready(function($){
+ //Add date picker listener on date fields
+ if ($.fn.datepicker){
+ jQuery('.wplm_pick_date').datepicker({
+ dateFormat : 'yy-mm-dd'
+ });
+ }
+});
+
+
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..fe45c85
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1,12 @@
+=== SLM Plus ===
+Contributors: Michel Velis, Tips and Tricks HQ
+Donate link: http://paypal.me/mvelis
+Tags: license, software license, woocommerce, license management
+Requires at least: 5.6
+Tested up to: 6.7
+Stable tag: 6.3.5
+Tags: license manager, license key, license genrator, subscription
+Requires PHP: 7.2
+License: GPLv2 or later
+License URI: https://www.gnu.org/licenses/gpl-2.0.html
+SLM Plus offers a powerful solution for managing licenses for WordPress plugins, themes, and web apps. With WooCommerce integration.
diff --git a/slm-plus.php b/slm-plus.php
new file mode 100644
index 0000000..f803664
--- /dev/null
+++ b/slm-plus.php
@@ -0,0 +1,88 @@
+prefix . "lic_key_tbl");
+define('SLM_TBL_EMAILS', $wpdb->prefix . "lic_emails_tbl");
+define('SLM_TBL_LIC_DOMAIN', $wpdb->prefix . "lic_reg_domain_tbl");
+define('SLM_TBL_LIC_DEVICES', $wpdb->prefix . "lic_reg_devices_tbl");
+define('SLM_TBL_LIC_LOG', $wpdb->prefix . "lic_log_tbl");
+define('SLM_TBL_LICENSE_STATUS', $wpdb->prefix . "lic_status_tbl");
+
+define('SLM_MANAGEMENT_PERMISSION', 'manage_options');
+define('SLM_MAIN_MENU_SLUG', 'slm_overview');
+define('SLM_MENU_ICON', 'dashicons-lock');
+define('SLM_API_URL', SLM_SITE_URL);
+
+// Load core plugin functionalities
+if (file_exists(SLM_LIB . 'slm-plugin-core.php')) {
+ require_once SLM_LIB . 'slm-plugin-core.php';
+}
+
+// Add settings link to plugin action links
+function slm_settings_link($links) {
+ $settings_link = '
' . __('Settings', 'slm-plus') . ' ';
+ $links[] = $settings_link;
+ return $links;
+}
+add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'slm_settings_link');
+
+// Define default max domains and devices
+define('SLM_DEFAULT_MAX_DOMAINS', SLM_API_Utility::get_slm_option('default_max_domains'));
+define('SLM_DEFAULT_MAX_DEVICES', SLM_API_Utility::get_slm_option('default_max_devices'));
+
+// Use native WordPress function for setting options
+define('WOO_SLM_API_SECRET', SLM_API_Utility::get_slm_option('lic_creation_secret'));
+define('KEY_API', SLM_API_Utility::get_slm_option('lic_creation_secret'));
+define('VERIFY_KEY_API', SLM_API_Utility::get_slm_option('lic_verification_secret'));
+define('KEY_API_PREFIX', SLM_API_Utility::get_slm_option('lic_prefix'));
diff --git a/software-license-manager/client-side-examples/sample-php-scripts/create-license.php b/software-license-manager/client-side-examples/sample-php-scripts/create-license.php
deleted file mode 100644
index 1c050e1..0000000
--- a/software-license-manager/client-side-examples/sample-php-scripts/create-license.php
+++ /dev/null
@@ -1,27 +0,0 @@
-';
- echo '
Sample License Management ';
-
- /*** License activate button was clicked ***/
- if (isset($_REQUEST['activate_license'])) {
- $license_key = $_REQUEST['sample_license_key'];
-
- // API query parameters
- $api_params = array(
- 'slm_action' => 'slm_activate',
- 'secret_key' => YOUR_SPECIAL_SECRET_KEY,
- 'license_key' => $license_key,
- 'registered_domain' => $_SERVER['SERVER_NAME'],
- 'item_reference' => urlencode(YOUR_ITEM_REFERENCE),
- );
-
- // Send query to the license manager server
- $query = esc_url_raw(add_query_arg($api_params, YOUR_LICENSE_SERVER_URL));
- $response = wp_remote_get($query, array('timeout' => 20, 'sslverify' => false));
-
- // Check for error in the response
- if (is_wp_error($response)){
- echo "Unexpected Error! The query returned with an error.";
- }
-
- //var_dump($response);//uncomment it if you want to look at the full response
-
- // License data.
- $license_data = json_decode(wp_remote_retrieve_body($response));
-
- // TODO - Do something with it.
- //var_dump($license_data);//uncomment it to look at the data
-
- if($license_data->result == 'success'){//Success was returned for the license activation
-
- //Uncomment the followng line to see the message that returned from the license server
- echo '
The following message was returned from the server: '.$license_data->message;
-
- //Save the license key in the options table
- update_option('sample_license_key', $license_key);
- }
- else{
- //Show error to the user. Probably entered incorrect license key.
-
- //Uncomment the followng line to see the message that returned from the license server
- echo '
The following message was returned from the server: '.$license_data->message;
- }
-
- }
- /*** End of license activation ***/
-
- /*** License activate button was clicked ***/
- if (isset($_REQUEST['deactivate_license'])) {
- $license_key = $_REQUEST['sample_license_key'];
-
- // API query parameters
- $api_params = array(
- 'slm_action' => 'slm_deactivate',
- 'secret_key' => YOUR_SPECIAL_SECRET_KEY,
- 'license_key' => $license_key,
- 'registered_domain' => $_SERVER['SERVER_NAME'],
- 'item_reference' => urlencode(YOUR_ITEM_REFERENCE),
- );
-
- // Send query to the license manager server
- $query = esc_url_raw(add_query_arg($api_params, YOUR_LICENSE_SERVER_URL));
- $response = wp_remote_get($query, array('timeout' => 20, 'sslverify' => false));
-
- // Check for error in the response
- if (is_wp_error($response)){
- echo "Unexpected Error! The query returned with an error.";
- }
-
- //var_dump($response);//uncomment it if you want to look at the full response
-
- // License data.
- $license_data = json_decode(wp_remote_retrieve_body($response));
-
- // TODO - Do something with it.
- //var_dump($license_data);//uncomment it to look at the data
-
- if($license_data->result == 'success'){//Success was returned for the license activation
-
- //Uncomment the followng line to see the message that returned from the license server
- echo '
The following message was returned from the server: '.$license_data->message;
-
- //Remove the licensse key from the options table. It will need to be activated again.
- update_option('sample_license_key', '');
- }
- else{
- //Show error to the user. Probably entered incorrect license key.
-
- //Uncomment the followng line to see the message that returned from the license server
- echo '
The following message was returned from the server: '.$license_data->message;
- }
-
- }
- /*** End of sample license deactivation ***/
-
- ?>
-
Please enter the license key for this product to activate it. You were given a license key when you purchased this item.
-
-
-
-
-
-
-
- ';
-}
\ No newline at end of file
diff --git a/software-license-manager/css/jquery-ui.css b/software-license-manager/css/jquery-ui.css
deleted file mode 100644
index b775b44..0000000
--- a/software-license-manager/css/jquery-ui.css
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*! jQuery UI - v1.11.0 - 2014-06-26
-* http://jqueryui.com
-* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
-* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
-* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden {
- display: none;
-}
-.ui-helper-hidden-accessible {
- border: 0;
- clip: rect(0 0 0 0);
- height: 1px;
- margin: -1px;
- overflow: hidden;
- padding: 0;
- position: absolute;
- width: 1px;
-}
-.ui-helper-reset {
- margin: 0;
- padding: 0;
- border: 0;
- outline: 0;
- line-height: 1.3;
- text-decoration: none;
- font-size: 100%;
- list-style: none;
-}
-.ui-helper-clearfix:before,
-.ui-helper-clearfix:after {
- content: "";
- display: table;
- border-collapse: collapse;
-}
-.ui-helper-clearfix:after {
- clear: both;
-}
-.ui-helper-clearfix {
- min-height: 0; /* support: IE7 */
-}
-.ui-helper-zfix {
- width: 100%;
- height: 100%;
- top: 0;
- left: 0;
- position: absolute;
- opacity: 0;
- filter:Alpha(Opacity=0);
-}
-
-.ui-front {
- z-index: 100;
-}
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled {
- cursor: default !important;
-}
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
- display: block;
- text-indent: -99999px;
- overflow: hidden;
- background-repeat: no-repeat;
-}
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
-}
-.ui-accordion .ui-accordion-header {
- display: block;
- cursor: pointer;
- position: relative;
- margin: 2px 0 0 0;
- padding: .5em .5em .5em .7em;
- min-height: 0; /* support: IE7 */
- font-size: 100%;
-}
-.ui-accordion .ui-accordion-icons {
- padding-left: 2.2em;
-}
-.ui-accordion .ui-accordion-icons .ui-accordion-icons {
- padding-left: 2.2em;
-}
-.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
- position: absolute;
- left: .5em;
- top: 50%;
- margin-top: -8px;
-}
-.ui-accordion .ui-accordion-content {
- padding: 1em 2.2em;
- border-top: 0;
- overflow: auto;
-}
-.ui-autocomplete {
- position: absolute;
- top: 0;
- left: 0;
- cursor: default;
-}
-.ui-button {
- display: inline-block;
- position: relative;
- padding: 0;
- line-height: normal;
- margin-right: .1em;
- cursor: pointer;
- vertical-align: middle;
- text-align: center;
- overflow: visible; /* removes extra width in IE */
-}
-.ui-button,
-.ui-button:link,
-.ui-button:visited,
-.ui-button:hover,
-.ui-button:active {
- text-decoration: none;
-}
-/* to make room for the icon, a width needs to be set here */
-.ui-button-icon-only {
- width: 2.2em;
-}
-/* button elements seem to need a little more width */
-button.ui-button-icon-only {
- width: 2.4em;
-}
-.ui-button-icons-only {
- width: 3.4em;
-}
-button.ui-button-icons-only {
- width: 3.7em;
-}
-
-/* button text element */
-.ui-button .ui-button-text {
- display: block;
- line-height: normal;
-}
-.ui-button-text-only .ui-button-text {
- padding: .4em 1em;
-}
-.ui-button-icon-only .ui-button-text,
-.ui-button-icons-only .ui-button-text {
- padding: .4em;
- text-indent: -9999999px;
-}
-.ui-button-text-icon-primary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
- padding: .4em 1em .4em 2.1em;
-}
-.ui-button-text-icon-secondary .ui-button-text,
-.ui-button-text-icons .ui-button-text {
- padding: .4em 2.1em .4em 1em;
-}
-.ui-button-text-icons .ui-button-text {
- padding-left: 2.1em;
- padding-right: 2.1em;
-}
-/* no icon support for input elements, provide padding by default */
-input.ui-button {
- padding: .4em 1em;
-}
-
-/* button icon element(s) */
-.ui-button-icon-only .ui-icon,
-.ui-button-text-icon-primary .ui-icon,
-.ui-button-text-icon-secondary .ui-icon,
-.ui-button-text-icons .ui-icon,
-.ui-button-icons-only .ui-icon {
- position: absolute;
- top: 50%;
- margin-top: -8px;
-}
-.ui-button-icon-only .ui-icon {
- left: 50%;
- margin-left: -8px;
-}
-.ui-button-text-icon-primary .ui-button-icon-primary,
-.ui-button-text-icons .ui-button-icon-primary,
-.ui-button-icons-only .ui-button-icon-primary {
- left: .5em;
-}
-.ui-button-text-icon-secondary .ui-button-icon-secondary,
-.ui-button-text-icons .ui-button-icon-secondary,
-.ui-button-icons-only .ui-button-icon-secondary {
- right: .5em;
-}
-
-/* button sets */
-.ui-buttonset {
- margin-right: 7px;
-}
-.ui-buttonset .ui-button {
- margin-left: 0;
- margin-right: -.3em;
-}
-
-/* workarounds */
-/* reset extra padding in Firefox, see h5bp.com/l */
-input.ui-button::-moz-focus-inner,
-button.ui-button::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-.ui-datepicker {
- width: 17em;
- padding: .2em .2em 0;
- display: none;
-}
-.ui-datepicker .ui-datepicker-header {
- position: relative;
- padding: .2em 0;
-}
-.ui-datepicker .ui-datepicker-prev,
-.ui-datepicker .ui-datepicker-next {
- position: absolute;
- top: 2px;
- width: 1.8em;
- height: 1.8em;
-}
-.ui-datepicker .ui-datepicker-prev-hover,
-.ui-datepicker .ui-datepicker-next-hover {
- top: 1px;
-}
-.ui-datepicker .ui-datepicker-prev {
- left: 2px;
-}
-.ui-datepicker .ui-datepicker-next {
- right: 2px;
-}
-.ui-datepicker .ui-datepicker-prev-hover {
- left: 1px;
-}
-.ui-datepicker .ui-datepicker-next-hover {
- right: 1px;
-}
-.ui-datepicker .ui-datepicker-prev span,
-.ui-datepicker .ui-datepicker-next span {
- display: block;
- position: absolute;
- left: 50%;
- margin-left: -8px;
- top: 50%;
- margin-top: -8px;
-}
-.ui-datepicker .ui-datepicker-title {
- margin: 0 2.3em;
- line-height: 1.8em;
- text-align: center;
-}
-.ui-datepicker .ui-datepicker-title select {
- font-size: 1em;
- margin: 1px 0;
-}
-.ui-datepicker select.ui-datepicker-month,
-.ui-datepicker select.ui-datepicker-year {
- width: 49%;
-}
-.ui-datepicker table {
- width: 100%;
- font-size: .9em;
- border-collapse: collapse;
- margin: 0 0 .4em;
-}
-.ui-datepicker th {
- padding: .7em .3em;
- text-align: center;
- font-weight: bold;
- border: 0;
-}
-.ui-datepicker td {
- border: 0;
- padding: 1px;
-}
-.ui-datepicker td span,
-.ui-datepicker td a {
- display: block;
- padding: .2em;
- text-align: right;
- text-decoration: none;
-}
-.ui-datepicker .ui-datepicker-buttonpane {
- background-image: none;
- margin: .7em 0 0 0;
- padding: 0 .2em;
- border-left: 0;
- border-right: 0;
- border-bottom: 0;
-}
-.ui-datepicker .ui-datepicker-buttonpane button {
- float: right;
- margin: .5em .2em .4em;
- cursor: pointer;
- padding: .2em .6em .3em .6em;
- width: auto;
- overflow: visible;
-}
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
- float: left;
-}
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi {
- width: auto;
-}
-.ui-datepicker-multi .ui-datepicker-group {
- float: left;
-}
-.ui-datepicker-multi .ui-datepicker-group table {
- width: 95%;
- margin: 0 auto .4em;
-}
-.ui-datepicker-multi-2 .ui-datepicker-group {
- width: 50%;
-}
-.ui-datepicker-multi-3 .ui-datepicker-group {
- width: 33.3%;
-}
-.ui-datepicker-multi-4 .ui-datepicker-group {
- width: 25%;
-}
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
- border-left-width: 0;
-}
-.ui-datepicker-multi .ui-datepicker-buttonpane {
- clear: left;
-}
-.ui-datepicker-row-break {
- clear: both;
- width: 100%;
- font-size: 0;
-}
-
-/* RTL support */
-.ui-datepicker-rtl {
- direction: rtl;
-}
-.ui-datepicker-rtl .ui-datepicker-prev {
- right: 2px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next {
- left: 2px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-prev:hover {
- right: 1px;
- left: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-next:hover {
- left: 1px;
- right: auto;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane {
- clear: right;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button {
- float: left;
-}
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
-.ui-datepicker-rtl .ui-datepicker-group {
- float: right;
-}
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
- border-right-width: 0;
- border-left-width: 1px;
-}
-.ui-dialog {
- overflow: hidden;
- position: absolute;
- top: 0;
- left: 0;
- padding: .2em;
- outline: 0;
-}
-.ui-dialog .ui-dialog-titlebar {
- padding: .4em 1em;
- position: relative;
-}
-.ui-dialog .ui-dialog-title {
- float: left;
- margin: .1em 0;
- white-space: nowrap;
- width: 90%;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.ui-dialog .ui-dialog-titlebar-close {
- position: absolute;
- right: .3em;
- top: 50%;
- width: 20px;
- margin: -10px 0 0 0;
- padding: 1px;
- height: 20px;
-}
-.ui-dialog .ui-dialog-content {
- position: relative;
- border: 0;
- padding: .5em 1em;
- background: none;
- overflow: auto;
-}
-.ui-dialog .ui-dialog-buttonpane {
- text-align: left;
- border-width: 1px 0 0 0;
- background-image: none;
- margin-top: .5em;
- padding: .3em 1em .5em .4em;
-}
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
- float: right;
-}
-.ui-dialog .ui-dialog-buttonpane button {
- margin: .5em .4em .5em 0;
- cursor: pointer;
-}
-.ui-dialog .ui-resizable-se {
- width: 12px;
- height: 12px;
- right: -5px;
- bottom: -5px;
- background-position: 16px 16px;
-}
-.ui-draggable .ui-dialog-titlebar {
- cursor: move;
-}
-.ui-draggable-handle {
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-menu {
- list-style: none;
- padding: 0;
- margin: 0;
- display: block;
- outline: none;
-}
-.ui-menu .ui-menu {
- position: absolute;
-}
-.ui-menu .ui-menu-item {
- position: relative;
- margin: 0;
- padding: 3px 1em 3px .4em;
- cursor: pointer;
- min-height: 0; /* support: IE7 */
- /* support: IE10, see #8844 */
- list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
-}
-.ui-menu .ui-menu-divider {
- margin: 5px 0;
- height: 0;
- font-size: 0;
- line-height: 0;
- border-width: 1px 0 0 0;
-}
-.ui-menu .ui-state-focus,
-.ui-menu .ui-state-active {
- margin: -1px;
-}
-
-/* icon support */
-.ui-menu-icons {
- position: relative;
-}
-.ui-menu-icons .ui-menu-item {
- padding-left: 2em;
-}
-
-/* left-aligned */
-.ui-menu .ui-icon {
- position: absolute;
- top: 0;
- bottom: 0;
- left: .2em;
- margin: auto 0;
-}
-
-/* right-aligned */
-.ui-menu .ui-menu-icon {
- left: auto;
- right: 0;
-}
-.ui-progressbar {
- height: 2em;
- text-align: left;
- overflow: hidden;
-}
-.ui-progressbar .ui-progressbar-value {
- margin: -1px;
- height: 100%;
-}
-.ui-progressbar .ui-progressbar-overlay {
- background: url("images/animated-overlay.gif");
- height: 100%;
- filter: alpha(opacity=25);
- opacity: 0.25;
-}
-.ui-progressbar-indeterminate .ui-progressbar-value {
- background-image: none;
-}
-.ui-resizable {
- position: relative;
-}
-.ui-resizable-handle {
- position: absolute;
- font-size: 0.1px;
- display: block;
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-resizable-disabled .ui-resizable-handle,
-.ui-resizable-autohide .ui-resizable-handle {
- display: none;
-}
-.ui-resizable-n {
- cursor: n-resize;
- height: 7px;
- width: 100%;
- top: -5px;
- left: 0;
-}
-.ui-resizable-s {
- cursor: s-resize;
- height: 7px;
- width: 100%;
- bottom: -5px;
- left: 0;
-}
-.ui-resizable-e {
- cursor: e-resize;
- width: 7px;
- right: -5px;
- top: 0;
- height: 100%;
-}
-.ui-resizable-w {
- cursor: w-resize;
- width: 7px;
- left: -5px;
- top: 0;
- height: 100%;
-}
-.ui-resizable-se {
- cursor: se-resize;
- width: 12px;
- height: 12px;
- right: 1px;
- bottom: 1px;
-}
-.ui-resizable-sw {
- cursor: sw-resize;
- width: 9px;
- height: 9px;
- left: -5px;
- bottom: -5px;
-}
-.ui-resizable-nw {
- cursor: nw-resize;
- width: 9px;
- height: 9px;
- left: -5px;
- top: -5px;
-}
-.ui-resizable-ne {
- cursor: ne-resize;
- width: 9px;
- height: 9px;
- right: -5px;
- top: -5px;
-}
-.ui-selectable {
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-selectable-helper {
- position: absolute;
- z-index: 100;
- border: 1px dotted black;
-}
-.ui-selectmenu-menu {
- padding: 0;
- margin: 0;
- position: absolute;
- top: 0;
- left: 0;
- display: none;
-}
-.ui-selectmenu-menu .ui-menu {
- overflow: auto;
- /* Support: IE7 */
- overflow-x: hidden;
- padding-bottom: 1px;
-}
-.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
- font-size: 1em;
- font-weight: bold;
- line-height: 1.5;
- padding: 2px 0.4em;
- margin: 0.5em 0 0 0;
- height: auto;
- border: 0;
-}
-.ui-selectmenu-open {
- display: block;
-}
-.ui-selectmenu-button {
- display: inline-block;
- overflow: hidden;
- position: relative;
- text-decoration: none;
- cursor: pointer;
-}
-.ui-selectmenu-button span.ui-icon {
- right: 0.5em;
- left: auto;
- margin-top: -8px;
- position: absolute;
- top: 50%;
-}
-.ui-selectmenu-button span.ui-selectmenu-text {
- text-align: left;
- padding: 0.4em 2.1em 0.4em 1em;
- display: block;
- line-height: 1.4;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-.ui-slider {
- position: relative;
- text-align: left;
-}
-.ui-slider .ui-slider-handle {
- position: absolute;
- z-index: 2;
- width: 1.2em;
- height: 1.2em;
- cursor: default;
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-slider .ui-slider-range {
- position: absolute;
- z-index: 1;
- font-size: .7em;
- display: block;
- border: 0;
- background-position: 0 0;
-}
-
-/* For IE8 - See #6727 */
-.ui-slider.ui-state-disabled .ui-slider-handle,
-.ui-slider.ui-state-disabled .ui-slider-range {
- filter: inherit;
-}
-
-.ui-slider-horizontal {
- height: .8em;
-}
-.ui-slider-horizontal .ui-slider-handle {
- top: -.3em;
- margin-left: -.6em;
-}
-.ui-slider-horizontal .ui-slider-range {
- top: 0;
- height: 100%;
-}
-.ui-slider-horizontal .ui-slider-range-min {
- left: 0;
-}
-.ui-slider-horizontal .ui-slider-range-max {
- right: 0;
-}
-
-.ui-slider-vertical {
- width: .8em;
- height: 100px;
-}
-.ui-slider-vertical .ui-slider-handle {
- left: -.3em;
- margin-left: 0;
- margin-bottom: -.6em;
-}
-.ui-slider-vertical .ui-slider-range {
- left: 0;
- width: 100%;
-}
-.ui-slider-vertical .ui-slider-range-min {
- bottom: 0;
-}
-.ui-slider-vertical .ui-slider-range-max {
- top: 0;
-}
-.ui-sortable-handle {
- -ms-touch-action: none;
- touch-action: none;
-}
-.ui-spinner {
- position: relative;
- display: inline-block;
- overflow: hidden;
- padding: 0;
- vertical-align: middle;
-}
-.ui-spinner-input {
- border: none;
- background: none;
- color: inherit;
- padding: 0;
- margin: .2em 0;
- vertical-align: middle;
- margin-left: .4em;
- margin-right: 22px;
-}
-.ui-spinner-button {
- width: 16px;
- height: 50%;
- font-size: .5em;
- padding: 0;
- margin: 0;
- text-align: center;
- position: absolute;
- cursor: default;
- display: block;
- overflow: hidden;
- right: 0;
-}
-/* more specificity required here to override default borders */
-.ui-spinner a.ui-spinner-button {
- border-top: none;
- border-bottom: none;
- border-right: none;
-}
-/* vertically center icon */
-.ui-spinner .ui-icon {
- position: absolute;
- margin-top: -8px;
- top: 50%;
- left: 0;
-}
-.ui-spinner-up {
- top: 0;
-}
-.ui-spinner-down {
- bottom: 0;
-}
-
-/* TR overrides */
-.ui-spinner .ui-icon-triangle-1-s {
- /* need to fix icons sprite */
- background-position: -65px -16px;
-}
-.ui-tabs {
- position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
- padding: .2em;
-}
-.ui-tabs .ui-tabs-nav {
- margin: 0;
- padding: .2em .2em 0;
-}
-.ui-tabs .ui-tabs-nav li {
- list-style: none;
- float: left;
- position: relative;
- top: 0;
- margin: 1px .2em 0 0;
- border-bottom-width: 0;
- padding: 0;
- white-space: nowrap;
-}
-.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
- float: left;
- padding: .5em 1em;
- text-decoration: none;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active {
- margin-bottom: -1px;
- padding-bottom: 1px;
-}
-.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
-.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
-.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
- cursor: text;
-}
-.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
- cursor: pointer;
-}
-.ui-tabs .ui-tabs-panel {
- display: block;
- border-width: 0;
- padding: 1em 1.4em;
- background: none;
-}
-.ui-tooltip {
- padding: 8px;
- position: absolute;
- z-index: 9999;
- max-width: 300px;
- -webkit-box-shadow: 0 0 5px #aaa;
- box-shadow: 0 0 5px #aaa;
-}
-body .ui-tooltip {
- border-width: 2px;
-}
-
-/* Component containers
-----------------------------------*/
-.ui-widget {
- font-family: Verdana,Arial,sans-serif;
- font-size: 1.1em;
-}
-.ui-widget .ui-widget {
- font-size: 1em;
-}
-.ui-widget input,
-.ui-widget select,
-.ui-widget textarea,
-.ui-widget button {
- font-family: Verdana,Arial,sans-serif;
- font-size: 1em;
-}
-.ui-widget-content {
- border: 1px solid #aaaaaa;
- background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;
- color: #222222;
-}
-.ui-widget-content a {
- color: #222222;
-}
-.ui-widget-header {
- border: 1px solid #aaaaaa;
- background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
- color: #222222;
- font-weight: bold;
-}
-.ui-widget-header a {
- color: #222222;
-}
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default,
-.ui-widget-content .ui-state-default,
-.ui-widget-header .ui-state-default {
- border: 1px solid #d3d3d3;
- background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
- font-weight: normal;
- color: #555555;
-}
-.ui-state-default a,
-.ui-state-default a:link,
-.ui-state-default a:visited {
- color: #555555;
- text-decoration: none;
-}
-.ui-state-hover,
-.ui-widget-content .ui-state-hover,
-.ui-widget-header .ui-state-hover,
-.ui-state-focus,
-.ui-widget-content .ui-state-focus,
-.ui-widget-header .ui-state-focus {
- border: 1px solid #999999;
- background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
- font-weight: normal;
- color: #212121;
-}
-.ui-state-hover a,
-.ui-state-hover a:hover,
-.ui-state-hover a:link,
-.ui-state-hover a:visited,
-.ui-state-focus a,
-.ui-state-focus a:hover,
-.ui-state-focus a:link,
-.ui-state-focus a:visited {
- color: #212121;
- text-decoration: none;
-}
-.ui-state-active,
-.ui-widget-content .ui-state-active,
-.ui-widget-header .ui-state-active {
- border: 1px solid #aaaaaa;
- background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
- font-weight: normal;
- color: #212121;
-}
-.ui-state-active a,
-.ui-state-active a:link,
-.ui-state-active a:visited {
- color: #212121;
- text-decoration: none;
-}
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight,
-.ui-widget-content .ui-state-highlight,
-.ui-widget-header .ui-state-highlight {
- border: 1px solid #fcefa1;
- background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
- color: #363636;
-}
-.ui-state-highlight a,
-.ui-widget-content .ui-state-highlight a,
-.ui-widget-header .ui-state-highlight a {
- color: #363636;
-}
-.ui-state-error,
-.ui-widget-content .ui-state-error,
-.ui-widget-header .ui-state-error {
- border: 1px solid #cd0a0a;
- background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
- color: #cd0a0a;
-}
-.ui-state-error a,
-.ui-widget-content .ui-state-error a,
-.ui-widget-header .ui-state-error a {
- color: #cd0a0a;
-}
-.ui-state-error-text,
-.ui-widget-content .ui-state-error-text,
-.ui-widget-header .ui-state-error-text {
- color: #cd0a0a;
-}
-.ui-priority-primary,
-.ui-widget-content .ui-priority-primary,
-.ui-widget-header .ui-priority-primary {
- font-weight: bold;
-}
-.ui-priority-secondary,
-.ui-widget-content .ui-priority-secondary,
-.ui-widget-header .ui-priority-secondary {
- opacity: .7;
- filter:Alpha(Opacity=70);
- font-weight: normal;
-}
-.ui-state-disabled,
-.ui-widget-content .ui-state-disabled,
-.ui-widget-header .ui-state-disabled {
- opacity: .35;
- filter:Alpha(Opacity=35);
- background-image: none;
-}
-.ui-state-disabled .ui-icon {
- filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
-}
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon {
- width: 16px;
- height: 16px;
-}
-.ui-icon,
-.ui-widget-content .ui-icon {
- background-image: url("images/ui-icons_222222_256x240.png");
-}
-.ui-widget-header .ui-icon {
- background-image: url("images/ui-icons_222222_256x240.png");
-}
-.ui-state-default .ui-icon {
- background-image: url("images/ui-icons_888888_256x240.png");
-}
-.ui-state-hover .ui-icon,
-.ui-state-focus .ui-icon {
- background-image: url("images/ui-icons_454545_256x240.png");
-}
-.ui-state-active .ui-icon {
- background-image: url("images/ui-icons_454545_256x240.png");
-}
-.ui-state-highlight .ui-icon {
- background-image: url("images/ui-icons_2e83ff_256x240.png");
-}
-.ui-state-error .ui-icon,
-.ui-state-error-text .ui-icon {
- background-image: url("images/ui-icons_cd0a0a_256x240.png");
-}
-
-/* positioning */
-.ui-icon-blank { background-position: 16px 16px; }
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-on { background-position: -96px -144px; }
-.ui-icon-radio-off { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-left,
-.ui-corner-tl {
- border-top-left-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-top,
-.ui-corner-right,
-.ui-corner-tr {
- border-top-right-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-left,
-.ui-corner-bl {
- border-bottom-left-radius: 4px;
-}
-.ui-corner-all,
-.ui-corner-bottom,
-.ui-corner-right,
-.ui-corner-br {
- border-bottom-right-radius: 4px;
-}
-
-/* Overlays */
-.ui-widget-overlay {
- background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
- opacity: .3;
- filter: Alpha(Opacity=30);
-}
-.ui-widget-shadow {
- margin: -8px 0 0 -8px;
- padding: 8px;
- background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
- opacity: .3;
- filter: Alpha(Opacity=30);
- border-radius: 8px;
-}
diff --git a/software-license-manager/includes/slm-api-listener.php b/software-license-manager/includes/slm-api-listener.php
deleted file mode 100644
index 065e5f3..0000000
--- a/software-license-manager/includes/slm-api-listener.php
+++ /dev/null
@@ -1,233 +0,0 @@
-creation_api_listener();
- $this->activation_api_listener();
- $this->deactivation_api_listener();
- $this->check_api_listener();
- }
- }
-
- function creation_api_listener() {
- if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) == 'slm_create_new') {
- //Handle the licene creation API query
- global $slm_debug_logger;
-
- $options = get_option('slm_plugin_options');
- $lic_key_prefix = $options['lic_prefix'];
-
- SLM_API_Utility::verify_secret_key_for_creation(); //Verify the secret key first.
-
- $slm_debug_logger->log_debug("API - license creation (slm_create_new) request received.");
-
- //Action hook
- do_action('slm_api_listener_slm_create_new');
-
- $fields = array();
- if (isset($_REQUEST['license_key']) && !empty($_REQUEST['license_key'])){
- $fields['license_key'] = strip_tags($_REQUEST['license_key']);//Use the key you pass via the request
- }else{
- $fields['license_key'] = uniqid($lic_key_prefix);//Use random generated key
- }
- $fields['lic_status'] = 'pending';
- $fields['first_name'] = wp_unslash(strip_tags($_REQUEST['first_name']));
- $fields['last_name'] = wp_unslash(strip_tags($_REQUEST['last_name']));
- $fields['email'] = strip_tags($_REQUEST['email']);
- $fields['company_name'] = wp_unslash(strip_tags($_REQUEST['company_name']));
- $fields['txn_id'] = strip_tags($_REQUEST['txn_id']);
- if (empty($_REQUEST['max_allowed_domains'])) {
- $fields['max_allowed_domains'] = $options['default_max_domains'];
- } else {
- $fields['max_allowed_domains'] = strip_tags($_REQUEST['max_allowed_domains']);
- }
- $fields['date_created'] = isset($_REQUEST['date_created'])?strip_tags($_REQUEST['date_created']):date("Y-m-d");
- $fields['date_expiry'] = isset($_REQUEST['date_expiry'])?strip_tags($_REQUEST['date_expiry']):'';
-
- global $wpdb;
- $tbl_name = SLM_TBL_LICENSE_KEYS;
- $result = $wpdb->insert($tbl_name, $fields);
- if ($result === false) {
- //error inserting
- $args = (array('result' => 'error', 'message' => 'License creation failed', 'error_code' => SLM_Error_Codes::CREATE_FAILED));
- SLM_API_Utility::output_api_response($args);
- } else {
- $args = (array('result' => 'success', 'message' => 'License successfully created', 'key' => $fields['license_key'], 'error_code' => SLM_Error_Codes::CREATE_FAILED));
- SLM_API_Utility::output_api_response($args);
- }
- }
- }
-
- /*
- * Query Parameters
- * 1) slm_action = slm_create_new
- * 2) secret_key
- * 3) license_key
- * 4) registered_domain (optional)
- */
-
- function activation_api_listener() {
- if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) == 'slm_activate') {
- //Handle the license activation API query
- global $slm_debug_logger;
-
- SLM_API_Utility::verify_secret_key(); //Verify the secret key first.
-
- $slm_debug_logger->log_debug("API - license activation (slm_activate) request received.");
-
- //Action hook
- do_action('slm_api_listener_slm_activate');
-
- $fields = array();
- $fields['lic_key'] = trim(strip_tags($_REQUEST['license_key']));
- $fields['registered_domain'] = trim(wp_unslash(strip_tags($_REQUEST['registered_domain']))); //gethostbyaddr($_SERVER['REMOTE_ADDR']);
- $fields['item_reference'] = trim(strip_tags($_REQUEST['item_reference']));
- $slm_debug_logger->log_debug("License key: " . $fields['lic_key'] . " Domain: " . $fields['registered_domain']);
-
- global $wpdb;
- $tbl_name = SLM_TBL_LICENSE_KEYS;
- $reg_table = SLM_TBL_LIC_DOMAIN;
- $key = $fields['lic_key'];
- $sql_prep1 = $wpdb->prepare("SELECT * FROM $tbl_name WHERE license_key = %s", $key);
- $retLic = $wpdb->get_row($sql_prep1, OBJECT);
-
- $sql_prep2 = $wpdb->prepare("SELECT * FROM $reg_table WHERE lic_key = %s", $key);
- $reg_domains = $wpdb->get_results($sql_prep2, OBJECT);
- if ($retLic) {
- if ($retLic->lic_status == 'blocked') {
- $args = (array('result' => 'error', 'message' => 'Your License key is blocked', 'error_code' => SLM_Error_Codes::LICENSE_BLOCKED));
- SLM_API_Utility::output_api_response($args);
- } elseif ($retLic->lic_status == 'expired') {
- $args = (array('result' => 'error', 'message' => 'Your License key has expired', 'error_code' => SLM_Error_Codes::LICENSE_EXPIRED));
- SLM_API_Utility::output_api_response($args);
- }
-
- if (count($reg_domains) < floor($retLic->max_allowed_domains)) {
- foreach ($reg_domains as $reg_domain) {
- if (isset($_REQUEST['migrate_from']) && (trim($_REQUEST['migrate_from']) == $reg_domain->registered_domain)) {
- $wpdb->update($reg_table, array('registered_domain' => $fields['registered_domain']), array('registered_domain' => trim(strip_tags($_REQUEST['migrate_from']))));
- $args = (array('result' => 'success', 'message' => 'Registered domain has been updated'));
- SLM_API_Utility::output_api_response($args);
- }
- if ($fields['registered_domain'] == $reg_domain->registered_domain) {
- $args = (array('result' => 'error', 'message' => 'License key already in use on ' . $reg_domain->registered_domain, 'error_code' => SLM_Error_Codes::LICENSE_IN_USE));
- SLM_API_Utility::output_api_response($args);
- }
- }
- $fields['lic_key_id'] = $retLic->id;
- $wpdb->insert($reg_table, $fields);
-
- $slm_debug_logger->log_debug("Updating license key status to active.");
- $data = array('lic_status' => 'active');
- $where = array('id' => $retLic->id);
- $updated = $wpdb->update($tbl_name, $data, $where);
-
- $args = (array('result' => 'success', 'message' => 'License key activated'));
- SLM_API_Utility::output_api_response($args);
- } else {
- $args = (array('result' => 'error', 'message' => 'Reached maximum allowable domains', 'error_code' => SLM_Error_Codes::REACHED_MAX_DOMAINS));
- SLM_API_Utility::output_api_response($args);
- }
- } else {
- $args = (array('result' => 'error', 'message' => 'Invalid license key', 'error_code' => SLM_Error_Codes::LICENSE_INVALID));
- SLM_API_Utility::output_api_response($args);
- }
- }
- }
-
- function deactivation_api_listener() {
- if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) == 'slm_deactivate') {
- //Handle the license deactivation API query
- global $slm_debug_logger;
-
- SLM_API_Utility::verify_secret_key(); //Verify the secret key first.
-
- $slm_debug_logger->log_debug("API - license deactivation (slm_deactivate) request received.");
-
- //Action hook
- do_action('slm_api_listener_slm_deactivate');
-
- if (empty($_REQUEST['registered_domain'])) {
- $args = (array('result' => 'error', 'message' => 'Registered domain information is missing', 'error_code' => SLM_Error_Codes::DOMAIN_MISSING));
- SLM_API_Utility::output_api_response($args);
- }
- $registered_domain = trim(wp_unslash(strip_tags($_REQUEST['registered_domain'])));
- $license_key = trim(strip_tags($_REQUEST['license_key']));
- $slm_debug_logger->log_debug("License key: " . $license_key . " Domain: " . $registered_domain);
-
- global $wpdb;
- $registered_dom_table = SLM_TBL_LIC_DOMAIN;
- $sql_prep = $wpdb->prepare("DELETE FROM $registered_dom_table WHERE lic_key=%s AND registered_domain=%s", $license_key, $registered_domain);
- $delete = $wpdb->query($sql_prep);
- if ($delete === false) {
- $slm_debug_logger->log_debug("Error - failed to delete the registered domain from the database.");
- } else if ($delete == 0) {
- $args = (array('result' => 'error', 'message' => 'The license key on this domain is already inactive', 'error_code' => SLM_Error_Codes::DOMAIN_ALREADY_INACTIVE));
- SLM_API_Utility::output_api_response($args);
- } else {
- $args = (array('result' => 'success', 'message' => 'The license key has been deactivated for this domain'));
- SLM_API_Utility::output_api_response($args);
- }
- }
- }
-
- function check_api_listener() {
- if (isset($_REQUEST['slm_action']) && trim($_REQUEST['slm_action']) == 'slm_check') {
- //Handle the license check API query
- global $slm_debug_logger;
-
- SLM_API_Utility::verify_secret_key(); //Verify the secret key first.
-
- $slm_debug_logger->log_debug("API - license check (slm_check) request received.");
-
- $fields = array();
- $fields['lic_key'] = trim(strip_tags($_REQUEST['license_key']));
- $slm_debug_logger->log_debug("License key: " . $fields['lic_key']);
-
- //Action hook
- do_action('slm_api_listener_slm_check');
-
- global $wpdb;
- $tbl_name = SLM_TBL_LICENSE_KEYS;
- $reg_table = SLM_TBL_LIC_DOMAIN;
- $key = $fields['lic_key'];
- $sql_prep1 = $wpdb->prepare("SELECT * FROM $tbl_name WHERE license_key = %s", $key);
- $retLic = $wpdb->get_row($sql_prep1, OBJECT);
-
- $sql_prep2 = $wpdb->prepare("SELECT * FROM $reg_table WHERE lic_key = %s", $key);
- $reg_domains = $wpdb->get_results($sql_prep2, OBJECT);
- if ($retLic) {//A license key exists
- $args = (array(
- 'result' => 'success',
- 'message' => 'License key details retrieved.',
- 'status' => $retLic->lic_status,
- 'max_allowed_domains' => $retLic->max_allowed_domains,
- 'email' => $retLic->email,
- 'registered_domains' => $reg_domains,
- 'date_created' => $retLic->date_created,
- 'date_renewed' => $retLic->date_renewed,
- 'date_expiry' => $retLic->date_expiry,
- ));
- //Output the license details
- SLM_API_Utility::output_api_response($args);
- } else {
- $args = (array('result' => 'error', 'message' => 'Invalid license key', 'error_code' => SLM_Error_Codes::LICENSE_INVALID));
- SLM_API_Utility::output_api_response($args);
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/software-license-manager/includes/slm-api-utility.php b/software-license-manager/includes/slm-api-utility.php
deleted file mode 100644
index 61b3e2f..0000000
--- a/software-license-manager/includes/slm-api-utility.php
+++ /dev/null
@@ -1,57 +0,0 @@
-log_debug('API Response - Result: ' . $args['result'] . ' Message: ' . $args['message']);
-
- //Send response
- echo json_encode($args);
- exit(0);
- }
-
- static function verify_secret_key() {
- $slm_options = get_option('slm_plugin_options');
- $right_secret_key = $slm_options['lic_verification_secret'];
- $received_secret_key = strip_tags($_REQUEST['secret_key']);
- if ($received_secret_key != $right_secret_key) {
- $args = (array('result' => 'error', 'message' => 'Verification API secret key is invalid', 'error_code' => SLM_Error_Codes::VERIFY_KEY_INVALID));
- SLM_API_Utility::output_api_response($args);
- }
- }
-
- static function verify_secret_key_for_creation() {
- $slm_options = get_option('slm_plugin_options');
- $right_secret_key = $slm_options['lic_creation_secret'];
- $received_secret_key = strip_tags($_REQUEST['secret_key']);
- if ($received_secret_key != $right_secret_key) {
- $args = (array('result' => 'error', 'message' => 'License Creation API secret key is invalid', 'error_code' => SLM_Error_Codes::CREATE_KEY_INVALID));
- SLM_API_Utility::output_api_response($args);
- }
- }
-
- static function insert_license_data_internal($fields) {
- /* The fields array should have values for the following keys
- //$fields['license_key']
- //$fields['lic_status']
- //$fields['first_name']
- //$fields['last_name']
- //$fields['email']
- //$fields['company_name']
- //$fields['txn_id']
- //$fields['max_allowed_domains']
- */
- global $wpdb;
- $tbl_name = SLM_TBL_LICENSE_KEYS;
- $fields = array_filter($fields);//Remove any null values.
- $result = $wpdb->insert($tbl_name, $fields);
- }
-
-}
\ No newline at end of file
diff --git a/software-license-manager/includes/slm-debug-logger.php b/software-license-manager/includes/slm-debug-logger.php
deleted file mode 100644
index f0ab6ae..0000000
--- a/software-license-manager/includes/slm-debug-logger.php
+++ /dev/null
@@ -1,115 +0,0 @@
-log_debug("Some debug message");
- *
- * OR
- *
- * SLM_Debug_Logger::log_debug_st("Some debug message");
- */
-
-class SLM_Debug_Logger
-{
- var $log_folder_path;
- var $default_log_file = 'log.txt';
- var $default_log_file_cron = 'log-cron-job.txt';
- var $debug_enabled = false;
- var $debug_status = array('SUCCESS','STATUS','NOTICE','WARNING','FAILURE','CRITICAL');
- var $section_break_marker = "\n----------------------------------------------------------\n\n";
- var $log_reset_marker = "-------- Log File Reset --------\n";
-
- function __construct()
- {
- $this->log_folder_path = WP_LICENSE_MANAGER_PATH . '/logs';
- //Check config and if debug is enabled then set the enabled flag to true
- $options = get_option('slm_plugin_options');
- if(!empty($options['enable_debug'])){//Debugging is enabled
- $this->debug_enabled = true;
- }
- }
-
- function get_debug_timestamp()
- {
- return '['.date('m/d/Y g:i A').'] - ';
- }
-
- function get_debug_status($level)
- {
- $size = count($this->debug_status);
- if($level >= $size){
- return 'UNKNOWN';
- }
- else{
- return $this->debug_status[$level];
- }
- }
-
- function get_section_break($section_break)
- {
- if ($section_break) {
- return $this->section_break_marker;
- }
- return "";
- }
-
- function reset_log_file($file_name='')
- {
- if(empty($file_name)){
- $file_name = $this->default_log_file;
- }
- $debug_log_file = $this->log_folder_path.'/'.$file_name;
- $content = $this->get_debug_timestamp().$this->log_reset_marker;
- $fp=fopen($debug_log_file,'w');
- fwrite($fp, $content);
- fclose($fp);
- }
-
- function append_to_file($content,$file_name)
- {
- if(empty($file_name))$file_name = $this->default_log_file;
- $debug_log_file = $this->log_folder_path.'/'.$file_name;
- $fp=fopen($debug_log_file,'a');
- fwrite($fp, $content);
- fclose($fp);
- }
-
- function log_debug($message,$level=0,$section_break=false,$file_name='')
- {
- if (!$this->debug_enabled) return;
- $content = $this->get_debug_timestamp();//Timestamp
- $content .= $this->get_debug_status($level);//Debug status
- $content .= ' : ';
- $content .= $message . "\n";
- $content .= $this->get_section_break($section_break);
- $this->append_to_file($content, $file_name);
- }
-
- function log_debug_cron($message,$level=0,$section_break=false)
- {
- if (!$this->debug_enabled) return;
- $content = $this->get_debug_timestamp();//Timestamp
- $content .= $this->get_debug_status($level);//Debug status
- $content .= ' : ';
- $content .= $message . "\n";
- $content .= $this->get_section_break($section_break);
- //$file_name = $this->default_log_file_cron;
- $this->append_to_file($content, $this->default_log_file_cron);
- }
-
- static function log_debug_st($message,$level=0,$section_break=false,$file_name='')
- {
- $options = get_option('slm_plugin_options');
- if(empty($options['enable_debug'])){//Debugging is disabled
- return;
- }
- $content = '['.date('m/d/Y g:i A').'] - STATUS : '. $message . "\n";
- $debug_log_file = WP_LICENSE_MANAGER_PATH . '/logs/log.txt';
- $fp=fopen($debug_log_file,'a');
- fwrite($fp, $content);
- fclose($fp);
- }
-
-}
\ No newline at end of file
diff --git a/software-license-manager/includes/slm-error-codes.php b/software-license-manager/includes/slm-error-codes.php
deleted file mode 100644
index c501d5d..0000000
--- a/software-license-manager/includes/slm-error-codes.php
+++ /dev/null
@@ -1,19 +0,0 @@
-load_scripts();
-
- //Add other init time operations here
- add_action ('slm_daily_cron_event', array(&$this, 'slm_daily_cron_event_handler'));
- }
-
- function load_scripts()
- {
- //Load all common scripts and styles only
- wp_enqueue_script('jquery');
-
- //Load all admin side scripts and styles only
- if(is_admin())
- {
- wp_enqueue_script('jquery-ui-datepicker');
- wp_enqueue_script('wplm-custom-admin-js', WP_LICENSE_MANAGER_URL . '/js/wplm-custom-admin.js', array( 'jquery-ui-dialog' ));//admin only custom js code
-
- if (isset($_GET['page']) && $_GET['page'] == 'wp_lic_mgr_addedit') {//Only include if we are in the license add/edit interface
- wp_enqueue_style('jquery-ui-style', WP_LICENSE_MANAGER_URL .'/css/jquery-ui.css');
- }
- //wp_enqueue_style('dialogStylesheet', includes_url().'css/jquery-ui-dialog.css');
- }
- }
-
- function slm_daily_cron_event_handler()
- {
- $options = get_option('slm_plugin_options');
-
- do_action('slm_daily_cron_event_triggered');
-
- if ($options['enable_auto_key_expiry'] == '1'){
- //Do the auto key expiry task
- SLM_Debug_Logger::log_debug_st("SLM daily cronjob - auto expiry of license key is enabled.");
- SLM_Utility::do_auto_key_expiry();
- }
-
- //Do any ohter daily cronjob tasks.
-
- }
-
-}//End of class
\ No newline at end of file
diff --git a/software-license-manager/includes/slm-third-party-integration.php b/software-license-manager/includes/slm-third-party-integration.php
deleted file mode 100644
index 8e06e33..0000000
--- a/software-license-manager/includes/slm-third-party-integration.php
+++ /dev/null
@@ -1,264 +0,0 @@
-log_debug("WP eStore integration - checking if a license key needs to be created for this transaction.");
- $products_table_name = $wpdb->prefix . "wp_eStore_tbl";
- $slm_data = "";
-
- foreach ($cart_items as $current_cart_item) {
- $prod_id = $current_cart_item['item_number'];
- $qty = $current_cart_item['quantity'];
- $retrieved_product = $wpdb->get_row("SELECT * FROM $products_table_name WHERE id = '$prod_id'", OBJECT);
- $package_product = eStore_is_package_product($retrieved_product);
- if ($package_product) {
- $slm_debug_logger->log_debug('Checking license key generation for package/bundle product.');
- $product_ids = explode(',', $retrieved_product->product_download_url);
- foreach ($product_ids as $id) {
- $id = trim($id);
- $retrieved_product_for_specific_id = $wpdb->get_row("SELECT * FROM $products_table_name WHERE id = '$id'", OBJECT);
- $slm_data .= slm_estore_check_and_generate_key($retrieved_product_for_specific_id, $payment_data, $cart_items, $qty);
- }
- } else {
- $slm_debug_logger->log_debug('Checking license key generation for single item product.');
- $slm_data .= slm_estore_check_and_generate_key($retrieved_product, $payment_data, $cart_items, $qty);
- }
- }
-
- $body = str_replace("{slm_data}", $slm_data, $body);
- return $body;
-}
-
-function slm_estore_check_and_generate_key($retrieved_product, $payment_data, $cart_items, $qty=1) {
- global $slm_debug_logger;
- $license_data = '';
-
- if ($retrieved_product->create_license == 1) {
- $requested_qty = (int)$qty;
- $slm_debug_logger->log_debug('Need to create a license key for this product: ' . $retrieved_product->id . '. Requested qty: ' . $requested_qty);
- if($requested_qty > 1){
- //More than 1 qty of the same product
- for($i=0; $i < $requested_qty; $i++){
- $slm_key = slm_estore_create_license($retrieved_product, $payment_data, $cart_items);
- $license_data .= "\n" . __('Item Name: ', 'slm') . $retrieved_product->name . " - " . __('License Key '.($i+1).': ', 'slm') . $slm_key;
- }
- }
- else {
- //Standard 1 qty
- $slm_key = slm_estore_create_license($retrieved_product, $payment_data, $cart_items);
- $license_data = "\n" . __('Item Name: ', 'slm') . $retrieved_product->name . " - " . __('License Key: ', 'slm') . $slm_key;
- }
-
- $slm_debug_logger->log_debug('Liense data: ' . $license_data);
- $license_data = apply_filters('slm_estore_item_license_data', $license_data);
- }
- return $license_data;
-}
-
-function slm_estore_create_license($retrieved_product, $payment_data, $cart_items) {
- global $slm_debug_logger;
- global $wpdb;
- $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME;
-
- //Retrieve the default settings values.
- $options = get_option('slm_plugin_options');
- $lic_key_prefix = $options['lic_prefix'];
- $max_domains = $options['default_max_domains'];
-
- //Lets check any product specific configuration.
- $prod_id = $retrieved_product->id;
- $product_meta = $wpdb->get_row("SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_max_allowed_domains'", OBJECT);
- if ($product_meta) {
- //Found product specific SLM config data.
- $max_domains = $product_meta->meta_value;
- } else {
- //Use the default value from settings (the $max_domains variable contains the default value already).
- }
- //Lets check if any product specific expiry date is set
- $product_meta = $wpdb->get_row("SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_date_of_expiry'", OBJECT);
- if ($product_meta) {
- //Found product specific SLM config data.
- $num_days_before_expiry = $product_meta->meta_value;
- $slm_date_of_expiry = date('Y-m-d', strtotime('+'.$num_days_before_expiry.' days'));
- } else {
- //Use the default value (1 year from today).
- $current_date_plus_1year = date('Y-m-d', strtotime('+1 year'));
- $slm_date_of_expiry = $current_date_plus_1year;
- }
-
-
- $fields = array();
- $fields['license_key'] = uniqid($lic_key_prefix);
- $fields['lic_status'] = 'pending';
- $fields['first_name'] = $payment_data['first_name'];
- $fields['last_name'] = $payment_data['last_name'];
- $fields['email'] = $payment_data['payer_email'];
- $fields['company_name'] = $payment_data['company_name'];
- $fields['txn_id'] = $payment_data['txn_id'];
- $fields['max_allowed_domains'] = $max_domains;
- $fields['date_created'] = date("Y-m-d"); //Today's date
- $fields['date_expiry'] = $slm_date_of_expiry;
-
- $slm_debug_logger->log_debug('Inserting license data into the license manager DB table.');
- $fields = array_filter($fields); //Remove any null values.
-
-
- $tbl_name = SLM_TBL_LICENSE_KEYS;
- $result = $wpdb->insert($tbl_name, $fields);
- if (!$result) {
- $slm_debug_logger->log_debug('Notice! initial database table insert failed on license key table (User Email: ' . $fields['email'] . '). Trying again by converting charset', true);
- //Convert the default PayPal IPN charset to UTF-8 format
- $first_name = mb_convert_encoding($fields['first_name'], "UTF-8", "windows-1252");
- $fields['first_name'] = esc_sql($first_name);
- $last_name = mb_convert_encoding($fields['last_name'], "UTF-8", "windows-1252");
- $fields['last_name'] = esc_sql($last_name);
- $company_name = mb_convert_encoding($fields['company_name'], "UTF-8", "windows-1252");
- $fields['company_name'] = esc_sql($company_name);
-
- $result = $wpdb->insert($tbl_name, $fields);
- if (!$result) {
- $slm_debug_logger->log_debug('Error! Failed to update license key table. DB insert query failed.', false);
- }
- }
- //SLM_API_Utility::insert_license_data_internal($fields);
-
- return $fields['license_key'];
-}
-
-/* Code to handle the eStore's product add/edit interface for SLM specific product configuration */
-add_filter('eStore_addon_product_settings_filter', 'slm_estore_product_configuration_html', 10, 2); //Render the product add/edit HTML
-add_action('eStore_new_product_added', 'slm_estore_new_product_added', 10, 2); //Handle the DB insert after a product add.
-add_action('eStore_product_updated', 'slm_estore_product_updated', 10, 2); //Handle the DB update after a product edit.
-add_action('eStore_product_deleted', 'slm_estore_product_deleted'); //Handle the DB delete after a product delete.
-
-function slm_estore_product_configuration_html($product_config_html, $prod_id) {
- global $wpdb;
- $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME;
-
- if (empty($prod_id)) {
- //New product add
- $slm_max_allowed_domains = "";
- $slm_date_of_expiry = "";
- } else {
- //Existing product edit
-
- //Retrieve the max domain value
- $product_meta = $wpdb->get_row("SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_max_allowed_domains'", OBJECT);
- if ($product_meta) {
- $slm_max_allowed_domains = $product_meta->meta_value;
- } else {
- $slm_max_allowed_domains = "";
- }
-
- //Retrieve the expiry date value
- $product_meta = $wpdb->get_row("SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_date_of_expiry'", OBJECT);
- if ($product_meta) {
- $slm_date_of_expiry = $product_meta->meta_value;
- } else {
- $slm_date_of_expiry = "";
- }
-
- }
-
- $product_config_html .= '
Software License Manager Plugin (Click to Expand)
';
-
- return $product_config_html;
-}
-
-function slm_estore_new_product_added($prod_dat_array, $prod_id) {
- global $wpdb;
- $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME;
-
- //Save max domain value
- $fields = array();
- $fields['prod_id'] = $prod_id;
- $fields['meta_key'] = 'slm_max_allowed_domains';
- $fields['meta_value'] = $prod_dat_array['slm_max_allowed_domains'];
- $result = $wpdb->insert($product_meta_table_name, $fields);
- if (!$result) {
- //insert query failed
- }
-
- //Save expiry date value
- $fields = array();
- $fields['prod_id'] = $prod_id;
- $fields['meta_key'] = 'slm_date_of_expiry';
- $fields['meta_value'] = $prod_dat_array['slm_date_of_expiry'];
- $result = $wpdb->insert($product_meta_table_name, $fields);
- if (!$result) {
- //insert query failed
- }
-
-}
-
-function slm_estore_product_updated($prod_dat_array, $prod_id) {
- global $wpdb;
- $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME;
-
- //Find the existing value for the max domains field (for the given product)
- $product_meta = $wpdb->get_row("SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_max_allowed_domains'", OBJECT);
- if ($product_meta) {
- //Found existing value so lets update it
- $fields = array();
- $fields['meta_key'] = 'slm_max_allowed_domains';
- $fields['meta_value'] = $prod_dat_array['slm_max_allowed_domains'];
- $result = $wpdb->update($product_meta_table_name, $fields, array('prod_id' => $prod_id));
-
- } else {
- //No value for this field was there so lets insert one.
- $fields = array();
- $fields['prod_id'] = $prod_id;
- $fields['meta_key'] = 'slm_max_allowed_domains';
- $fields['meta_value'] = $prod_dat_array['slm_max_allowed_domains'];
- $result = $wpdb->insert($product_meta_table_name, $fields);
- }
-
- //Find the existing value for the expiry date field (for the given product)
- $product_meta = $wpdb->get_row("SELECT * FROM $product_meta_table_name WHERE prod_id = '$prod_id' AND meta_key='slm_date_of_expiry'", OBJECT);
- if ($product_meta) {
- //Found existing value so lets update it
- $fields = array();
- $fields['meta_key'] = 'slm_date_of_expiry';
- $fields['meta_value'] = $prod_dat_array['slm_date_of_expiry'];
- $result = $wpdb->update($product_meta_table_name, $fields, array('prod_id' => $prod_id));
-
- } else {
- //No value for this field was there so lets insert one.
- $fields = array();
- $fields['prod_id'] = $prod_id;
- $fields['meta_key'] = 'slm_date_of_expiry';
- $fields['meta_value'] = $prod_dat_array['slm_date_of_expiry'];
- $result = $wpdb->insert($product_meta_table_name, $fields);
- }
-
-}
-
-function slm_estore_product_deleted($prod_id) {
- global $wpdb;
- $product_meta_table_name = WP_ESTORE_PRODUCTS_META_TABLE_NAME;
-
- $result = $wpdb->delete($product_meta_table_name, array('prod_id' => $prod_id, 'meta_key' => 'slm_max_allowed_domains'));
- $result = $wpdb->delete($product_meta_table_name, array('prod_id' => $prod_id, 'meta_key' => 'slm_date_of_expiry'));
-}
-
-/************************************/
-/*** End of WP eStore integration ***/
-/************************************/
\ No newline at end of file
diff --git a/software-license-manager/includes/slm-utility.php b/software-license-manager/includes/slm-utility.php
deleted file mode 100644
index 2fdb8f5..0000000
--- a/software-license-manager/includes/slm-utility.php
+++ /dev/null
@@ -1,74 +0,0 @@
-prepare("SELECT * FROM $tbl_name WHERE lic_status !=%s", 'expired');//Load the non-expired keys
- $licenses = $wpdb->get_results($sql_prep, OBJECT);
- if(!$licenses){
- SLM_Debug_Logger::log_debug_st("do_auto_key_expiry() - no license keys found.");
- return false;
- }
-
- foreach($licenses as $license){
- $key = $license->license_key;
- $expiry_date = $license->date_expiry;
- if ($expiry_date == '0000-00-00'){
- SLM_Debug_Logger::log_debug_st("This key (".$key.") doesn't have a valid expiry date set. The expiry of this key will not be checked.");
- continue;
- }
-
- $today_dt = new DateTime($current_date);
- $expire_dt = new DateTime($expiry_date);
- if ($today_dt > $expire_dt) {
- //This key has reached the expiry. So expire this key.
- SLM_Debug_Logger::log_debug_st("This key (".$key.") has expired. Expiry date: ".$expiry_date.". Setting license key status to expired.");
- $data = array('lic_status' => 'expired');
- $where = array('id' => $license->id);
- $updated = $wpdb->update($tbl_name, $data, $where);
- do_action('slm_license_key_expired',$license->id);//Trigger the license expired action hook.
- }
-
- }
- }
-
- /*
- * Deletes a license key from the licenses table
- */
- static function delete_license_key_by_row_id($key_row_id) {
- global $wpdb;
- $license_table = SLM_TBL_LICENSE_KEYS;
-
- //First delete the registered domains entry of this key (if any).
- SLM_Utility::delete_registered_domains_of_key($key_row_id);
-
- //Now, delete the key from the licenses table.
- $wpdb->delete( $license_table, array( 'id' => $key_row_id ) );
-
- }
-
- /*
- * Deletes any registered domains info from the domain table for the given key's row id.
- */
- static function delete_registered_domains_of_key($key_row_id) {
- global $slm_debug_logger;
- global $wpdb;
- $reg_table = SLM_TBL_LIC_DOMAIN;
- $sql_prep = $wpdb->prepare("SELECT * FROM $reg_table WHERE lic_key_id = %s", $key_row_id);
- $reg_domains = $wpdb->get_results($sql_prep, OBJECT);
- foreach ($reg_domains as $domain) {
- $row_to_delete = $domain->id;
- $wpdb->delete( $reg_table, array( 'id' => $row_to_delete ) );
- //$slm_debug_logger->log_debug("Registered domain with row id (".$row_to_delete.") deleted.");
- }
- }
-
-}
-
diff --git a/software-license-manager/js/index.html b/software-license-manager/js/index.html
deleted file mode 100644
index e69de29..0000000
diff --git a/software-license-manager/logs/log.txt b/software-license-manager/logs/log.txt
deleted file mode 100644
index e69de29..0000000
diff --git a/software-license-manager/menu/includes/index.html b/software-license-manager/menu/includes/index.html
deleted file mode 100644
index e69de29..0000000
diff --git a/software-license-manager/menu/includes/slm-list-table-class.php b/software-license-manager/menu/includes/slm-list-table-class.php
deleted file mode 100644
index 82e9df9..0000000
--- a/software-license-manager/menu/includes/slm-list-table-class.php
+++ /dev/null
@@ -1,907 +0,0 @@
- '',
- 'singular' => '',
- 'ajax' => false,
- 'screen' => null,
- ) );
-
- $this->screen = convert_to_screen( $args['screen'] );
-
- add_filter( "manage_{$this->screen->id}_columns", array( &$this, 'get_columns' ), 0 );
-
- if ( !$args['plural'] )
- $args['plural'] = $this->screen->base;
-
- $args['plural'] = sanitize_key( $args['plural'] );
- $args['singular'] = sanitize_key( $args['singular'] );
-
- $this->_args = $args;
-
- if ( $args['ajax'] ) {
- // wp_enqueue_script( 'list-table' );
- add_action( 'admin_footer', array( &$this, '_js_vars' ) );
- }
- }
-
- /**
- * Checks the current user's permissions
- * @uses wp_die()
- *
- * @since 3.1.0
- * @access public
- * @abstract
- */
- function ajax_user_can() {
- die( 'function WP_Photo_Seller_List_Table::ajax_user_can() must be over-ridden in a sub-class.' );
- }
-
- /**
- * Prepares the list of items for displaying.
- * @uses WP_Photo_Seller_List_Table::set_pagination_args()
- *
- * @since 3.1.0
- * @access public
- * @abstract
- */
- function prepare_items() {
- die( 'function WP_Photo_Seller_List_Table::prepare_items() must be over-ridden in a sub-class.' );
- }
-
- /**
- * An internal method that sets all the necessary pagination arguments
- *
- * @param array $args An associative array with information about the pagination
- * @access protected
- */
- function set_pagination_args( $args ) {
- $args = wp_parse_args( $args, array(
- 'total_items' => 0,
- 'total_pages' => 0,
- 'per_page' => 0,
- ) );
-
- if ( !$args['total_pages'] && $args['per_page'] > 0 )
- $args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] );
-
- // redirect if page number is invalid and headers are not already sent
- if ( ! headers_sent() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) {
- wp_redirect( esc_url(add_query_arg( 'paged', $args['total_pages'] )) );
- exit;
- }
-
- $this->_pagination_args = $args;
- }
-
- /**
- * Access the pagination args
- *
- * @since 3.1.0
- * @access public
- *
- * @param string $key
- * @return array
- */
- function get_pagination_arg( $key ) {
- if ( 'page' == $key )
- return $this->get_pagenum();
-
- if ( isset( $this->_pagination_args[$key] ) )
- return $this->_pagination_args[$key];
- }
-
- /**
- * Whether the table has items to display or not
- *
- * @since 3.1.0
- * @access public
- *
- * @return bool
- */
- function has_items() {
- return !empty( $this->items );
- }
-
- /**
- * Message to be displayed when there are no items
- *
- * @since 3.1.0
- * @access public
- */
- function no_items() {
- _e( 'No items found.' );
- }
-
- /**
- * Display the search box.
- *
- * @since 3.1.0
- * @access public
- *
- * @param string $text The search button text
- * @param string $input_id The search input id
- */
- function search_box( $text, $input_id ) {
- if ( empty( $_REQUEST['s'] ) && !$this->has_items() )
- return;
-
- $input_id = $input_id . '-search-input';
-
- if ( ! empty( $_REQUEST['orderby'] ) )
- echo '
';
- if ( ! empty( $_REQUEST['order'] ) )
- echo '
';
- if ( ! empty( $_REQUEST['post_mime_type'] ) )
- echo '
';
- if ( ! empty( $_REQUEST['detached'] ) )
- echo '
';
-?>
-
- :
-
- 'search-submit') ); ?>
-
- link ) with the list
- * of views available on this table.
- *
- * @since 3.1.0
- * @access protected
- *
- * @return array
- */
- function get_views() {
- return array();
- }
-
- /**
- * Display the list of views available on this table.
- *
- * @since 3.1.0
- * @access public
- */
- function views() {
- $views = $this->get_views();
- $views = apply_filters( 'views_' . $this->screen->id, $views );
-
- if ( empty( $views ) )
- return;
-
- echo "
\n";
- foreach ( $views as $class => $view ) {
- $views[ $class ] = "\t$view";
- }
- echo implode( " | \n", $views ) . "\n";
- echo " ";
- }
-
- /**
- * Get an associative array ( option_name => option_title ) with the list
- * of bulk actions available on this table.
- *
- * @since 3.1.0
- * @access protected
- *
- * @return array
- */
- function get_bulk_actions() {
- return array();
- }
-
- /**
- * Display the bulk actions dropdown.
- *
- * @since 3.1.0
- * @access public
- */
- function bulk_actions() {
- if ( is_null( $this->_actions ) ) {
- $no_new_actions = $this->_actions = $this->get_bulk_actions();
- // This filter can currently only be used to remove actions.
- $this->_actions = apply_filters( 'bulk_actions-' . $this->screen->id, $this->_actions );
- $this->_actions = array_intersect_assoc( $this->_actions, $no_new_actions );
- $two = '';
- } else {
- $two = '2';
- }
-
- if ( empty( $this->_actions ) )
- return;
-
- echo "
\n";
- echo "" . __( 'Bulk Actions' ) . " \n";
-
- foreach ( $this->_actions as $name => $title ) {
- $class = 'edit' == $name ? ' class="hide-if-no-js"' : '';
-
- echo "\t$title \n";
- }
-
- echo " \n";
-
- submit_button( __( 'Apply' ), 'action', false, false, array( 'id' => "doaction$two" ) );
- echo "\n";
- }
-
- /**
- * Get the current action selected from the bulk actions dropdown.
- *
- * @since 3.1.0
- * @access public
- *
- * @return string|bool The action name or False if no action was selected
- */
- function current_action() {
- if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] )
- return $_REQUEST['action'];
-
- if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] )
- return $_REQUEST['action2'];
-
- return false;
- }
-
- /**
- * Generate row actions div
- *
- * @since 3.1.0
- * @access protected
- *
- * @param array $actions The list of actions
- * @param bool $always_visible Whether the actions should be always visible
- * @return string
- */
- function row_actions( $actions, $always_visible = false ) {
- $action_count = count( $actions );
- $i = 0;
-
- if ( !$action_count )
- return '';
-
- $out = '
';
- foreach ( $actions as $action => $link ) {
- ++$i;
- ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
- $out .= "$link$sep ";
- }
- $out .= '
';
-
- return $out;
- }
-
- /**
- * Display a monthly dropdown for filtering items
- *
- * @since 3.1.0
- * @access protected
- */
- function months_dropdown( $post_type ) {
- global $wpdb, $wp_locale;
-
- $months = $wpdb->get_results( $wpdb->prepare( "
- SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
- FROM $wpdb->posts
- WHERE post_type = %s
- ORDER BY post_date DESC
- ", $post_type ) );
-
- $month_count = count( $months );
-
- if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) )
- return;
-
- $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
-?>
-
- value='0'>
-year )
- continue;
-
- $month = zeroise( $arc_row->month, 2 );
- $year = $arc_row->year;
-
- printf( "%s \n",
- selected( $m, $year . $month, false ),
- esc_attr( $arc_row->year . $month ),
- /* translators: 1: month name, 2: 4-digit year */
- sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year )
- );
- }
-?>
-
- __( 'List View' ),
- 'excerpt' => __( 'Excerpt View' )
- );
-
-?>
-
-
- $title ) {
- $class = ( $current_mode == $mode ) ? 'class="current"' : '';
- echo "
\n";
- }
- ?>
-
-';
-
- echo "
";
-
- if ( $pending_comments )
- echo '';
- }
-
- /**
- * Get the current page number
- *
- * @since 3.1.0
- * @access protected
- *
- * @return int
- */
- function get_pagenum() {
- $pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0;
-
- if( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] )
- $pagenum = $this->_pagination_args['total_pages'];
-
- return max( 1, $pagenum );
- }
-
- /**
- * Get number of items to display on a single page
- *
- * @since 3.1.0
- * @access protected
- *
- * @return int
- */
- function get_items_per_page( $option, $default = 20 ) {
- $per_page = (int) get_user_option( $option );
- if ( empty( $per_page ) || $per_page < 1 )
- $per_page = $default;
-
- return (int) apply_filters( $option, $per_page );
- }
-
- /**
- * Display the pagination.
- *
- * @since 3.1.0
- * @access protected
- */
- function pagination( $which ) {
- if ( empty( $this->_pagination_args ) )
- return;
-
- extract( $this->_pagination_args, EXTR_SKIP );
-
- $output = '
' . sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . ' ';
-
- $current = $this->get_pagenum();
-
- $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
-
- $current_url = remove_query_arg( array( 'hotkeys_highlight_last', 'hotkeys_highlight_first' ), $current_url );
-
- $page_links = array();
-
- $disable_first = $disable_last = '';
- if ( $current == 1 )
- $disable_first = ' disabled';
- if ( $current == $total_pages )
- $disable_last = ' disabled';
-
- $page_links[] = sprintf( "
%s ",
- 'first-page' . $disable_first,
- esc_attr__( 'Go to the first page' ),
- esc_url( remove_query_arg( 'paged', $current_url ) ),
- '«'
- );
-
- $page_links[] = sprintf( "
%s ",
- 'prev-page' . $disable_first,
- esc_attr__( 'Go to the previous page' ),
- esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
- '‹'
- );
-
- if ( 'bottom' == $which )
- $html_current_page = $current;
- else
- $html_current_page = sprintf( "
",
- esc_attr__( 'Current page' ),
- $current,
- strlen( $total_pages )
- );
-
- $html_total_pages = sprintf( "
%s ", number_format_i18n( $total_pages ) );
- $page_links[] = '
' . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . ' ';
-
- $page_links[] = sprintf( "
%s ",
- 'next-page' . $disable_last,
- esc_attr__( 'Go to the next page' ),
- esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
- '›'
- );
-
- $page_links[] = sprintf( "
%s ",
- 'last-page' . $disable_last,
- esc_attr__( 'Go to the last page' ),
- esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
- '»'
- );
-
- $pagination_links_class = 'pagination-links';
- if ( ! empty( $infinite_scroll ) )
- $pagination_links_class = ' hide-if-js';
- $output .= "\n';
-
- if ( $total_pages )
- $page_class = $total_pages < 2 ? ' one-page' : '';
- else
- $page_class = ' no-pages';
-
- $this->_pagination = "
$output
";
-
- echo $this->_pagination;
- }
-
- /**
- * Get a list of columns. The format is:
- * 'internal-name' => 'Title'
- *
- * @since 3.1.0
- * @access protected
- * @abstract
- *
- * @return array
- */
- function get_columns() {
- die( 'function WP_Photo_Seller_List_Table::get_columns() must be over-ridden in a sub-class.' );
- }
-
- /**
- * Get a list of sortable columns. The format is:
- * 'internal-name' => 'orderby'
- * or
- * 'internal-name' => array( 'orderby', true )
- *
- * The second format will make the initial sorting order be descending
- *
- * @since 3.1.0
- * @access protected
- *
- * @return array
- */
- function get_sortable_columns() {
- return array();
- }
-
- /**
- * Get a list of all, hidden and sortable columns, with filter applied
- *
- * @since 3.1.0
- * @access protected
- *
- * @return array
- */
- function get_column_info() {
- if ( isset( $this->_column_headers ) )
- return $this->_column_headers;
-
- $columns = get_column_headers( $this->screen );
- $hidden = get_hidden_columns( $this->screen );
-
- $_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $this->get_sortable_columns() );
-
- $sortable = array();
- foreach ( $_sortable as $id => $data ) {
- if ( empty( $data ) )
- continue;
-
- $data = (array) $data;
- if ( !isset( $data[1] ) )
- $data[1] = false;
-
- $sortable[$id] = $data;
- }
-
- $this->_column_headers = array( $columns, $hidden, $sortable );
-
- return $this->_column_headers;
- }
-
- /**
- * Return number of visible columns
- *
- * @since 3.1.0
- * @access public
- *
- * @return int
- */
- function get_column_count() {
- list ( $columns, $hidden ) = $this->get_column_info();
- $hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
- return count( $columns ) - count( $hidden );
- }
-
- /**
- * Print column headers, accounting for hidden and sortable columns.
- *
- * @since 3.1.0
- * @access protected
- *
- * @param bool $with_id Whether to set the id attribute or not
- */
- function print_column_headers( $with_id = true ) {
- list( $columns, $hidden, $sortable ) = $this->get_column_info();
-
- $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
- $current_url = remove_query_arg( 'paged', $current_url );
-
- if ( isset( $_GET['orderby'] ) )
- $current_orderby = $_GET['orderby'];
- else
- $current_orderby = '';
-
- if ( isset( $_GET['order'] ) && 'desc' == $_GET['order'] )
- $current_order = 'desc';
- else
- $current_order = 'asc';
-
- if ( ! empty( $columns['cb'] ) ) {
- static $cb_counter = 1;
- $columns['cb'] = '
' . __( 'Select All' ) . ' '
- . '
';
- $cb_counter++;
- }
-
- foreach ( $columns as $column_key => $column_display_name ) {
- $class = array( 'manage-column', "column-$column_key" );
-
- $style = '';
- if ( in_array( $column_key, $hidden ) )
- $style = 'display:none;';
-
- $style = ' style="' . $style . '"';
-
- if ( 'cb' == $column_key )
- $class[] = 'check-column';
- elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) )
- $class[] = 'num';
-
- if ( isset( $sortable[$column_key] ) ) {
- list( $orderby, $desc_first ) = $sortable[$column_key];
-
- if ( $current_orderby == $orderby ) {
- $order = 'asc' == $current_order ? 'desc' : 'asc';
- $class[] = 'sorted';
- $class[] = $current_order;
- } else {
- $order = $desc_first ? 'desc' : 'asc';
- $class[] = 'sortable';
- $class[] = $desc_first ? 'asc' : 'desc';
- }
-
- $column_display_name = '
' . $column_display_name . ' ';
- }
-
- $id = $with_id ? "id='$column_key'" : '';
-
- if ( !empty( $class ) )
- $class = "class='" . join( ' ', $class ) . "'";
-
- echo "
$column_display_name ";
- }
- }
-
- /**
- * Display the table
- *
- * @since 3.1.0
- * @access public
- */
- function display() {
- extract( $this->_args );
-
- $this->display_tablenav( 'top' );
-
-?>
-
-
-
- print_column_headers(); ?>
-
-
-
-
-
- print_column_headers( false ); ?>
-
-
-
- >
- display_rows_or_placeholder(); ?>
-
-
-display_tablenav( 'bottom' );
- }
-
- /**
- * Get a list of CSS classes for the
tag
- *
- * @since 3.1.0
- * @access protected
- *
- * @return array
- */
- function get_table_classes() {
- return array( 'widefat', 'fixed', $this->_args['plural'] );
- }
-
- /**
- * Generate the table navigation above or below the table
- *
- * @since 3.1.0
- * @access protected
- */
- function display_tablenav( $which ) {
- if ( 'top' == $which )
- wp_nonce_field( 'bulk-' . $this->_args['plural'] );
-?>
-
-
-
- bulk_actions(); ?>
-
-extra_tablenav( $which );
- $this->pagination( $which );
-?>
-
-
-
- part of the table
- *
- * @since 3.1.0
- * @access protected
- */
- function display_rows_or_placeholder() {
- if ( $this->has_items() ) {
- $this->display_rows();
- } else {
- list( $columns, $hidden ) = $this->get_column_info();
- echo '';
- $this->no_items();
- echo ' ';
- }
- }
-
- /**
- * Generate the table rows
- *
- * @since 3.1.0
- * @access protected
- */
- function display_rows() {
- foreach ( $this->items as $item )
- $this->single_row( $item );
- }
-
- /**
- * Generates content for a single row of the table
- *
- * @since 3.1.0
- * @access protected
- *
- * @param object $item The current item
- */
- function single_row( $item ) {
- static $row_class = '';
- $row_class = ( $row_class == '' ? ' class="alternate"' : '' );
-
- echo '';
- echo $this->single_row_columns( $item );
- echo ' ';
- }
-
- /**
- * Generates the columns for a single row of the table
- *
- * @since 3.1.0
- * @access protected
- *
- * @param object $item The current item
- */
- function single_row_columns( $item ) {
- list( $columns, $hidden ) = $this->get_column_info();
-
- foreach ( $columns as $column_name => $column_display_name ) {
- $class = "class='$column_name column-$column_name'";
-
- $style = '';
- if ( in_array( $column_name, $hidden ) )
- $style = ' style="display:none;"';
-
- $attributes = "$class$style";
-
- if ( 'cb' == $column_name ) {
- echo '';
- echo $this->column_cb( $item );
- echo ' ';
- }
- elseif ( method_exists( $this, 'column_' . $column_name ) ) {
- echo "";
- echo call_user_func( array( &$this, 'column_' . $column_name ), $item );
- echo " ";
- }
- else {
- echo "";
- echo $this->column_default( $item, $column_name );
- echo " ";
- }
- }
- }
-
- /**
- * Handle an incoming ajax request (called from admin-ajax.php)
- *
- * @since 3.1.0
- * @access public
- */
- function ajax_response() {
- $this->prepare_items();
-
- extract( $this->_args );
- extract( $this->_pagination_args, EXTR_SKIP );
-
- ob_start();
- if ( ! empty( $_REQUEST['no_placeholder'] ) )
- $this->display_rows();
- else
- $this->display_rows_or_placeholder();
-
- $rows = ob_get_clean();
-
- $response = array( 'rows' => $rows );
-
- if ( isset( $total_items ) )
- $response['total_items_i18n'] = sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) );
-
- if ( isset( $total_pages ) ) {
- $response['total_pages'] = $total_pages;
- $response['total_pages_i18n'] = number_format_i18n( $total_pages );
- }
-
- die( json_encode( $response ) );
- }
-
- /**
- * Send required variables to JavaScript land
- *
- * @access private
- */
- function _js_vars() {
- $args = array(
- 'class' => get_class( $this ),
- 'screen' => array(
- 'id' => $this->screen->id,
- 'base' => $this->screen->base,
- )
- );
-
- printf( "\n", json_encode( $args ) );
- }
-}
diff --git a/software-license-manager/menu/index.html b/software-license-manager/menu/index.html
deleted file mode 100644
index e69de29..0000000
diff --git a/software-license-manager/menu/slm-add-licenses.php b/software-license-manager/menu/slm-add-licenses.php
deleted file mode 100644
index 53648fa..0000000
--- a/software-license-manager/menu/slm-add-licenses.php
+++ /dev/null
@@ -1,311 +0,0 @@
-';
- echo 'Add/Edit Licenses ';
- echo '';
-
- //If product is being edited, grab current product info
- if (isset($_GET['edit_record'])) {
- $errors = '';
- $id = $_GET['edit_record'];
- $lk_table = SLM_TBL_LICENSE_KEYS;
- $sql_prep = $wpdb->prepare("SELECT * FROM $lk_table WHERE id = %s", $id);
- $record = $wpdb->get_row($sql_prep, OBJECT);
- $license_key = $record->license_key;
- $max_domains = $record->max_allowed_domains;
- $license_status = $record->lic_status;
- $first_name = $record->first_name;
- $last_name = $record->last_name;
- $email = $record->email;
- $company_name = $record->company_name;
- $txn_id = $record->txn_id;
- $reset_count = $record->manual_reset_count;
- $created_date = $record->date_created;
- $renewed_date = $record->date_renewed;
- $expiry_date = $record->date_expiry;
- }
-
-
- if (isset($_POST['save_record'])) {
-
- //Check nonce
- if ( !isset($_POST['slm_add_edit_nonce_val']) || !wp_verify_nonce($_POST['slm_add_edit_nonce_val'], 'slm_add_edit_nonce_action' )){
- //Nonce check failed.
- wp_die("Error! Nonce verification failed for license save action.");
- }
-
- do_action('slm_add_edit_interface_save_submission');
-
- //TODO - do some validation
- $license_key = $_POST['license_key'];
- $max_domains = $_POST['max_allowed_domains'];
- $license_status = $_POST['lic_status'];
- $first_name = $_POST['first_name'];
- $last_name = $_POST['last_name'];
- $email = $_POST['email'];
- $company_name = $_POST['company_name'];
- $txn_id = $_POST['txn_id'];
- $reset_count = $_POST['manual_reset_count'];
- $created_date = $_POST['date_created'];
- $renewed_date = $_POST['date_renewed'];
- $expiry_date = $_POST['date_expiry'];
-
- if(empty($created_date)){
- $created_date = $current_date;
- }
- if(empty($renewed_date)){
- $renewed_date = $current_date;
- }
- if(empty($expiry_date)){
- $expiry_date = $current_date_plus_1year;
- }
-
- //Save the entry to the database
- $fields = array();
- $fields['license_key'] = $license_key;
- $fields['max_allowed_domains'] = $max_domains;
- $fields['lic_status'] = $license_status;
- $fields['first_name'] = $first_name;
- $fields['last_name'] = $last_name;
- $fields['email'] = $email;
- $fields['company_name'] = $company_name;
- $fields['txn_id'] = $txn_id;
- $fields['manual_reset_count'] = $reset_count;
- $fields['date_created'] = $created_date;
- $fields['date_renewed'] = $renewed_date;
- $fields['date_expiry'] = $expiry_date;
-
- $id = isset($_POST['edit_record'])?$_POST['edit_record']:'';
- $lk_table = SLM_TBL_LICENSE_KEYS;
- if (empty($id)) {//Insert into database
- $result = $wpdb->insert( $lk_table, $fields);
- $id = $wpdb->insert_id;
- if($result === false){
- $errors .= __('Record could not be inserted into the database!', 'slm');
- }
- } else { //Update record
- $where = array('id'=>$id);
- $updated = $wpdb->update($lk_table, $fields, $where);
- if($updated === false){
- //TODO - log error
- $errors .= __('Update of the license key table failed!', 'slm');
- }
- }
-
- if(empty($errors)){
- $message = "Record successfully saved!";
- echo '
';
- echo $message;
- echo '
';
- }else{
- echo '
' . $errors . '
';
- }
-
- $data = array('row_id' => $id, 'key' => $license_key);
- do_action('slm_add_edit_interface_save_record_processed',$data);
-
- }
-
-?>
-
- You can add a new license or edit an existing one from this interface.
-
-
-
-
License Details
-
-
-
">
-
-
-
- $id, 'key' => $license_key);
- $extra_output = apply_filters('slm_add_edit_interface_above_submit','', $data);
- if(!empty($extra_output)){
- echo $extra_output;
- }
- ?>
-
-
-
-
-
-
-
Manage Licenses
-
-
-
-
-';
- echo 'License Manager Admin Functions ';
- echo '';
-
- $slm_options = get_option('slm_plugin_options');
-
- if (isset($_POST['send_deactivation_request'])) {
- $postURL = $_POST['lic_mgr_deactivation_req_url'];
- $secretKeyForVerification = $slm_options['lic_verification_secret'];
- $data = array();
- $data['secret_key'] = $secretKeyForVerification;
-
- $ch = curl_init($postURL);
- curl_setopt($ch, CURLOPT_POST, true);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- $returnValue = curl_exec($ch);
-
- $msg = "";
- if ($returnValue == "Success") {
- $msg .= "Success message returned from the remote host.";
- }
- echo '
';
- echo 'Request sent to the specified URL!';
- echo ' ' . $msg;
- echo '
';
- }
- ?>
-
-
-
Send Deactivation Message for a License
-
-
';
- echo '
';
-}
diff --git a/software-license-manager/menu/slm-admin-init.php b/software-license-manager/menu/slm-admin-init.php
deleted file mode 100644
index aed5fe7..0000000
--- a/software-license-manager/menu/slm-admin-init.php
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
- License Manager Integration Help v' . WP_LICENSE_MANAGER_VERSION . '';
- echo '';
- echo '
';
-
- echo '
For information, updates and documentation, please visit the License Manager Documentation page.
';
-
- $api_query_post_url = SLM_SITE_HOME_URL;
- echo "
The License API Query POST URL For Your Installation ";
- echo '
' . $api_query_post_url . '
';
-
- echo "
The License Activation or Deactivation API secret key ";
- echo '
' . $secret_verification_key . '
';
-
- echo "
The License Creation API secret key ";
- echo '
' . $creation_secret_key . '
';
- ?>
-
3rd Party Integration
-
- Integrating a 3rd party payment system or shopping cart with License Manager is easy.
-
- The integration process can be accomplished in three steps, namely:
-
-
1. Generate POST data
-
2. Send POST data to the API POST URL
-
3. Process the returned data
-
-
POST Values
-
- License Manager expects a certain set of variables to be sent to it via HTTP POST or GET. These variables are:
-
- Mandatory Variables
-
- ----------------
-
a. secret_key - A Secret API key for authentication (you can find the secret key value in the settings menu of this plugin)
-
b. slm_action - The action being performed. The values can be slm_create_new or slm_activate or slm_deactivate
-
- Optional Variables
-
- ---------------
-
c. Customer First Name: The first name of the customer
-
d. Customer Last Name: The last name of the customer
-
e. Customer Email: The email address of the customer
-
f. Company Name: The customer's company name
-
g. Maximum Domains Allowed: The number of domains this license key can be used on
-
h. Transaction ID: A unique transaction ID to reference the transaction
-
-
Return Value
-
- Upon successful processing, License Manager will return a plain text message that will have two or three lines similar to the following:
-
-
- Success
- License key
- WPLICMGR4bc29fd61e471
-
- or
-
- Error
- Secret key is invalid
-
-
- 1. The first line is an indication of success or error
-
2. The second line is the result.
-
3. The third line is additional message that resulted from the request.
-
-
Sample PHP Code
-
- Below is a sample PHP code that shows how you can create a license via the API
-
-
-
- /*** Mandatory data ***/
- // Post URL
- $postURL = "";
- // The Secret key
- $secretKey = "";
-
- /*** Optional Data ***/
- $firstname = "John";
- $lastname = "Doe";
- $email = "john.doe@gmail.com";
-
- // prepare the data
- $data = array ();
- $data['secret_key'] = $secretKey;
- $data['slm_action'] = 'slm_create_new';
- $data['first_name'] = $firstname;
- $data['last_name'] = $lastname;
- $data['email'] = $email;
-
- // send data to post URL
- $ch = curl_init ($postURL);
- curl_setopt ($ch, CURLOPT_POST, true);
- curl_setopt ($ch, CURLOPT_POSTFIELDS, $data);
- curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
- $returnValue = curl_exec ($ch);
-
- // Process the return values
- //var_dump($returnValue);
-
-
-
';
- echo '
';
-}
diff --git a/software-license-manager/menu/slm-lic-settings.php b/software-license-manager/menu/slm-lic-settings.php
deleted file mode 100644
index 5b3d0bb..0000000
--- a/software-license-manager/menu/slm-lic-settings.php
+++ /dev/null
@@ -1,133 +0,0 @@
-';
- echo '
WP License Manager Settings v' . WP_LICENSE_MANAGER_VERSION . ' ';
- echo '
';
-
- wp_lic_mgr_general_settings();
-
- echo '
';
- echo '
';
-}
-
-function wp_lic_mgr_general_settings() {
-
- if (isset($_REQUEST['slm_reset_log'])){
- //$slm_logger = new SLM_Debug_Logger();
- global $slm_debug_logger;
- $slm_debug_logger->reset_log_file("log.txt");
- $slm_debug_logger->reset_log_file("log-cron-job.txt");
- echo 'Debug log files have been reset!
';
- }
-
- if (isset($_POST['slm_save_settings'])) {
-
- if (!is_numeric($_POST["default_max_domains"])) {//Set it to one by default if incorrect value is entered
- $_POST["default_max_domains"] = '1';
- }
-
- $options = array(
- 'lic_creation_secret' => trim($_POST["lic_creation_secret"]),
- 'lic_prefix' => trim($_POST["lic_prefix"]),
- 'default_max_domains' => trim($_POST["default_max_domains"]),
- 'lic_verification_secret' => trim($_POST["lic_verification_secret"]),
- 'enable_auto_key_expiry' => isset($_POST['enable_auto_key_expiry']) ? '1':'',
- 'enable_debug' => isset($_POST['enable_debug']) ? '1':'',
- );
- update_option('slm_plugin_options', $options);
-
- echo '';
- echo 'Options Updated!';
- echo '
';
- }
-
- $options = get_option('slm_plugin_options');
-
- $secret_key = $options['lic_creation_secret'];
- if (empty($secret_key)) {
- $secret_key = uniqid('', true);
- }
- $secret_verification_key = $options['lic_verification_secret'];
- if (empty($secret_verification_key)) {
- $secret_verification_key = uniqid('', true);
- }
- ?>
- For information, updates and documentation, please visit the License Manager Documentation page.
-
-
-
Quick Usage Guide
-
-
-
1. First register a key at purchase time.
-
2. Add the code so at activation time it asks for the key.
-
3. Integrate the real time online key verification part.
-
-
-
-
-
-
General License Manager Settings
-
-
-
-
Debugging and Testing Settings
-
-
-
-
-
-
- 'item', //singular name of the listed records
- 'plural' => 'items', //plural name of the listed records
- 'ajax' => false //does this table support ajax?
- ) );
-
- }
-
- function column_default($item, $column_name){
- return $item[$column_name];
- }
-
- function column_id($item){
- $row_id = $item['id'];
- $actions = array(
- 'edit' => sprintf('Edit ', $row_id),
- 'delete' => sprintf('Delete ',$row_id),
- );
- return sprintf('%1$s %2$s',
- /*$1%s*/ $item['id'],
- /*$2%s*/ $this->row_actions($actions)
- );
- }
-
-
- function column_cb($item){
- return sprintf(
- ' ',
- /*$1%s*/ $this->_args['singular'], //Let's simply repurpose the table's singular label
- /*$2%s*/ $item['id'] //The value of the checkbox should be the record's id
- );
- }
-
- function column_active($item){
- if ($item['active'] == 1){
- return 'active';
- } else{
- return 'inactive';
- }
- }
-
-
- function get_columns(){
- $columns = array(
- 'cb' => ' ', //Render a checkbox
- 'id' => 'ID',
- 'license_key' => 'License Key',
- 'lic_status' => 'Status',
- 'max_allowed_domains' => 'Domains Allowed',
- 'email' => 'Registered Email',
- 'date_created' => 'Date Created',
- 'date_renewed' => 'Date Renewed',
- 'date_expiry' => 'Expiry',
- );
- return $columns;
- }
-
- function get_sortable_columns() {
- $sortable_columns = array(
- 'id' => array('id',false),
- 'license_key' => array('license_key',false),
- 'lic_status' => array('lic_status',false),
- 'date_created' => array('date_created',false),
- 'date_renewed' => array('date_renewed',false),
- 'date_expiry' => array('date_expiry',false),
- );
- return $sortable_columns;
- }
-
- function get_bulk_actions() {
- $actions = array(
- 'delete' => 'Delete',
- );
- return $actions;
- }
-
- function process_bulk_action() {
- if('delete'===$this->current_action())
- {
- //Process delete bulk actions
- if(!isset($_REQUEST['item'])){
- $error_msg = ''.__('Error - Please select some records using the checkboxes', 'slm').'
';
- echo ''.$error_msg.'
';
- return;
- }else {
- $nvp_key = $this->_args['singular'];
- $records_to_delete = $_GET[$nvp_key];
- foreach ($records_to_delete as $row){
- SLM_Utility::delete_license_key_by_row_id($row);
- }
- echo 'Selected records deleted successfully!
';
- }
- }
- }
-
-
- /*
- * This function will delete the selected license key entries from the DB.
- */
- function delete_license_key($key_row_id)
- {
- SLM_Utility::delete_license_key_by_row_id($key_row_id);
- $success_msg = '';
- $success_msg .= 'The selected entry was deleted successfully!';
- $success_msg .= '
';
- echo $success_msg;
- }
-
-
- function prepare_items() {
- /**
- * First, lets decide how many records per page to show
- */
- $per_page = 50;
- $columns = $this->get_columns();
- $hidden = array();
- $sortable = $this->get_sortable_columns();
-
- $this->_column_headers = array($columns, $hidden, $sortable);
-
- $this->process_bulk_action();
-
- global $wpdb;
- $license_table = SLM_TBL_LICENSE_KEYS;
-
- /* -- Ordering parameters -- */
- //Parameters that are going to be used to order the result
- $orderby = !empty($_GET["orderby"]) ? strip_tags($_GET["orderby"]) : 'id';
- $order = !empty($_GET["order"]) ? strip_tags($_GET["order"]) : 'DESC';
-
- if (isset($_POST['slm_search'])) {
- $search_term = trim(strip_tags($_POST['slm_search']));
- $prepare_query = $wpdb->prepare("SELECT * FROM " . $license_table . " WHERE `license_key` LIKE '%%%s%%' OR `email` LIKE '%%%s%%' OR `txn_id` LIKE '%%%s%%' OR `first_name` LIKE '%%%s%%' OR `last_name` LIKE '%%%s%%'", $search_term, $search_term, $search_term, $search_term, $search_term);
- $data = $wpdb->get_results($prepare_query, ARRAY_A);
- }else{
- $data = $wpdb->get_results("SELECT * FROM $license_table ORDER BY $orderby $order", ARRAY_A);
- }
-
- $current_page = $this->get_pagenum();
- $total_items = count($data);
- $data = array_slice($data,(($current_page-1)*$per_page),$per_page);
- $this->items = $data;
- $this->set_pagination_args( array(
- 'total_items' => $total_items, //WE have to calculate the total number of items
- 'per_page' => $per_page, //WE have to determine how many items to show on a page
- 'total_pages' => ceil($total_items/$per_page) //WE have to calculate the total number of pages
- ) );
- }
-}
\ No newline at end of file
diff --git a/software-license-manager/menu/slm-manage-licenses.php b/software-license-manager/menu/slm-manage-licenses.php
deleted file mode 100644
index b1da0fa..0000000
--- a/software-license-manager/menu/slm-manage-licenses.php
+++ /dev/null
@@ -1,49 +0,0 @@
-';
- echo 'Manage Licenses ';
- echo '';
- ?>
-
-
-
-
-
-
Software Licenses
-
- delete_license_key(sanitize_text_field($_REQUEST['id']));
- }
- }
- //Fetch, prepare, sort, and filter our data...
- $license_list->prepare_items();
- //echo "put table of locked entries here";
- ?>
-
-
-
-
- display(); ?>
-
-
-
-
-
';
- echo '
';
-}
-
diff --git a/software-license-manager/readme.txt b/software-license-manager/readme.txt
deleted file mode 100644
index 8b170f1..0000000
--- a/software-license-manager/readme.txt
+++ /dev/null
@@ -1,136 +0,0 @@
-=== Software License Manager ===
-Contributors: Tips and Tricks HQ, Ruhul Amin
-Donate link: https://www.tipsandtricks-hq.com/software-license-manager-plugin-for-wordpress
-Tags: license key, serial key, manager, license, serial, key, selling, sell, license activation, manage license, software license, software license manager
-Requires at least: 4.0
-Tested up to: 4.8
-Stable tag: 3.0
-License: GPLv2 or later
-
-Create and manage license keys for your software applications easily
-
-== Description ==
-
-Software license management solution for your web applications (WordPress plugins, Themes, PHP based membership script etc.)
-
-This plugin is very useful for creating a license server and doing the following via API:
-
-- Create license keys in your system (license server)
-- Check the status of a license key from from your application (remotely)
-- Activate a license key from your application (remotely)
-- Deactivate a license key (remotely)
-- Check a license key (remotely)
-- Track where the license key is being used.
-
-You can also create license keys manually from the admin dashboard of this plugin.
-
-= Please note that this plugin is ONLY for developers =
-
-Check [license manager documentation](https://www.tipsandtricks-hq.com/software-license-manager-plugin-for-wordpress) to learn more.
-
-= Integration with WP eStore plugin =
-Check [WP eStore integration documentation](https://www.tipsandtricks-hq.com/ecommerce/integrate-wp-estore-with-software-license-manager-plugin-3731)
-
-= Github repository =
-
-https://github.com/Arsenal21/software-license-manager
-
-If you need some extra action hooks or filters for this plugin then let us know.
-
-== Installation ==
-
-1. Go to the Add New plugins screen in your WordPress admin area
-1. Click the upload tab
-1. Browse for the plugin file (software-license-manager.zip)
-1. Click Install Now and then activate the plugin
-
-== Frequently Asked Questions ==
-None
-
-== Screenshots ==
-See the following page:
-https://www.tipsandtricks-hq.com/software-license-manager-plugin-for-wordpress
-
-== Changelog ==
-
-= 3.0 =
-- The integration with WP eStore cart will create multiple licenses when a customer purchases more than 1 quantity of a product.
-
-= 2.9 =
-- The API response will now include a numeric error code (in the event of an error). Thanks to Steve Gehrman.
-
-= 2.8 =
-- The registered domains (if any) of a license key will get deleted when that key is deleted from the manage licenses menu.
-- Added wp_unslash() for firstname, lastname, registered domain and company name. Thanks to @sgehrman.
-- Added a new action hook (slm_license_key_expired) that gets triggered when a license key expires.
-
-= 2.7 =
-- eStore integration update: changed expiry date field to accept number of days so the plugin can dynamically calculate the expiry date for the key.
-
-= 2.6 =
-- Updated the eStore integration so a custom "Expiry Date" value can be set in the product configuration.
-
-= 2.5 =
-- Updated the eStore plugin integration so a custom "Maximum Allowed Domains" value can be specified in the eStore product configuration.
-
-= 2.4 =
-- Added new action and filter hooks in the add/edit interface so an addon can extend the functionality of that interface.
-- Added nonce check in the add/edit license interface.
-
-= 2.3 =
-- Added a new feature to enable auto expiry of the license keys. You can enable this option from the settings.
-- If you don't specify a expiry date, when adding a manual license key, it will use the current date plus 1 year as the expiry date.
-- Increased the width and height of the "Registered Domains" box in the edit license interface.
-- Added a new table column product_ref in the license keys table.
-- Added couple of new hooks in the plugin.
-
-= 2.2 =
-- Added integration with the squeeze form submission of eStore plugin.
-
-= 2.1 =
-- The license check query now outputs the date values also.
-- Improvement for the WP eStore integration.
-
-= 2.0 =
-- Added a filter to remove any null values from the DB insert query parameter of the API Utility class.
-
-= 1.9 =
-- Replaced "esc_url()" with "esc_url_raw()" in the sample plugin.
-- Updated some CSS in the admin interface for WordPress 4.4
-
-= 1.8 =
-- Added new hooks before the API query is executed. This allows a developer to override the API query and do custom stuff.
-- Added a new API to check the details of an existing license key.
-
-= 1.7 =
-* The license key is also included with the response sent to the new license creation request. Below is an example response:
-{"result":"success","message":"License successfully created","key":"5580effe188d3"}
-
-* You can now pass a pre-generated license key to the license creation API using the "license_key" parameter in the request.
-
-= 1.6 =
-* Updated the sample plugin code so the query works better.
-* Added the ability to reset the debug log file from the plugin settings interface.
-* The item_reference value will be stored in the database (if sent via the activation API query).
-
-= 1.5 =
-* Added the option to search a license key from the manage licenses interface.
-
-= 1.4 =
-* Updated the license key creation API check to use the value from "Secret Key for License Creation" field.
-
-= 1.3 =
-* Added more sanitization.
-
-= 1.2 =
-* Fixed a bug with the bulk delete license operation.
-
-= 1.1 =
-* First commit to wordpress repository.
-
-== Upgrade Notice ==
-None
-
-== Arbitrary section ==
-See the following sample/example for multi-site environment/setup:
-https://github.com/paratheme/Software-License-Manager-Multisite-licensed
\ No newline at end of file
diff --git a/software-license-manager/slm_bootstrap.php b/software-license-manager/slm_bootstrap.php
deleted file mode 100644
index 933267e..0000000
--- a/software-license-manager/slm_bootstrap.php
+++ /dev/null
@@ -1,53 +0,0 @@
-charset)){
- $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
-}else{
- $charset_collate = "DEFAULT CHARSET=utf8";
-}
-if (!empty($wpdb->collate)){
- $charset_collate .= " COLLATE $wpdb->collate";
-}
-
-$lk_tbl_sql = "CREATE TABLE " . $lic_key_table . " (
- id int(12) NOT NULL auto_increment,
- license_key varchar(255) NOT NULL,
- max_allowed_domains int(12) NOT NULL,
- lic_status ENUM('pending', 'active', 'blocked', 'expired') NOT NULL DEFAULT 'pending',
- first_name varchar(32) NOT NULL default '',
- last_name varchar(32) NOT NULL default '',
- email varchar(64) NOT NULL,
- company_name varchar(100) NOT NULL default '',
- txn_id varchar(64) NOT NULL default '',
- manual_reset_count varchar(128) NOT NULL default '',
- date_created date NOT NULL DEFAULT '0000-00-00',
- date_renewed date NOT NULL DEFAULT '0000-00-00',
- date_expiry date NOT NULL DEFAULT '0000-00-00',
- product_ref varchar(255) NOT NULL default '',
- PRIMARY KEY (id)
- )" . $charset_collate . ";";
-dbDelta($lk_tbl_sql);
-
-$ld_tbl_sql = "CREATE TABLE " .$lic_domain_table. " (
- id INT NOT NULL AUTO_INCREMENT ,
- lic_key_id INT NOT NULL ,
- lic_key varchar(255) NOT NULL ,
- registered_domain text NOT NULL ,
- item_reference varchar(255) NOT NULL,
- PRIMARY KEY ( id )
- )" . $charset_collate . ";";
-dbDelta($ld_tbl_sql);
-
-update_option("wp_lic_mgr_db_version", WP_LICENSE_MANAGER_DB_VERSION);
-
-// Add default options
-$options = array(
- 'lic_creation_secret' => uniqid('', true),
- 'lic_prefix' => '',
- 'default_max_domains' => '1',
- 'lic_verification_secret' => uniqid('', true),
- 'enable_debug' => '',
-);
-add_option('slm_plugin_options', $options);
diff --git a/software-license-manager/slm_plugin_core.php b/software-license-manager/slm_plugin_core.php
deleted file mode 100644
index 0005fe6..0000000
--- a/software-license-manager/slm_plugin_core.php
+++ /dev/null
@@ -1,60 +0,0 @@
-prefix . "lic_key_tbl");
-define('SLM_TBL_LIC_DOMAIN', $wpdb->prefix . "lic_reg_domain_tbl");
-define('SLM_MANAGEMENT_PERMISSION', 'manage_options');
-define('SLM_MAIN_MENU_SLUG', 'slm-main');
-define('SLM_MENU_ICON', 'dashicons-lock');
-
-//Includes
-include_once('includes/slm-debug-logger.php');
-include_once('includes/slm-error-codes.php');
-include_once('includes/slm-utility.php');
-include_once('includes/slm-init-time-tasks.php');
-include_once('includes/slm-api-utility.php');
-include_once('includes/slm-api-listener.php');
-include_once('includes/slm-third-party-integration.php');
-//Include admin side only files
-if (is_admin()) {
- include_once('menu/slm-admin-init.php');
- include_once('menu/includes/slm-list-table-class.php'); //Load our own WP List Table class
-}
-
-//Action hooks
-add_action('init', 'slm_init_handler');
-add_action('plugins_loaded', 'slm_plugins_loaded_handler');
-
-//Initialize debug logger
-global $slm_debug_logger;
-$slm_debug_logger = new SLM_Debug_Logger();
-
-//Do init time tasks
-function slm_init_handler() {
- $init_task = new SLM_Init_Time_Tasks();
- $api_listener = new SLM_API_Listener();
-}
-
-//Do plugins loaded time tasks
-function slm_plugins_loaded_handler() {
- //Runs when plugins_loaded action gets fired
- if (is_admin()) {
- //Check if db update needed
- if (get_option('wp_lic_mgr_db_version') != WP_LICENSE_MANAGER_DB_VERSION) {
- require_once(dirname(__FILE__) . '/slm_installer.php');
- }
- }
-
-}
-
-//TODO - need to move this to an ajax handler file
-add_action('wp_ajax_del_reistered_domain', 'slm_del_reg_dom');
-function slm_del_reg_dom() {
- global $wpdb;
- $reg_table = SLM_TBL_LIC_DOMAIN;
- $id = strip_tags($_GET['id']);
- $ret = $wpdb->query("DELETE FROM $reg_table WHERE id='$id'");
- echo ($ret) ? 'success' : 'failed';
- exit(0);
-}
diff --git a/templates/page-license-cart.php b/templates/page-license-cart.php
new file mode 100644
index 0000000..272a029
--- /dev/null
+++ b/templates/page-license-cart.php
@@ -0,0 +1,134 @@
+session) {
+ WC()->session->set('renew_license_key', $renew_license_key);
+ }
+ SLM_Helper_Class::write_log("Renewal license key set from URL: {$renew_license_key}");
+ return $renew_license_key;
+ }
+
+ // Retrieve license key from session
+ if (class_exists('WooCommerce') && WC()->session) {
+ $renew_license_key = WC()->session->get('renew_license_key');
+ if (!empty($renew_license_key)) {
+ SLM_Helper_Class::write_log("Renewal license key retrieved from session: {$renew_license_key}");
+ return $renew_license_key;
+ }
+ }
+
+ SLM_Helper_Class::write_log("No renewal license key found in URL or session.");
+ return null;
+}
+
+// Determine if it's a renewal
+$renew_license_key = get_renew_license_key();
+$is_renewal = !empty($renew_license_key);
+
+?>
+
+
+
+
+ cart && WC()->cart->is_empty()) : ?>
+
+
+
+
+
+
+
+
+
+ 'product',
+ 'posts_per_page' => 5, // Number of products to display
+ 'tax_query' => array(
+ array(
+ 'taxonomy' => 'product_type',
+ 'field' => 'slug',
+ 'terms' => 'slm_license',
+ ),
+ ),
+ );
+
+ $license_products = new WP_Query($args);
+
+ if ($license_products->have_posts()) :
+ while ($license_products->have_posts()) : $license_products->the_post();
+ global $product;
+
+ // Ensure the product is valid and contains license data
+ if ($product && $product->is_type('slm_license')) :
+ ?>
+
+
+
+
+
+
+ get_price_html(); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+prefix . 'lic_key_tbl',
+ $wpdb->prefix . 'lic_reg_domain_tbl',
+ $wpdb->prefix . 'lic_reg_devices_tbl',
+ $wpdb->prefix . 'lic_log_tbl',
+ $wpdb->prefix . 'slm_license_status',
+ $wpdb->prefix . 'slm_subscribers_tbl',
+ $wpdb->prefix . 'slm_activations_tbl',
+);
+
+// Drop custom database tables using the `prepare` method
+foreach ($tables_to_drop as $table) {
+ // Check if the table exists before attempting to drop it
+ if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table)) !== null) {
+ // Drop the table if it exists
+ $wpdb->query("DROP TABLE IF EXISTS {$table}");
+ }
+}
+
+// Delete Custom Post Type posts and related metadata using the `delete` method
+$post_types = array('slm_manage_license', 'slm_license_product'); // Add any other custom post types if needed
+foreach ($post_types as $post_type) {
+ // Check if post type data is cached
+ $cached_posts = wp_cache_get($post_type, 'slm_posts');
+ if ($cached_posts) {
+ wp_cache_delete($post_type, 'slm_posts');
+ }
+
+ // Safely delete posts and metadata for this post type
+ $wpdb->delete($wpdb->posts, array('post_type' => $post_type));
+ $wpdb->delete($wpdb->postmeta, array('post_id' => $post_type));
+}
+
+// Clean orphaned postmeta entries using `DELETE` queries
+$wpdb->query(
+ "DELETE pm FROM {$wpdb->postmeta} pm
+ LEFT JOIN {$wpdb->posts} p ON pm.post_id = p.ID
+ WHERE p.ID IS NULL"
+);
+
+// Clean orphaned term relationships if there are custom taxonomies involved
+$wpdb->query(
+ "DELETE tr FROM {$wpdb->term_relationships} tr
+ LEFT JOIN {$wpdb->posts} p ON tr.object_id = p.ID
+ WHERE p.ID IS NULL"
+);
+
+// Delete custom user meta related to the plugin (if applicable)
+$user_meta_keys = array(
+ 'slm_user_license_data',
+ // Add any other related user meta keys here
+);
+
+foreach ($user_meta_keys as $meta_key) {
+ // Check if user meta data is cached
+ $cached_meta = wp_cache_get($meta_key, 'slm_usermeta');
+ if ($cached_meta) {
+ wp_cache_delete($meta_key, 'slm_usermeta');
+ }
+
+ $wpdb->delete($wpdb->usermeta, array('meta_key' => $meta_key));
+}
+
+// Clear the relevant cache after heavy operations
+wp_cache_flush();
diff --git a/woocommerce/includes/create-license-orders.php b/woocommerce/includes/create-license-orders.php
new file mode 100644
index 0000000..b8db286
--- /dev/null
+++ b/woocommerce/includes/create-license-orders.php
@@ -0,0 +1,308 @@
+ ''];
+ $success_count = 0;
+ $failure_count = 0;
+ $skipped_orders = [];
+ $skipped_reasons = [];
+ $generated_licenses = [];
+
+ // Retrieve Product ID and Subscription Type from the request
+ $default_product_id = isset($_POST['slm_product_id']) ? absint($_POST['slm_product_id']) : null;
+ $slm_lic_type = isset($_POST['subscription_type']) && in_array($_POST['subscription_type'], ['subscription', 'lifetime'])
+ ? sanitize_text_field($_POST['subscription_type'])
+ : 'subscription';
+
+ //SLM_Helper_Class::write_log("Starting license generation with Product ID: {$default_product_id} and License Type: {$slm_lic_type}.");
+
+ // Check if Product ID is missing; if so, log an error, add an error response, and exit.
+ if (empty($default_product_id)) {
+ //SLM_Helper_Class::write_log('Error: Product ID is missing in the request.');
+
+ // Track failure and skip reason for the response
+ $failure_count++;
+ $skipped_orders[] = 0;
+ $skipped_reasons[0] = __('Product ID is missing in the request.', 'slm-plus');
+
+ // Return early with a JSON error response for AJAX display
+ $response_data['html'] .= 'Error: Product ID is missing in the request. Please provide a valid product ID. ';
+ wp_send_json_error($response_data);
+ return;
+ }
+
+ // Check if the Product ID corresponds to an existing WooCommerce product
+ $product = wc_get_product($default_product_id);
+ if (!$product) {
+ //SLM_Helper_Class::write_log("Error: Product with ID $default_product_id does not exist in WooCommerce.");
+
+ // Track failure and skip reason for the response
+ $failure_count++;
+ $skipped_orders[] = 0;
+ $skipped_reasons[0] = __('The provided Product ID does not correspond to a valid WooCommerce product. Please check the ID and try again.', 'slm-plus');
+
+ // Return early with a JSON error response for AJAX display
+ $response_data['html'] .= 'Error: The provided Product ID does not correspond to a valid WooCommerce product. Please check the ID and try again. ';
+ wp_send_json_error($response_data);
+ return;
+ }
+
+ // Query to get WooCommerce orders without a license key
+ $orders_without_license = $wpdb->get_results("
+ SELECT p.ID as order_id
+ FROM {$wpdb->prefix}posts p
+ LEFT JOIN {$wpdb->prefix}postmeta pm ON pm.post_id = p.ID AND pm.meta_key = '_license_key'
+ WHERE p.post_type = 'shop_order'
+ AND (pm.meta_value IS NULL OR pm.meta_value = '')
+ GROUP BY p.ID
+ ");
+
+ foreach ($orders_without_license as $order_data) {
+ $order_id = $order_data->order_id;
+ $order = wc_get_order($order_id);
+
+ // Only proceed for orders that are completed or processing
+ if (!in_array($order->get_status(), ['completed', 'processing'])) {
+ $skipped_orders[] = $order_id;
+ $skipped_reasons[$order_id] = 'Status not completed/processing';
+ continue;
+ }
+
+ // Gather customer info and order details
+ $first_name = $order->get_billing_first_name();
+ $last_name = $order->get_billing_last_name();
+ $email = $order->get_billing_email();
+ $purchase_id = $order->get_id();
+ $txn_id = $order->get_transaction_id();
+ $company_name = $order->get_billing_company();
+ $date_created = $order->get_date_created()->date('Y-m-d');
+ $user_id = $order->get_user_id();
+
+ // Billing length and interval for subscription
+ $slm_billing_length = SLM_API_Utility::get_slm_option('slm_billing_length');
+ $slm_billing_interval = SLM_API_Utility::get_slm_option('slm_billing_interval');
+ $subscr_id = $user_id;
+
+ // Check license type and set expiration date accordingly
+ if ($slm_lic_type === 'lifetime') {
+ $date_expiry = date('Y-m-d', strtotime("+120 years", strtotime($date_created)));
+ } else {
+ // Calculate expiration based on billing interval and length
+ switch ($slm_billing_interval) {
+ case 'years':
+ $date_expiry = date('Y-m-d', strtotime("+$slm_billing_length years", strtotime($date_created)));
+ break;
+ case 'months':
+ $date_expiry = date('Y-m-d', strtotime("+$slm_billing_length months", strtotime($date_created)));
+ break;
+ case 'days':
+ $date_expiry = date('Y-m-d', strtotime("+$slm_billing_length days", strtotime($date_created)));
+ break;
+ default:
+ $date_expiry = $date_created;
+ }
+ }
+
+ //SLM_Helper_Class::write_log("Interval: {$slm_billing_interval} - Length: {$slm_billing_length}");
+
+ $order_items = $order->get_items();
+
+ if (count($order_items) === 0) {
+ // Handle empty orders by adding a default product item
+
+ $product = wc_get_product($default_product_id);
+ if (!$product) {
+ //SLM_Helper_Class::write_log("Error: Product with ID {$default_product_id} does not exist.");
+ continue;
+ }
+
+ $item = new WC_Order_Item_Product();
+ $item->set_product_id($default_product_id);
+ $item->set_name($product->get_name());
+ $item->set_quantity(1);
+ $item->set_total($product->get_price());
+
+ if ($item->meta_exists('_slm_lic_key')) {
+ $skipped_orders[] = $order_id;
+ $skipped_reasons[$order_id] = 'Already has a license';
+ continue;
+ }
+
+ $license_data = [
+ 'slm_action' => 'slm_create_new',
+ 'lic_status' => 'pending',
+ 'lic_type' => $slm_lic_type,
+ 'first_name' => $first_name,
+ 'last_name' => $last_name,
+ 'email' => $email,
+ 'purchase_id_' => $purchase_id,
+ 'txn_id' => $txn_id,
+ 'company_name' => $company_name,
+ 'max_allowed_domains' => SLM_DEFAULT_MAX_DOMAINS,
+ 'max_allowed_devices' => SLM_DEFAULT_MAX_DEVICES,
+ 'date_created' => $date_created,
+ 'date_expiry' => $date_expiry,
+ 'product_ref' => $product->get_name(),
+ 'current_ver' => SLM_API_Utility::get_slm_option('license_current_version'),
+ 'until' => SLM_API_Utility::get_slm_option('license_until_version'),
+ 'subscr_id' => $subscr_id,
+ 'item_reference' => $order_id,
+ 'slm_billing_length' => $slm_billing_length,
+ 'slm_billing_interval' => $slm_billing_interval,
+ 'secret_key' => KEY_API
+ ];
+
+ $license_key = '';
+ $response = wp_remote_post(SLM_API_URL, [
+ 'method' => 'POST',
+ 'body' => $license_data,
+ 'timeout' => 45,
+ 'sslverify' => false,
+ ]);
+
+ if (!is_wp_error($response)) {
+ $body = wp_remote_retrieve_body($response);
+ $api_response = json_decode($body, true);
+
+ if ($api_response && isset($api_response['result']) && $api_response['result'] === 'success') {
+ $license_key = sanitize_text_field($api_response['key']);
+ $success_count++;
+
+ $order->add_order_note(
+ // Translators: %s is the generated license key
+ sprintf(__('License Key generated: %s', 'slm-plus'), $license_key)
+ );
+ $generated_licenses[] = [
+ 'license_key' => $license_key,
+ 'order_id' => $order_id,
+ ];
+ } else {
+ $failure_count++;
+ }
+ } else {
+ $failure_count++;
+ }
+
+ $order->add_item($item);
+ $order->save();
+ } else {
+ foreach ($order_items as $item) {
+ $product_id = $item->get_product_id();
+ $product_name = $item->get_name();
+
+ // Fetch the license key directly using the order ID
+ $existing_license_key = SLM_Utility::slm_get_license_by_order_id($order_id);
+
+ if ($existing_license_key) {
+ // Add the current order to associated orders for the existing license
+ SLM_Utility::slm_add_associated_order($existing_license_key, $order_id);
+
+ $skipped_orders[] = $order_id;
+ $skipped_reasons[$order_id] = 'Already has a license';
+ continue;
+ }
+
+ if ($item->meta_exists('_slm_lic_key')) {
+ $skipped_orders[] = $order_id;
+ $skipped_reasons[$order_id] = 'Already has a license';
+ continue;
+ }
+
+ $license_data['product_ref'] = $product_name;
+ $license_key = '';
+
+ $response = wp_remote_post(SLM_API_URL, [
+ 'method' => 'POST',
+ 'body' => $license_data,
+ 'timeout' => 45,
+ 'sslverify' => false,
+ ]);
+
+ if (!is_wp_error($response)) {
+ $body = wp_remote_retrieve_body($response);
+ $api_response = json_decode($body, true);
+
+ if ($api_response && isset($api_response['result']) && $api_response['result'] === 'success') {
+ $license_key = sanitize_text_field($api_response['key']);
+ $success_count++;
+ $generated_licenses[] = ['license_key' => $license_key, 'order_id' => $order_id];
+
+ $item->add_meta_data('_slm_lic_key', $license_key, true);
+ $item->add_meta_data('License Key', $license_key, true);
+ $item->add_meta_data('License Type', $slm_lic_type, true);
+
+ $order->add_order_note(
+ // Translators: %s is the generated license key
+ sprintf(__('License Key generated: %s', 'slm-plus'), $license_key)
+ );
+ } else {
+ $failure_count++;
+ }
+ } else {
+ $failure_count++;
+ }
+ $item->save();
+ }
+ $order->save();
+ }
+ }
+
+ if (!empty($skipped_orders)) {
+ $response_data['html'] .= '' . sprintf(
+ // Translators: %1$d is the number of orders skipped
+ __('%1$d orders were skipped:', 'slm-plus'),
+ count($skipped_orders)
+ ) . ' ';
+ foreach ($skipped_orders as $order_id) {
+ if ($order_id !== 0) {
+ $order_link = admin_url('post.php?post=' . $order_id . '&action=edit');
+ // Translators: %1$d is the order ID, %2$s is the reason why the order was skipped, %3$s is the order view link
+ $response_data['html'] .= '' . sprintf(__('Order ID %1$d was skipped due to: %2$s. View Order ', 'slm-plus'), $order_id, esc_html($skipped_reasons[$order_id]), esc_url($order_link)) . ' ';
+ } else {
+ $response_data['html'] .= '' . esc_html($skipped_reasons[0]) . ' ';
+ }
+ }
+ $response_data['html'] .= ' ';
+ }
+
+ if ($success_count > 0) {
+ $response_data['html'] .= '' . sprintf(
+ // Translators: %1$d is the number of successfully generated licenses
+ __('%1$d licenses generated successfully:', 'slm-plus'),
+ $success_count
+ ) . ' ';
+ foreach ($generated_licenses as $license_data) {
+ $order_link = admin_url('post.php?post=' . $license_data['order_id'] . '&action=edit');
+ // Translators: %1$s is the license key, %2$d is the order ID, %3$s is the order view link
+ $response_data['html'] .= '' . sprintf(__('License Key: %1$s for Order ID %2$d - View Order ', 'slm-plus'), esc_html($license_data['license_key']), $license_data['order_id'], esc_url($order_link)) . ' ';
+ }
+ $response_data['html'] .= ' ';
+ }
+
+ if ($failure_count > 0) {
+ $response_data['html'] .= '' . sprintf(
+ // Translators: %1$d is the number of licenses that failed to generate
+ __('%1$d licenses failed to generate.', 'slm-plus'),
+ $failure_count
+ ) . ' ';
+ }
+
+ wp_send_json_success($response_data);
+}
diff --git a/woocommerce/includes/hooks/license-checkout-hooks.php b/woocommerce/includes/hooks/license-checkout-hooks.php
new file mode 100644
index 0000000..65f1629
--- /dev/null
+++ b/woocommerce/includes/hooks/license-checkout-hooks.php
@@ -0,0 +1,444 @@
+get_id(), '_renew_license_key', true);
+ if (!empty($renew_license_key)) {
+ echo '' . esc_html__('Renewal License Key:', 'slm-plus') . ' ' . esc_html($renew_license_key) . '
';
+ }
+}
+
+/**
+ * Add the renewal key to WooCommerce email notifications.
+ */
+add_action('woocommerce_email_order_meta', 'slm_add_renewal_key_to_email', 10, 3);
+function slm_add_renewal_key_to_email($order, $sent_to_admin, $plain_text) {
+ $renew_license_key = get_post_meta($order->get_id(), '_renew_license_key', true);
+
+ if (!empty($renew_license_key)) {
+ echo '' . esc_html__('Renewal License Key:', 'slm-plus') . ' ' . esc_html($renew_license_key) . '
';
+ }
+}
+
+
+
+
+/**
+ * Remove the "Additional Information" section on the custom checkout page.
+ */
+add_action('template_redirect', 'slm_remove_additional_info_on_custom_checkout');
+function slm_remove_additional_info_on_custom_checkout() {
+ // Check if the current page is your custom checkout page
+ if (is_page_template('license-checkout.php')) {
+ add_filter('woocommerce_enable_order_notes_field', '__return_false');
+ }
+}
+
+/**
+ * Handle license renewal during order processing.
+ */
+add_action('woocommerce_order_status_completed', 'slm_process_license_renewal', 10, 1);
+function slm_process_license_renewal($order_id) {
+ $renew_license_key = get_post_meta($order_id, '_renew_license_key', true);
+
+ if (!empty($renew_license_key)) {
+ // Log the renewal process
+ SLM_Helper_Class::write_log("Processing renewal for License Key {$renew_license_key} on Order ID {$order_id}");
+
+ // Call the renewal function from purchase.php
+ wc_slm_renew_license(wc_get_order($order_id));
+ } else {
+ // Log and fallback to new license creation
+ SLM_Helper_Class::write_log("No renewal key found. Proceeding with new license creation for Order ID {$order_id}");
+ wc_slm_create_new_license(wc_get_order($order_id));
+ }
+}
+
+
+add_action('woocommerce_add_to_cart', 'slm_clear_old_renew_license_key', 5);
+function slm_clear_old_renew_license_key() {
+ if (WC()->session->get('renew_license_key')) {
+ WC()->session->__unset('renew_license_key');
+ slm_debug_log("Cleared old renewal license key from session.");
+ }
+}
+
+
+add_action('woocommerce_before_cart_item_quantity_zero', 'slm_clear_renew_license_key_on_cart_change', 10);
+function slm_clear_renew_license_key_on_cart_change($cart_item_key) {
+ $cart = WC()->cart->get_cart();
+
+ if (isset($cart[$cart_item_key]['renew_license_key'])) {
+ unset(WC()->cart->cart_contents[$cart_item_key]['renew_license_key']);
+ SLM_Helper_Class::write_log("License key removed from cart item: {$cart_item_key}");
+ }
+}
+
+add_filter('woocommerce_cart_item_display', 'slm_reset_license_key_on_cart_change', 10, 3);
+function slm_reset_license_key_on_cart_change($cart_item_html, $cart_item, $cart_item_key) {
+ if (isset($cart_item['renew_license_key'])) {
+ $current_license = $cart_item['renew_license_key'];
+
+ // Check if license key is mismatched or invalid
+ if (!slm_is_valid_license($current_license)) {
+ WC()->cart->cart_contents[$cart_item_key]['renew_license_key'] = null;
+ SLM_Helper_Class::write_log("Invalid or mismatched license key cleared from cart.");
+ }
+ }
+
+ return $cart_item_html;
+}
+
+function slm_is_valid_license($license_key) {
+ global $wpdb;
+ $lic_key_table = $wpdb->prefix . 'lic_key_tbl';
+ $license = $wpdb->get_var($wpdb->prepare("SELECT license_key FROM $lic_key_table WHERE license_key = %s", $license_key));
+ return !empty($license);
+}
+
+/**
+ * Restrict cart to one license product.
+ */
+add_filter('woocommerce_add_to_cart_validation', 'slm_restrict_cart_quantity', 10, 5);
+function slm_restrict_cart_quantity($passed, $product_id, $quantity, $variation_id = '', $cart_item_data = []) {
+ // Ensure WooCommerce is initialized
+ if (!WC()->cart) {
+ return $passed;
+ }
+
+ // Get the product being added
+ $product = wc_get_product($product_id);
+
+ // Check if the product is a license product
+ if ($product && $product->is_type('slm_license')) {
+ // Loop through existing cart items
+ foreach (WC()->cart->get_cart() as $cart_item) {
+ if ($cart_item['data']->is_type('slm_license')) {
+ // Add notice only once
+ if (!wc_has_notice(__('You can only add one license product (either new or renewal) to your cart at a time.', 'slm-plus'))) {
+ wc_add_notice(__('You can only add one license product (either new or renewal) to your cart at a time.', 'slm-plus'), 'error');
+ }
+ return false;
+ }
+ }
+ }
+
+ return $passed;
+}
+
+/**
+ * Validate cart before checkout to ensure only one license product.
+ */
+add_action('woocommerce_check_cart_items', 'slm_validate_cart_before_checkout');
+function slm_validate_cart_before_checkout() {
+ if (!WC()->cart) {
+ return;
+ }
+
+ $license_count = 0;
+
+ // Count license products in the cart
+ foreach (WC()->cart->get_cart() as $cart_item) {
+ if ($cart_item['data']->is_type('slm_license')) {
+ $license_count++;
+ }
+ }
+
+ // If more than one license product is in the cart, display an error and block checkout
+ if ($license_count > 1) {
+ if (!wc_has_notice(__('You can only have one license product (new or renewal) in your cart.', 'slm-plus'))) {
+ wc_add_notice(__('You can only have one license product (new or renewal) in your cart.', 'slm-plus'), 'error');
+ }
+ }
+}
+
+/**
+ * Automatically remove extra license products if multiple are added to the cart.
+ */
+add_action('woocommerce_before_calculate_totals', 'slm_remove_extra_license_products', 10, 1);
+function slm_remove_extra_license_products($cart) {
+ if (is_admin() && !defined('DOING_AJAX')) {
+ return;
+ }
+
+ $license_product_key = null;
+
+ // Loop through the cart to find license products
+ foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
+ $product = $cart_item['data'];
+
+ if ($product && $product->is_type('slm_license')) {
+ // Keep the first license product, remove the rest
+ if ($license_product_key === null) {
+ $license_product_key = $cart_item_key;
+ } else {
+ $cart->remove_cart_item($cart_item_key);
+ wc_add_notice(__('Only one license product is allowed in the cart. Extra items have been removed.', 'slm-plus'), 'notice');
+ }
+ }
+ }
+}
+
+
+
+add_filter('woocommerce_cart_item_quantity', 'slm_limit_cart_quantity', 10, 3);
+
+function slm_limit_cart_quantity($product_quantity, $cart_item_key, $cart_item) {
+ if ($cart_item['data']->is_type('slm_license')) {
+ $product_quantity = sprintf(
+ ' ',
+ $cart_item_key
+ );
+ }
+
+ return $product_quantity;
+}
+
+
+
+add_filter('woocommerce_cart_item_quantity', 'slm_disable_quantity_change', 10, 3);
+
+function slm_disable_quantity_change($quantity, $cart_item_key, $cart_item) {
+ if ($cart_item['data']->is_type('slm_license')) {
+ // Display quantity as non-editable text
+ return '' . esc_html($cart_item['quantity']) . ' ';
+ }
+
+ return $quantity;
+}
+
+/**
+ * Handle license product restrictions in cart.
+ */
+add_action('woocommerce_check_cart_items', 'slm_remove_existing_license_product');
+function slm_remove_existing_license_product() {
+ $license_product_key = null;
+
+ foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
+ $product = $cart_item['data'];
+ if ($product->is_type('slm_license')) {
+ if ($license_product_key === null) {
+ $license_product_key = $cart_item_key;
+ } else {
+ WC()->cart->remove_cart_item($cart_item_key);
+ slm_debug_log("Removed additional license product from the cart.");
+ }
+ }
+ }
+}
+
+
+
+
+add_filter('woocommerce_add_cart_item_data', 'slm_add_renew_license_key_to_cart', 10, 2);
+
+function slm_add_renew_license_key_to_cart($cart_item_data, $product_id) {
+ if (isset($_POST['renew_license_key']) && !empty($_POST['renew_license_key'])) {
+ $renew_license_key = sanitize_text_field($_POST['renew_license_key']);
+ $cart_item_data['renew_license_key'] = $renew_license_key;
+
+ // Save to session for later use
+ WC()->session->set('renew_license_key', $renew_license_key);
+ slm_debug_log("Renewal License Key added to cart item data and session: {$renew_license_key}");
+ }
+
+ return $cart_item_data;
+}
+
+
+
+add_filter('woocommerce_get_cart_item_from_session', 'slm_get_renew_license_key_from_session', 10, 2);
+
+function slm_get_renew_license_key_from_session($cart_item, $values) {
+ if (isset($values['renew_license_key'])) {
+ $cart_item['renew_license_key'] = $values['renew_license_key'];
+ slm_debug_log("Renewal License Key retrieved from session for cart item: {$values['renew_license_key']}");
+ }
+
+ return $cart_item;
+}
+
+
+add_action('woocommerce_check_cart_items', 'slm_validate_license_cart');
+
+function slm_validate_license_cart() {
+ $license_count = 0;
+
+ foreach (WC()->cart->get_cart() as $cart_item) {
+ if ($cart_item['data']->is_type('slm_license')) {
+ $license_count++;
+ }
+ }
+
+ if ($license_count > 1) {
+ wc_add_notice(__('You can only have one license (new or renewal) in your cart.', 'slm-plus'), 'error');
+ }
+}
+
+
+/**
+ * Redirect to custom cart page for license products.
+ */
+add_filter('woocommerce_add_to_cart_redirect', 'slm_redirect_to_custom_cart_page');
+function slm_redirect_to_custom_cart_page($url) {
+ if (isset($_POST['add-to-cart']) && !empty($_POST['add-to-cart'])) {
+ $product_id = intval($_POST['add-to-cart']);
+ $product = wc_get_product($product_id);
+
+ if ($product && $product->is_type('slm_license')) {
+ $custom_cart_url = home_url('/license-cart');
+ if (isset($_POST['renew_license_key']) && !empty($_POST['renew_license_key'])) {
+ $renew_license_key = sanitize_text_field($_POST['renew_license_key']);
+ $custom_cart_url = add_query_arg('renew_license_key', $renew_license_key, $custom_cart_url);
+ }
+ return $custom_cart_url;
+ }
+ }
+ return $url;
+}
+
+
+/**
+ * Customize WooCommerce checkout fields.
+ */
+/**
+ * Customize WooCommerce checkout fields.
+ */
+add_filter('woocommerce_checkout_fields', 'slm_customize_checkout_fields');
+function slm_customize_checkout_fields($fields) {
+ // Retrieve the renewal license key from the session
+ $renew_license_key = WC()->session->get('renew_license_key');
+ SLM_Helper_Class::write_log("Renew license key retrieved in customize_checkout_fields: {$renew_license_key}");
+
+ // Add the renewal license field if the key is set
+ if (!empty($renew_license_key)) {
+ $fields['billing']['billing_license_renewal'] = array(
+ 'type' => 'text',
+ 'label' => esc_html__('This order includes a license renewal for:', 'slm-plus'),
+ 'placeholder' => '',
+ 'class' => array('form-row-wide'),
+ 'custom_attributes' => array('readonly' => 'readonly'),
+ 'priority' => 29, // Position it above "Company Name"
+ );
+
+ // Force the value of the field to the session key
+ add_filter('woocommerce_checkout_get_value', function ($value, $input) use ($renew_license_key) {
+ if ($input === 'billing_license_renewal') {
+ SLM_Helper_Class::write_log("Forcing value for billing_license_renewal: {$renew_license_key}");
+ return $renew_license_key;
+ }
+ return $value;
+ }, 10, 2);
+ }
+
+ return $fields;
+}
+
+
+// Set renew license key in session during redirect.
+add_action('init', function () {
+ if (isset($_GET['renew_license']) && isset($_GET['product_id'])) {
+ // Ensure WooCommerce session exists
+ if (class_exists('WooCommerce') && WC()->session) {
+ $renew_license_key = sanitize_text_field($_GET['renew_license']);
+ WC()->session->set('renew_license_key', $renew_license_key);
+ SLM_Helper_Class::write_log("Renew license key set in session during redirect: {$renew_license_key}");
+ } else {
+ SLM_Helper_Class::write_log("WooCommerce session not initialized. Cannot set renew license key.");
+ }
+ }
+});
+
+// Clear the renew license key from session on specific conditions.
+add_action('wp_loaded', function () {
+ if (class_exists('WooCommerce') && WC()->session) {
+ // Example: Clear session key after completing the process or on specific conditions
+ if (isset($_GET['clear_renew_key'])) { // Example condition
+ $renew_license_key = WC()->session->get('renew_license_key');
+ WC()->session->__unset('renew_license_key');
+ SLM_Helper_Class::write_log("Renew license key cleared from session: {$renew_license_key}");
+ }
+ } else {
+ SLM_Helper_Class::write_log("WooCommerce session not available. Cannot clear renew license key.");
+ }
+});
+
+/**
+ * Display a notice on the checkout page for license renewal.
+ */
+add_action('woocommerce_before_checkout_form', function () {
+ $renew_license_key = WC()->session->get('renew_license_key');
+});
+
+
+
+
+/**
+ * Clear renewal license session data when the cart is empty.
+ */
+add_action('woocommerce_cart_updated', 'slm_clear_session_if_cart_empty');
+function slm_clear_session_if_cart_empty() {
+ // Ensure WooCommerce session is initialized
+ if (class_exists('WooCommerce') && WC()->session) {
+ // Check if the cart is empty
+ if (WC()->cart->is_empty()) {
+ // Clear the renew license key from the session
+ if (WC()->session->get('renew_license_key')) {
+ $renew_license_key = WC()->session->get('renew_license_key');
+ WC()->session->__unset('renew_license_key');
+ SLM_Helper_Class::write_log("Cart is empty. Cleared renew license key from session: {$renew_license_key}");
+ }
+
+ // Optionally, clear WooCommerce cookies
+ WC()->session->destroy_session();
+ SLM_Helper_Class::write_log("Cart is empty. WooCommerce session and cookies cleared.");
+ }
+ }
+}
+
+add_action('woocommerce_before_cart', function () {
+ if (WC()->cart->is_empty()) {
+ wc_add_notice(__('Your cart is empty. Session data has been cleared.', 'slm-plus'), 'notice');
+ }
+});
+
+add_action('woocommerce_cart_is_empty', function () {
+ if (WC()->session && WC()->session->get('renew_license_key')) {
+ WC()->session->__unset('renew_license_key');
+ SLM_Helper_Class::write_log("Cleared renew_license_key as cart is empty.");
+ }
+});
diff --git a/woocommerce/includes/hooks/slm-create-pages.php b/woocommerce/includes/hooks/slm-create-pages.php
new file mode 100644
index 0000000..1c335fa
--- /dev/null
+++ b/woocommerce/includes/hooks/slm-create-pages.php
@@ -0,0 +1,49 @@
+ 'page',
+ 'name' => 'license-cart', // Check for the slug
+ 'post_status' => 'publish',
+ 'posts_per_page' => 1,
+ ));
+
+ if (!$query->have_posts()) {
+ // Create the License Cart page
+ $page_id = wp_insert_post(array(
+ 'post_title' => 'License Cart',
+ 'post_content' => '', // Empty content for now
+ 'post_status' => 'publish',
+ 'post_type' => 'page',
+ 'post_name' => 'license-cart', // Set the slug
+ 'meta_input' => array('_wp_page_template' => 'page-license-cart.php'), // Assign the custom template
+ ));
+
+ if ($page_id && !is_wp_error($page_id)) {
+ // Optionally, hide the page from menus/navigation
+ update_post_meta($page_id, '_menu_item_visibility', 'hidden');
+ error_log(__('License Cart page created successfully with ID: ', 'slm-plus') . $page_id);
+ } else {
+ error_log(__('Failed to create License Cart page.', 'slm-plus'));
+ }
+ } else {
+ error_log(__('License Cart page already exists.', 'slm-plus'));
+ }
+}
+
+/**
+ * Hook into plugin activation to create the License Cart page.
+ */
+register_activation_hook(__FILE__, 'slm_create_license_cart_page');
diff --git a/woocommerce/includes/purchase.php b/woocommerce/includes/purchase.php
new file mode 100755
index 0000000..fd3da5e
--- /dev/null
+++ b/woocommerce/includes/purchase.php
@@ -0,0 +1,273 @@
+get_id(), '_renew_license_key', true);
+
+ if (empty($renew_license_key)) {
+ return SLM_Helper_Class::write_log("No renew_license_key found for Order ID: " . $order->get_id());
+ }
+
+ // Define the license key table
+ $lic_key_table = $wpdb->prefix . 'lic_key_tbl';
+
+ // Fetch the license data
+ $license_data = $wpdb->get_row(
+ $wpdb->prepare(
+ "SELECT * FROM $lic_key_table WHERE license_key = %s LIMIT 1",
+ $renew_license_key
+ ),
+ ARRAY_A
+ );
+
+ if (!$license_data) {
+ return SLM_Helper_Class::write_log("License not found for renewal. Order ID: " . $order->get_id());
+ }
+
+ if ($license_data['lic_status'] === 'blocked') {
+ return SLM_Helper_Class::write_log("Blocked license cannot be renewed. License Key: {$renew_license_key}");
+ }
+
+ // Calculate the new expiration date
+ $current_expiry_date = $license_data['date_expiry'];
+ $new_expiration_date = date(
+ 'Y-m-d',
+ strtotime($current_expiry_date . ' +' . $license_data['slm_billing_length'] . ' ' . $license_data['slm_billing_interval'])
+ );
+
+ // Loop through the order items to get the product ID
+ $product_id = null;
+ foreach ($order->get_items() as $item) {
+ $product_id = $item->get_product_id(); // Get the product ID
+ SLM_Helper_Class::write_log("Processing renewal for Product ID: {$product_id}, Order ID: " . $order->get_id());
+ break; // Only one product ID is needed for a single license renewal
+ }
+
+ // Update the license data
+ $updated = $wpdb->update(
+ $lic_key_table,
+ [
+ 'date_expiry' => $new_expiration_date,
+ 'lic_status' => 'active',
+ 'date_renewed' => current_time('mysql'),
+ 'wc_order_id' => $order->get_id(),
+ 'txn_id' => $order->get_id(),
+ 'item_reference' => $product_id,
+ 'purchase_id_' => $order->get_id(),
+ ],
+ ['license_key' => $renew_license_key],
+ ['%s', '%s', '%s', '%d', '%d', '%s', '%d'], // Added placeholders for product ID
+ ['%s']
+ );
+
+ // Debugging: Check if update was successful
+ if ($updated === false) {
+ SLM_Helper_Class::write_log("Failed to renew license. License Key: {$renew_license_key}, Order ID: " . $order->get_id());
+ } else {
+ SLM_Helper_Class::write_log("License renewed successfully. License Key: {$renew_license_key}, Product ID: {$product_id}, Order ID: " . $order->get_id() . ", New Expiration Date: $new_expiration_date.");
+
+ // Add the order to the associated orders
+ $associated_updated = SLM_Utility::slm_add_associated_order($renew_license_key, $order->get_id());
+
+ if ($associated_updated) {
+ SLM_Helper_Class::write_log("Order ID: {$order->get_id()} successfully added to associated orders for License Key: {$renew_license_key}");
+ } else {
+ SLM_Helper_Class::write_log("Failed to add Order ID: {$order->get_id()} to associated orders for License Key: {$renew_license_key}");
+ }
+ }
+}
+
+function slm_display_licenses_in_order_details($order) {
+ global $wpdb;
+
+ // Fetch the WooCommerce order ID
+ $order_id = $order->get_id();
+
+ // Fetch license keys for this order from the license table
+ $lic_key_table = $wpdb->prefix . 'lic_key_tbl';
+ $licenses = $wpdb->get_results(
+ $wpdb->prepare("SELECT license_key, lic_status FROM $lic_key_table WHERE wc_order_id = %d", $order_id),
+ ARRAY_A
+ );
+
+ // If no licenses exist, return
+ if (empty($licenses)) {
+ return;
+ }
+
+ // Display licenses
+ echo '' . esc_html__('License Information', 'slm-plus') . ' ';
+ echo '
+
+
+ ' . esc_html__('License Key', 'slm-plus') . '
+ ' . esc_html__('Status', 'slm-plus') . '
+ ' . esc_html__('Actions', 'slm-plus') . '
+
+
+ ';
+
+ foreach ($licenses as $license) {
+ $license_key = esc_html($license['license_key']);
+ $status = esc_html(ucfirst($license['lic_status']));
+ $license_url = esc_url(add_query_arg('license_key', $license_key, wc_get_page_permalink('myaccount') . 'my-licenses'));
+
+ echo "
+ $license_key
+ $status
+ " . esc_html__('View License', 'slm-plus') . "
+ ";
+ }
+
+ echo '
';
+}
+
+function wc_slm_create_new_license($order) {
+ global $wpdb;
+
+ // Validate the order object
+ if (!$order instanceof WC_Order) {
+ SLM_Helper_Class::write_log("Invalid order object passed.");
+ return;
+ }
+
+ // Check if a license has already been created for this order
+ $license_created = get_post_meta($order->get_id(), '_slm_license_created', true);
+ if (!empty($license_created)) {
+ SLM_Helper_Class::write_log("License already created for Order ID: {$order->get_id()}");
+ return;
+ }
+
+ $items = $order->get_items();
+ $customer_id = $order->get_user_id();
+ $billing_email = sanitize_email($order->get_billing_email());
+
+ // Loop through the order items
+ foreach ($items as $item_key => $values) {
+ $product_id = $values->get_product_id();
+ $product = $values->get_product();
+
+ // Skip if product is not a license product
+ if (!$product->is_type('slm_license')) {
+ continue;
+ }
+
+ // Retrieve product custom fields
+ $custom_fields = [
+ 'max_allowed_domains' => intval(get_post_meta($product_id, '_domain_licenses', true)),
+ 'max_allowed_devices' => intval(get_post_meta($product_id, '_devices_licenses', true)),
+ 'slm_billing_interval' => sanitize_text_field(get_post_meta($product_id, '_license_renewal_period_term', true)),
+ 'slm_billing_length' => intval(get_post_meta($product_id, '_license_renewal_period_length', true)),
+ 'current_ver' => sanitize_text_field(get_post_meta($product_id, '_license_current_version', true)),
+ 'until' => sanitize_text_field(get_post_meta($product_id, '_license_until_version', true)),
+ 'lic_type' => sanitize_text_field(get_post_meta($product_id, '_license_type', true)),
+ 'item_reference' => sanitize_text_field(get_post_meta($product_id, '_license_item_reference', true)),
+ ];
+
+ // Calculate expiration date
+ $expiration_date = ($custom_fields['slm_billing_interval'] === 'onetime')
+ ? date('Y-m-d', strtotime('+200 years'))
+ : date('Y-m-d', strtotime('+' . $custom_fields['slm_billing_length'] . ' ' . $custom_fields['slm_billing_interval']));
+
+ // Generate a new license key
+ $new_license_key = slm_get_license(get_option('slm_license_prefix', 'SLM'));
+
+ // Insert the license into the database
+ $result = $wpdb->insert(
+ SLM_TBL_LICENSE_KEYS, // Ensure constant is defined for table name
+ [
+ 'license_key' => $new_license_key,
+ 'max_allowed_domains' => $custom_fields['max_allowed_domains'],
+ 'max_allowed_devices' => $custom_fields['max_allowed_devices'],
+ 'slm_billing_interval' => $custom_fields['slm_billing_interval'],
+ 'slm_billing_length' => $custom_fields['slm_billing_length'],
+ 'current_ver' => $custom_fields['current_ver'],
+ 'until' => $custom_fields['until'],
+ 'lic_type' => $custom_fields['lic_type'],
+ 'item_reference' => $product_id,
+ 'wc_order_id' => $order->get_id(),
+ 'product_ref' => $product_id,
+ 'email' => $billing_email,
+ 'first_name' => sanitize_text_field($order->get_billing_first_name()),
+ 'last_name' => sanitize_text_field($order->get_billing_last_name()),
+ 'date_created' => current_time('mysql'),
+ 'date_expiry' => $expiration_date,
+ 'lic_status' => 'pending',
+ 'purchase_id_' => $order->get_id(),
+ 'txn_id' => $order->get_id(),
+ 'subscr_id' => $customer_id,
+ ]
+ );
+
+ if ($result === false) {
+ SLM_Helper_Class::write_log("Failed to create license for Product ID: {$product_id} in Order ID: {$order->get_id()}. Error: {$wpdb->last_error}");
+ continue;
+ }
+
+ // Associate license with WooCommerce order
+ update_post_meta($order->get_id(), '_slm_license_key', $new_license_key);
+ update_post_meta($order->get_id(), 'License Key', $new_license_key);
+
+ SLM_Helper_Class::write_log("New license key created for Product ID: {$product_id} in Order ID: {$order->get_id()}");
+ }
+
+ // Mark the license as created
+ update_post_meta($order->get_id(), '_slm_license_created', true);
+ SLM_Helper_Class::write_log("License creation process completed for Order ID: {$order->get_id()}");
+}
diff --git a/woocommerce/includes/register-template.php b/woocommerce/includes/register-template.php
new file mode 100644
index 0000000..9a6435c
--- /dev/null
+++ b/woocommerce/includes/register-template.php
@@ -0,0 +1,126 @@
+get_type() : $product->product_type;
+
+ // Check if the product type is 'slm_license'
+ if ($product_type === 'slm_license') {
+ $template_path = SLM_WOO;
+
+ // Detect if the request includes a renew_license_key
+ $is_renewal = isset($_GET['renew_license_key']) && !empty($_GET['renew_license_key']);
+ $renew_license_key = $is_renewal ? sanitize_text_field($_GET['renew_license_key']) : '';
+
+ // Pass renewal status and key as variables to the template
+ wc_get_template(
+ 'single-product/add-to-cart/slm_license.php',
+ array(
+ 'is_renewal' => $is_renewal,
+ 'renew_license_key' => $renew_license_key,
+ ),
+ '',
+ trailingslashit($template_path)
+ );
+ }
+}
+
+
+
+/**
+ * Override default WooCommerce templates and template parts from plugin.
+ *
+ * E.g.
+ * Override template 'woocommerce/loop/result-count.php' with 'my-plugin/woocommerce/loop/result-count.php'.
+ * Override template part 'woocommerce/content-product.php' with 'my-plugin/woocommerce/content-product.php'.
+ *
+ * Note: We used folder name 'woocommerce' in plugin to override all woocommerce templates and template parts.
+ * You can change it as per your requirement.
+ */
+// Override Template Part's.
+add_filter( 'wc_get_template_part', 'slm_override_woocommerce_template_part', 10, 3 );
+// Override Template's.
+add_filter( 'woocommerce_locate_template', 'slm_override_woocommerce_template', 10, 3 );
+/**
+ * Template Part's
+ *
+ * @param string $template Default template file path.
+ * @param string $slug Template file slug.
+ * @param string $name Template file name.
+ * @return string Return the template part from plugin.
+ */
+function slm_override_woocommerce_template_part( $template, $slug, $name ) {
+ // UNCOMMENT FOR @DEBUGGING
+ // echo '';
+ // echo 'template: ' . $template . ' ';
+ // echo 'slug: ' . $slug . ' ';
+ // echo 'name: ' . $name . ' ';
+ // echo ' ';
+ // Template directory.
+ // E.g. /wp-content/plugins/my-plugin/woocommerce/
+ $template_directory = untrailingslashit( plugin_dir_path( __FILE__ ) ) . 'woocommerce/';
+ if ( $name ) {
+ $path = $template_directory . "{$slug}-{$name}.php";
+ } else {
+ $path = $template_directory . "{$slug}.php";
+ }
+ return file_exists( $path ) ? $path : $template;
+}
+/**
+ * Template File
+ *
+ * @param string $template Default template file path.
+ * @param string $template_name Template file name.
+ * @param string $template_path Template file directory file path.
+ * @return string Return the template file from plugin.
+ */
+function slm_override_woocommerce_template( $template, $template_name, $template_path ) {
+ // UNCOMMENT FOR @DEBUGGING
+ // echo '';
+ // echo 'template: ' . $template . ' ';
+ // echo 'template_name: ' . $template_name . ' ';
+ // echo 'template_path: ' . $template_path . ' ';
+ // echo ' ';
+ // Template directory.
+ // E.g. /wp-content/plugins/my-plugin/woocommerce/
+ $template_directory = untrailingslashit( plugin_dir_path( __FILE__ ) ) . 'woocommerce/';
+ $path = $template_directory . $template_name;
+ return file_exists( $path ) ? $path : $template;
+}
+
+
+
+// Load template for the specific page
+add_filter('page_template', 'slm_load_license_cart_template');
+function slm_load_license_cart_template($page_template) {
+ if (get_page_template_slug() == 'page-license-cart.php') {
+ $page_template = SLM_TEMPLATES . 'page-license-cart.php';
+ }
+ return $page_template;
+}
+
+/**
+ * Add "License Cart" template to the Page Attributes template dropdown.
+ */
+add_filter('theme_page_templates', 'slm_add_license_cart_template', 10, 4);
+function slm_add_license_cart_template($post_templates, $wp_theme, $post, $post_type) {
+ // Add the custom template to the dropdown
+ $post_templates['page-license-cart.php'] = __('License Cart', 'slm-plus');
+ return $post_templates;
+}
diff --git a/woocommerce/includes/slm-meta-boxes.php b/woocommerce/includes/slm-meta-boxes.php
new file mode 100644
index 0000000..38a5170
--- /dev/null
+++ b/woocommerce/includes/slm-meta-boxes.php
@@ -0,0 +1,629 @@
+version, '3.0.0', '>=')) {
+ class WC_Product_SLM_License extends WC_Product_Simple
+ {
+ protected $product_type = 'slm_license';
+
+ public function __construct($product = 0)
+ {
+ parent::__construct($product);
+ }
+
+ public function get_type()
+ {
+ return 'slm_license';
+ }
+ }
+ } else {
+ // Older versions use WC_Product as the base class
+ class WC_Product_SLM_License extends WC_Product
+ {
+ protected $product_type = 'slm_license';
+
+ public function __construct($product = 0)
+ {
+ parent::__construct($product);
+ }
+
+ public function get_type()
+ {
+ return 'slm_license';
+ }
+ }
+ }
+ }
+}
+add_action('init', 'slm_register_product_type');
+
+
+function slm_register_product_class($classname, $product_type)
+{
+ if ($product_type == 'slm_license') {
+ $classname = 'WC_Product_SLM_License';
+ }
+ return $classname;
+}
+add_filter('woocommerce_product_class', 'slm_register_product_class', 10, 2);
+
+
+function slm_add_product_type($types)
+{
+ $types['slm_license'] = __('License product', 'slm-plus');
+ return $types;
+ error_log("Saving product type for Product ID: " . $types);
+}
+add_filter('product_type_selector', 'slm_add_product_type');
+
+
+/**
+ * Add 'License Manager' product option.
+ */
+function add_wc_slm_data_tab_enabled_product_option($product_type_options)
+{
+ // Check if the current product type is the custom license product type
+ if (isset($_GET['product_type']) && $_GET['product_type'] === 'slm_license') {
+ $product_type_options['wc_slm_data_tab_enabled'] = array(
+ 'id' => '_wc_slm_data_tab_enabled',
+ 'wrapper_class' => 'show_if_slm_license',
+ 'label' => __('License Manager', 'slm-plus'),
+ 'default' => 'no',
+ 'description' => __('Enables the license creation API.', 'slm-plus'),
+ 'type' => 'checkbox'
+ );
+ }
+ return $product_type_options;
+}
+add_filter('product_type_options', 'add_wc_slm_data_tab_enabled_product_option', 10);
+
+
+/**
+ * CSS To Add Custom tab Icon
+ */
+function wcpp_custom_style()
+{
+?>
+
+
+ __('License Info', 'slm-plus'),
+ 'target' => 'wc_slm_meta',
+ 'class' => array('show_if_slm_license', 'show_if_wc_slm_data_tab_enabled'),
+ );
+ return $wc_slm_data_tabs;
+}
+add_filter('woocommerce_product_data_tabs', 'wc_slm_add_tab');
+
+/**
+ * Custom WooCommerce Data Panel
+ */
+function wc_slm_data_panel()
+{
+ global $post;
+ $product_id = get_the_ID();
+ $slm_options = get_option('slm_plugin_options');
+?>
+
+
+ '_domain_licenses',
+ 'label' => __('Domain Licenses', 'slm-plus'),
+ 'placeholder' => SLM_Helper_Class::slm_get_option('default_max_domains'),
+ 'desc_tip' => 'true',
+ 'value' => $value,
+ 'type' => 'number',
+ 'custom_attributes' => array('step' => 'any', 'min' => 0),
+ 'description' => __('Enter the allowed number of domains this license can have (websites).', 'slm-plus')
+ ));
+
+ // Device Licenses Input
+ $value = get_post_meta($product_id, '_devices_licenses', true);
+ $value = ($value === '') ? SLM_Helper_Class::slm_get_option('default_max_devices') : $value;
+
+ woocommerce_wp_text_input(array(
+ 'id' => '_devices_licenses',
+ 'label' => __('Devices Licenses', 'slm-plus'),
+ 'placeholder' => SLM_Helper_Class::slm_get_option('default_max_devices'),
+ 'desc_tip' => 'true',
+ 'value' => $value,
+ 'type' => 'number',
+ 'custom_attributes' => array('step' => 'any', 'min' => 0),
+ 'description' => __('Enter the allowed number of devices this license can have (computers, mobile, etc).', 'slm-plus')
+ ));
+
+ // Item Reference Field (if enabled)
+ if (!empty($slm_options['slm_multiple_items']) && $slm_options['slm_multiple_items'] == 1) {
+ woocommerce_wp_text_input(array(
+ 'id' => '_license_item_reference',
+ 'label' => __('Item Reference', 'slm-plus'),
+ 'placeholder' => __("Software's item reference", 'slm-plus'),
+ 'desc_tip' => 'true',
+ 'description' => __('Enter the item reference of your application, theme, or plug-in. The license will be then bound to this exact software.', 'slm-plus')
+ ));
+ }
+
+ // License Type Dropdown
+ woocommerce_wp_select(array(
+ 'id' => '_license_type',
+ 'label' => __('License Type', 'slm-plus'),
+ 'desc_tip' => 'true',
+ 'description' => __('Type of license: subscription base or lifetime', 'slm-plus'),
+ 'options' => array(
+ 'none' => __('Select one', 'slm-plus'),
+ 'subscription' => __('Subscription', 'slm-plus'),
+ 'lifetime' => __('Lifetime', 'slm-plus'),
+ )
+ ));
+
+ // License Renewal Period Length
+ woocommerce_wp_text_input(array(
+ 'id' => '_license_renewal_period_length',
+ 'label' => __('Renewal Period Length', 'slm-plus'),
+ 'description' => __('XX Amount of days, months, or years.', 'slm-plus'),
+ 'type' => 'text',
+ 'value' => get_post_meta($product_id, '_license_renewal_period_length', true) ?: SLM_Helper_Class::slm_get_option('slm_billing_length'),
+ ));
+
+
+ // License Renewal Period Term Dropdown
+ woocommerce_wp_select(array(
+ 'id' => '_license_renewal_period_term',
+ 'label' => __('Expiration Term', 'slm-plus'),
+ 'placeholder' => 'select time frame',
+ 'description' => __('Choose between days, months, or years', 'slm-plus'),
+ 'options' => array(
+ 'days' => __('Day(s)', 'slm-plus'),
+ 'months' => __('Month(s)', 'slm-plus'),
+ 'years' => __('Year(s)', 'slm-plus'),
+ 'onetime' => __('One Time', 'slm-plus'),
+ ),
+ 'value' => get_post_meta($product_id, '_license_renewal_period_term', true) ?: SLM_Helper_Class::slm_get_option('slm_billing_interval'), // Ensure default value is set to 'years' if empty
+ ));
+
+ echo '
';
+
+ // Current Version Input
+ woocommerce_wp_text_input(array(
+ 'id' => '_license_current_version',
+ 'label' => __('Current Version', 'slm-plus'),
+ 'placeholder' => '0.0.0',
+ 'desc_tip' => 'true',
+ 'description' => __('Enter the current version of your application, theme, or plug-in', 'slm-plus')
+ ));
+
+ // Until Version Input
+ woocommerce_wp_text_input(array(
+ 'id' => '_license_until_version',
+ 'label' => __('Until Version', 'slm-plus'),
+ 'placeholder' => '0.0.0',
+ 'desc_tip' => 'true',
+ 'description' => __('Enter the version until support expires.', 'slm-plus')
+ ));
+ ?>
+
+
+
+
+ID);
+ if (!$order) {
+ echo '' . esc_html__('Order not found.', 'slm-plus') . '
';
+ return;
+ }
+
+ $order_id = $order->get_id();
+ $order_status = $order->get_status();
+
+ // Fetch license details from the database
+ $license_data = $wpdb->get_row(
+ $wpdb->prepare(
+ "SELECT license_key, lic_type FROM " . SLM_TBL_LICENSE_KEYS . " WHERE wc_order_id = %d LIMIT 1",
+ $order_id
+ )
+ );
+
+ $license_key = $license_data->license_key ?? '';
+ $license_type = $license_data->lic_type ?? '';
+
+ // Determine if a new license can be created based on the order status
+ $can_create_license = empty($license_key) && in_array($order_status, ['completed', 'processing']);
+
+ // Display license information if it exists
+ if (!empty($license_key)) {
+ $license_id = $wpdb->get_var(
+ $wpdb->prepare(
+ "SELECT id FROM " . SLM_TBL_LICENSE_KEYS . " WHERE license_key = %s LIMIT 1",
+ $license_key
+ )
+ );
+
+ if ($license_id) {
+ echo '' . esc_html__('License Key:', 'slm-plus') . ' ' . esc_html($license_key) . '
';
+ echo '' . esc_html__('License Type:', 'slm-plus') . ' ' . esc_html($license_type) . '
';
+ echo '' . esc_html__('A license key is already assigned to this order.', 'slm-plus') . '
';
+
+ // Link to view the license using its ID
+ $license_view_url = esc_url(admin_url('admin.php?page=slm_manage_license&edit_record=' . $license_id));
+ echo '' . esc_html__('View License', 'slm-plus') . ' ';
+ } else {
+ echo '' . esc_html__('License information could not be retrieved.', 'slm-plus') . '
';
+ }
+ }
+ elseif ($can_create_license) {
+ // Show license creation options for eligible orders
+ echo '' . esc_html__('License Type:', 'slm-plus') . ' ';
+ echo '
+ ' . esc_html__('Subscription', 'slm-plus') . '
+ ' . esc_html__('Lifetime', 'slm-plus') . '
+ ';
+
+ echo '' . esc_html__('Create License', 'slm-plus') . ' ';
+ } else {
+ // Informational message for ineligible orders
+ echo '' . esc_html__('Order must be completed or processing to create a license.', 'slm-plus') . '
';
+ echo '' . esc_html__('Create License', 'slm-plus') . ' ';
+ }
+
+?>
+
+
+ __('Invalid order ID', 'slm-plus')]);
+ }
+
+ // Fetch the WooCommerce order
+ $order = wc_get_order($order_id);
+ if (!$order || !in_array($order->get_status(), ['completed', 'processing'])) {
+ wp_send_json_error(['message' => __('Order must be completed or processing to create a license', 'slm-plus')]);
+ }
+
+ // Fetch necessary details from the order
+ $first_name = $order->get_billing_first_name();
+ $last_name = $order->get_billing_last_name();
+ $email = $order->get_billing_email();
+ $txn_id = $order->get_transaction_id();
+ $company_name = $order->get_billing_company();
+ $date_created = $order->get_date_created() ? $order->get_date_created()->date('Y-m-d') : current_time('mysql');
+ $user_id = $order->get_user_id();
+
+ // Default values from options
+ $slm_billing_length = SLM_API_Utility::get_slm_option('slm_billing_length');
+ $slm_billing_interval = SLM_API_Utility::get_slm_option('slm_billing_interval');
+ $default_domains = SLM_DEFAULT_MAX_DOMAINS;
+ $default_devices = SLM_DEFAULT_MAX_DEVICES;
+
+ // Determine expiration date
+ $date_expiry = $lic_type === 'lifetime'
+ ? date('Y-m-d', strtotime('+120 years', strtotime($date_created)))
+ : date('Y-m-d', strtotime("+$slm_billing_length $slm_billing_interval", strtotime($date_created)));
+
+ $licenses = [];
+ foreach ($order->get_items() as $item) {
+ $product_id = $item->get_product_id();
+ $product = wc_get_product($product_id);
+
+ if ($product && $product->is_type('slm_license')) {
+ // Fetch custom fields for the license
+ $product_data = [
+ 'current_ver' => get_post_meta($product_id, '_license_current_version', true),
+ 'until_ver' => get_post_meta($product_id, '_license_until_version', true),
+ 'max_devices' => get_post_meta($product_id, '_devices_licenses', true) ?: $default_devices,
+ 'max_domains' => get_post_meta($product_id, '_domain_licenses', true) ?: $default_domains,
+ 'item_reference' => get_post_meta($product_id, '_license_item_reference', true),
+ ];
+
+ // Generate a new license key
+ $new_license_key = slm_get_license(KEY_API_PREFIX);
+
+ // Insert the new license into the database
+ $wpdb->insert(SLM_TBL_LICENSE_KEYS, [
+ 'license_key' => $new_license_key,
+ 'wc_order_id' => $order_id,
+ 'product_ref' => $product_id,
+ 'txn_id' => $order_id,
+ 'purchase_id_' => $order_id,
+ 'subscr_id' => $user_id,
+ 'item_reference' => $product_data['item_reference'],
+ 'max_allowed_domains' => intval($product_data['max_domains']),
+ 'max_allowed_devices' => intval($product_data['max_devices']),
+ 'date_created' => $date_created,
+ 'date_expiry' => $date_expiry,
+ 'slm_billing_length' => intval($slm_billing_length),
+ 'slm_billing_interval' => sanitize_text_field($slm_billing_interval),
+ 'current_ver' => sanitize_text_field($product_data['current_ver']),
+ 'until' => sanitize_text_field($product_data['until_ver']),
+ 'lic_type' => sanitize_text_field($lic_type),
+ 'email' => sanitize_email($email),
+ 'first_name' => sanitize_text_field($first_name),
+ 'last_name' => sanitize_text_field($last_name),
+ 'company_name' => sanitize_text_field($company_name),
+ 'lic_status' => 'pending',
+ ]);
+
+ // Add the license key to the order note
+ $order->add_order_note(sprintf(__('License Key generated: %s', 'slm-plus'), $new_license_key));
+
+ // Collect license info for the response
+ $licenses[] = [
+ 'license_key' => $new_license_key,
+ 'product_name' => $product->get_name(),
+ ];
+ }
+ }
+
+ // Save the order after updating
+ $order->save();
+
+ // Send success response with license information
+ if (!empty($licenses)) {
+ wp_send_json_success([
+ 'message' => __('License created successfully', 'slm-plus'),
+ 'licenses' => $licenses,
+ ]);
+ } else {
+ wp_send_json_error(['message' => __('No licenses were generated', 'slm-plus')]);
+ }
+}
+
+
+add_action('wp_ajax_check_order_user_info', 'check_order_user_info_callback');
+function check_order_user_info_callback(){
+ check_ajax_referer('slm_generate_license_nonce', 'security');
+
+ $order_id = isset($_POST['order_id']) ? absint($_POST['order_id']) : null;
+ if (!$order_id) {
+ wp_send_json_error(['message' => __('Invalid order ID', 'slm-plus')]);
+ }
+
+ $order = wc_get_order($order_id);
+ if ($order) {
+ $last_name = $order->get_billing_last_name();
+ $email = $order->get_billing_email();
+ wp_send_json_success(['last_name' => $last_name, 'email' => $email]);
+ }
+ else {
+ wp_send_json_error(['message' => __('Order not found', 'slm-plus')]);
+ }
+}
diff --git a/woocommerce/includes/wc_licenses_class.php b/woocommerce/includes/wc_licenses_class.php
new file mode 100755
index 0000000..275c6b5
--- /dev/null
+++ b/woocommerce/includes/wc_licenses_class.php
@@ -0,0 +1,569 @@
+
+ * @link https://github.com/michelve/software-license-manager
+ */
+
+// If this file is called directly, abort.
+if (!defined('WPINC')) {
+ die();
+
+}
+
+//slm_woo_downloads
+function slm_remove_downloads_from_account_menu($items) {
+ // Remove "Downloads" menu item.
+ unset($items['downloads']);
+ return $items;
+}
+
+function slm_disable_downloads_endpoint_redirect() {
+ // Check if the current endpoint is "downloads" and if it's part of the My Account page.
+ if (is_wc_endpoint_url('downloads')) {
+ // Redirect to the My Account dashboard.
+ wp_safe_redirect(wc_get_page_permalink('myaccount'));
+ exit;
+ }
+}
+
+$enable_downloads_page = SLM_API_Utility::get_slm_option('slm_woo_downloads');
+// Check if the 'enable_downloads_page' option is enabled.
+if ($enable_downloads_page == 1) {
+ // If the option is set and enabled, trigger the action.
+ add_action('template_redirect', 'slm_disable_downloads_endpoint_redirect');
+ add_filter('woocommerce_account_menu_items', 'slm_remove_downloads_from_account_menu', 10);
+}
+
+
+// Register the endpoint and add it to WooCommerce’s query vars
+add_filter('woocommerce_get_query_vars', function($query_vars) {
+ $query_vars['my-licenses'] = 'my-licenses';
+ return $query_vars;
+});
+
+// Flush rewrite rules to ensure the endpoint is recognized on activation
+function slm_flush_rewrite_rules() {
+ flush_rewrite_rules();
+}
+register_activation_hook(__FILE__, 'slm_flush_rewrite_rules');
+
+//Add the My Licenses link to WooCommerce account menu
+function slm_add_my_licenses_endpoint($items) {
+ if (SLM_API_Utility::get_slm_option('slm_woo')) {
+ // Add "My Licenses" item just before "Log out"
+ $logout = $items['customer-logout']; // Store the "Log out" item
+ unset($items['customer-logout']); // Remove "Log out" temporarily
+
+ // Add "My Licenses" to the array
+ $items['my-licenses'] = __('My Licenses', 'slm-plus');
+
+ // Re-add "Log out" to the end
+ $items['customer-logout'] = $logout;
+ }
+
+ return $items;
+}
+add_filter('woocommerce_account_menu_items', 'slm_add_my_licenses_endpoint');
+
+//Display content based on endpoint value
+add_action('woocommerce_account_my-licenses_endpoint', function($value) {
+
+ //SLM_Helper_Class::write_log('slm_add_my_licenses_endpoint loaded');
+
+ if ($value === 'view') {
+ // Use $_GET instead of get_query_var to directly retrieve the URL parameter
+ $license_id = isset($_GET['slm_lic']) ? $_GET['slm_lic'] : false;
+ //SLM_Helper_Class::write_log('license_id var ' . $license_id);
+
+ if ($license_id) {
+ //SLM_Helper_Class::write_log('license_id call2 ' . $license_id);
+ slm_license_view($license_id);
+ }
+ else {
+ echo '' . esc_html__('Invalid license or access denied.', 'slm-plus') . '
';
+ //SLM_Helper_Class::write_log('user id ' . get_current_user_id());
+ }
+ } else {
+ // Display the licenses table if no specific value is passed
+ slm_display_license_table();
+ }
+});
+
+//Display the main licenses table
+function slm_display_license_table() {
+
+ //SLM_Helper_Class::write_log('slm_display_license_table loaded');
+
+ $user_id = get_current_user_id();
+ $user_email = wp_get_current_user()->user_email;
+
+ global $wpdb;
+
+ // Sanitize user inputs
+ $user_email = sanitize_email($user_email);
+ $user_id = intval($user_id);
+
+ // Directly using the constant table name as it's not possible to prepare table names
+ $table_name = SLM_TBL_LICENSE_KEYS; // Ensure that SLM_TBL_LICENSE_KEYS is defined as a constant
+
+ // Use prepare for query construction with placeholders for dynamic values
+ $query = $wpdb->prepare(
+ "SELECT DISTINCT license_key, purchase_id_, lic_status
+ FROM $table_name
+ WHERE email = %s OR subscr_id = %d",
+ $user_email, $user_id
+ );
+
+ // Execute the query safely
+ $licenses = $wpdb->get_results($query);
+
+
+ if ($licenses) {
+ echo '';
+ echo '';
+ echo '' . esc_html__('Order ID', 'slm-plus') . ' ';
+ echo '' . esc_html__('License Key', 'slm-plus') . ' ';
+ echo '' . esc_html__('Status', 'slm-plus') . ' ';
+ echo '' . esc_html__('Action', 'slm-plus') . ' ';
+ echo ' ';
+ echo '';
+
+ foreach ($licenses as $license) {
+ $order_id = $license->purchase_id_;
+ $license_key = $license->license_key;
+ $status = $license->lic_status;
+ $encoded_license = base64_encode($license_key);
+ $action_link = esc_url(add_query_arg(['my-licenses' => 'view', 'slm_lic' => $encoded_license], site_url('/my-account/my-licenses')));
+
+ echo '';
+
+ // Display Order ID or Custom Message
+ if (!empty($order_id)) {
+ echo '' . esc_html($order_id) . ' ';
+ } else {
+ echo '' . esc_html__('Manual', 'slm-plus') . ' ';
+ }
+
+ echo '' . esc_html($license_key) . ' ';
+
+ // Display the status with custom badge classes
+ echo '' . esc_html($status) . ' ';
+
+ echo '' . esc_html__('View', 'slm-plus') . ' ';
+ echo ' ';
+ }
+
+ echo ' ';
+ echo '
';
+ } else {
+ echo '' . esc_html__('No licenses found.', 'slm-plus') . '
';
+ }
+
+}
+
+
+add_action('wp_loaded', function () {
+ if (isset($_GET['renew_license']) && isset($_GET['product_id'])) {
+ // Sanitize inputs
+ $license_key = sanitize_text_field($_GET['renew_license']);
+ $product_id = absint($_GET['product_id']);
+
+ // Validate and process
+ if (!empty($license_key) && !empty($product_id)) {
+ slm_direct_renew_and_redirect($license_key, $product_id);
+ }
+ }
+});
+
+
+
+function slm_direct_renew_and_redirect($license_key, $product_id) {
+ // Ensure WooCommerce is loaded
+ if (!function_exists('wc_get_product')) {
+ error_log('WooCommerce is not loaded. Cannot process renewal.');
+ return;
+ }
+
+ // Prevent redirection loops by checking a custom flag
+ if (isset($_GET['redirected']) && $_GET['redirected'] === 'true') {
+ return; // Skip processing if already redirected
+ }
+
+ // Validate inputs
+ if (empty($license_key) || empty($product_id)) {
+ wc_add_notice(__('Invalid license or product.', 'slm-plus'), 'error');
+ return;
+ }
+
+ // Safely retrieve the product
+ $product = wc_get_product($product_id);
+ if (!$product || !$product->is_type('simple')) {
+ wc_add_notice(__('Invalid product for renewal.', 'slm-plus'), 'error');
+ return;
+ }
+
+ // Delay cart operations
+ add_action('woocommerce_cart_loaded_from_session', function () use ($license_key, $product_id) {
+ $cart_item_data = [
+ 'renew_license_key' => sanitize_text_field($license_key), // Attach the license key
+ ];
+ $added_to_cart = WC()->cart->add_to_cart($product_id, 1, 0, [], $cart_item_data);
+
+ if (!$added_to_cart) {
+ wc_add_notice(__('Failed to add product to cart.', 'slm-plus'), 'error');
+ return;
+ }
+
+ // Build the redirect URL with a 'redirected' flag
+ $redirect_url = add_query_arg([
+ 'renew_license' => $license_key,
+ 'product_id' => $product_id,
+ 'add-to-cart' => $product_id,
+ 'redirected' => 'true', // Add the flag to prevent loops
+ ], site_url('/license-cart')); // Update to your cart URL
+
+ // Redirect to the custom cart page
+ wp_safe_redirect($redirect_url);
+ exit;
+ });
+}
+
+add_action('woocommerce_before_cart', function() {
+ WC()->cart->get_cart_contents_count(); // Total cart items
+ error_log(print_r(WC()->cart->get_cart(), true)); // Logs all cart items
+});
+
+
+
+
+
+
+// Example usage with enhanced safety checks
+// Example usage with enhanced safety checks
+add_action('init', function () {
+ if (isset($_GET['renew_license']) && isset($_GET['product_id'])) {
+ // Ensure WooCommerce is active
+ if (!function_exists('wc_get_product')) {
+ if (!is_plugin_active('woocommerce/woocommerce.php')) {
+ error_log('WooCommerce is not active. Please enable it to use the SLM Plus plugin.');
+ return;
+ }
+ }
+
+ // Sanitize input values
+ $license_key = sanitize_text_field($_GET['renew_license']);
+ $product_id = absint($_GET['product_id']);
+
+ // Validate required values
+ if (!empty($license_key) && !empty($product_id)) {
+ // Start WooCommerce session if not already initialized
+ if (!WC()->session) {
+ WC()->initialize_session_handler();
+ WC()->session = new WC_Session_Handler();
+ WC()->session->init();
+ error_log('WooCommerce session initialized.');
+ }
+
+ // Store license key in session for later use in checkout
+ WC()->session->set('renew_license_key', $license_key);
+
+ // Log for debugging
+ SLM_Helper_Class::write_log("Renew license key set in session during redirect: {$license_key}");
+
+ // Redirect or process renewal
+ slm_direct_renew_and_redirect($license_key, $product_id);
+ } else {
+ error_log('Missing or invalid license key or product ID for renewal.');
+ }
+ }
+});
+
+
+
+// Step 5: Display individual license details
+function slm_license_view($encoded_license_id) {
+ global $wpdb;
+ $user_email = wp_get_current_user()->user_email;
+ $user_id = get_current_user_id();
+
+ // Decode the license key and trim any whitespace
+ $license_id = trim(base64_decode($encoded_license_id));
+
+ // Log the decoded license key, user email, and user ID
+ //SLM_Helper_Class::write_log('Decoded License Key: ' . $license_id);
+ //SLM_Helper_Class::write_log('User Email: ' . $user_email);
+ //SLM_Helper_Class::write_log('User ID (subscr_id): ' . $user_id);
+
+ // Construct the query based on whether user ID is available
+ if ($user_id) {
+ $query = $wpdb->prepare(
+ "SELECT * FROM " . SLM_TBL_LICENSE_KEYS . " WHERE (email = %s OR subscr_id = %d) AND license_key = %s",
+ $user_email, $user_id, $license_id
+ );
+ } else {
+ $query = $wpdb->prepare(
+ "SELECT * FROM " . SLM_TBL_LICENSE_KEYS . " WHERE email = %s AND license_key = %s",
+ $user_email, $license_id
+ );
+ }
+
+ // Log the SQL query for debugging
+ //SLM_Helper_Class::write_log('SQL Query: ' . $query);
+
+ // Execute the query
+ $license = $wpdb->get_row($query);
+
+ // Check if license was found
+ if (!$license) {
+ echo '' . esc_html__('Invalid license or access denied.', 'slm-plus') . '
';
+ //SLM_Helper_Class::write_log('error');
+ return;
+ }
+
+ // Back Button with dynamic URL generation
+ $back_url = wc_get_account_endpoint_url('my-licenses');
+ echo '' . esc_html__('Back to My Licenses', 'slm-plus') . ' ';
+
+ // Define the fields and labels for dynamic generation
+ $slm_license_fields = [
+ 'license_key' => __('License Key', 'slm-plus'),
+ 'lic_status' => __('Status', 'slm-plus'),
+ 'lic_type' => __('License Type', 'slm-plus'),
+ 'purchase_id_' => __('Order ID', 'slm-plus'),
+ 'date_created' => __('Date Created', 'slm-plus'),
+ 'date_activated' => __('Date Activated', 'slm-plus'),
+ 'date_renewed' => __('Date Renewed', 'slm-plus'),
+ 'date_expiry' => __('Date Expiry', 'slm-plus'),
+ 'product_ref' => __('Product Reference', 'slm-plus'),
+ 'subscr_id' => __('Subscription ID', 'slm-plus'),
+ 'subscr_id' => __('Subscription ID', 'slm-plus'),
+ 'max_allowed_domains' => __('Max Allowed Domains', 'slm-plus'),
+ 'associated_orders' => __('Associated Orders', 'slm-plus'),
+ 'company_name' => __('Company Name', 'slm-plus'),
+ ];
+
+ // Display license details header
+ echo '' . esc_html__('License Details', 'slm-plus') . ' ';
+ echo '';
+ echo '';
+
+ // Loop through each field and output its label and value dynamically
+ foreach ($slm_license_fields as $field_key => $field_label) {
+ // Check if the field is set and get the value
+ $field_value = isset($license->$field_key) ? esc_html($license->$field_key) : '';
+
+
+ // Special handling for purchase_id_ to link to the order
+ if ($field_key === 'purchase_id_') {
+ if (!empty($field_value)) {
+ // Generate the link to the specific order in the My Account section
+ $order_link = wc_get_account_endpoint_url('view-order/' . $field_value);
+ $field_value = '' . esc_html($field_value) . ' ';
+ } else {
+ $field_value = __('No Order Information Available', 'slm-plus');
+ }
+ }
+
+
+ if ($field_key === 'associated_orders') {
+ if (!empty($field_value)) {
+ // Fetch the associated orders using the provided function
+ $associated_orders = SLM_Utility::slm_get_associated_orders($license->license_key);
+
+ // Debugging: Log the retrieved value
+ SLM_Helper_Class::write_log('Associated Orders Raw Data: ' . print_r($associated_orders, true));
+
+ if (!empty($associated_orders) && is_array($associated_orders)) {
+ $links = [];
+ foreach ($associated_orders as $order_id) {
+ // Generate a link to the WooCommerce account orders page
+ $order_url = wc_get_endpoint_url('view-order', $order_id, wc_get_page_permalink('myaccount'));
+ $links[] = sprintf(
+ '#%s ',
+ esc_url($order_url), // Sanitize the URL
+ esc_html($order_id) // Escape and sanitize the order ID
+ );
+ }
+
+ // Join all links with a comma for display
+ $field_value = implode(', ', $links);
+ } else {
+ $field_value = __('No Associated Orders Found (Data Issue)', 'slm-plus');
+ }
+ } else {
+ $field_value = __('No Order Information Available', 'slm-plus');
+ }
+ }
+
+
+
+ if ($field_key === 'lic_status') {
+ $license_key = isset($license->license_key) ? esc_html($license->license_key) : '';
+ $purchase_id = isset($license->purchase_id_) ? absint($license->purchase_id_) : 0;
+
+ // Ensure date_expiry is checked safely
+ $expiration_date = isset($license->date_expiry) ? strtotime($license->date_expiry) : false;
+
+ // Determine if the license is expired
+ $is_expired = (!empty($expiration_date) && $expiration_date < time()) || $license->lic_status === 'expired';
+
+ if ($is_expired && !empty($license_key) && !empty($purchase_id)) {
+ $product_id = 0; // Initialize product_id
+
+ // Ensure WooCommerce functions are available
+ if (!function_exists('wc_get_order')) {
+ // Include WooCommerce files to make functions accessible
+ if (defined('WC_ABSPATH')) {
+ include_once WC_ABSPATH . 'includes/wc-order-functions.php';
+ include_once WC_ABSPATH . 'includes/wc-product-functions.php';
+ } else {
+ // If WooCommerce is not loaded, skip further processing
+ $field_value = sprintf(
+ '%s %s ',
+ __('Expired', 'slm-plus'),
+ __('WooCommerce not loaded.', 'slm-plus')
+ );
+ return;
+ }
+ }
+
+ // Retrieve the product ID associated with the license
+ $order = wc_get_order($purchase_id);
+
+ // Ensure order is valid and contains items
+ if ($order) {
+ $items = $order->get_items();
+ $product_id = $items ? current($items)->get_product_id() : 0;
+ }
+
+ if (!empty($product_id)) {
+ // Generate the renewal URL
+ $renew_url = add_query_arg([
+ 'renew_license' => $license_key,
+ 'product_id' => $product_id,
+ ], site_url('/my-account/my-licenses'));
+
+ // Update field value to include Renew button
+ $field_value = sprintf(
+ '%s %s ',
+ __('Expired', 'slm-plus'),
+ esc_url($renew_url),
+ __('Renew', 'slm-plus')
+ );
+ } else {
+ // Handle missing product ID case (e.g., display a warning)
+ $field_value = sprintf(
+ '%s %s ',
+ __('Expired', 'slm-plus'),
+ __('Product not found for renewal.', 'slm-plus')
+ );
+ }
+ }
+ }
+
+ // Special handling for product_ref to link to the product page
+ if ($field_key === 'product_ref') {
+ if (!empty($field_value)) {
+ // Retrieve the product URL and name by product ID
+ $product_id = $field_value;
+ $product_url = get_permalink($product_id);
+ $product_name = get_the_title($product_id);
+
+ if ($product_url && $product_name) {
+ // Format as "#ID - ProductName"
+ $field_value = sprintf(
+ '#%s - %s ',
+ esc_url($product_url), // Sanitize the URL
+ esc_html($product_id), // Escape and sanitize the product ID
+ esc_html($product_name) // Escape and sanitize the product name
+ );
+ } else {
+ $field_value = __('Product Not Found', 'slm-plus');
+ }
+ } else {
+ $field_value = __('No Product Information Available', 'slm-plus');
+ }
+ }
+
+ // Special handling for date fields with '0000-00-00' as value
+ if (($field_key === 'date_activated' || $field_key === 'date_renewed') && $field_value === '0000-00-00') {
+ $field_value = ($field_key === 'date_activated') ? __('Not activated yet', 'slm-plus') : __('Not renewed yet', 'slm-plus');
+ }
+
+ echo '' . esc_html($field_label) . ' ' . $field_value . ' ';
+ }
+ echo ' ';
+ echo '
';
+
+
+ global $wpdb;
+
+ // Define the license key for querying activations
+ $license_key = $license->license_key;
+
+ // Fetch all domain and device activations associated with the license key
+ $domains = $wpdb->get_results($wpdb->prepare(
+ "SELECT id, 'domain' AS type, registered_domain AS origin FROM " . SLM_TBL_LIC_DOMAIN . " WHERE lic_key = %s",
+ $license_key
+ ));
+
+ $devices = $wpdb->get_results($wpdb->prepare(
+ "SELECT id, 'device' AS type, registered_devices AS origin FROM " . SLM_TBL_LIC_DEVICES . " WHERE lic_key = %s",
+ $license_key
+ ));
+
+ // Merge domains and devices into a single array
+ $activations = array_merge($domains, $devices);
+
+ // Display the "Activations" section header
+ echo '' . esc_html__('Activations', 'slm-plus') . ' ';
+
+ // Check if there are any activations
+ if (empty($activations)) {
+ echo '' . esc_html__('No activations found.', 'slm-plus') . '
';
+ } else {
+ // Display the table header if activations exist
+ echo '';
+ echo '' . esc_html__('ID', 'slm-plus') . ' ' . esc_html__('Type', 'slm-plus') . ' ' . esc_html__('Origin', 'slm-plus') . ' ' . esc_html__('Action', 'slm-plus') . ' ';
+ echo '';
+
+ // Loop through each activation and display in the table
+ foreach ($activations as $activation) {
+ echo '';
+ echo '' . esc_html($activation->id) . ' ';
+ echo '' . esc_html(ucfirst($activation->type)) . ' ';
+ echo '' . esc_html($activation->origin) . ' ';
+ echo '';
+ echo ' ';
+ echo ' ';
+ echo '' . esc_html__('Delete', 'slm-plus') . ' ';
+ echo ' ';
+ echo ' ';
+ }
+
+ echo ' ';
+ echo '
';
+
+ }
+
+ // Handle the deletion request
+ if (isset($_POST['delete_activation'])) {
+ $activation_id = intval($_POST['activation_id']);
+ $activation_type = sanitize_text_field($_POST['activation_type']);
+
+ // Determine the table based on the activation type
+ $table = ($activation_type === 'domain') ? SLM_TBL_LIC_DOMAIN : SLM_TBL_LIC_DEVICES;
+
+ // Delete the activation record from the relevant table
+ $deleted = $wpdb->delete($table, ['id' => $activation_id], ['%d']);
+
+ // Display a confirmation or error message
+ if ($deleted) {
+ echo '' . esc_html__('Activation successfully deleted. Reload Page.', 'slm-plus') . '
';
+ } else {
+ echo '' . esc_html__('Failed to delete activation. Please try again.', 'slm-plus') . '
';
+ }
+
+ }
+}
diff --git a/woocommerce/single-product/add-to-cart/slm_license.php b/woocommerce/single-product/add-to-cart/slm_license.php
new file mode 100644
index 0000000..30676eb
--- /dev/null
+++ b/woocommerce/single-product/add-to-cart/slm_license.php
@@ -0,0 +1,63 @@
+is_purchasable()) {
+ return;
+}
+
+echo wc_get_stock_html($product); // Display stock status if applicable.
+
+if ($product->is_in_stock()) :
+ // Determine if this is a renewal (renew_license_key present in URL).
+ $is_renewal = isset($_GET['renew_license_key']) && !empty($_GET['renew_license_key']);
+ $renew_license_key = $is_renewal ? sanitize_text_field($_GET['renew_license_key']) : '';
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ apply_filters('woocommerce_quantity_input_min', $product->get_min_purchase_quantity(), $product),
+ 'max_value' => apply_filters('woocommerce_quantity_input_max', $product->get_max_purchase_quantity(), $product),
+ 'input_value' => isset($_POST['quantity']) ? wc_stock_amount(wp_unslash($_POST['quantity'])) : $product->get_min_purchase_quantity(), // CSRF ok.
+ )
+ );
+ do_action('woocommerce_after_add_to_cart_quantity');
+ ?>
+
+
+
+
+ single_add_to_cart_text()); ?>
+
+
+
+
+
+
+
+