Skip to content

Commit

Permalink
Add custom block category "SLM Plus" and improve shortcode blocks
Browse files Browse the repository at this point in the history
feat: Add custom block category "SLM Plus" and improve shortcode blocks

- Registered a new block category "SLM Plus" for better organization.
- Updated "Forgot License" and "List Licenses" blocks to assign them to the custom category.
- Improved block editor previews for both blocks:
  - "Forgot License" block displays a preview with a form placeholder.
  - "List Licenses" block displays a preview with a sample list of licenses.
- Fixed issues with blocks appearing under "Uncategorized" by ensuring proper category registration.
- Ensured unique naming in block scripts to avoid conflicts.
- Added clear styles for block previews and frontend rendering in `slm-blocks.css`.
- Verified shortcode functionality for rendering licenses dynamically.
  • Loading branch information
michelve committed Dec 6, 2024
1 parent 3d6a5b3 commit f1918eb
Show file tree
Hide file tree
Showing 8 changed files with 543 additions and 2 deletions.
25 changes: 25 additions & 0 deletions includes/slm-blocks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

// If this file is called directly, abort.
if (!defined('WPINC')) {
die();
}

// Register block editor assets.
add_action('enqueue_block_editor_assets', function () {
wp_enqueue_script(
'slm-blocks-js',
SLM_ASSETS_URL . 'js/slm-blocks.js',
['wp-blocks', 'wp-editor', 'wp-element', 'wp-i18n'], // Dependencies.
SLM_VERSION,
true
);

wp_enqueue_style(
'slm-blocks-style',
SLM_ASSETS_URL . 'css/slm-blocks.css',
[],
SLM_VERSION
);
});

7 changes: 7 additions & 0 deletions includes/slm-plugin-core.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<?php

// If this file is called directly, abort.
if (!defined('WPINC')) {
die();
}

/**
*
* @package SLM Plus
Expand All @@ -20,6 +25,8 @@
require_once(SLM_LIB . 'slm-init-time-tasks.php');
require_once(SLM_LIB . 'slm-api-listener.php');
require_once(SLM_LIB . 'slm-scripts.php');
require_once(SLM_LIB . 'slm-shortcodes.php');
require_once(SLM_LIB . 'slm-blocks.php');

// Admin-only includes
if (is_admin()) {
Expand Down
287 changes: 287 additions & 0 deletions includes/slm-shortcodes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
<?php

// If this file is called directly, abort.
if (!defined('WPINC')) {
die();
}

// If this file is called directly, abort.
if (!defined('WPINC')) {
die();
}

if (!defined('HOUR_IN_SECONDS')) {
define('HOUR_IN_SECONDS', 3600);
}


add_action('admin_init', function () {
if (is_user_logged_in() && current_user_can('manage_options') && isset($_GET['slm_clear_transients'])) {
global $wpdb;
$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);

add_action('admin_notices', function () {
echo '<div class="notice notice-success"><p>All rate-limiting transients have been cleared.</p></div>';
});
}
});


// 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 '<p>Invalid request. Please try again.</p>';
}

// Sanitize and validate email.
$email = sanitize_email($_POST['slm_forgot_license_email']);
if (!is_email($email)) {
return apply_filters('slm_invalid_email_message', '<p>Invalid email address.</p>');
}

// Rate limiting: prevent repeated submissions from the same IP.
$ip = $_SERVER['REMOTE_ADDR'];
if ($this->is_rate_limited($ip)) {
return '<p>You are submitting requests too quickly. Please try again later.</p>';
}

// 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', '<p>Your licenses have been sent to your email.</p>');
}

return apply_filters('slm_no_license_message', '<p>No licenses found for the provided email.</p>');
}

/**
* 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();
?>
<form method="POST" class="slm-forgot-license-form">
<label for="slm_email"><?php echo esc_html(apply_filters('slm_form_label', 'Enter your email address:')); ?></label>
<input type="email" id="slm_email" name="slm_forgot_license_email" required>
<?php wp_nonce_field('slm_forgot_license_action', 'slm_forgot_license_nonce'); ?>
<button type="submit"><?php echo esc_html(apply_filters('slm_form_button_text', 'Retrieve License')); ?></button>
</form>
<?php
return ob_get_clean();
}
}


class SLM_List_Licenses_FE {
/**
* Initialize the class and hooks.
*/
public function __construct() {
// Register shortcode.
add_shortcode('slm_list_licenses', [$this, 'render_shortcode']);
}

/**
* Render the shortcode.
*
* @return string
*/
public function render_shortcode() {
// Check if the user is logged in.
if (!is_user_logged_in()) {
return '<p>' . __('You must be logged in to view your licenses.', 'slm-plus') . '</p>';
}

// 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', '<p>' . __('No licenses found for your account.', 'slm-plus') . '</p>');
}

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();
?>
<table class="slm-licenses-table">
<thead>
<tr>
<th><?php echo esc_html(__('License Key', 'slm-plus')); ?></th>
<th><?php echo esc_html(__('Product', 'slm-plus')); ?></th>
<th><?php echo esc_html(__('Status', 'slm-plus')); ?></th>
<th><?php echo esc_html(__('Activated On', 'slm-plus')); ?></th>
<th><?php echo esc_html(__('Expiry Date', 'slm-plus')); ?></th>
<th><?php echo esc_html(__('Max Domains', 'slm-plus')); ?></th>
<th><?php echo esc_html(__('Max Devices', 'slm-plus')); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($licenses as $license): ?>
<tr>
<td><?php echo esc_html($license['license_key']); ?></td>
<td><?php echo esc_html($license['product_ref']); ?></td>
<td><?php echo esc_html($license['lic_status']); ?></td>
<td><?php echo esc_html($license['date_activated'] ?: __('N/A', 'slm-plus')); ?></td>
<td><?php echo esc_html($license['date_expiry'] ?: __('N/A', 'slm-plus')); ?></td>
<td><?php echo esc_html($license['max_allowed_domains']); ?></td>
<td><?php echo esc_html($license['max_allowed_devices']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php
return ob_get_clean();
}
}

// Initialize
new SLM_Forgot_License();
new SLM_List_Licenses_FE();

14 changes: 14 additions & 0 deletions includes/slm-utility.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ static function console($data)

class SLM_API_Utility
{

/*
* The args array can contain the following:
* result (success or error)
Expand Down Expand Up @@ -189,6 +190,19 @@ public static function insert_license_data_internal($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.
*/
Expand Down
Loading

0 comments on commit f1918eb

Please sign in to comment.