5 Commits

12 changed files with 425 additions and 814 deletions

111
DEVELOPMENT.md Normal file
View File

@ -0,0 +1,111 @@
# WP Allstars Plugin Development Workflow
This document outlines the development workflow for the WP Allstars Plugin to ensure stable and reliable feature implementation.
## Development Principles
1. **Stability First**: The primary goal is maintaining a stable plugin that works reliably
2. **Incremental Changes**: Implement changes in small, manageable increments
3. **Complete Testing**: Every change must be thoroughly tested before integration
4. **Documentation**: All features and changes must be well-documented
## Branch Structure
- `main` - Production-ready code, always stable
- `v0.2.3-stable` - Our current stable development branch
- `feature/v0.2.3-stable/{feature-name}` - Feature branches for new development
## Development Workflow
### 1. Feature Planning
1. Identify a feature from the ROADMAP.md file to implement
2. Review any existing implementation in unstable versions
3. Document the implementation plan in ROADMAP.md
4. Create a new feature branch from the stable base
```bash
git checkout v0.2.3-stable
git checkout -b feature/v0.2.3-stable/sync-guard
```
### 2. Feature Implementation
1. Start with the smallest possible functional change
2. Commit frequently with descriptive commit messages including stability classification
3. Example commit message format:
```
[EXPERIMENTAL] Add basic sync guard detection functionality
- Adds file existence check for .syncing flag
- Implements conditional loading based on flag
- Does not yet handle admin notices
```
4. Reference the ROADMAP.md and TESTING.md documents while implementing
### 3. Testing
1. Complete all relevant tests from TESTING.md
2. Add feature-specific tests if needed
3. Test in a clean WordPress environment
4. Test with WP_DEBUG enabled
5. Document any issues found and fix them
### 4. Code Review
1. Self-review code for:
- PHP best practices
- WordPress coding standards
- Security considerations
- Performance implications
- Error handling
2. Consider peer review if possible
### 5. Integration
1. Create a pull request to merge into the stable branch
2. Summarize changes, testing performed, and any caveats
3. Once approved, merge using `--no-ff` to preserve feature history
```bash
git checkout v0.2.3-stable
git merge --no-ff feature/v0.2.3-stable/sync-guard
```
4. Tag new version if appropriate:
```bash
git tag v0.2.3.1-stable
git push origin v0.2.3.1-stable
```
5. Update STABILITY.md with the new version information
### 6. Post-Integration
1. Deploy to test environment and confirm functionality
2. Update ROADMAP.md to reflect the implemented feature
3. Clean up feature branch if no longer needed
## Handling Unstable Code References
When examining code from unstable versions:
1. **Never copy-paste directly** - Understand the approach and reimplement
2. **Isolate problematic code** - Identify why it might have failed
3. **Take the best ideas** - Implement the concept, not the exact implementation
4. **Document the reference** - Note which version inspired each implementation
## Versioning Scheme
- `vX.Y.Z` - Major.Minor.Patch
- `vX.Y.Z-stable` - Stable development branches
- `vX.Y.Z.N-stable` - Minor updates to stable branches
## Continuous Improvement
- Regularly review and update these development procedures
- Document lessons learned
- Improve testing procedures based on discoveries

View File

@ -1,6 +1,7 @@
# WP Allstars # WP Allstars
A WordPress plugin that enhances your WordPress experience with curated plugins, themes, and optimization tools. A WordPress plugin that enhances your WordPress experience with curated plugins, themes, and optimization tools.
Testing a stable v0.2.3 version with rsync deployment.
## Description ## Description

51
ROADMAP.md Normal file
View File

@ -0,0 +1,51 @@
# WP Allstars Plugin Development Roadmap
This document outlines features from later versions that we plan to integrate into our stable development branch. The goal is to incrementally implement these features in a stable manner, without introducing critical errors.
## Feature Backlog
| Feature | Source Version | Priority | Complexity | Risk | Status |
|---------|----------------|----------|------------|------|--------|
| Multisite Category | v0.2.6 | High | Low | Low | ✅ Implemented in v0.2.3-stable |
| Sync Guard | v0.2.6-fix | High | Low | Low | 🔄 To be implemented |
| More Robust File Loading | v0.2.6-fix | High | Low | Low | ✅ Implemented in v0.2.3-stable |
| Enhanced Admin UI | v0.2.4+ | Medium | Medium | Medium | 🔄 To be implemented |
| Plugin Dashboard | v0.2.6-fix | Medium | Medium | Medium | 🔄 To be implemented |
| New Category Pages | v0.2.4+ | Medium | Low | Low | 🔄 To be implemented |
## Implementation Strategy
### Multisite Category with Network Plugin Auditor
- **Description**: Add a "Multisite" filter after Advanced and include network-plugin-auditor
- **Why it failed before**: Didn't properly update all required files for the feature
- **Implementation plan**: Add to free-plugins.php and update class-free-plugins-manager.php to display the category correctly
- **Testing criteria**: Verify category appears in UI and plugin can be installed
### Sync Guard
- **Description**: Prevent plugin loading during rsync operations to avoid partial file loading
- **Why it failed before**: Added to wrong location, dependent on missing files
- **Implementation plan**:
1. Create a simpler version of the sync guard
2. Update post-commit hook to handle sync operations better
3. Use file flag to signal when sync is in progress
- **Testing criteria**: Verify plugin doesn't attempt to load during sync operations
### Enhanced Admin UI
- **Description**: Improve the admin interface with better styling and more intuitive navigation
- **Why it failed before**: Too many changes at once without proper testing
- **Implementation plan**:
1. Small, incremental UI improvements
2. Focus on one component at a time
3. Thorough testing after each change
- **Testing criteria**: UI changes shouldn't affect functionality, should be responsive
## Development Order
The suggested implementation order is:
1. Sync Guard
2. Enhanced Admin UI (component by component)
3. Plugin Dashboard improvements
4. New Category Pages
Each feature should be developed in its own branch and only merged after thorough testing.

32
STABILITY.md Normal file
View File

@ -0,0 +1,32 @@
# WP Allstars Plugin Stability Status
This document tracks the stability status of different versions of the WP Allstars Plugin.
## Stability Classification
- **[STABLE]**: Thoroughly tested, works as expected in production environments
- **[FUNCTIONAL]**: Works but may have minor issues or incomplete features
- **[EXPERIMENTAL]**: Contains new features that are not fully tested
- **[UNSTABLE]**: Known to have critical issues that affect functionality
## Version Status
| Version | Status | Notes |
|---------|--------|-------|
| v0.2.3-stable-base | **[STABLE]** | Base stable version with robust file loading. All core functionality works properly. |
| v0.2.4 | **[UNSTABLE]** | Contains critical errors - reference only for feature ideas. |
| v0.2.6 | **[UNSTABLE]** | Contains file structure issues and critical errors - reference only for feature ideas. |
| v0.2.6-fix | **[UNSTABLE]** | Attempted fixes but still has issues - reference only. |
| v0.2.6-revert | **[UNSTABLE]** | Failed attempt to revert to stable version - do not use. |
## Current Development
Current development is based on the v0.2.3-stable-base version. Features from later versions are being analyzed and reimplemented in a stable manner.
## Stability Guidelines
1. All new features must be developed in isolated feature branches
2. Comprehensive testing is required before merging
3. Each feature should be implemented as a series of small, atomic commits
4. All commits should include a stability classification in commit messages: [STABLE], [FUNCTIONAL], etc.
5. Full testing checklist must be completed before marking a version as [STABLE]

70
TESTING.md Normal file
View File

@ -0,0 +1,70 @@
# WP Allstars Plugin Testing Procedures
This document outlines the testing procedures for the WP Allstars Plugin to ensure stability and reliability.
## Pre-Merge Testing Checklist
### Basic Functionality Tests
- [ ] Plugin activates without errors
- [ ] Plugin deactivates without errors
- [ ] Admin menu appears correctly
- [ ] All submenu items load without errors
- [ ] Settings can be saved without errors
- [ ] Plugin works with WordPress debug mode enabled
### Feature-Specific Tests
Each new feature should have its own testing checklist added here.
#### Multisite Category Feature
- [ ] "Multisite" category appears in the correct location in the UI
- [ ] Network Plugin Auditor appears in the Multisite category
- [ ] Category filter works when clicked
- [ ] Plugin can be installed from the category
#### Sync Guard Feature
- [ ] Plugin doesn't load when .syncing file is present
- [ ] .syncing file is created during sync operations
- [ ] .syncing file is removed after sync completes
- [ ] User is notified when plugin is in sync mode
### Compatibility Tests
- [ ] Plugin works with latest WordPress version
- [ ] Plugin works with PHP 7.4+
- [ ] Plugin works with common themes (Twenty Twenty-Three, Kadence)
- [ ] Plugin co-exists with other popular plugins without conflicts
### Browser Compatibility
- [ ] UI works correctly in Chrome
- [ ] UI works correctly in Firefox
- [ ] UI works correctly in Safari
- [ ] UI works correctly in Edge
### Mobile Responsiveness
- [ ] Admin interface is usable on mobile devices
- [ ] No layout issues on small screens
## Testing Process
1. Create a clean WordPress installation for testing
2. Install and activate the plugin
3. Enable WordPress debug mode (WP_DEBUG = true)
4. Complete all tests in the checklist
5. Document any issues found
6. Fix issues and retest
7. Only mark as [STABLE] when all tests pass
## Continuous Integration
For future implementation:
- [ ] Automated unit tests
- [ ] Integration tests
- [ ] End-to-end tests
- [ ] Code quality checks

View File

@ -156,7 +156,7 @@
} }
input:checked + .wp-toggle-slider { input:checked + .wp-toggle-slider {
background-color: #00a32a; /* WordPress standard green color */ background-color: #2271b1;
} }
input:checked + .wp-toggle-slider:before { input:checked + .wp-toggle-slider:before {
@ -209,7 +209,7 @@ input:checked + .wp-toggle-slider:before {
.wp-setting-base:hover, .wp-setting-base:hover,
.wp-setting-row:hover, .wp-setting-row:hover,
.wp-allstars-toggle:hover { .wp-allstars-toggle:hover {
border-color: #00a32a; border-color: #2271b1;
box-shadow: 0 2px 6px rgba(0,0,0,0.15); box-shadow: 0 2px 6px rgba(0,0,0,0.15);
} }
@ -333,8 +333,8 @@ input:checked + .wp-toggle-slider:before {
.wp-allstars-setting-row input[type="text"]:focus, .wp-allstars-setting-row input[type="text"]:focus,
.wp-allstars-setting-row input[type="number"]:focus, .wp-allstars-setting-row input[type="number"]:focus,
.wp-allstars-setting-row textarea:focus { .wp-allstars-setting-row textarea:focus {
border-color: #00a32a; border-color: #2271b1;
box-shadow: 0 0 0 1px #00a32a; box-shadow: 0 0 0 1px #2271b1;
outline: 2px solid transparent; outline: 2px solid transparent;
} }
@ -733,9 +733,6 @@ input:checked + .wp-toggle-slider:before {
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
transform: translateY(-3px); transform: translateY(-3px);
white-space: nowrap;
min-width: 60px;
justify-content: center;
} }
.wp-setting-notification.error { .wp-setting-notification.error {
@ -761,105 +758,6 @@ input:checked + .wp-toggle-slider:before {
line-height: 1.4; line-height: 1.4;
} }
/* Role Checkboxes - Consistent component design */
.wp-allstars-role-checkboxes {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.wp-allstars-role-checkbox {
flex: 0 0 calc(33.333% - 10px);
max-width: calc(33.333% - 10px);
display: flex;
align-items: center;
gap: 8px;
padding: 8px 10px;
background: #f8f9fa;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
}
.wp-allstars-role-checkbox:hover {
background: #f0f0f1;
border-color: #2271b1;
}
.wp-allstars-role-checkbox input[type="checkbox"] {
margin: 0;
}
.wp-allstars-role-checkbox span {
font-size: 13px;
color: #50575e;
}
/* Responsive adjustments */
@media screen and (max-width: 992px) {
.wp-allstars-role-checkbox {
flex: 0 0 calc(50% - 10px);
max-width: calc(50% - 10px);
}
}
@media screen and (max-width: 782px) {
.wp-allstars-role-checkbox {
flex: 0 0 calc(50% - 8px);
max-width: calc(50% - 8px);
padding: 6px 8px;
}
.wp-allstars-role-checkbox span {
font-size: 12px;
}
}
@media screen and (max-width: 480px) {
.wp-allstars-role-checkbox {
flex: 0 0 100%;
max-width: 100%;
}
}
/* Enhanced toggle component */
.wp-allstars-toggle {
position: relative;
overflow: hidden;
}
.wp-allstars-toggle-header[aria-expanded="true"] {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
/* Better settings panel styling */
.wp-allstars-toggle-settings {
padding: 20px;
background: #f8f9fa;
border-top: 1px solid #ddd;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
}
.wp-allstars-setting-row {
margin-bottom: 20px;
}
.wp-allstars-setting-row:last-child {
margin-bottom: 0;
}
.wp-allstars-setting-row label {
display: block;
margin-bottom: 8px;
font-size: 14px;
font-weight: 600;
color: #1d2327;
}
@keyframes fadeIn { @keyframes fadeIn {
from { opacity: 0; } from { opacity: 0; }
to { opacity: 1; } to { opacity: 1; }

View File

@ -1,450 +0,0 @@
<?php
/**
* WP ALLSTARS Access Manager
*
* Handles access control features like admin bar and dashboard access
*
* @package WP_ALLSTARS
* @since 0.2.5
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
class WP_Allstars_Access_Manager {
/**
* Initialize the class
*/
public static function init() {
add_action('admin_init', array(__CLASS__, 'register_settings'));
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'));
// Add hooks for admin bar and dashboard access control
add_action('init', array(__CLASS__, 'setup_access_control'));
// Add AJAX handlers
add_action('wp_ajax_wp_allstars_update_access_setting', array(__CLASS__, 'handle_access_setting_update'));
}
/**
* Register settings for access control
*/
public static function register_settings() {
register_setting('wp_allstars_access', 'wp_allstars_hide_admin_bar_roles');
register_setting('wp_allstars_access', 'wp_allstars_restrict_dashboard_roles');
}
/**
* Enqueue scripts for the access control settings
*
* @param string $hook Current admin page hook
*/
public static function enqueue_scripts($hook) {
if ('settings_page_wp-allstars' !== $hook) {
return;
}
wp_enqueue_style(
'wp-allstars-admin',
plugins_url('css/wp-allstars-admin.css', dirname(__FILE__)),
array(),
WP_ALLSTARS_VERSION
);
// Add inline JS for handling settings updates
$access_js = '
jQuery(document).ready(function($) {
// Handle main toggle switches using the standard update_option AJAX call
$("#wp_allstars_hide_admin_bar, #wp_allstars_restrict_dashboard").on("change", function(e) {
e.stopPropagation();
var $this = $(this);
var setting = $this.attr("id");
var value = $this.is(":checked") ? 1 : 0;
// Clear any existing notifications
$(".wp-setting-notification").remove();
$.ajax({
url: ajaxurl,
type: "POST",
data: {
action: "wp_allstars_update_option",
option: setting,
value: value,
nonce: wpAllstars.nonce
},
success: function(response) {
if (response.success) {
// Show success notification
showNotification("Saved", $this);
// Update UI based on toggle state
var $container = $this.closest(".wp-allstars-toggle");
var $settingsArea = $container.find(".wp-allstars-toggle-settings");
var $header = $container.find(".wp-allstars-toggle-header");
if (value) {
// Set default roles (subscriber, customer) as checked when enabled
$settingsArea.find("input[value=\'subscriber\'], input[value=\'customer\']").prop("checked", true);
// Update role settings via AJAX
var setting_key = setting === "wp_allstars_hide_admin_bar" ?
"wp_allstars_hide_admin_bar_roles" :
"wp_allstars_restrict_dashboard_roles";
$.ajax({
url: ajaxurl,
type: "POST",
data: {
action: "wp_allstars_update_access_setting",
setting: setting_key,
value: ["subscriber", "customer"],
nonce: wpAllstars.nonce
}
});
// Expand the section if it was toggled on
if ($header.attr("aria-expanded") === "false") {
$header.attr("aria-expanded", "true");
$settingsArea.slideDown(200);
}
} else {
// Clear all role checkboxes when disabled
$settingsArea.find("input[type=checkbox]").prop("checked", false);
// Update role settings via AJAX
var setting_key = setting === "wp_allstars_hide_admin_bar" ?
"wp_allstars_hide_admin_bar_roles" :
"wp_allstars_restrict_dashboard_roles";
$.ajax({
url: ajaxurl,
type: "POST",
data: {
action: "wp_allstars_update_access_setting",
setting: setting_key,
value: [],
nonce: wpAllstars.nonce
}
});
}
} else {
// Show error notification
showNotification("Error Saving", $this, "error");
// Revert the toggle to its previous state
$this.prop("checked", !$this.is(":checked"));
}
},
error: function() {
// Show error notification
showNotification("Error Saving", $this, "error");
// Revert the toggle to its previous state
$this.prop("checked", !$this.is(":checked"));
}
});
});
// Handle role checkbox changes
$(".wp-allstars-role-checkbox input").on("change", function(e) {
e.stopPropagation();
var $this = $(this);
var $container = $this.closest(".wp-allstars-role-checkboxes");
var settingName = $container.find("input").first().attr("name");
var settingKey = settingName.replace("[]", "");
var selectedRoles = [];
// Get all checked roles
$container.find("input:checked").each(function() {
selectedRoles.push($(this).val());
});
// Clear any existing notifications
$(".wp-setting-notification").remove();
// Find the main toggle for this section
var $mainToggle = $this.closest(".wp-allstars-toggle").find(".wp-toggle-switch input");
// Update the setting via AJAX
$.ajax({
url: ajaxurl,
type: "POST",
data: {
action: "wp_allstars_update_access_setting",
setting: settingKey,
value: selectedRoles,
nonce: wpAllstars.nonce
},
success: function(response) {
if (response.success) {
// Update the main toggle based on role selection
$mainToggle.prop("checked", selectedRoles.length > 0);
// Show success notification
showNotification("Saved", $mainToggle);
} else {
// Show error notification
showNotification("Error Saving", $mainToggle, "error");
// Revert the checkbox to its previous state
$this.prop("checked", !$this.prop("checked"));
}
},
error: function() {
// Show error notification
showNotification("Error Saving", $mainToggle, "error");
// Revert the checkbox to its previous state
$this.prop("checked", !$this.prop("checked"));
}
});
});
// Utility function to show notifications
function showNotification(message, $element, type) {
type = type || "success"; // Default to success
// Find the nearest toggle header for notification placement
var $toggleHeader = $element.closest(".wp-allstars-toggle").find(".wp-allstars-toggle-header");
var $label = $toggleHeader.find("label");
var $notification = $("<span>").addClass("wp-setting-notification " + type).text(message);
// Remove any existing notifications
$toggleHeader.find(".wp-setting-notification").remove();
// Add the notification
$label.append($notification);
// Remove notification after delay
setTimeout(function() {
$notification.fadeOut(300, function() {
$(this).remove();
});
}, 2000);
}
});
';
wp_add_inline_script('wp-allstars-admin', $access_js);
}
/**
* Handle AJAX updates for access settings
*/
public static function handle_access_setting_update() {
// Verify nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'wp-allstars-nonce')) {
wp_send_json_error(array('message' => 'Invalid nonce'));
return;
}
// Check user capabilities
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => 'Insufficient permissions'));
return;
}
// Get and validate setting
$setting = isset($_POST['setting']) ? sanitize_text_field($_POST['setting']) : '';
$value = isset($_POST['value']) ? $_POST['value'] : '';
if (empty($setting)) {
wp_send_json_error(array('message' => 'Invalid setting'));
return;
}
// Handle the role settings update
if ($setting === 'wp_allstars_hide_admin_bar_roles' || $setting === 'wp_allstars_restrict_dashboard_roles') {
// Sanitize the array of roles
if (is_array($value)) {
$value = array_map('sanitize_text_field', $value);
} else {
$value = array();
}
// Update the option
$result = update_option($setting, $value);
if ($result) {
// Also update the corresponding toggle setting for consistency
if ($setting === 'wp_allstars_hide_admin_bar_roles') {
update_option('wp_allstars_hide_admin_bar', !empty($value) ? 1 : 0);
} else if ($setting === 'wp_allstars_restrict_dashboard_roles') {
update_option('wp_allstars_restrict_dashboard', !empty($value) ? 1 : 0);
}
wp_send_json_success(array('message' => 'Setting updated successfully'));
} else {
wp_send_json_error(array('message' => 'Error Saving'));
}
} else {
wp_send_json_error(array('message' => 'Invalid setting name'));
}
}
/**
* Set up access control hooks
*/
public static function setup_access_control() {
// Get current user
$user = wp_get_current_user();
if (!$user->exists()) {
return;
}
// Get user roles
$user_roles = $user->roles;
// Get restricted roles from settings
$hide_admin_bar_roles = get_option('wp_allstars_hide_admin_bar_roles', array());
$restrict_dashboard_roles = get_option('wp_allstars_restrict_dashboard_roles', array());
// Check if user's role is in restricted roles
$should_hide_admin_bar = array_intersect($user_roles, $hide_admin_bar_roles);
$should_restrict_dashboard = array_intersect($user_roles, $restrict_dashboard_roles);
// Hide admin bar if needed
if (!empty($should_hide_admin_bar)) {
add_filter('show_admin_bar', '__return_false');
}
// Restrict dashboard access if needed
if (!empty($should_restrict_dashboard) && is_admin() && !wp_doing_ajax()) {
// Allow access to profile page
if (isset($_GET['page']) && $_GET['page'] === 'profile.php') {
return;
}
// Redirect to home page
wp_redirect(home_url());
exit;
}
}
/**
* Display the access control settings in the advanced tab
*/
public static function display_access_settings() {
// Register the additional toggle settings (matching the working toggle switches format)
register_setting('wp_allstars_access', 'wp_allstars_hide_admin_bar');
register_setting('wp_allstars_access', 'wp_allstars_restrict_dashboard');
// Get current settings
$hide_admin_bar = get_option('wp_allstars_hide_admin_bar', 0);
$restrict_dashboard = get_option('wp_allstars_restrict_dashboard', 0);
$hide_admin_bar_roles = get_option('wp_allstars_hide_admin_bar_roles', array());
$restrict_dashboard_roles = get_option('wp_allstars_restrict_dashboard_roles', array());
// Ensure the toggle state matches the role array
if (!empty($hide_admin_bar_roles) && !$hide_admin_bar) {
update_option('wp_allstars_hide_admin_bar', 1);
$hide_admin_bar = 1;
} else if (empty($hide_admin_bar_roles) && $hide_admin_bar) {
update_option('wp_allstars_hide_admin_bar', 0);
$hide_admin_bar = 0;
}
if (!empty($restrict_dashboard_roles) && !$restrict_dashboard) {
update_option('wp_allstars_restrict_dashboard', 1);
$restrict_dashboard = 1;
} else if (empty($restrict_dashboard_roles) && $restrict_dashboard) {
update_option('wp_allstars_restrict_dashboard', 0);
$restrict_dashboard = 0;
}
// Get all available roles
$roles = wp_roles()->get_names();
?>
<!-- Admin Bar Control -->
<div class="wp-allstars-toggle">
<div class="wp-allstars-toggle-header" aria-expanded="<?php echo !empty($hide_admin_bar_roles) ? 'true' : 'false'; ?>">
<div class="wp-allstars-toggle-main">
<div class="wp-allstars-toggle-left">
<div class="wp-toggle-switch">
<input type="checkbox"
id="wp_allstars_hide_admin_bar"
name="wp_allstars_hide_admin_bar"
value="1"
<?php checked($hide_admin_bar); ?>
/>
<span class="wp-toggle-slider"></span>
</div>
<label for="wp_allstars_hide_admin_bar">
<?php esc_html_e('Admin Bar: Remove for these User Roles', 'wp-allstars'); ?>
</label>
</div>
</div>
<p class="wp-setting-description">
<?php esc_html_e('Remove the Admin Bar from showing for logged-in Users that have consumer Roles, where Admin is not relevant to.', 'wp-allstars'); ?>
</p>
</div>
<div class="wp-allstars-toggle-settings" style="<?php echo !empty($hide_admin_bar_roles) ? 'display: block;' : 'display: none;'; ?>">
<div class="wp-allstars-setting-row">
<label><?php esc_html_e('Select User Roles', 'wp-allstars'); ?></label>
<div class="wp-allstars-role-checkboxes">
<?php foreach ($roles as $role_key => $role_name): ?>
<label class="wp-allstars-role-checkbox">
<input type="checkbox"
name="wp_allstars_hide_admin_bar_roles[]"
value="<?php echo esc_attr($role_key); ?>"
<?php checked(in_array($role_key, $hide_admin_bar_roles)); ?>
/>
<?php echo esc_html($role_name); ?>
</label>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<!-- Dashboard Access Control -->
<div class="wp-allstars-toggle">
<div class="wp-allstars-toggle-header" aria-expanded="<?php echo !empty($restrict_dashboard_roles) ? 'true' : 'false'; ?>">
<div class="wp-allstars-toggle-main">
<div class="wp-allstars-toggle-left">
<div class="wp-toggle-switch">
<input type="checkbox"
id="wp_allstars_restrict_dashboard"
name="wp_allstars_restrict_dashboard"
value="1"
<?php checked($restrict_dashboard); ?>
/>
<span class="wp-toggle-slider"></span>
</div>
<label for="wp_allstars_restrict_dashboard">
<?php esc_html_e('Dashboard: Prevent access for these User Roles', 'wp-allstars'); ?>
</label>
</div>
</div>
<p class="wp-setting-description">
<?php esc_html_e('Prevent the Admin Dashboard from being accessed by consumer Roles, where WP Admin is not relevant.', 'wp-allstars'); ?>
</p>
</div>
<div class="wp-allstars-toggle-settings" style="<?php echo !empty($restrict_dashboard_roles) ? 'display: block;' : 'display: none;'; ?>">
<div class="wp-allstars-setting-row">
<label><?php esc_html_e('Select User Roles', 'wp-allstars'); ?></label>
<div class="wp-allstars-role-checkboxes">
<?php foreach ($roles as $role_key => $role_name): ?>
<label class="wp-allstars-role-checkbox">
<input type="checkbox"
name="wp_allstars_restrict_dashboard_roles[]"
value="<?php echo esc_attr($role_key); ?>"
<?php checked(in_array($role_key, $restrict_dashboard_roles)); ?>
/>
<?php echo esc_html($role_name); ?>
</label>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<?php
}
}

View File

@ -113,9 +113,7 @@ class WP_Allstars_Admin_Manager {
'wp_allstars_max_height', 'wp_allstars_max_height',
'wp_allstars_exclude_urls', 'wp_allstars_exclude_urls',
'wp_allstars_image_name_pattern', 'wp_allstars_image_name_pattern',
'wp_allstars_image_alt_pattern', 'wp_allstars_image_alt_pattern'
'wp_allstars_hide_admin_bar',
'wp_allstars_restrict_dashboard'
); );
if (!in_array($option, $allowed_options)) { if (!in_array($option, $allowed_options)) {

View File

@ -71,7 +71,7 @@ class WP_Allstars_Settings_Manager {
?> ?>
<div class="wp-allstars-settings-section"> <div class="wp-allstars-settings-section">
<div class="wp-allstars-settings-grid"> <div class="wp-allstars-settings-grid">
<!-- Modern Admin Colors Setting --> <!-- Example of a simple toggle setting (no panel) -->
<div class="wp-setting-row"> <div class="wp-setting-row">
<div class="wp-setting-header"> <div class="wp-setting-header">
<div class="wp-setting-main"> <div class="wp-setting-main">
@ -86,12 +86,12 @@ class WP_Allstars_Settings_Manager {
<span class="wp-toggle-slider"></span> <span class="wp-toggle-slider"></span>
</div> </div>
<label for="wp_allstars_simple_setting" class="wp-setting-label"> <label for="wp_allstars_simple_setting" class="wp-setting-label">
<?php esc_html_e('Modern Admin Colors', 'wp-allstars'); ?> <?php esc_html_e('Example: Simple Toggle', 'wp-allstars'); ?>
</label> </label>
</div> </div>
</div> </div>
<p class="wp-setting-description"> <p class="wp-setting-description">
<?php esc_html_e('Switch to the Modern Admin colours, to remind that you\'re using an SEO Pro Stack :)', 'wp-allstars'); ?> <?php esc_html_e('This is an example of a simple toggle setting without an expandable panel. Currently for demonstration purposes only.', 'wp-allstars'); ?>
</p> </p>
</div> </div>
</div> </div>
@ -107,10 +107,41 @@ class WP_Allstars_Settings_Manager {
?> ?>
<div class="wp-allstars-settings-section"> <div class="wp-allstars-settings-section">
<div class="wp-allstars-settings-grid"> <div class="wp-allstars-settings-grid">
<?php <!-- Example of an expandable panel setting -->
// Display access control settings <div class="wp-allstars-toggle">
WP_Allstars_Access_Manager::display_access_settings(); <div class="wp-allstars-toggle-header" aria-expanded="false">
?> <div class="wp-allstars-toggle-main">
<div class="wp-allstars-toggle-left">
<div class="wp-toggle-switch">
<input type="checkbox"
id="wp_allstars_auto_upload_images"
name="wp_allstars_auto_upload_images"
value="1"
<?php checked(get_option('wp_allstars_auto_upload_images', false)); ?>
/>
<span class="wp-toggle-slider"></span>
</div>
<label for="wp_allstars_auto_upload_images">
<?php esc_html_e('Example: Expandable Panel', 'wp-allstars'); ?>
</label>
</div>
</div>
<p class="wp-setting-description">
<?php esc_html_e('This is an example of an expandable panel setting. Currently for demonstration purposes only - no actual functionality.', 'wp-allstars'); ?>
</p>
</div>
<div class="wp-allstars-toggle-settings">
<div class="wp-allstars-setting-row">
<label for="example_text"><?php esc_html_e('Example Text Field', 'wp-allstars'); ?></label>
<input type="text"
id="example_text"
name="example_text"
value="Example value"
/>
<p class="description"><?php esc_html_e('This is an example text field for demonstration purposes.', 'wp-allstars'); ?></p>
</div>
</div>
</div>
</div> </div>
</div> </div>
<?php <?php

View File

@ -1,199 +0,0 @@
<?php
/**
* WP ALLSTARS Admin Colors Feature
*
* Handles setting the admin color scheme based on user preferences
*
* @package WP_ALLSTARS
* @since 0.2.4
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
/**
* Admin Colors Handler Class
*/
class WP_Allstars_Admin_Colors {
/**
* Option name for the admin color scheme setting
*
* @var string
*/
private $option_name = 'wp_allstars_simple_setting';
/**
* Modern color scheme key
*
* @var string
*/
private $modern_scheme = 'modern';
/**
* Default color scheme key
*
* @var string
*/
private $default_scheme = 'fresh';
/**
* Initialize the class and set up hooks
*/
public function __construct() {
// Set up hooks
add_action('admin_init', array($this, 'set_admin_color_scheme'));
add_action('wp_ajax_wp_allstars_update_option', array($this, 'handle_color_scheme_update'), 5);
// Add script to handle the toggle
add_action('admin_enqueue_scripts', array($this, 'enqueue_color_scripts'));
// Add script for showing saved notification
add_action('admin_footer', array($this, 'add_saved_notification_script'));
}
/**
* Add script to show saved notification after page refresh
*/
public function add_saved_notification_script() {
// Only add on our settings page
$screen = get_current_screen();
if (!$screen || strpos($screen->id, 'wp-allstars') === false) {
return;
}
// Check if we have a transient indicating a recent save
$user_id = get_current_user_id();
$transient_name = 'wp_allstars_colors_updated_' . $user_id;
if (get_transient($transient_name)) {
// Add inline script to show the notification
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
// Get the label element
var $label = $('label[for="wp_allstars_simple_setting"]');
// Show notification using the plugin's existing showNotification function
if (typeof showNotification === 'function') {
showNotification('Saved', $label);
} else {
// Fallback implementation if showNotification isn't available
$('.wp-setting-notification').remove();
var $notification = $('<span class="wp-setting-notification">Saved</span>');
$label.after($notification);
setTimeout(function() {
$notification.fadeOut(300, function() {
$(this).remove();
});
}, 2000);
}
});
</script>
<?php
// Delete the transient so it only shows once
delete_transient($transient_name);
}
}
/**
* Enqueue JavaScript to handle toggle and page refresh
*/
public function enqueue_color_scripts($hook) {
// Only load on the plugin settings page
if (strpos($hook, 'wp-allstars') === false) {
return;
}
// Add inline JS for handling toggle and refresh
$color_js = '
jQuery(document).ready(function($) {
// Special handler for admin color scheme toggle
$("#wp_allstars_simple_setting").on("change", function() {
var isEnabled = $(this).is(":checked");
// Save setting via AJAX and refresh page
$.ajax({
url: ajaxurl,
type: "POST",
data: {
action: "wp_allstars_update_option",
option: "wp_allstars_simple_setting",
value: isEnabled ? 1 : 0,
nonce: "' . wp_create_nonce('wp-allstars-nonce') . '"
},
success: function() {
// Refresh the page after successful update
window.location.reload();
}
});
});
});
';
wp_add_inline_script('wp-allstars-admin', $color_js);
}
/**
* Set the admin color scheme based on the setting value
*/
public function set_admin_color_scheme() {
// Get current user
$user_id = get_current_user_id();
if (!$user_id) {
return;
}
// Check if our setting is enabled
$modern_colors_enabled = get_option($this->option_name, false);
// Get the scheme to set
$scheme = $modern_colors_enabled ? $this->modern_scheme : $this->default_scheme;
// Update user meta to set the color scheme
update_user_meta($user_id, 'admin_color', $scheme);
}
/**
* Handle color scheme update via AJAX
*/
public function handle_color_scheme_update() {
// Check for required params
if (!isset($_POST['option']) || !isset($_POST['value']) || !isset($_POST['nonce'])) {
return;
}
// Verify nonce
check_ajax_referer('wp-allstars-nonce', 'nonce');
// Only process our specific option
if ($_POST['option'] !== $this->option_name) {
return;
}
// Get the current user ID
$user_id = get_current_user_id();
if (!$user_id) {
return;
}
// Determine which scheme to set based on the value
$value = (bool) $_POST['value'];
$scheme = $value ? $this->modern_scheme : $this->default_scheme;
// Update the user's color scheme
update_user_meta($user_id, 'admin_color', $scheme);
// Update the option
update_option($this->option_name, $value ? 1 : 0);
// Set a transient to show the saved notice
set_transient('wp_allstars_colors_updated_' . $user_id, true, 30);
// Return success
wp_send_json_success();
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* WP ALLSTARS Sync Guard
*
* Prevents plugin loading during sync operations to avoid fatal errors.
*
* @package WP_ALLSTARS
* @since 0.2.3.1
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Class responsible for detecting sync operations and preventing plugin loading
*/
class WP_Allstars_Sync_Guard {
/**
* Flag file name for sync operations
*/
const SYNC_FLAG_FILE = '.syncing';
/**
* Check if sync is in progress
*
* @return bool Whether sync is in progress
*/
public static function is_sync_in_progress() {
$flag_file = plugin_dir_path(dirname(__FILE__)) . self::SYNC_FLAG_FILE;
return file_exists($flag_file);
}
/**
* Handle sync mode by showing admin notice and preventing plugin loading
*
* @return bool True if sync is in progress, false otherwise
*/
public static function handle_sync_mode() {
if (self::is_sync_in_progress()) {
// Add admin notice
add_action('admin_notices', array(__CLASS__, 'display_sync_notice'));
// Return true to indicate plugin should not continue loading
return true;
}
return false;
}
/**
* Display sync in progress notice
*/
public static function display_sync_notice() {
echo '<div class="notice notice-warning is-dismissible">';
echo '<p><strong>WP Allstars:</strong> Plugin files are currently syncing. The plugin functionality is temporarily disabled to prevent errors. Please try again in a moment.</p>';
echo '</div>';
}
}

View File

@ -6,7 +6,7 @@
* site performance, improve workflow, and provide recommendations for plugins and hosting. * site performance, improve workflow, and provide recommendations for plugins and hosting.
* *
* @package WP_ALLSTARS * @package WP_ALLSTARS
* @version v0.2.4 * @version v0.2.3.1
* *
* Plugin Name: WP Allstars * Plugin Name: WP Allstars
* Plugin URI: https://wpallstars.com * Plugin URI: https://wpallstars.com
@ -15,13 +15,13 @@
* Author URI: https://wpallstars.com * Author URI: https://wpallstars.com
* Text Domain: wp-allstars * Text Domain: wp-allstars
* Domain Path: /languages * Domain Path: /languages
* @version v0.2.4 * @version v0.2.3.1
* *
* WP Allstars is free software: you can redistribute it and/or modify * WP Allstars is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or
* any later version. * any later version.
* Version: v0.2.4 (Beta) * Version: v0.2.3.1 (Beta)
* *
* WP Allstars is distributed in the hope that it will be useful, * WP Allstars is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -30,61 +30,81 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with WP Allstars. If not, see https://www.gnu.org/licenses/gpl-2.0.html. * along with WP Allstars. If not, see https://www.gnu.org/licenses/gpl-2.0.html.
*
* Requires at least: 5.0
* Requires PHP: 7.2
*/ */
if (!defined('WPINC')) { if (!defined('WPINC')) {
exit; exit;
} }
// Define plugin version from the file header define('WP_ALLSTARS_VERSION', 'v0.2.3.1');
if (!function_exists('get_plugin_data')) {
require_once(ABSPATH . 'wp-admin/includes/plugin.php'); /**
* Load files safely by checking if they exist first
*/
function wp_allstars_require_if_exists($file) {
if (file_exists($file)) {
require_once $file;
return true;
}
return false;
} }
$plugin_data = get_plugin_data(__FILE__, false, false); /**
define('WP_ALLSTARS_VERSION', $plugin_data['Version']); * Check for sync operations before loading the plugin
*/
// Simple sync detection - check for .syncing file
if (file_exists(__DIR__ . '/.syncing')) {
// Only load the minimal code needed for admin notice
if (is_admin()) {
add_action('admin_notices', function() {
echo '<div class="notice notice-warning is-dismissible">';
echo '<p><strong>WP Allstars:</strong> Plugin files are currently syncing. The plugin functionality is temporarily disabled to prevent errors. Please try again in a moment.</p>';
echo '</div>';
});
}
// Exit early to prevent loading other files
return;
}
// Load the sync guard for future use and more advanced sync detection
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-sync-guard.php');
/** /**
* Plugin activation hook * Plugin activation hook
*/ */
function wp_allstars_activate() { function wp_allstars_activate() {
// Setup initial configuration when needed // Setup initial config
} }
register_activation_hook(__FILE__, 'wp_allstars_activate'); register_activation_hook(__FILE__, 'wp_allstars_activate');
/** // Core includes
* Load core plugin components wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-auto-upload.php');
*/
require_once plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-auto-upload.php';
require_once plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-admin-colors.php';
// Load admin-specific components // Admin includes
if (is_admin()) { if (is_admin()) {
// Include manager classes $admin_includes = array(
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-admin-manager.php'; 'admin/includes/class-admin-manager.php',
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-settings-manager.php'; 'admin/includes/class-settings-manager.php',
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-theme-manager.php'; 'admin/includes/class-theme-manager.php',
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-workflow-manager.php'; 'admin/includes/class-workflow-manager.php',
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-tools-manager.php'; 'admin/includes/class-tools-manager.php',
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-hosting-manager.php'; 'admin/includes/class-hosting-manager.php',
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-pro-plugins-manager.php'; 'admin/includes/class-pro-plugins-manager.php',
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-plugin-manager.php'; 'admin/includes/class-plugin-manager.php',
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-free-plugins-manager.php'; 'admin/includes/class-free-plugins-manager.php',
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-readme-manager.php'; 'admin/includes/class-readme-manager.php'
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-access-manager.php'; );
// Initialize the admin manager foreach ($admin_includes as $file) {
add_action('plugins_loaded', array('WP_Allstars_Admin_Manager', 'init')); wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . $file);
}
// Data files // Settings and data
require_once plugin_dir_path(__FILE__) . 'admin/data/pro-plugins.php'; wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'admin/data/pro-plugins.php');
require_once plugin_dir_path(__FILE__) . 'admin/data/readme.php'; wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'admin/data/readme.php');
// Legacy files (for backward compatibility) // Admin settings
require_once plugin_dir_path(__FILE__) . 'admin/settings.php'; wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'admin/settings.php');
} }
/** /**
@ -100,18 +120,6 @@ function wp_allstars_init_auto_upload() {
} }
add_action('init', 'wp_allstars_init_auto_upload'); add_action('init', 'wp_allstars_init_auto_upload');
/**
* Initialize core features
*/
function wp_allstars_init_features() {
// Initialize the Admin Colors feature
new WP_Allstars_Admin_Colors();
// Initialize the Access Manager
WP_Allstars_Access_Manager::init();
}
add_action('plugins_loaded', 'wp_allstars_init_features');
/** /**
* Initialize core plugin classes * Initialize core plugin classes
*/ */