diff --git a/.svnignore b/.svnignore index 78b5422..29bc5dc 100644 --- a/.svnignore +++ b/.svnignore @@ -8,4 +8,6 @@ LICENSE.md README.md composer.json tests +docs +TODO.md *composer.lock" . \ No newline at end of file diff --git a/README.md b/README.md index 5a948f8..1ad3b81 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ This plugin improves the login look for the website and defaults to the page log * Just activating it already adds personality to the login * Choose from pre-designed themes to instantly transform your login page * Create your own custom theme with the Style Builder +* User-friendly feedback system for continuous improvement ## Features @@ -44,9 +45,40 @@ This plugin improves the login look for the website and defaults to the page log * Fine-tune borders, margins, and padding * Live preview of changes +### User Feedback +* Unobtrusive review request system for administrators +* Helps improve the plugin through user suggestions +* Fully dismissible with permanent opt-out + ## Frequently Asked Questions [Link Wiki](https://github.com/AWP-Software/Login-AWP_WordPress_Plugin/wiki/Frequently-Asked-Questions) +## Changelog + +### 3.1.0 +* Added user feedback system for administrators to help improve the plugin +* Enhanced compatibility with older PHP versions +* Fixed various minor styling issues + +### 3.0.0 +* Added theme selection system with pre-designed layouts +* Visual Style Builder for advanced customization +* Custom fonts, colors, spacing, and border settings + +### 2.1.0 +* Added status notifications for image updates +* Added Spanish language translation + +### 2.0.0 +* Plugin moved to Appearance menu for easier access +* Added logo and background image customization + +### 1.1.0 +* Fixed: Automatically display custom site icon on login page if available + +### 1.0.0 +* Initial stable release + ## About [Vegas2 JS](https://vegas.jaysalvat.com/) diff --git a/assets/banner-772x250.png b/assets/banner-772x250.png index 9a741e4..1fef0ed 100644 Binary files a/assets/banner-772x250.png and b/assets/banner-772x250.png differ diff --git a/assets/icon-128x128.png b/assets/icon-128x128.png index b771e6e..1ab2e0f 100644 Binary files a/assets/icon-128x128.png and b/assets/icon-128x128.png differ diff --git a/assets/icon-256x256.png b/assets/icon-256x256.png new file mode 100644 index 0000000..373bc45 Binary files /dev/null and b/assets/icon-256x256.png differ diff --git a/trunk/assets/css/feedback-modal.css b/trunk/assets/css/feedback-modal.css new file mode 100644 index 0000000..c5532af --- /dev/null +++ b/trunk/assets/css/feedback-modal.css @@ -0,0 +1,96 @@ +/** + * Feedback Modal Styles for Login AWP + */ +#login-awp-feedback-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 999999; + display: flex; + align-items: center; + justify-content: center; +} + +.login-awp-feedback-modal-content { + background-color: #fff; + border-radius: 4px; + box-shadow: 0 2px 30px rgba(0, 0, 0, 0.3); + width: 550px; + max-width: 90%; + padding: 20px 30px; + position: relative; + max-height: 90vh; + overflow-y: auto; +} + +.login-awp-feedback-modal-content h2 { + margin-top: 0; + color: #23282d; + border-bottom: 1px solid #eee; + padding-bottom: 15px; +} + +.login-awp-feedback-options { + margin-bottom: 20px; +} + +.login-awp-feedback-options label { + display: block; + margin-bottom: 10px; + padding: 10px; + background: #f9f9f9; + border-radius: 3px; +} + +.login-awp-feedback-options label:hover { + background: #f5f5f5; +} + +.login-awp-feedback-info { + margin-top: 8px; + width: 100%; + display: block; +} + +.login-awp-feedback-info.hidden { + display: none; +} + +.login-awp-anonymous-feedback { + margin-bottom: 15px; + padding: 10px; + background: #f9f9f9; + border-radius: 3px; +} + +.login-awp-anonymous-feedback .description { + color: #666; + font-style: italic; + margin: 5px 0 0 24px; +} + +.login-awp-feedback-actions { + text-align: right; + margin-top: 20px; + padding-top: 15px; + border-top: 1px solid #eee; +} + +.login-awp-feedback-actions button { + margin-left: 10px; +} + +textarea.login-awp-feedback-info { + min-height: 80px; + resize: vertical; +} + +input[type="text"].login-awp-feedback-info, +textarea.login-awp-feedback-info { + padding: 8px; + margin-left: 24px; + width: calc(100% - 24px); +} \ No newline at end of file diff --git a/trunk/assets/js/feedback-modal.js b/trunk/assets/js/feedback-modal.js new file mode 100644 index 0000000..63b88e2 --- /dev/null +++ b/trunk/assets/js/feedback-modal.js @@ -0,0 +1,210 @@ +/** + * Feedback Modal JavaScript for Login AWP + * + * Handles the deactivation feedback modal functionality + */ +(function($) { + 'use strict'; + + // Initialize once DOM is fully loaded + $(function() { + // Make sure we have the proper AJAX URL from the localized script + const ajaxUrl = loginAwpFeedback.ajax_url || window.ajaxurl || '/wp-admin/admin-ajax.php'; + + const pluginSlug = loginAwpFeedback.plugin_slug; + const baseSlug = pluginSlug.split('/')[0]; + + // Set up for deactivation link + setupDeactivationFeedback(); + + /** + * Set up feedback for deactivation + */ + function setupDeactivationFeedback() { + const pluginRow = $('tr[data-slug="' + baseSlug + '"]'); + const deactivateLink = pluginRow.find('.deactivate a'); + + if (deactivateLink.length) { + const originalDeactivateLink = deactivateLink.attr('href'); + + // Replace the default deactivation action with our modal trigger + deactivateLink.on('click', function(e) { + e.preventDefault(); + showModal(originalDeactivateLink, 'deactivate'); + }); + } + } + + /** + * Show the feedback modal + * @param {string} actionUrl - The URL to redirect to after submission + * @param {string} actionType - 'deactivate' + */ + function showModal(actionUrl, actionType) { + $('#login-awp-feedback-modal').show(); + + // Update modal title and text + $('#login-awp-feedback-title').text(loginAwpFeedback.translations.heading || 'Quick Feedback'); + $('#login-awp-feedback-intro').text(loginAwpFeedback.translations.intro || 'If you have a moment, please let us know why you are deactivating Login AWP:'); + $('#login-awp-skip-feedback').text(loginAwpFeedback.translations.skip || 'Skip & Deactivate'); + $('#login-awp-submit-feedback').text(loginAwpFeedback.translations.submit || 'Submit & Deactivate'); + + // Store the action URL for form submission + $('#login-awp-feedback-form').data('actionUrl', actionUrl); + + setupModalEvents(); + } + + /** + * Set up event listeners for the modal + */ + function setupModalEvents() { + // Remove existing event handlers to prevent duplicates + $('#login-awp-feedback-form').off('submit'); + $('#login-awp-skip-feedback').off('click'); + $('#login-awp-cancel-feedback').off('click'); + $('input[name="reason"]').off('change'); + + const form = $('#login-awp-feedback-form'); + const actionUrl = form.data('actionUrl'); + + // Process form submission + form.on('submit', function(e) { + e.preventDefault(); + submitFeedback(); + }); + + // Skip feedback and proceed directly + $('#login-awp-skip-feedback').on('click', function() { + window.location.href = actionUrl; + }); + + // Close modal when clicking cancel + $('#login-awp-cancel-feedback').on('click', function() { + closeModal(); + }); + + // Show/hide additional fields based on selected reason + $('input[name="reason"]').on('change', function() { + // Hide all detail fields first + $('.login-awp-feedback-info').addClass('hidden'); + + // Show the specific detail field if needed + const reason = $(this).val(); + switch(reason) { + case 'found_better_plugin': + $('input[name="better_plugin"]').removeClass('hidden'); + break; + case 'not_working': + $('textarea[name="not_working_details"]').removeClass('hidden'); + break; + case 'other': + $('textarea[name="other_details"]').removeClass('hidden'); + break; + } + }); + + // Close on clicking outside the modal + $(window).on('click', function(e) { + if ($(e.target).is('#login-awp-feedback-modal')) { + closeModal(); + } + }); + + // Close on ESC key + $(document).on('keydown', function(e) { + if (e.keyCode === 27) { // ESC key + closeModal(); + } + }); + } + + /** + * Submit the feedback form via AJAX + */ + function submitFeedback() { + const form = $('#login-awp-feedback-form'); + const actionUrl = form.data('actionUrl'); + let reason = form.find('input[name="reason"]:checked').val(); + const includeEmail = form.find('input[name="include_email"]').is(':checked'); + + // If no reason selected but email is included, set default reason to "no context" + if (!reason && includeEmail) { + reason = 'no context'; + } else if (!reason) { + // If no reason selected and no email, just proceed with action + window.location.href = actionUrl; + return; + } + + // Collect additional details if provided + let details = ''; + if (reason === 'found_better_plugin') { + details = form.find('input[name="better_plugin"]').val(); + } else if (reason === 'not_working') { + details = form.find('textarea[name="not_working_details"]').val(); + } else if (reason === 'other') { + details = form.find('textarea[name="other_details"]').val(); + } + + // Prepare the data to send + const data = { + action: 'login_awp_submit_feedback', + nonce: loginAwpFeedback.nonce, + reason: reason, + action_type: 'deactivate' + }; + + // Add additional data if provided + if (details) { + if (reason === 'found_better_plugin') { + data.better_plugin = details; + } else if (reason === 'not_working') { + data.not_working_details = details; + } else if (reason === 'other') { + data.other_details = details; + } + } + + // Include email if checkbox is checked + if (includeEmail) { + data.include_email = '1'; + } + + // Show submitting state + const submitButton = $('#login-awp-submit-feedback'); + const originalText = submitButton.text(); + submitButton.text(loginAwpFeedback.translations.submitting || 'Submitting...'); + submitButton.prop('disabled', true); + + // Use a try-catch block to handle AJAX errors + try { + // Send the data to the correct AJAX URL + $.post(ajaxUrl, data) + .done(function(response) { + // After submitting feedback, proceed with action + window.location.href = actionUrl; + }) + .fail(function(xhr, textStatus, errorThrown) { + // Log error details for debugging but still proceed with action + console.error('Feedback submission failed:', textStatus, errorThrown); + // Still proceed with the requested action even if feedback fails + window.location.href = actionUrl; + }); + } catch(e) { + // If any error occurs, still proceed with the action + console.error('Error during feedback submission:', e); + window.location.href = actionUrl; + } + } + + /** + * Close and reset the feedback modal + */ + function closeModal() { + $('#login-awp-feedback-modal').hide(); + $('#login-awp-feedback-form')[0].reset(); + $('.login-awp-feedback-info').addClass('hidden'); + } + }); +})(jQuery); \ No newline at end of file diff --git a/trunk/login_awp.php b/trunk/login_awp.php index 26bf269..310130e 100755 --- a/trunk/login_awp.php +++ b/trunk/login_awp.php @@ -6,7 +6,7 @@ * Plugin Name: Login AWP * Plugin URI: https://wordpress.org/plugins/login-awp * Description: This plugin modifies the login area for WordPress admin - * Version: 3.0.0 + * Version: 3.2.1 * Requires at least: 5.4 * Requires PHP: 7.4 * Author: AWP-Software @@ -18,12 +18,21 @@ * https://www.gnu.org/licenses/gpl-3.0.html */ - -if (!defined(constant_name: 'ABSPATH')) { +if (!defined('ABSPATH')) { die('You are not allowed to call this page directly.'); } +// Define plugin constants (previously in settings.php) +if (!defined('AWP_LOGIN_FEEDBACK_EMAIL')) { + define('AWP_LOGIN_FEEDBACK_EMAIL', 'support@awp-software.com'); +} + +if (!defined('AWP_LOGIN_FEEDBACK_WEBHOOK')) { + define('AWP_LOGIN_FEEDBACK_WEBHOOK', 'https://telemetry.awp-software.com/feedback'); +} + require_once __DIR__ . '/vendor/autoload.php'; +// settings.php is now integrated directly in this file use Login\Awp\Register; diff --git a/trunk/readme.txt b/trunk/readme.txt index ce6571a..01af45c 100644 --- a/trunk/readme.txt +++ b/trunk/readme.txt @@ -1,82 +1,113 @@ === Login AWP === Contributors: alexanderwp Donate link: https://www.paypal.com/donate/?hosted_button_id=32A55GWU7JKY4 -Tags: login, customize, custom login +Tags: login, custom login, login page, login branding, style builder Requires at least: 5.4 Tested up to: 6.8 -Stable tag: 3.0.0 +Stable tag: 3.2.1 Requires PHP: 7.4 +Support link: https://awp-software.com/docs-category/login-awp-plugin/ License: GPLv3 or later -License URI: https://www.gnu.org/licenses/gpl-3.0.html +License URI: https://www.gnu.org/licenses/gpl-3.0.html -This plugin improves the login look for the website and defaults to the page logo. +Customize your WordPress login page with themes, logos, and styles. Fast, lightweight, and built for a polished first impression. == Description == -This plugin improves the login look for the website and defaults to the page logo +**Login AWP** enhances the default WordPress login page with powerful customization features: -* Add a background image with transitions -* Put the main logo of the website -* Responsive -* Just activating it already adds personality to the login -* Choose from pre-designed themes to instantly transform your login page -* Create your own custom theme with the Style Builder +- Add a custom background image with transitions +- Display your website's logo automatically +- Choose from pre-designed login themes +- Customize colors, fonts, borders, and spacing using the visual Style Builder +- Fully responsive and retina-ready design +- Seamless integration under the WordPress "Appearance" menu +- Lightweight and fast +- Translation-ready (includes Spanish) +- User-friendly feedback system for continuous improvement +- Plugin deactivation feedback to help us improve -== Frequently Asked Questions == +Whether you manage a client site, a brand, or a community platform, Login AWP lets you deliver a professional first impression — effortlessly. + +== Installation == -= Can I change the background image? = +1. Upload the plugin files to the `/wp-content/plugins/login-awp/` directory, or install the plugin through the WordPress Plugin Directory. +2. Activate the plugin through the "Plugins" menu. +3. Navigate to **Appearance → Login AWP** to start customizing your login screen. -Yes, now you can do it from the "log in" option in the appearance menu. +== Frequently Asked Questions == -= What happens if I don't have a logo? = += Can I change the background image? = +Yes. Go to **Appearance → Login AWP**, then select the "Background" tab to upload your image. -The WordPress logo will be displayed by default. -You can also customize your logo from the "log in" option in the appearance menu. += What happens if I don't set a logo? = +WordPress will use the default logo. You can upload a custom logo from the plugin settings. -= I changed the background image but it takes a while to load = += My background image is slow to load. What should I do? = +Use optimized images under 500KB in JPG or WEBP format for better performance. -Try reducing the image size or restoring the plugin to its initial version. += How do I apply a pre-designed theme? = +In the plugin settings, navigate to the "Themes" tab. Click a theme to preview and activate it. -= How do I apply a pre-designed theme? = += Can I fully customize styles? = +Yes! Use the "Style Builder" tab to visually change colors, fonts, borders, spacing, and more. -Go to the "Login" option in the appearance menu, and navigate to the "Themes" tab. Click on the theme you want to apply and save your changes. += How can I provide feedback about this plugin? = +After using the plugin for a short period, administrators will see a feedback notification where they can leave a review. You can also provide feedback when deactivating the plugin. This helps us improve Login AWP. -= Can I customize the colors and styles of my login page? = += The login page isn't loading my custom styles. What should I do? = +Ensure your browser's cache is cleared. If the issue persists, try disabling other plugins that might conflict with login page customizations. -Yes, use the Style Builder feature to customize colors, fonts, borders, and more. Go to the "Login" option in the appearance menu and select the "Style Builder" tab. += I'm getting an error when trying to send feedback while deactivating the plugin. What should I do? = +In version 3.2.0, we've fixed an issue that could cause AJAX errors when submitting feedback. Make sure you're using the latest version of the plugin. If the issue persists, you can safely skip the feedback step. == Screenshots == -1. Login with default logo. -2. Login wiht custom logo. -3. Menu location. -4. Image upload example. -5. Theme selection interface. -6. Style Builder customization panel. +1. Login page with default WordPress logo. +2. Login page with custom logo. +3. Plugin location in the Appearance menu. +4. Background image upload interface. +5. Pre-designed theme selector. +6. Style Builder customization interface. +7. Feedback modal when deactivating the plugin. == Changelog == -= 1.0.0 = -* First stable version += 3.2.0 = +* FIXED: Resolved AJAX error during plugin deactivation feedback submission +* FIXED: Corrected issue with feedback submission pointing to incorrect domain +* IMPROVED: Enhanced error handling for feedback email and webhook submissions +* IMPROVED: Better fallbacks for email delivery when feedback settings are incomplete +* SECURITY: Improved data sanitization for feedback submissions + += 3.1.0 = +* NEW: Added user feedback system for administrators to help improve the plugin +* NEW: Added deactivation feedback modal to collect improvement suggestions +* FIXED: Login page JavaScript loading issue on specific server configurations +* IMPROVED: Enhanced compatibility with older PHP versions +* IMPROVED: Better handling of modal dialogs with event delegation +* FIXED: Various minor styling issues -= 1.1.0 = -* Fix: - - Site icon loads to show on login when custom icon exists += 3.0.0 = +* NEW: Theme selection system with pre-designed layouts +* NEW: Visual Style Builder for advanced customization +* NEW: Custom fonts, colors, spacing, and border settings + += 2.1.0 = +* NEW: Status notifications for image updates +* Added: Spanish language translation = 2.0.0 = -* Features: - - The admin area is added to the appearance menu. - - You can update the login logo and background. +* NEW: Plugin moved to Appearance menu for easier access +* NEW: Logo and background image customization -= 2.1.0 = -* Features: - - Messages about the status of image updates are added. - - Spanish translation added. += 1.1.0 = +* FIX: Automatically display custom site icon on login page if available -= 3.0.0 = -* Features: - - Theme selection system with pre-designed themes. - - Style Builder for complete customization of login page appearance. - - Advanced color controls for backgrounds, text, and form elements. - - Font customization options. - - Border and spacing controls. += 1.0.0 = +* Initial stable release + +== Upgrade Notice == + += 3.2.0 = +This update includes all improvements and fixes from version 3.1.0 and resolves an important issue with the feedback system when deactivating the plugin. The previous version could generate AJAX errors during feedback submission, which has been fixed. Additionally, this version enhances error handling for feedback submissions and improves data sanitization. We recommend all users update to this version. diff --git a/trunk/src/Admin/AdminRegister.php b/trunk/src/Admin/AdminRegister.php index 66be1e2..09f2b11 100644 --- a/trunk/src/Admin/AdminRegister.php +++ b/trunk/src/Admin/AdminRegister.php @@ -14,14 +14,16 @@ class AdminRegister { - public string $dirUrl; + public $dirUrl; - public static string $imgLogoName = 'login_awp_logo_url'; - public static string $imgBackName = 'login_awp_background_url'; - private string $adminTemplate = 'templates/menu_admin.php'; - private string $messageTemplate = 'templates/status_message.php'; - private ThemeManager $themeManager; - private StyleBuilder $styleBuilder; + public static $imgLogoName = 'login_awp_logo_url'; + public static $imgBackName = 'login_awp_background_url'; + public static $activateDateOption = 'login_awp_activation_date'; + public static $reviewNoticeDismissedOption = 'login_awp_review_notice_dismissed'; + private $adminTemplate = 'templates/menu_admin.php'; + private $messageTemplate = 'templates/status_message.php'; + private $themeManager; + private $styleBuilder; public function __construct($dir_url) { @@ -30,7 +32,7 @@ public function __construct($dir_url) $this->styleBuilder = new StyleBuilder($dir_url); } - public function load(): void + public function load() { add_action( 'admin_menu', @@ -53,61 +55,73 @@ public function load(): void 'admin_notices', array($this, 'statusMessage') ); - + + // Add the review notice action + add_action( + 'admin_notices', + array($this, 'displayReviewNotice') + ); + + // Add the dismiss review notice action hook + add_action( + 'admin_post_login_awp_dismiss_review_notice', + array($this, 'dismissReviewNoticeHandler') + ); + // Load theme manager and style builder components $this->themeManager->load(); $this->styleBuilder->load(); } - public function registerSubMenu(): void + public function registerSubMenu() { add_submenu_page( - parent_slug: 'themes.php', - page_title: __('Login AWP Plugin', 'login-awp'), - menu_title: __('Login', 'login-awp'), - capability: 'manage_options', - menu_slug: 'login-awp', - callback: array($this, 'loginAwpSubMenuTemplate') + 'themes.php', + __('Login AWP Plugin', 'login-awp'), + __('Login', 'login-awp'), + 'manage_options', + 'login-awp', + array($this, 'loginAwpSubMenuTemplate') ); } - public function loginAwpSubMenuTemplate(): void + public function loginAwpSubMenuTemplate() { if (\file_exists(plugin_dir_path(__FILE__) . $this->adminTemplate)) { wp_create_nonce('login_awp_form_nonce'); - + // Current active tab $active_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'general'; - + include_once plugin_dir_path(__FILE__) . $this->adminTemplate; } } - public function adminStyles(): void + public function adminStyles() { wp_enqueue_style( - handle: 'loginAdminCSS', - src: $this->dirUrl . 'css/loginAdminStyles.css', - deps: array(), - ver: '3.0.0' + 'loginAdminCSS', + $this->dirUrl . 'css/loginAdminStyles.css', + array(), + '3.0.0' ); } - - public function adminScripts(): void + + public function adminScripts() { wp_enqueue_media(); wp_enqueue_script('jquery'); wp_enqueue_script( - handle: 'loginAdminScript', - src: $this->dirUrl . 'js/loginAdmin.js', - deps: array('jquery'), - ver: '3.0.0', - args: true + 'loginAdminScript', + $this->dirUrl . 'js/loginAdmin.js', + array('jquery'), + '3.0.0', + true ); wp_localize_script( - handle: 'loginAdminScript', - object_name: 'login_text', - l10n: array( + 'loginAdminScript', + 'login_text', + array( 'text' => __('Select the image', 'login-awp'), 'delete_button' => __('Delete image', 'login-awp') ) @@ -115,14 +129,14 @@ public function adminScripts(): void } - public function loginAwpAdminform(): void + public function loginAwpAdminform() { if ( !isset($_POST['login_awp_form_nonce_field']) || !wp_verify_nonce( - nonce: $_POST['login_awp_form_nonce_field'], - action: 'login_awp_form_nonce' + $_POST['login_awp_form_nonce_field'], + 'login_awp_form_nonce' ) ) { wp_die(__('Verification failed', 'login-awp')); @@ -141,9 +155,9 @@ public function loginAwpAdminform(): void ) { $message .= $this->updateOption( - upload_data: $upload_img_logo, - message: 'logo_status', - db_file: self::$imgLogoName + $upload_img_logo, + 'logo_status', + self::$imgLogoName ); } @@ -152,9 +166,9 @@ public function loginAwpAdminform(): void filter_var($upload_img_back, \FILTER_VALIDATE_URL) ) { $message .= $this->updateOption( - upload_data: $upload_img_back, - message: 'background_status', - db_file: self::$imgBackName + $upload_img_back, + 'background_status', + self::$imgBackName ); } } @@ -164,11 +178,10 @@ public function loginAwpAdminform(): void !is_null($_POST["delete-upload-img-logo-button"]) ) { $message .= $this->updateOption( - upload_data: "", - message: 'logo_status', - db_file: self::$imgLogoName + "", + 'logo_status', + self::$imgLogoName ); - } if ( @@ -176,9 +189,9 @@ public function loginAwpAdminform(): void !is_null($_POST["delete-upload-img-back-button"]) ) { $message .= $this->updateOption( - upload_data: "", - message: 'background_status', - db_file: self::$imgBackName + "", + 'background_status', + self::$imgBackName ); } @@ -195,7 +208,7 @@ public function loginAwpAdminform(): void * @param string $db_file * @return string */ - private function updateOption($upload_data, $message, $db_file): string + private function updateOption($upload_data, $message, $db_file) { $status = "&{$message}=error"; $data = sanitize_text_field($upload_data); @@ -206,7 +219,7 @@ private function updateOption($upload_data, $message, $db_file): string return $status; } - public function statusMessage(): void + public function statusMessage() { if (isset($_GET['logo_status'])) { $this->messageTemplate( @@ -223,7 +236,7 @@ public function statusMessage(): void } } - private function messageTemplate($status, $message): void + private function messageTemplate($status, $message) { switch ($status) { case 'success': @@ -256,4 +269,93 @@ private function messageTemplate($status, $message): void include_once plugin_dir_path(__FILE__) . $this->messageTemplate; } } + + /** + * Display the review request admin notice if applicable. + * + * Shows a non-intrusive admin notice to administrators after 3 days of plugin usage, + * asking for a review on wordpress.org. + */ + public function displayReviewNotice() + { + // Only show to administrators + if (!current_user_can('manage_options')) { + return; + } + + // Check if the notice has been dismissed + $dismissed = get_option(self::$reviewNoticeDismissedOption, '0'); + if ('1' === $dismissed) { + return; + } + + // Check if 24 hours (86400 seconds) have passed since activation + $activation_date = get_option(self::$activateDateOption); + if (!$activation_date || (time() - $activation_date < 86400)) { + return; + } + + // Prepare dismiss URL + $dismiss_url = add_query_arg( + array( + 'action' => 'login_awp_dismiss_review_notice', + '_wpnonce' => wp_create_nonce('login_awp_dismiss_review_nonce') + ), + admin_url('admin-post.php') + ); + + // Plugin review URL + $review_url = 'https://wordpress.org/support/plugin/login-awp/reviews/?filter=5#new-post'; + +?> +
+

+ +

+

+ + + + + + +

+
+ +dirUrl = $dir_url . 'assets/'; + } + + public function load() + { + // Only load on admin pages + if (!is_admin()) { + return; + } + + if (false === get_option(self::$activateDateOption)) { + add_option(self::$activateDateOption, time()); + } + // Also add the option for dismissal tracking, default to not dismissed + if (false === get_option(self::$reviewNoticeDismissedOption)) { + add_option(self::$reviewNoticeDismissedOption, '0'); + } + + // Initialize feedback options + if (false === get_option(self::$feedbackEmailOption)) { + add_option(self::$feedbackEmailOption, self::$feedbackEmailDefault); + } + if (false === get_option(self::$feedbackWebhookOption)) { + add_option(self::$feedbackWebhookOption, self::$feedbackWebhookDefault); + } + + // Add scripts and styles for the feedback modal + add_action('admin_enqueue_scripts', array($this, 'enqueueScripts')); + + // Add the modal HTML to the admin footer + add_action('admin_footer', array($this, 'renderModal')); + + // Register AJAX handler for feedback submission + add_action('wp_ajax_login_awp_submit_feedback', array($this, 'handleFeedbackSubmission')); + + // Add settings fields for feedback email and webhook + add_action('admin_init', array($this, 'registerSettings')); + } + + public function enqueueScripts($hook) + { + // Only load on plugins page + if ('plugins.php' !== $hook) { + return; + } + + wp_enqueue_style( + 'login-awp-feedback-css', + $this->dirUrl . 'css/feedback-modal.css', + array(), + '3.2.0' + ); + + wp_enqueue_script( + 'login-awp-feedback-js', + $this->dirUrl . 'js/feedback-modal.js', + array('jquery'), + '3.2.0', + true + ); + + wp_localize_script( + 'login-awp-feedback-js', + 'loginAwpFeedback', + array( + 'ajax_url' => admin_url('admin-ajax.php'), + 'nonce' => wp_create_nonce('login_awp_feedback_nonce'), + 'plugin_slug' => 'login-awp/login_awp.php', + 'translations' => array( + 'heading' => __('Quick Feedback', 'login-awp'), + 'intro' => __('If you have a moment, please let us know why you are deactivating Login AWP:', 'login-awp'), + 'skip' => __('Skip & Deactivate', 'login-awp'), + 'submit' => __('Submit & Deactivate', 'login-awp'), + 'cancel' => __('Cancel', 'login-awp'), + 'submitting' => __('Submitting...', 'login-awp') + ) + ) + ); + } + + public function renderModal() + { + // Only show on plugins page + $screen = get_current_screen(); + if (!$screen || 'plugins' !== $screen->id) { + return; + } + +?> + +user_email; + } + + // Get active and inactive plugins + $active_plugins = array(); + $inactive_plugins = array(); + $all_plugins = get_plugins(); + + foreach ($all_plugins as $plugin_file => $plugin_data) { + if (is_plugin_active($plugin_file)) { + $active_plugins[] = array( + 'name' => $plugin_data['Name'], + 'version' => $plugin_data['Version'] + ); + } else { + $inactive_plugins[] = array( + 'name' => $plugin_data['Name'], + 'version' => $plugin_data['Version'] + ); + } + } + + // Get plugin information dynamically + $plugin_data = array(); + if (function_exists('get_plugin_data')) { + $plugin_file = WP_PLUGIN_DIR . '/login-awp/login_awp.php'; + if (file_exists($plugin_file)) { + $plugin_data = get_plugin_data($plugin_file); + } + } + + $plugin_name = !empty($plugin_data['Name']) ? $plugin_data['Name'] : 'Login AWP'; + $plugin_version = !empty($plugin_data['Version']) ? $plugin_data['Version'] : '3.2.0'; + + // Prepare feedback message + $feedback = array( + 'reason' => $reason, + 'details' => $details, + 'email' => $email, + 'action_type' => $action_type, + 'site_url' => home_url(), + 'plugin_name' => $plugin_name, + 'plugin_version' => $plugin_version, + 'wp_version' => get_bloginfo('version'), + 'php_version' => phpversion(), + 'timestamp' => current_time('mysql'), + 'active_plugins' => $active_plugins, + 'inactive_plugins' => $inactive_plugins, + 'server_info' => array( + 'software' => $_SERVER['SERVER_SOFTWARE'] ?? '', + 'memory_limit' => ini_get('memory_limit'), + 'max_execution_time' => ini_get('max_execution_time') + ) + ); + + $email_result = false; + $webhook_result = false; + + // Try to send email with error handling + try { + $email_result = $this->sendFeedbackEmail($feedback); + } catch (\Exception $e) { + error_log('Login AWP: Email feedback error - ' . $e->getMessage()); + // Don't stop execution, just log the error + } + + // Try to send to webhook with error handling + try { + $webhook_result = $this->sendFeedbackWebhook($feedback); + } catch (\Exception $e) { + error_log('Login AWP: Webhook feedback error - ' . $e->getMessage()); + // Don't stop execution, just log the error + } + + wp_send_json_success(array( + 'message' => 'Feedback submitted successfully', + 'email_sent' => $email_result, + 'webhook_sent' => $webhook_result + )); + } + + private function sendFeedbackEmail($feedback) + { + $to = get_option(self::$feedbackEmailOption, self::$feedbackEmailDefault); + + if (empty($to)) { + return false; + } + + + $subject = sprintf( + __('[Login AWP] Deactivation Feedback from %s', 'login-awp'), + parse_url(home_url(), PHP_URL_HOST) + ); + + $message = __('Action: Deactivation', 'login-awp') . "\n"; + $message .= sprintf(__('Reason: %s', 'login-awp'), $this->getReadableReason($feedback['reason'])) . "\n\n"; + + if (!empty($feedback['details'])) { + $message .= sprintf(__('Details: %s', 'login-awp'), $feedback['details']) . "\n\n"; + } + + $message .= sprintf(__('Site URL: %s', 'login-awp'), $feedback['site_url']) . "\n"; + $message .= sprintf(__('Plugin name: %s', 'login-awp'), $feedback['plugin_name']) . "\n"; + $message .= sprintf(__('Plugin version: %s', 'login-awp'), $feedback['plugin_version']) . "\n"; + $message .= sprintf(__('WordPress version: %s', 'login-awp'), $feedback['wp_version']) . "\n"; + $message .= sprintf(__('PHP version: %s', 'login-awp'), $feedback['php_version']) . "\n"; + $message .= sprintf(__('Timestamp: %s', 'login-awp'), $feedback['timestamp']) . "\n\n"; + $message .= __('Server information:', 'login-awp') . "\n"; + $message .= sprintf(__('Server software: %s', 'login-awp'), $feedback['server_info']['software']) . "\n"; + $message .= sprintf(__('Memory limit: %s', 'login-awp'), $feedback['server_info']['memory_limit']) . "\n"; + $message .= sprintf(__('Max execution time: %s', 'login-awp'), $feedback['server_info']['max_execution_time']) . "\n\n"; + + + // Add active plugins information + if (!empty($feedback['active_plugins'])) { + $message .= "\n" . __('Active plugins:', 'login-awp') . "\n"; + foreach ($feedback['active_plugins'] as $plugin) { + $message .= "- {$plugin['name']} {$plugin['version']}\n"; + } + } + + // Add inactive plugins information + if (!empty($feedback['inactive_plugins'])) { + $message .= "\n" . __('Inactive plugins:', 'login-awp') . "\n"; + foreach ($feedback['inactive_plugins'] as $plugin) { + $message .= "- {$plugin['name']} {$plugin['version']}\n"; + } + } + + $headers = array('Content-Type: text/plain; charset=UTF-8'); + + if (!empty($feedback['email'])) { + $message .= sprintf(__('User email: %s', 'login-awp'), $feedback['email']) . "\n"; + } else { + $message .= __('User email: Anonymous', 'login-awp') . "\n"; + } + + return wp_mail($to, $subject, $message, $headers); + } + + private function sendFeedbackWebhook($feedback) + { + $webhook_url = get_option(self::$feedbackWebhookOption, self::$feedbackWebhookDefault); + + if (empty($webhook_url)) { + return false; + } + + // Format feedback for webhook + $data = array( + 'feedback_type' => 'deactivation', + 'feedback' => $feedback + ); + + // Send to webhook with error handling + $response = wp_remote_post($webhook_url, array( + 'method' => 'POST', + 'timeout' => 45, + 'redirection' => 5, + 'httpversion' => '1.0', + 'blocking' => true, // Cambio a true para capturar errores + 'headers' => array('Content-Type' => 'application/json'), + 'body' => wp_json_encode($data), + 'cookies' => array() + )); + + // Verificar si hubo un error en la solicitud + if (is_wp_error($response)) { + error_log('Login AWP: Webhook error - ' . $response->get_error_message()); + return false; + } + + // Verificar el código de respuesta HTTP + $http_code = wp_remote_retrieve_response_code($response); + if ($http_code >= 400) { + error_log('Login AWP: Webhook HTTP error - ' . $http_code); + return false; + } + + return true; + } + + private function getReadableReason($reason) + { + $reasons = array( + 'no_longer_needed' => __('I no longer need the plugin', 'login-awp'), + 'found_better_plugin' => __('I found a better plugin', 'login-awp'), + 'not_working' => __('The plugin is not working', 'login-awp'), + 'temporary_deactivation' => __('It\'s a temporary deactivation', 'login-awp'), + 'other' => __('Other', 'login-awp') + ); + + return isset($reasons[$reason]) ? $reasons[$reason] : $reason; + } + + public function registerSettings() + { + // Register a new section in the Login AWP settings + add_settings_section( + 'login_awp_feedback_settings', + __('Feedback Settings', 'login-awp'), + array($this, 'renderSettingsSection'), + 'login-awp-feedback' + ); + + // Register the email field + add_settings_field( + 'login_awp_feedback_email', + __('Feedback Email', 'login-awp'), + array($this, 'renderEmailField'), + 'login-awp-feedback', + 'login_awp_feedback_settings' + ); + + // Register the webhook field + add_settings_field( + 'login_awp_feedback_webhook', + __('Feedback Webhook URL', 'login-awp'), + array($this, 'renderWebhookField'), + 'login-awp-feedback', + 'login_awp_feedback_settings' + ); + + // Register the settings + register_setting('login-awp-feedback', 'login_awp_feedback_email', 'sanitize_email'); + register_setting('login-awp-feedback', 'login_awp_feedback_webhook', 'esc_url_raw'); + } + + public function renderSettingsSection() + { + echo '

' . esc_html__('Configure where feedback should be sent when users deactivate the plugin.', 'login-awp') . '

'; + } + + public function renderEmailField() + { + $email = get_option('login_awp_feedback_email', get_option('admin_email')); + echo ''; + echo '

' . esc_html__('Email address where feedback will be sent.', 'login-awp') . '

'; + } + + public function renderWebhookField() + { + $webhook = get_option('login_awp_feedback_webhook', ''); + echo ''; + echo '

' . esc_html__('Optional webhook URL where feedback will be sent in JSON format.', 'login-awp') . '

'; + } +} diff --git a/trunk/src/Admin/ThemeManager.php b/trunk/src/Admin/ThemeManager.php index b50b5e7..6595d4e 100644 --- a/trunk/src/Admin/ThemeManager.php +++ b/trunk/src/Admin/ThemeManager.php @@ -15,17 +15,17 @@ class ThemeManager { - public string $dirUrl; - public static string $themeOptionName = 'login_awp_selected_theme'; - public static string $customStylesOptionName = 'login_awp_custom_styles'; - private array $predefinedThemes = []; + public $dirUrl; + public static $themeOptionName = 'login_awp_selected_theme'; + public static $customStylesOptionName = 'login_awp_custom_styles'; + private $predefinedThemes = []; /** * Constructor * * @param string $dir_url Plugin directory URL */ - public function __construct(string $dir_url) + public function __construct($dir_url) { $this->dirUrl = $dir_url . 'assets/'; } @@ -33,22 +33,22 @@ public function __construct(string $dir_url) /** * Initialize the theme manager */ - public function load(): void + public function load() { // Registrar eventos después de que WordPress esté completamente cargado add_action('admin_enqueue_scripts', array($this, 'enqueueAdminAssets')); add_action('wp_ajax_login_awp_preview_theme', array($this, 'ajaxPreviewTheme')); add_action('wp_ajax_login_awp_save_theme', array($this, 'ajaxSaveTheme')); - + // Inicializar los temas predefinidos add_action('init', array($this, 'initializePredefinedThemes')); } - + /** * Inicializa los temas predefinidos una vez que WordPress está completamente cargado * y las traducciones están disponibles */ - public function initializePredefinedThemes(): void + public function initializePredefinedThemes() { $this->predefinedThemes = $this->registerPredefinedThemes(); } @@ -58,7 +58,7 @@ public function initializePredefinedThemes(): void * * @return array Array of predefined themes */ - private function registerPredefinedThemes(): array + private function registerPredefinedThemes() { return [ 'default' => [ @@ -174,13 +174,13 @@ private function registerPredefinedThemes(): array * * @return array List of available themes */ - public function getThemes(): array + public function getThemes() { // Si los temas aún no están inicializados, inicializarlos aquí if (empty($this->predefinedThemes)) { $this->predefinedThemes = $this->registerPredefinedThemes(); } - + return $this->predefinedThemes; } @@ -189,16 +189,16 @@ public function getThemes(): array * * @return string Theme key */ - public function getSelectedTheme(): string + public function getSelectedTheme() { // Si los temas aún no están inicializados, inicializarlos aquí if (empty($this->predefinedThemes)) { $this->predefinedThemes = $this->registerPredefinedThemes(); } - + $selectedTheme = get_option(self::$themeOptionName); - return $selectedTheme && isset($this->predefinedThemes[$selectedTheme]) - ? $selectedTheme + return $selectedTheme && isset($this->predefinedThemes[$selectedTheme]) + ? $selectedTheme : 'default'; } @@ -208,25 +208,25 @@ public function getSelectedTheme(): string * @param string $theme_key Theme identifier * @return array|null Theme configuration or null if not found */ - public function getThemeConfig(string $theme_key): ?array + public function getThemeConfig($theme_key) { // Si los temas aún no están inicializarlos, inicializarlos aquí if (empty($this->predefinedThemes)) { $this->predefinedThemes = $this->registerPredefinedThemes(); } - - return isset($this->predefinedThemes[$theme_key]) - ? $this->predefinedThemes[$theme_key] + + return isset($this->predefinedThemes[$theme_key]) + ? $this->predefinedThemes[$theme_key] : null; } /** * Enqueue admin assets for theme management */ - public function enqueueAdminAssets(): void + public function enqueueAdminAssets() { $screen = get_current_screen(); - + // Only load on our plugin page if ($screen && $screen->id === 'appearance_page_login-awp') { wp_enqueue_style( @@ -235,7 +235,7 @@ public function enqueueAdminAssets(): void array(), '3.0.0' ); - + wp_enqueue_script( 'login-awp-theme-preview', $this->dirUrl . 'js/themePreview.js', @@ -243,25 +243,25 @@ public function enqueueAdminAssets(): void '3.0.0', true ); - + // Get current logo and background images using the correct option names $logo_img = get_option('login_awp_logo_url', ''); $background_img = get_option('login_awp_background_url', ''); - + // Default background if not set if (empty($background_img)) { $background_img = $this->dirUrl . 'img/slider.jpg'; } - + // Default logo uses site icon if available if (empty($logo_img)) { $logo_img = get_site_icon_url(); } - + // Verificar si existen estilos personalizados $custom_styles = get_option(self::$customStylesOptionName, ''); $has_custom_styles = !empty($custom_styles); - + wp_localize_script( 'login-awp-theme-preview', 'loginAwpThemes', @@ -284,66 +284,66 @@ public function enqueueAdminAssets(): void /** * AJAX handler for theme preview */ - public function ajaxPreviewTheme(): void + public function ajaxPreviewTheme() { // Check permissions and nonce if (!current_user_can('manage_options')) { wp_send_json_error(array('message' => __('You do not have sufficient permissions', 'login-awp'))); return; } - + if (!check_ajax_referer('login_awp_theme_preview', 'nonce', false)) { wp_send_json_error(array('message' => __('Invalid security token', 'login-awp'))); return; } - + // Si los temas aún no están inicializados, inicializarlos aquí if (empty($this->predefinedThemes)) { $this->predefinedThemes = $this->registerPredefinedThemes(); } - + $theme_key = isset($_POST['theme']) ? sanitize_text_field($_POST['theme']) : ''; $theme_config = $this->getThemeConfig($theme_key); - + if ($theme_config) { wp_send_json_success(array('config' => $theme_config)); } else { wp_send_json_error(array('message' => __('Theme not found', 'login-awp'))); } - + wp_die(); } /** * AJAX handler for saving theme */ - public function ajaxSaveTheme(): void + public function ajaxSaveTheme() { // Check permissions and nonce if (!current_user_can('manage_options')) { wp_send_json_error(array('message' => __('You do not have sufficient permissions', 'login-awp'))); return; } - + if (!check_ajax_referer('login_awp_theme_preview', 'nonce', false)) { wp_send_json_error(array('message' => __('Invalid security token', 'login-awp'))); return; } - + // Si los temas aún no están inicializados, inicializarlos aquí if (empty($this->predefinedThemes)) { $this->predefinedThemes = $this->registerPredefinedThemes(); } - + $theme_key = isset($_POST['theme']) ? sanitize_text_field($_POST['theme']) : ''; - + if (isset($this->predefinedThemes[$theme_key])) { update_option(self::$themeOptionName, $theme_key); wp_send_json_success(array('message' => __('Theme saved successfully', 'login-awp'))); } else { wp_send_json_error(array('message' => __('Invalid theme selected', 'login-awp'))); } - + wp_die(); } @@ -352,61 +352,61 @@ public function ajaxSaveTheme(): void * * @return string Generated CSS */ - public function generateThemeCSS(): string + public function generateThemeCSS() { $theme_key = $this->getSelectedTheme(); - + // Si los temas aún no están inicializados, inicializarlos aquí if (empty($this->predefinedThemes)) { $this->predefinedThemes = $this->registerPredefinedThemes(); } - + $theme = $this->getThemeConfig($theme_key); - + if (!$theme) { return ''; } - + $custom_styles = get_option(self::$customStylesOptionName, ''); - + // If we have custom styles, use those instead if (!empty($custom_styles)) { return $custom_styles; } - + // Otherwise generate CSS from theme config ob_start(); - ?> -body.login { - background-color: ; - font-family: ; - font-size: ; -} +?> + body.login { + background-color: ; + font-family: ; + font-size: ; + } -body.login div#login { - background-color: ; - border-radius: ; - box-shadow: ; -} + body.login div#login { + background-color: ; + border-radius: ; + box-shadow: ; + } -body.login div#login form#loginform p, -body.login div#login form#loginform p label { - color: ; -} + body.login div#login form#loginform p, + body.login div#login form#loginform p label { + color: ; + } -body.login div#login form#loginform p.submit input#wp-submit { - background-color: ; -} + body.login div#login form#loginform p.submit input#wp-submit { + background-color: ; + } -body.login div#login form#loginform p.submit input#wp-submit:hover { - background-color: ; -} + body.login div#login form#loginform p.submit input#wp-submit:hover { + background-color: ; + } -body.login div#login p#nav a, -body.login div#login p#backtoblog a { - color: ; -} - ; + } +

- - - +
+
- +
- +
- +
- +
- +

- +
- +
- +
- +

- +
- +
- +
- +
- +
-
+ \ No newline at end of file diff --git a/trunk/src/Public/PublicRegister.php b/trunk/src/Public/PublicRegister.php index fc7089e..0ac5b10 100644 --- a/trunk/src/Public/PublicRegister.php +++ b/trunk/src/Public/PublicRegister.php @@ -17,8 +17,8 @@ class PublicRegister { - public string $dirUrl; - private ThemeManager $themeManager; + public $dirUrl; + private $themeManager; public function __construct($dir_url) { @@ -26,85 +26,85 @@ public function __construct($dir_url) $this->themeManager = new ThemeManager($dir_url); } - public function load(): void + public function load() { add_action( - hook_name: 'login_enqueue_scripts', - callback: array($this, 'loginAwpStyles'), - priority: 1 + 'login_enqueue_scripts', + array($this, 'loginAwpStyles'), + 1 ); add_action( - hook_name: 'login_enqueue_scripts', - callback: array($this, 'loginAwpScripts'), - priority: 1 + 'login_enqueue_scripts', + array($this, 'loginAwpScripts'), + 1 ); add_action( - hook_name: 'login_enqueue_scripts', - callback: array($this, 'loginAwpLocalize'), - priority: 1 + 'login_enqueue_scripts', + array($this, 'loginAwpLocalize'), + 1 ); // Add the custom theme styles add_action( - hook_name: 'login_head', - callback: array($this, 'loginAwpThemeStyles') + 'login_head', + array($this, 'loginAwpThemeStyles') ); } - public function loginAwpStyles(): void + public function loginAwpStyles() { wp_enqueue_style( - handle: 'vegasCSS', - src: $this->dirUrl . 'css/vegas.min.css', - deps: array(), - ver: false + 'vegasCSS', + $this->dirUrl . 'css/vegas.min.css', + array(), + false ); wp_enqueue_style( - handle: 'loginCSS', - src: $this->dirUrl . 'css/loginStyles.css', - deps: array(), - ver: false + 'loginCSS', + $this->dirUrl . 'css/loginStyles.css', + array(), + false ); } - public function loginAwpScripts(): void + public function loginAwpScripts() { - wp_enqueue_script(handle: 'jquery'); + wp_enqueue_script('jquery'); wp_enqueue_script( - handle: 'vegasJS', - src: $this->dirUrl . 'js/vegas.min.js', - deps: array('jquery'), - ver: '2.5.4', - args: true + 'vegasJS', + $this->dirUrl . 'js/vegas.min.js', + array('jquery'), + '2.5.4', + true ); wp_enqueue_script( - handle: 'loginJS', - src: $this->dirUrl . 'js/loginJS.js', - deps: array('jquery'), - ver: '1.0.0', - args: true + 'loginJs', + $this->dirUrl . 'js/loginJs.js', + array('jquery'), + '1.0.0', + true ); } - public function loginAwpLocalize(): void + public function loginAwpLocalize() { - $upload_img_logo = get_option(option: AdminRegister::$imgLogoName); + $upload_img_logo = get_option(AdminRegister::$imgLogoName); $upload_img_logo = isset($upload_img_logo) && !empty($upload_img_logo) ? $upload_img_logo : get_site_icon_url(); - $upload_img_back = get_option(option: AdminRegister::$imgBackName); + $upload_img_back = get_option(AdminRegister::$imgBackName); $upload_img_back = isset($upload_img_back) && !empty($upload_img_back) ? $upload_img_back : $this->dirUrl . 'img/slider.jpg'; wp_localize_script( - handle: 'loginJS', - object_name: 'login_imagenes', - l10n: array( - 'logo' => esc_url(url: $upload_img_logo), - 'sliders' => esc_url(url: $upload_img_back), - 'overlay' => esc_url(url: $this->dirUrl . 'img/overlay.png') + 'loginJs', + 'login_imagenes', + array( + 'logo' => esc_url($upload_img_logo), + 'sliders' => esc_url($upload_img_back), + 'overlay' => esc_url($this->dirUrl . 'img/overlay.png') ) ); } @@ -112,7 +112,7 @@ public function loginAwpLocalize(): void /** * Output theme styles in the login page head */ - public function loginAwpThemeStyles(): void + public function loginAwpThemeStyles() { $theme_css = $this->themeManager->generateThemeCSS(); if (!empty($theme_css)) { diff --git a/trunk/src/Register.php b/trunk/src/Register.php index f4f0930..95057eb 100644 --- a/trunk/src/Register.php +++ b/trunk/src/Register.php @@ -13,6 +13,7 @@ use Login\Awp\Public\PublicRegister; use Login\Awp\Admin\AdminRegister; +use Login\Awp\Admin\FeedbackManager; class Register { @@ -21,7 +22,7 @@ class Register public string $domainPath; /** - * Summary of __construct + * __construct * * @param string $dir_url * @param string $dir_path @@ -38,19 +39,16 @@ public function load(): void { // Registrar primero la carga del textdomain add_action('plugins_loaded', array($this, 'initPlugin')); + } /** * Inicializa el plugin después de cargar las traducciones */ public function initPlugin(): void - { - $this->initComponents(); - - // Primero cargar las traducciones + { $this->loginAwpTextdomain(); - - // Luego inicializar los componentes del plugin + $this->initComponents(); } /** @@ -63,6 +61,9 @@ protected function initComponents(): void $admin = new AdminRegister(dir_url: $this->dirUrl); $admin->load(); + + $feedback = new FeedbackManager(dir_url: $this->dirUrl); + $feedback->load(); } public function loginAwpTextdomain(): void diff --git a/trunk/uninstall.php b/trunk/uninstall.php index b0fba6d..2b2f37a 100644 --- a/trunk/uninstall.php +++ b/trunk/uninstall.php @@ -5,18 +5,48 @@ * * @author AWP-Software * @since 2.0.0 - * @version 2.0.0 + * @version 3.1.0 */ -if (!defined(constant_name: 'WP_UNINSTALL_PLUGIN')) { +if (!defined('WP_UNINSTALL_PLUGIN')) { die('You are not allowed to uninstall the plugin'); } +// Define constants directly instead of requiring settings.php +if (!defined('AWP_LOGIN_FEEDBACK_EMAIL')) { + define('AWP_LOGIN_FEEDBACK_EMAIL', 'support@awp-software.com'); +} + +if (!defined('AWP_LOGIN_FEEDBACK_WEBHOOK')) { + define('AWP_LOGIN_FEEDBACK_WEBHOOK', 'https://telemetry.awp-software.com/feedback'); +} + require_once __DIR__ . '/vendor/autoload.php'; use Login\Awp\Admin\AdminRegister; +use Login\Awp\Admin\ThemeManager; + +// Delete plugin settings +delete_option(AdminRegister::$imgLogoName); +delete_option(AdminRegister::$imgBackName); +delete_option(AdminRegister::$activateDateOption); +delete_option(AdminRegister::$reviewNoticeDismissedOption); + +delete_site_option(AdminRegister::$imgLogoName); +delete_site_option(AdminRegister::$imgBackName); +delete_site_option(AdminRegister::$activateDateOption); +delete_site_option(AdminRegister::$reviewNoticeDismissedOption); + +// Delete custom theme settings +delete_option(ThemeManager::$themeOptionName); +delete_option(ThemeManager::$customStylesOptionName); + +delete_site_option(ThemeManager::$themeOptionName); +delete_site_option(ThemeManager::$customStylesOptionName); + +// Delete feedback settings +delete_option('login_awp_feedback_email'); +delete_option('login_awp_feedback_webhook'); +delete_site_option('login_awp_feedback_email'); +delete_site_option('login_awp_feedback_webhook'); -delete_option(option: AdminRegister::$imgLogoName); -delete_option(option: AdminRegister::$imgBackName); -delete_site_option(option: AdminRegister::$imgLogoName); -delete_site_option(option: AdminRegister::$imgBackName);