12 Commits

Author SHA1 Message Date
84525b07b9 Fix tab navigation styling to match reference plugin exactly: correct spacing, remove unwanted background, fix active tab color, and ensure proper styling of toggle elements 2025-03-24 04:10:20 +00:00
4cf485041f Improve tab styling and refactor plugin architecture. Make Hosting tab class fully self-contained by internalizing data structures, fix CSS to match reference plugin, and remove duplicate function declarations. 2025-03-24 03:59:41 +00:00
a7537a000c Fix tab navigation styling and CSS class consistency. Update all wp-allstars and wpa- prefixes to seoprostack prefix for CSS classes, text domains, and selectors. 2025-03-24 03:51:56 +00:00
3cf5f63174 Fix refactoring issues in SEO Pro Stack plugin: Update CSS classes, text domains, and file references from wp-allstars to seoprostack 2025-03-24 03:43:20 +00:00
a6fef6200f Fix critical error in WordPress site
- Fixed incorrect path to auto-upload class file
- Updated JavaScript to use proper AJAX URL reference
- Fixed syntax and indentation issues in the admin JS file
- Ensured correct class instantiation
2025-03-24 03:38:03 +00:00
1259843d4c Match reference plugin structure and styling
- Updated main plugin file to match reference plugin structure
- Fixed CSS class naming to consistently use seoprostack prefix
- Updated JavaScript selectors to match CSS classes
- Restored original plugin functionality while maintaining new naming conventions
- Ensured exact match with reference plugin appearance and behavior
2025-03-24 03:32:53 +00:00
0e7b8a5cc6 Maintain exact functionality with reference plugin
- Updated wp-seoprostack-plugin.php to match reference plugin behavior
- Fixed JavaScript variable references to use wpSeoProStack consistently
- Updated AJAX action names to use wp_seoprostack_ prefix
- Ensured plugin matches reference plugin exactly in appearance and functionality
- Maintained pure naming convention and code structure refactoring without functional changes
2025-03-24 03:20:58 +00:00
6fc054f2bf Fix plugin activation and critical errors
- Fixed class naming inconsistency in auto-upload functionality
- Resolved duplicate menu items by removing direct inclusion of settings.php
- Fixed JavaScript variable naming from seoProStack to wpSeoProStack
- Added deprecation notice to legacy auto-upload class
- Updated AJAX nonce references for consistency
2025-03-24 03:11:03 +00:00
7f4ea3ec0c Fix fatal error: Address naming inconsistencies from WP Allstars to SEO Pro Stack refactoring
- Resolved class naming conflicts in auto-upload functionality
- Fixed menu slug from 'wp-allstars' to 'seoprostack'
- Corrected AJAX nonce references for consistency
- Updated JavaScript variable name to 'wpSeoProStack'
- Added deprecation notice to legacy auto-upload class
2025-03-24 03:06:21 +00:00
f2929bb43a Fix fatal error: Rename SEO_Pro_Stack_Auto_Upload class to SEOProStack_Auto_Upload to match autoloader naming convention 2025-03-24 03:00:59 +00:00
918d19085a Test updated post-commit hook 2025-03-24 02:53:09 +00:00
aee3cb91e2 Rename plugin to wp-seoprostack-plugin, update file structure 2025-03-24 02:48:06 +00:00
54 changed files with 7923 additions and 5383 deletions

2
.gitignore vendored
View File

@ -38,7 +38,7 @@ $RECYCLE.BIN/
.git_status_temp.txt
project-documents/
reference-plugins/
*.bak*
*.bak
node_modules/
composer.lock
package-lock.json

View File

@ -1,111 +0,0 @@
# 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

144
README.md
View File

@ -1,19 +1,19 @@
# WP Allstars
# SEO Pro Stack
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.
A WordPress plugin that enhances your WordPress site's SEO capabilities with curated tools, themes, hosting recommendations, and optimization features.
## Description
WP Allstars is a powerful WordPress plugin designed to help site owners and developers optimize their WordPress installations. It provides a curated collection of recommended plugins, themes, and optimization tools all in one place.
SEO Pro Stack is a powerful WordPress plugin designed to help site owners and developers optimize their WordPress installations for better search engine performance. It provides a curated collection of recommended plugins, themes, hosting providers, and optimization tools all in one place.
## Features
- **Curated Plugin Recommendations**: Browse and install recommended free plugins organized by category.
- **Pro Plugin Showcase**: Discover premium plugins with direct links to purchase.
- **Theme Integration**: Easily install and activate the Kadence theme.
- **Workflow Optimization**: Tools to streamline your WordPress workflow.
- **Advanced Settings**: Fine-tune your WordPress installation with advanced configuration options.
- **Pro Plugin Recommendations**: Browse and discover premium SEO and performance plugins with detailed information.
- **Theme Recommendations**: Find SEO-friendly themes that are optimized for performance and user experience.
- **Hosting Recommendations**: Choose the best hosting providers optimized for WordPress and SEO performance.
- **Advanced Settings**: Fine-tune your WordPress installation with SEO-focused configuration options.
- **Tools**: Optimize your database, generate robots.txt, and access other helpful SEO utilities.
- **Auto Upload**: Automatically upload and organize images for better content management.
## Installation
@ -24,90 +24,86 @@ WP Allstars is a powerful WordPress plugin designed to help site owners and deve
## Usage
After activation, you'll find the WP Allstars menu in your WordPress admin sidebar. The plugin includes several tabs:
After activation, you'll find the SEO Pro Stack menu in your WordPress admin sidebar. The plugin includes several tabs:
### General
### Pro Plugins
Basic settings for the plugin, including:
- Auto Upload Images
- Image Optimization
- Cache Management
Discover premium plugins specifically chosen to enhance your site's SEO performance:
- SEO Plugins
- Performance Plugins
- Content Plugins
- Analytics Plugins
### Theme
Find and install SEO-optimized themes:
- Fast-loading themes
- Schema-ready themes
- Mobile-optimized themes
- Accessibility-focused themes
### Advanced
Advanced configuration options for WordPress optimization:
- Disable unnecessary WordPress features
- Remove query strings from static resources
- Disable XML-RPC, embeds, and emojis
- Remove REST API links and other unnecessary metadata
- Performance Settings
- Security Enhancements
- Development Tools
### Recommended Plugins
### Workflow
Free and beneficial plugins that complement the SEO Pro Stack ecosystem:
- Essential plugin recommendations
- Plugin compatibility information
- Simplified installation process
Tools to improve your WordPress workflow:
### Hosting
- Content Management
- Media Handling
- Site Maintenance
Recommendations for WordPress hosting providers optimized for SEO:
- Managed WordPress hosting
- Performance-focused hosting
- Hosting provider comparisons
- Special offers and discounts
### Free Plugins
### Tools
Browse and install recommended free plugins organized by categories:
Utilities to help optimize your WordPress site:
- Database optimization
- Robots.txt generator
- SEO audit tools
- Cache management
- Minimal
- Admin
- AI
- CMS
- Compliance
- CRM
- Ecommerce
- LMS
- Media
- SEO
- Setup
- Social
- Speed
- Translation
- Advanced
- Debug
## File Structure
### Pro Plugins
The plugin follows a modular structure for better maintainability:
Discover premium plugins with direct links to purchase.
```
wp-seoprostack-plugin/
├── admin/
│ ├── css/
│ ├── images/
│ │ ├── hosting/
│ │ └── themes/
│ ├── js/
│ └── settings/
│ ├── ajax/
│ └── tabs/
├── includes/
│ ├── core/
│ └── features/
└── public/
```
### Theme
## Requirements
Easily install and activate the Kadence theme.
- WordPress 5.0 or higher
- PHP 7.2 or higher
## Development
## Changelog
### Requirements
- WordPress 5.8 or higher
- PHP 7.4 or higher
### Contributing
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature-name`
3. Commit your changes: `git commit -am 'Add some feature'`
4. Push to the branch: `git push origin feature/your-feature-name`
5. Submit a pull request
## License
This plugin is licensed under the GPL v2 or later.
### 1.0.0
- Initial release with comprehensive SEO tools and recommendations
## Credits
Developed by [Your Name/Company]
## Support
For support, please [create an issue](https://github.com/yourusername/wp-allstars/issues) on the GitHub repository.
## Debugging
- Debug mode can be enabled in wp-config.php
- Errors are logged to `wp-content/wp-allstars.log`
#
Developed by Marcus QuinnTest sync after hook update

View File

@ -1,51 +0,0 @@
# 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.

View File

@ -1,32 +0,0 @@
# 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]

View File

@ -1,70 +0,0 @@
# 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

@ -0,0 +1,123 @@
<?php
/**
* The admin-specific functionality of the plugin.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The admin-specific functionality of the plugin.
*/
class SEOProStack_Admin {
/**
* Initialize the admin functionality.
*/
public function initialize() {
// Register settings page
add_action('admin_menu', array($this, 'add_settings_page'));
// Register admin assets
add_action('admin_enqueue_scripts', array($this, 'enqueue_styles'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
// Initialize AJAX handlers
$this->init_ajax_handlers();
}
/**
* Register the stylesheets for the admin area.
*
* @param string $hook The current admin page.
*/
public function enqueue_styles($hook) {
// Only load styles on our settings page
if (strpos($hook, 'seoprostack') === false && strpos($hook, 'page=seoprostack') === false) {
return;
}
wp_enqueue_style(
'seoprostack-admin',
SEOPROSTACK_PLUGIN_URL . 'admin/css/seoprostack-admin.css',
array(),
SEOPROSTACK_VERSION
);
wp_enqueue_style(
'seoprostack-plugins',
SEOPROSTACK_PLUGIN_URL . 'admin/css/seoprostack-plugins.css',
array(),
SEOPROSTACK_VERSION
);
}
/**
* Register the JavaScript for the admin area.
*
* @param string $hook The current admin page.
*/
public function enqueue_scripts($hook) {
// Only load scripts on our settings page
if (strpos($hook, 'seoprostack') === false && strpos($hook, 'page=seoprostack') === false) {
return;
}
// Enqueue WordPress updates script for theme installation
wp_enqueue_script('updates');
wp_enqueue_script(
'seoprostack-admin',
SEOPROSTACK_PLUGIN_URL . 'admin/js/seoprostack-admin.js',
array('jquery', 'updates'),
SEOPROSTACK_VERSION,
true
);
// Localize script for AJAX
$ajax_data = array(
'ajaxurl' => admin_url('admin-ajax.php'),
'adminUrl' => admin_url(),
'nonce' => wp_create_nonce('seoprostack_ajax_nonce'),
'updateNonce' => wp_create_nonce('updates')
);
wp_localize_script('seoprostack-admin', 'seoProStack', $ajax_data);
}
/**
* Add settings page to the WordPress admin menu.
*/
public function add_settings_page() {
// Initialize settings page
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/class-seoprostack-settings-page.php';
$settings_page = new SEOProStack_Settings_Page();
$settings_page->add_menu_page();
$settings_page->register_settings();
}
/**
* Initialize AJAX handlers.
*/
public function init_ajax_handlers() {
// Pro Plugins AJAX handler
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/ajax/class-seoprostack-ajax-pro-plugins.php';
$pro_plugins_ajax = new SEOProStack_AJAX_Pro_Plugins();
$pro_plugins_ajax->init();
// Advanced Settings AJAX handler
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/ajax/class-seoprostack-ajax-advanced.php';
$advanced_ajax = new SEOProStack_AJAX_Advanced();
$advanced_ajax->init();
// Tools AJAX handler
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/ajax/class-seoprostack-ajax-tools.php';
$tools_ajax = new SEOProStack_AJAX_Tools();
$tools_ajax->init();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,65 +1,45 @@
/* Plugin Browser Styles */
.wp-allstars-wrap .wp-allstars-plugin-browser {
margin: 0 !important;
padding: 0 !important;
.seoprostack-wrap .seoprostack-plugin-browser {
margin: 0 -8px !important;
padding: 0 8px !important;
width: 100% !important;
max-width: 100% !important;
}
/* Plugin List Container */
.wp-allstars-wrap #wpa-plugin-list {
display: flex;
flex-direction: column;
align-items: center;
margin: 0;
padding: 20px;
max-width: 700px;
margin: 0 auto;
}
/* Filter Bar - Full Width */
.wp-allstars-wrap #wpa-plugin-filters.wp-filter {
margin: 0 0 11px 0 !important;
width: 100% !important;
max-width: 100% !important;
box-sizing: border-box;
text-align: center;
}
/* Center filter links */
.wp-filter .filter-links {
.seoprostack-wrap #seoprostack-plugin-list {
display: flex;
flex-wrap: wrap;
justify-content: center;
float: none !important;
margin: 0 auto;
margin: 0;
width: 100%;
}
.wp-filter .filter-links li {
float: none;
display: inline-block;
/* Filter Bar */
.seoprostack-wrap #seoprostack-plugin-filters.wp-filter {
margin-left: 0;
margin-right: 0;
width: 100%;
box-sizing: border-box;
}
/* Responsive filters */
@media screen and (max-width: 782px) {
.wp-filter .filter-links li > a {
padding: 12px 8px;
font-size: 13px;
}
/* Standard WordPress Plugin Grid Layout - exactly matching core */
.seoprostack-wrap .wp-list-table.plugin-install {
margin-top: 20px;
clear: both;
padding: 0;
}
@media screen and (max-width: 600px) {
.wp-filter .filter-links li > a {
padding: 10px 6px;
font-size: 12px;
}
.seoprostack-wrap #the-list {
margin: 0;
display: flex;
flex-wrap: wrap;
padding: 0;
}
/* Plugin Cards - Use consistent layout similar to 768px width for all screens */
/* Plugin Cards - essential layout only */
.plugin-card {
margin: 0 0 24px 0 !important;
width: 100% !important;
margin: 0 8px 16px;
width: calc(50% - 16px);
background-color: #fff;
border: 1px solid #dcdcde;
border-radius: 8px;
@ -67,13 +47,6 @@
box-sizing: border-box;
transition: all 0.2s ease;
overflow: hidden;
display: flex;
flex-direction: column;
position: relative !important;
}
.plugin-card:last-child {
margin-bottom: 0 !important;
}
.plugin-card:hover {
@ -81,123 +54,23 @@
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
/* Card Content */
.plugin-card-top {
padding: 24px !important;
position: relative;
flex-grow: 1;
/* Ensure the right edge aligns with the navigation above */
.plugin-card:nth-child(even) {
margin-right: 0;
}
.plugin-icon {
position: relative !important;
float: left !important;
width: 64px !important;
height: 64px !important;
margin: 0 20px 15px 0 !important;
.plugin-card:nth-child(odd) {
margin-left: 0;
}
/* Name and description positioning - 768px style */
.name.column-name {
margin: 0 0 12px 84px !important;
margin-right: 0 !important; /* Full width content */
/* Consistent styling for all widths */
/* Force equal spacing between all cards */
.plugin-card:nth-child(odd) {
margin-right: 8px;
}
.name.column-name h3 {
font-size: 16px !important;
font-weight: 600 !important;
line-height: 1.4 !important;
margin: 0 0 12px !important;
color: #1d2327 !important;
word-wrap: break-word !important;
}
.desc.column-description {
margin: 0 0 20px 84px !important;
margin-right: 0 !important; /* Full width content */
font-size: 14px !important;
line-height: 1.6 !important;
color: #50575e !important;
}
/* Action Links - Position below content */
.action-links {
position: relative !important;
width: 100% !important;
display: flex !important;
flex-direction: row !important;
align-items: center !important;
justify-content: flex-end !important;
gap: 8px !important;
padding: 0 !important;
margin-top: 10px !important;
}
.plugin-action-buttons {
margin: 0 !important;
float: none !important;
width: auto !important;
}
.plugin-action-buttons .button {
width: auto !important;
min-width: 120px !important;
text-align: center !important;
}
/* Card Bottom - Right aligned compatibility text */
.plugin-card-bottom {
background: #f6f7f7 !important;
padding: 15px 20px !important;
border-top: 1px solid #ddd !important;
text-align: right !important;
margin-top: auto !important;
}
/* Loading Overlay without white background */
.wp-allstars-loading-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: transparent !important;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 100;
}
/* Extra small screens only */
@media screen and (max-width: 480px) {
.plugin-card {
padding-top: 80px !important; /* Space for icon at top */
}
.name.column-name,
.desc.column-description {
margin-left: 0 !important;
}
.plugin-icon {
position: absolute !important;
top: 16px !important;
left: 16px !important;
float: none !important;
}
.action-links {
flex-direction: column !important;
align-items: stretch !important;
}
.plugin-action-buttons {
width: 100% !important;
}
.plugin-action-buttons .button {
width: 100% !important;
}
.plugin-card:nth-child(even) {
margin-left: 8px;
}
/* Global plugin icon positioning that applies to all viewport sizes */
@ -271,7 +144,7 @@ body.wp-admin .wp-list-table.plugin-install #the-list .plugin-card .plugin-card-
min-height: 100px !important;
position: relative !important;
padding: 20px !important;
padding-top: 22px !important; /* Force top padding to stay at 22px */
padding-top: 20px !important; /* Force top padding to stay at 20px */
overflow: hidden !important;
}
@ -279,7 +152,7 @@ body.wp-admin .wp-list-table.plugin-install #the-list .plugin-card .plugin-card-
@supports (display: flex) {
body.wp-admin .wp-list-table.plugin-install #the-list .plugin-card .plugin-card-top {
padding: 20px !important;
padding-top: 22px !important;
padding-top: 20px !important;
min-height: 100px !important;
}
}
@ -363,6 +236,13 @@ body.wp-admin .plugin-card-bottom {
margin-top: 0 !important;
text-align: left !important;
margin-left: 0 !important;
margin-right: 0 !important;
max-width: none !important;
clear: both !important;
width: 100% !important;
box-sizing: border-box !important;
border-bottom-left-radius: 8px !important;
border-bottom-right-radius: 8px !important;
}
/* Remove excessive spacing between elements */
@ -449,40 +329,6 @@ body.wp-admin .wp-list-table.plugin-install #the-list .plugin-card .action-links
line-height: 28px !important;
padding-top: 0 !important;
padding-bottom: 0 !important;
background-color: #d35400 !important;
color: #fff !important;
border-color: #c24e00 !important;
transition: all 0.3s ease !important;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2) !important;
position: relative !important;
overflow: hidden !important;
}
body.wp-admin .wp-list-table.plugin-install #the-list .plugin-card .action-links .button.go-pro::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: -100% !important;
width: 100% !important;
height: 100% !important;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent) !important;
transition: all 0.5s ease !important;
}
body.wp-admin .wp-list-table.plugin-install #the-list .plugin-card .action-links .button.go-pro:hover {
background-color: #aa4300 !important;
border-color: #953b00 !important;
transform: translateY(-2px) !important;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3) !important;
}
body.wp-admin .wp-list-table.plugin-install #the-list .plugin-card .action-links .button.go-pro:hover::before {
left: 100% !important;
}
body.wp-admin .wp-list-table.plugin-install #the-list .plugin-card .action-links .button.go-pro:active {
transform: translateY(0) !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3) !important;
}
/* Ensure consistent layout for action buttons */
@ -524,6 +370,7 @@ body.wp-admin .plugin-card-bottom .compatibility-untested *,
display: block;
}
.plugin-card:hover {
border-color: #999;
}
@ -676,7 +523,7 @@ body.wp-admin .plugin-card-bottom .compatibility-untested *,
.wp-filter {
display: flex;
flex-wrap: wrap;
margin: 12px 0 0;
margin: 12px 0 25px;
padding: 0 10px;
background: #fff;
border: 1px solid #dcdcde;
@ -770,12 +617,6 @@ body.wp-admin .plugin-card-bottom .compatibility-untested *,
}
/* Theme Browser */
.theme-browser {
max-width: 800px;
margin: 0 auto;
width: 100%;
}
.theme-browser .theme {
cursor: pointer;
float: left;
@ -910,10 +751,3 @@ body.wp-admin .plugin-card-bottom .compatibility-untested *,
.theme-browser .theme:nth-child(2n) {
margin-right: 0;
}
/* Theme browser proper layout */
.theme-browser .theme:nth-child(2n) {
margin-right: 0;
}
/* Remove media query for wider screens since we're using consistent layout */

File diff suppressed because it is too large Load Diff

View File

@ -1,161 +0,0 @@
<?php
/**
* Recommended plugins data for WP ALLSTARS plugin
*/
// Define recommended plugins
function wp_allstars_get_free_plugins() {
return array(
'minimal' => array(
'antispam-bee',
'compressx',
'fluent-smtp',
'kadence-blocks',
'simple-cloudflare-turnstile'
),
'admin' => array(
'admin-bar-dashboard-control',
'codepress-admin-columns',
'admin-menu-editor',
'hide-admin-notices',
'mainwp-child',
'mainwp-child-reports',
'magic-login',
'manage-notification-emails',
'plugin-groups',
'plugin-toggle'
),
'affiliates' => array(
'pretty-links',
'simple-urls',
'slicewp'
),
'ai' => array(
'ai-engine',
),
'cms' => array(
'auto-post-scheduler',
'block-options',
'bookmark-card',
'browser-shots',
'bulk-actions-select-all',
'bulk-edit-categories-tags',
'bulk-edit-user-profiles-in-spreadsheet',
'carbon-copy',
'code-block-pro',
'iframe-block',
'ics-calendar',
'mammoth-docx-converter',
'nav-menu-roles',
'ninja-tables',
'post-draft-preview',
'post-type-switcher',
'simple-custom-post-order',
'simple-icons',
'sticky-posts-switch',
'term-management-tools',
'the-paste',
'ultimate-addons-for-gutenberg',
'wikipedia-preview',
'wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages'
),
'compliance' => array(
'avatar-privacy',
'complianz-gdpr',
'complianz-terms-conditions',
'really-simple-ssl'
),
'crm' => array(
'fluent-boards',
'fluent-booking',
'fluent-community',
'fluent-crm',
'fluentform',
'fluentforms-pdf',
'fluentform-block',
'fluent-support'
),
'ecommerce' => array(
'woocommerce',
'woo-bulk-edit-products',
'woo-coupons-bulk-editor',
'woocommerce-gateway-gocardless',
'kadence-woocommerce-email-designer',
'pymntpl-paypal-woocommerce',
'woo-stripe-payment'
),
'lms' => array(
'fluent-community',
'masterstudy-lms-learning-management-system',
'tutor'
),
'media' => array(
'easy-watermark',
'enable-media-replace',
'image-copytrack',
'imsanity',
'media-file-renamer',
'safe-svg'
),
'seo' => array(
'burst-statistics',
'pretty-link',
'revive-so',
'seo-by-rank-math',
'syndication-links',
'ultimate-410',
'webmention'
),
'setup' => array(
'kadence-starter-templates',
'wordpress-importer'
),
'social' => array(
'bit-social',
'easy-video-reviews',
'social-engine',
'wp-social-ninja',
'wp-social-reviews'
),
'speed' => array(
'disable-wordpress-updates',
'flying-analytics',
'flying-pages',
'flying-scripts',
'freesoul-deactivate-plugins',
'index-wp-mysql-for-speed',
'litespeed-cache',
'performant-translations',
'wp-optimize',
'wp-widget-disable'
),
'translation' => array(
'hreflang-manager-lite',
'performant-translations',
'translatepress-multilingual'
),
'advanced' => array(
'acf-better-search',
'advanced-custom-fields',
'automatorwp',
'bit-pi',
'bit-integrations',
'code-snippets',
'easy-code-manager',
'favorites',
'remove-cpt-base',
'remove-old-slugspermalinks',
'secure-custom-fields',
'yellow-pencil-visual-theme-customizer'
),
'debug' => array(
'advanced-database-cleaner',
'debug-log-manager',
'gotmls',
'query-monitor',
'string-locator',
'user-switching',
'wp-crontrol'
)
);
}

View File

@ -1,46 +0,0 @@
<?php
/**
* Read Me data for WP ALLSTARS plugin
* Content is pulled from the README.md file
*/
if (!defined('ABSPATH')) {
exit;
}
// Define readme content
function wp_allstars_get_readme_content() {
// Get README.md content
$readme_path = WP_PLUGIN_DIR . '/wpa-superstar-plugin/README.md';
$readme_content = '';
if (file_exists($readme_path)) {
$readme_content = file_get_contents($readme_path);
} else {
// Fallback content if README.md is not found
$readme_content = <<<MARKDOWN
# WP Allstars
A WordPress plugin that enhances your WordPress experience with curated plugins, themes, and optimization tools.
## Description
WP Allstars is a powerful WordPress plugin designed to help site owners and developers optimize their WordPress installations. It provides a curated collection of recommended plugins, themes, and optimization tools all in one place.
## Features
- **Curated Plugin Recommendations**: Browse and install recommended free plugins organized by category.
- **Pro Plugin Showcase**: Discover premium plugins with direct links to purchase.
- **Theme Integration**: Easily install and activate the Kadence theme.
- **Workflow Optimization**: Tools to streamline your WordPress workflow.
- **Advanced Settings**: Fine-tune your WordPress installation with advanced configuration options.
Version: {WP_ALLSTARS_VERSION}
MARKDOWN;
}
return [
'title' => 'Read Me',
'content' => $readme_content
];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

View File

@ -1,313 +0,0 @@
<?php
/**
* WP ALLSTARS Admin Manager
*
* @package WP_ALLSTARS
* @since 0.2.0
*/
if (!defined('ABSPATH')) {
exit;
}
class WP_Allstars_Admin_Manager {
/**
* Initialize the class and register hooks
*/
public static function init() {
add_action('admin_menu', array(__CLASS__, 'register_admin_menu'));
add_action('wp_ajax_wp_allstars_update_option', array(__CLASS__, 'update_option'));
add_action('admin_init', array(__CLASS__, 'register_settings'));
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_admin_scripts'));
// Initialize all manager classes
WP_Allstars_Settings_Manager::init();
WP_Allstars_Theme_Manager::init();
WP_Allstars_Workflow_Manager::init();
WP_Allstars_Pro_Plugins_Manager::init();
WP_Allstars_Tools_Manager::init();
WP_Allstars_Hosting_Manager::init();
WP_Allstars_Free_Plugins_Manager::init();
}
/**
* Enqueue admin scripts and styles
*
* @param string $hook The current admin page hook
*/
public static function enqueue_admin_scripts($hook) {
if ('settings_page_wp-allstars' !== $hook) {
return;
}
// Enqueue admin stylesheet
wp_enqueue_style(
'wp-allstars-admin',
plugins_url('css/wp-allstars-admin.css', dirname(__FILE__)),
array(),
WP_ALLSTARS_VERSION
);
// Enqueue admin JavaScript
wp_enqueue_script(
'wp-allstars-admin',
plugins_url('js/wp-allstars-admin.js', dirname(__FILE__)),
array('jquery'),
WP_ALLSTARS_VERSION,
true
);
// Localize the script with necessary data for AJAX
wp_localize_script('wp-allstars-admin', 'wpAllstars', array(
'nonce' => wp_create_nonce('wp-allstars-nonce'),
'ajaxurl' => admin_url('admin-ajax.php')
));
}
/**
* Register core plugin settings
*/
public static function register_settings() {
// Core settings groups - tab-specific settings are registered in their respective manager classes
register_setting('wp_allstars_general', 'wp_allstars_general_settings');
register_setting('wp_allstars_advanced', 'wp_allstars_advanced_settings');
}
/**
* AJAX handler for updating options
*/
public static function update_option() {
// Verify nonce for security
check_ajax_referer('wp-allstars-nonce', 'nonce');
// Check if user has proper permissions
if (!current_user_can('manage_options')) {
wp_send_json_error('Insufficient permissions');
return;
}
// Validate and sanitize input
if (!isset($_POST['option']) || !isset($_POST['value'])) {
wp_send_json_error('Missing required parameters');
return;
}
$option = sanitize_text_field($_POST['option']);
// Different sanitization based on expected value type
$value = $_POST['value'];
if (is_numeric($value)) {
$value = intval($value);
} elseif (is_string($value)) {
$value = sanitize_text_field($value);
} elseif (is_array($value)) {
$value = array_map('sanitize_text_field', $value);
}
// Whitelist of allowed options to update for security
$allowed_options = array(
'wp_allstars_simple_setting',
'wp_allstars_auto_upload_images',
'wp_allstars_max_width',
'wp_allstars_max_height',
'wp_allstars_exclude_urls',
'wp_allstars_image_name_pattern',
'wp_allstars_image_alt_pattern'
);
if (!in_array($option, $allowed_options)) {
wp_send_json_error('Invalid option');
return;
}
// Update the option
$result = update_option($option, $value);
if ($result) {
wp_send_json_success(array(
'message' => 'Option updated successfully',
'option' => $option,
'value' => $value
));
} else {
wp_send_json_success(array(
'message' => 'No changes made to option',
'option' => $option
));
}
}
/**
* Register the admin menu item
*/
public static function register_admin_menu() {
add_options_page(
'WP ALLSTARS Settings',
'WP ALLSTARS',
'manage_options',
'wp-allstars',
array(__CLASS__, 'render_settings_page')
);
}
/**
* Render the settings page
*/
public static function render_settings_page() {
global $tabs;
$active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'general';
$active_category = isset($_GET['category']) ? $_GET['category'] : 'minimal';
// Tab-specific resources
if ($active_tab === 'recommended') {
WP_Allstars_Plugin_Manager::clear_plugin_cache();
wp_enqueue_script('plugin-install');
wp_enqueue_script('updates');
add_thickbox();
wp_enqueue_style('wp-allstars-plugins', plugins_url('css/wp-allstars-plugins.css', dirname(__FILE__)));
// Add inline script to load plugins on page load
wp_add_inline_script('wp-allstars-admin', '
jQuery(document).ready(function($) {
if ($("#wpa-plugin-list").length && $("#wpa-plugin-list").is(":empty")) {
var category = "' . esc_js($active_category) . '";
var $container = $("#wpa-plugin-list");
var $loadingOverlay = $("<div class=\"wp-allstars-loading-overlay\"><span class=\"spinner is-active\"></span></div>");
// Show loading overlay
$container.css("position", "relative").append($loadingOverlay);
// AJAX request to get plugins
$.ajax({
url: ajaxurl,
type: "POST",
data: {
action: "wp_allstars_get_plugins",
category: category,
_wpnonce: wpAllstars.nonce
},
success: function(response) {
$loadingOverlay.remove();
if (response.success) {
$container.html(response.data);
// Initialize plugin action buttons
if (typeof initPluginActions === "function") {
initPluginActions();
}
// Spinners have been removed from individual cards
} else {
$container.html("<div class=\"notice notice-error\"><p>" + response.data + "</p></div>");
}
},
error: function(xhr, status, error) {
$loadingOverlay.remove();
$container.html("<div class=\"notice notice-error\"><p>Failed to load plugins. Please try again. Error: " + error + "</p></div>");
console.error("AJAX Error:", xhr.responseText);
}
});
}
});
');
}
?>
<div class="wrap wp-allstars-wrap">
<div class="wp-allstars-header">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<div class="wp-allstars-header-actions">
<span class="wp-allstars-version"><?php echo esc_html(WP_ALLSTARS_VERSION); ?></span>
<a href="https://www.wpallstars.com/" target="_blank" class="button button-secondary green-button-secondary green-visit-website">
<?php esc_html_e('Visit Website', 'wp-allstars'); ?>
</a>
</div>
</div>
<div class="wp-allstars-tabs-wrapper">
<h2 class="nav-tab-wrapper">
<a href="?page=wp-allstars&tab=general" class="nav-tab <?php echo $active_tab === 'general' ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e('General', 'wp-allstars'); ?>
</a>
<a href="?page=wp-allstars&tab=advanced" class="nav-tab <?php echo $active_tab === 'advanced' ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e('Advanced', 'wp-allstars'); ?>
</a>
<a href="?page=wp-allstars&tab=workflow" class="nav-tab <?php echo $active_tab === 'workflow' ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e('Workflow', 'wp-allstars'); ?>
</a>
<a href="?page=wp-allstars&tab=theme" class="nav-tab <?php echo $active_tab === 'theme' ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e('Theme', 'wp-allstars'); ?>
</a>
<a href="?page=wp-allstars&tab=recommended" class="nav-tab <?php echo $active_tab === 'recommended' ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e('Free Plugins', 'wp-allstars'); ?>
</a>
<a href="?page=wp-allstars&tab=pro" class="nav-tab <?php echo $active_tab === 'pro' ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e('Pro Plugins', 'wp-allstars'); ?>
</a>
<a href="?page=wp-allstars&tab=hosting" class="nav-tab <?php echo $active_tab === 'hosting' ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e('Hosting', 'wp-allstars'); ?>
</a>
<a href="?page=wp-allstars&tab=tools" class="nav-tab <?php echo $active_tab === 'tools' ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e('Tools', 'wp-allstars'); ?>
</a>
<a href="?page=wp-allstars&tab=readme" class="nav-tab <?php echo $active_tab === 'readme' ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e('Read Me', 'wp-allstars'); ?>
</a>
</h2>
<div class="wp-allstars-tab-content">
<?php
// Each tab's content is handled by its respective manager class
switch ($active_tab) {
case 'general':
WP_Allstars_Settings_Manager::display_general_tab();
break;
case 'advanced':
WP_Allstars_Settings_Manager::display_advanced_tab();
break;
case 'workflow':
WP_Allstars_Workflow_Manager::display_tab_content();
break;
case 'theme':
WP_Allstars_Theme_Manager::display_tab_content();
break;
case 'recommended':
WP_Allstars_Free_Plugins_Manager::display_tab_content();
break;
case 'pro':
WP_Allstars_Pro_Plugins_Manager::display_tab_content();
break;
case 'hosting':
WP_Allstars_Hosting_Manager::display_tab_content();
break;
case 'tools':
WP_Allstars_Tools_Manager::display_tab_content();
break;
case 'readme':
WP_Allstars_Readme_Manager::display_tab_content();
break;
}
?>
</div>
</div>
</div>
<?php
}
/**
* Alias for enqueue_admin_scripts to maintain compatibility with settings.php
*
* @param string $hook The current admin page hook
*/
public static function enqueue_scripts($hook) {
self::enqueue_admin_scripts($hook);
}
}

View File

@ -1,186 +0,0 @@
<?php
/**
* WP ALLSTARS Free Plugins Manager
*
* Manages the Free Plugins tab including:
* - Category filtering system
* - Plugin recommendations by use case
* - Plugin installation functionality
*
* @package WP_ALLSTARS
* @since 0.2.0
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
/**
* WP_Allstars_Free_Plugins_Manager class
*
* Provides categorized plugin recommendations based on website needs
*/
class WP_Allstars_Free_Plugins_Manager {
/**
* Initialize the class and register hooks if needed
*
* @return void
*/
public static function init() {
// We'll implement AJAX handlers in a future update if needed
// add_action('wp_ajax_wp_allstars_load_free_plugins', array(self::class, 'ajax_load_free_plugins'));
}
/**
* Display the free plugins tab content
*
* Renders the category filter bar and plugin list container.
* Initial view shows 'minimal' category plugins by default.
*
* @return void
*/
public static function display_tab_content() {
// Get the active category from query params or use default
$active_category = isset($_GET['category']) ? sanitize_text_field($_GET['category']) : 'minimal';
// Get all available plugin categories from the data file
$plugin_categories = wp_allstars_get_free_plugins();
// Define all categories in the desired display order
$priority_categories = array(
'minimal', 'admin', 'affiliates', 'ai', 'cms',
'compliance', 'crm', 'ecommerce', 'lms', 'media',
'seo', 'setup', 'social', 'speed', 'translation',
'advanced', 'debug'
);
// Start HTML output
?>
<div class="wp-allstars-settings-content tab-content" id="recommended">
<div id="wpa-plugin-filters" class="wp-filter">
<ul class="filter-links">
<?php
// First output priority categories
foreach ($priority_categories as $category) {
if (isset($plugin_categories[$category])) {
$category_name = ucfirst($category);
if ($category == 'cms') $category_name = 'CMS';
if ($category == 'crm') $category_name = 'CRM';
if ($category == 'ecommerce') $category_name = 'eCommerce';
if ($category == 'lms') $category_name = 'LMS';
if ($category == 'seo') $category_name = 'SEO';
?>
<li><a href="#" data-category="<?php echo esc_attr($category); ?>" class="<?php echo $active_category == $category ? 'current' : ''; ?>">
<?php echo esc_html($category_name); ?>
</a></li>
<?php
}
}
// Add any new categories that might have been added to the data file but aren't in our priority list
$remaining_categories = array_diff(array_keys($plugin_categories), $priority_categories);
sort($remaining_categories);
foreach ($remaining_categories as $category) {
$category_name = ucfirst($category);
if ($category == 'cms') $category_name = 'CMS';
if ($category == 'crm') $category_name = 'CRM';
if ($category == 'ecommerce') $category_name = 'eCommerce';
if ($category == 'lms') $category_name = 'LMS';
if ($category == 'seo') $category_name = 'SEO';
?>
<li><a href="#" data-category="<?php echo esc_attr($category); ?>" class="<?php echo $active_category == $category ? 'current' : ''; ?>">
<?php echo esc_html($category_name); ?>
</a></li>
<?php
}
?>
</ul>
</div>
<div class="wp-allstars-plugin-browser" style="margin-top: 22px;">
<div id="wpa-plugin-list" class="wpa-plugin-container" style="position: relative; min-height: 200px;">
<!-- Plugin content will be loaded via AJAX -->
<div class="wp-allstars-loading-overlay">
<span class="spinner is-active"></span>
<p>Loading plugin data...</p>
</div>
</div>
</div>
<script>
jQuery(document).ready(function($) {
// Filter tab click handler
$('#wpa-plugin-filters .filter-links a').on('click', function(e) {
e.preventDefault();
var category = $(this).data('category');
var $container = $('#wpa-plugin-list');
// Update filter UI
$('#wpa-plugin-filters .filter-links a').removeClass('current');
$(this).addClass('current');
// Create new loading overlay
$container.empty();
var $loadingOverlay = $('<div class="wp-allstars-loading-overlay"><span class="spinner is-active"></span><p>Loading plugin data...</p></div>');
$container.append($loadingOverlay);
// Load plugins in selected category
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'wp_allstars_get_plugins',
category: category,
_wpnonce: '<?php echo wp_create_nonce('wp-allstars-nonce'); ?>'
},
success: function(response) {
$loadingOverlay.remove();
if (response.success) {
// Add plugins to the container
$container.html(response.data);
// Initialize plugin action buttons (fix for AJAX install/activate functionality)
if (typeof initPluginActions === "function") {
initPluginActions();
} else if (typeof window.initPluginActions === "function") {
window.initPluginActions();
}
} else {
$container.html('<div class="notice notice-error"><p>' + response.data + '</p></div>');
console.error('Error loading plugins:', response.data);
}
},
error: function(xhr, status, error) {
$loadingOverlay.remove();
$container.html('<div class="notice notice-error"><p>Failed to load plugins. Please try again. Error: ' + error + '</p></div>');
console.error('AJAX error:', xhr.responseText);
}
});
});
// Load initial category (minimal or from URL)
$('#wpa-plugin-filters .filter-links a.current').trigger('click');
});
</script>
</div>
<?php
}
/**
* Get the recommended plugins data
*
* @return array Array of recommended plugins by category
*/
public static function get_recommended_plugins() {
// Define the plugins data if it hasn't been included yet
if (!function_exists('wp_allstars_get_free_plugins')) {
require_once dirname(dirname(__FILE__)) . '/data/free-plugins.php';
}
return wp_allstars_get_free_plugins();
}
}

View File

@ -1,138 +0,0 @@
<?php
/**
* WP ALLSTARS Hosting Manager
*
* Manages the hosting providers tab and functionality
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
class WP_Allstars_Hosting_Manager {
/**
* Initialize the class
*/
public static function init() {
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_styles'));
}
/**
* Display the hosting tab content
*/
public static function display_tab_content() {
?>
<div class="wp-allstars-settings-content tab-content" id="hosting">
<div class="wpa-pro-plugins">
<?php
$hosting_providers = self::get_hosting_providers();
// Sort providers alphabetically by name
uasort($hosting_providers, function($a, $b) {
return strcasecmp($a['name'], $b['name']);
});
foreach ($hosting_providers as $provider) {
?>
<div class="wpa-pro-plugin">
<h3><?php echo esc_html($provider['name']); ?></h3>
<p><?php echo esc_html($provider['description']); ?></p>
<?php if (isset($provider['button_group'])): ?>
<div class="button-group">
<?php foreach ($provider['button_group'] as $button): ?>
<?php
$button_class = 'button';
if (isset($button['primary']) && $button['primary']) {
$button_class .= ' button-primary go-pro-button';
} else {
// Add green styling to secondary buttons
$button_class .= ' green-button-secondary';
// Special handling for Pricing buttons
if ($button['text'] === 'Pricing') {
$button_class .= ' pricing-button';
}
}
?>
<a href="<?php echo esc_url($button['url']); ?>" target="_blank" class="<?php echo esc_attr($button_class); ?>">
<?php echo esc_html($button['text']); ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php
}
?>
</div>
</div>
<?php
}
/**
* Get the list of hosting providers
*
* @return array Array of hosting providers
*/
public static function get_hosting_providers() {
// Define the providers data if it hasn't been included yet
if (!function_exists('wp_allstars_get_hosting_providers')) {
require_once dirname(dirname(__FILE__)) . '/data/hosting-providers.php';
}
return wp_allstars_get_hosting_providers();
}
/**
* Enqueue styles for the hosting tab
*
* @param string $hook Current admin page hook
*/
public static function enqueue_styles($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 CSS for hosting to match the single column layout
$custom_css = '
#hosting .wpa-pro-plugins {
padding: 15px 20px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 700px;
margin: 0 auto;
}
#hosting .wpa-pro-plugin {
background: #fff;
border: 1px solid #ddd;
padding: 24px;
border-radius: 8px;
display: flex;
flex-direction: column;
transition: all 0.2s ease;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
width: 100%;
margin-bottom: 24px;
max-width: 100%;
}
#hosting .wpa-pro-plugin:last-child {
margin-bottom: 0;
}
#hosting .wpa-pro-plugin:hover {
border-color: #2271b1;
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
#hosting .wpa-pro-plugin .button-group {
justify-content: flex-start;
}
';
wp_add_inline_style('wp-allstars-admin', $custom_css);
}
}

View File

@ -1,363 +0,0 @@
<?php
/**
* WP ALLSTARS Plugin Manager
*
* Core class for handling WordPress plugin data and operations:
* - Plugin data retrieval and caching mechanism
* - AJAX handlers for asynchronous plugin data loading
* - Plugin card UI generation with install/update actions
* - Cache clearing on plugin changes
*
* @package WP_ALLSTARS
* @since 0.2.0
*/
// Exit if accessed directly
if (!defined('ABSPATH')) {
exit;
}
/**
* WP_Allstars_Plugin_Manager class
*
* Manages the Free Plugins tab and provides core plugin functionality
* for other plugin-related managers.
*/
class WP_Allstars_Plugin_Manager {
/**
* Initialize the class and register all action hooks
*
* @return void
*/
public static function init() {
// Register AJAX handler for plugin data retrieval
add_action('wp_ajax_wp_allstars_get_plugins', [self::class, 'ajax_get_plugins']);
// Register hooks for automatic cache clearing when plugins change
add_action('upgrader_process_complete', [self::class, 'clear_plugin_cache'], 10, 0);
add_action('activated_plugin', [self::class, 'clear_plugin_cache']);
add_action('deactivated_plugin', [self::class, 'clear_plugin_cache']);
add_action('deleted_plugin', [self::class, 'clear_plugin_cache']);
add_action('update_option_active_plugins', [self::class, 'clear_plugin_cache']);
}
/**
* Get cached plugin data for a specific category
*
* Uses the WordPress transients API to store plugin data
* for improved performance and reduced API calls.
*
* @param string $category The plugin category to retrieve (e.g., 'featured', 'popular')
* @return mixed Array of plugin data if cache exists, false otherwise
*/
public static function get_cached_plugins($category) {
$cache_key = 'wp_allstars_plugins_' . sanitize_key($category);
$cached_data = get_transient($cache_key);
if ($cached_data !== false) {
return $cached_data;
}
return false;
}
/**
* Set cached plugin data for a category
*
* @param string $category The plugin category
* @param mixed $data The data to cache
*/
public static function set_cached_plugins($category, $data) {
$cache_key = 'wp_allstars_plugins_' . $category;
set_transient($cache_key, $data, 12 * HOUR_IN_SECONDS);
}
/**
* AJAX handler for getting plugin data
*/
public static function ajax_get_plugins() {
// Check nonce with the correct action name
if (!check_ajax_referer('wp-allstars-nonce', false, false)) {
wp_send_json_error('Invalid security token sent.');
return;
}
if (!current_user_can('install_plugins')) {
wp_die(-1);
}
$category = isset($_POST['category']) ? sanitize_key($_POST['category']) : 'minimal';
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
// Get our recommended plugins for this category
$recommended_plugins = wp_allstars_get_free_plugins();
if (!isset($recommended_plugins[$category])) {
wp_send_json_error('Invalid category: ' . $category);
return;
}
// Try to get cached data first
$cached_data = self::get_cached_plugins($category);
if ($cached_data !== false) {
error_log('Using cached data for category: ' . $category);
try {
// Generate plugin cards HTML
$html = self::generate_plugin_cards($cached_data->plugins);
wp_send_json_success($html);
return;
} catch (Exception $e) {
error_log('Error displaying cached plugins: ' . $e->getMessage());
// Fall through to fetch fresh data
}
}
error_log('Fetching fresh data for category: ' . $category);
error_log('Plugins to fetch: ' . implode(', ', $recommended_plugins[$category]));
try {
$plugins = array();
// Only fetch plugins that are in our recommended list for this category
foreach ($recommended_plugins[$category] as $slug) {
try {
error_log('Fetching plugin data for: ' . $slug);
$plugin_data = plugins_api('plugin_information', array(
'slug' => $slug,
'fields' => array(
'short_description' => true,
'sections' => false,
'requires' => true,
'rating' => true,
'ratings' => false,
'downloaded' => true,
'last_updated' => true,
'added' => false,
'tags' => false,
'compatibility' => false,
'homepage' => true,
'versions' => false,
'donate_link' => false,
'reviews' => false,
'banners' => false,
'icons' => true,
'active_installs' => true,
'group' => false,
'contributors' => false,
)
));
if (is_wp_error($plugin_data)) {
error_log('Error fetching plugin data for ' . $slug . ': ' . $plugin_data->get_error_message());
} else {
$plugins[] = $plugin_data;
error_log('Successfully fetched data for: ' . $slug);
}
} catch (Exception $e) {
error_log('Exception fetching plugin data for ' . $slug . ': ' . $e->getMessage());
continue;
}
}
if (empty($plugins)) {
wp_send_json_error('No plugin data could be retrieved for category: ' . $category);
return;
}
error_log('Total plugins fetched: ' . count($plugins));
// Create response object
$res = (object) array(
'info' => array(
'page' => 1,
'pages' => 1,
'results' => count($plugins),
),
'plugins' => $plugins
);
// Cache the results
self::set_cached_plugins($category, $res);
// Generate plugin cards HTML
$html = self::generate_plugin_cards($plugins);
wp_send_json_success($html);
} catch (Exception $e) {
error_log('Failed to fetch plugin data: ' . $e->getMessage());
wp_send_json_error('Failed to fetch plugin data: ' . $e->getMessage());
}
}
/**
* Generate HTML for plugin cards
*
* @param array $plugins Array of plugin data
* @return string HTML for the plugin cards
*/
public static function generate_plugin_cards($plugins) {
if (empty($plugins)) {
return '<div class="notice notice-error"><p>No plugins found.</p></div>';
}
ob_start();
?>
<div class="wp-list-table widefat plugin-install">
<div id="the-list">
<?php foreach ($plugins as $plugin): ?>
<div class="plugin-card plugin-card-<?php echo esc_attr($plugin->slug); ?>">
<div class="plugin-card-top">
<div class="name column-name">
<h3>
<?php echo esc_html($plugin->name); ?>
</h3>
</div>
<div class="action-links">
<ul class="plugin-action-buttons">
<?php
$status = install_plugin_install_status($plugin);
switch ($status['status']) {
case 'install':
echo '<li><a class="button install-now" data-slug="' . esc_attr($plugin->slug) . '" href="' . esc_url($status['url']) . '" aria-label="' . esc_attr(sprintf(__('Install %s now'), $plugin->name)) . '">' . __('Install now') . '</a></li>';
break;
case 'update_available':
echo '<li><a class="button button-primary update-now" data-plugin="' . esc_attr($status['file']) . '" data-slug="' . esc_attr($plugin->slug) . '" href="' . esc_url($status['url']) . '" aria-label="' . esc_attr(sprintf(__('Update %s now'), $plugin->name)) . '">' . __('Update Now') . '</a></li>';
break;
case 'latest_installed':
case 'newer_installed':
if (is_plugin_active($status['file'])) {
echo '<li><button type="button" class="button button-disabled" disabled="disabled">' . __('Active') . '</button></li>';
} else {
echo '<li><a class="button button-primary activate-now" href="' . esc_url(wp_nonce_url('plugins.php?action=activate&amp;plugin=' . $status['file'], 'activate-plugin_' . $status['file'])) . '" aria-label="' . esc_attr(sprintf(__('Activate %s'), $plugin->name)) . '">' . __('Activate') . '</a></li>';
}
break;
}
// Add PRO button if available
self::add_pro_button($plugin);
// Add "More Details" link
echo '<li><a class="thickbox open-plugin-details-modal" href="' . esc_url(admin_url('plugin-install.php?tab=plugin-information&plugin=' . $plugin->slug . '&TB_iframe=true&width=600&height=550')) . '" aria-label="' . esc_attr(sprintf(__('More information about %s'), $plugin->name)) . '">' . __('More Details') . '</a></li>';
?>
</ul>
</div>
<?php if (!empty($plugin->icons) && !empty($plugin->icons['1x'])): ?>
<div class="plugin-icon">
<img src="<?php echo esc_url($plugin->icons['1x']); ?>" alt="">
</div>
<?php endif; ?>
<div class="desc column-description">
<p><?php echo esc_html($plugin->short_description); ?></p>
<p class="authors">
<cite><?php printf(__('By %s'), $plugin->author); ?></cite>
</p>
</div>
</div>
<div class="plugin-card-bottom">
<div class="vers column-rating">
<?php wp_star_rating(array('rating' => $plugin->rating, 'type' => 'percent', 'number' => $plugin->num_ratings)); ?>
<span class="num-ratings" aria-hidden="true">(<?php echo number_format_i18n($plugin->num_ratings); ?>)</span>
</div>
<div class="column-updated">
<strong><?php _e('Last Updated:'); ?></strong>
<?php printf(__('%s ago'), human_time_diff(strtotime($plugin->last_updated))); ?>
</div>
<div class="column-downloaded">
<?php
if ($plugin->active_installs >= 1000000) {
$active_installs_millions = floor($plugin->active_installs / 1000000);
$active_installs_text = sprintf(
_n('%s+ Million Active Installations', '%s+ Million Active Installations', $active_installs_millions),
number_format_i18n($active_installs_millions)
);
} elseif (0 == $plugin->active_installs) {
$active_installs_text = _x('Less Than 10 Active Installations', 'Active plugin installations');
} else {
$active_installs_text = sprintf(
_n('%s+ Active Installation', '%s+ Active Installations', $plugin->active_installs),
number_format_i18n($plugin->active_installs)
);
}
/* translators: %s: number of active installations */
echo esc_html($active_installs_text);
?>
</div>
<div class="column-compatibility">
<?php
$version = get_bloginfo('version');
if (!empty($plugin->tested) && version_compare($version, $plugin->tested, '>')) {
echo '<span class="compatibility-untested">' . __('Untested with your version of WordPress') . '</span>';
} elseif (!empty($plugin->requires) && version_compare($version, $plugin->requires, '<')) {
echo '<span class="compatibility-incompatible">' . __('Incompatible with your version of WordPress') . '</span>';
} else {
echo '<span class="compatibility-compatible">' . __('Compatible with your version of WordPress') . '</span>';
}
?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php
return ob_get_clean();
}
/**
* Add PRO button to plugin cards if a pro version exists
*
* @param object $plugin The plugin object
*/
public static function add_pro_button($plugin) {
$pro_plugins = wp_allstars_get_pro_plugins();
if (isset($pro_plugins[$plugin->slug])) {
$pro_plugin = $pro_plugins[$plugin->slug];
$pro_url = self::get_pro_plugin_url($pro_plugin);
if (!empty($pro_url)) {
echo '<li><a href="' . esc_url($pro_url) . '" target="_blank" class="button button-primary go-pro-button">' . esc_html__('Go Pro', 'wp-allstars') . '</a></li>';
}
}
}
/**
* Get the URL for a pro plugin from its config
*
* @param array $pro_plugin The pro plugin configuration array
* @return string The URL for the pro plugin
*/
public static function get_pro_plugin_url($pro_plugin) {
// First check if there's a button_group defined
if (isset($pro_plugin['button_group']) && is_array($pro_plugin['button_group'])) {
foreach ($pro_plugin['button_group'] as $button) {
// Return the URL for the primary button if available
if (isset($button['primary']) && $button['primary'] && !empty($button['url'])) {
return $button['url'];
}
}
// If no primary button found, return the first button URL
if (!empty($pro_plugin['button_group'][0]['url'])) {
return $pro_plugin['button_group'][0]['url'];
}
}
// Fall back to the main URL if available
if (!empty($pro_plugin['url'])) {
return $pro_plugin['url'];
}
return '';
}
/**
* Clear plugin cache when plugins are updated, activated, or deactivated
*/
public static function clear_plugin_cache() {
$recommended_plugins = wp_allstars_get_free_plugins();
foreach (array_keys($recommended_plugins) as $category) {
delete_transient('wp_allstars_plugins_' . $category);
}
}
}

View File

@ -1,227 +0,0 @@
<?php
/**
* WP ALLSTARS Pro Plugins Manager
*
* Handles premium plugin recommendations including:
* - Premium plugin information display
* - Purchase links and affiliate management
* - Plugin feature highlighting
* - Price and promotion display
*
* @package WP_ALLSTARS
* @since 0.2.0
*/
// If this file is called directly, abort.
if (!defined('WPINC')) {
die;
}
/**
* WP_Allstars_Pro_Plugins_Manager class
*
* Responsible for the Pro Plugins tab in the plugin interface.
*/
class WP_Allstars_Pro_Plugins_Manager {
/**
* Initialize the class and register required hooks
*
* @return void
*/
public static function init() {
// Enqueue pro plugins specific styles
add_action('admin_enqueue_scripts', array(self::class, 'enqueue_styles'));
}
/**
* Get all pro plugin configurations
*
* Retrieves premium plugin information from configuration,
* including pricing, features, and purchase links.
*
* @return array Array of premium plugin data
*/
public static function get_pro_plugins() {
// Load pro plugin configuration from the data file
return wp_allstars_get_pro_plugins();
}
/**
* Display the pro plugins tab content
*
* Renders the premium plugins tab with plugin cards
* in alphabetical order by name.
*
* @return void
*/
public static function display_tab_content() {
// Get premium plugin data
$pro_plugins = self::get_pro_plugins();
// Sort plugins alphabetically by name for consistent display
uasort($pro_plugins, function($a, $b) {
return strcasecmp($a['name'], $b['name']);
});
// Start the tab content container
echo '<div class="wp-allstars-settings-content tab-content" id="pro"><div class="wpa-pro-plugins">';
// Render each plugin card
foreach ($pro_plugins as $plugin) {
self::display_plugin_card($plugin);
}
// Close the container
echo '</div></div>';
}
/**
* Display a single plugin card
*
* @param array $plugin Plugin configuration
*/
public static function display_plugin_card($plugin) {
?>
<div class="wpa-pro-plugin">
<h3><?php echo esc_html($plugin['name']); ?></h3>
<p><?php echo esc_html($plugin['description']); ?></p>
<?php if (isset($plugin['button_group'])): ?>
<div class="button-group">
<?php foreach ($plugin['button_group'] as $button): ?>
<?php
$button_class = 'button';
if (isset($button['primary']) && $button['primary']) {
$button_class .= ' button-primary';
// Add green color to 'Go Pro' buttons
if ($button['text'] === 'Go Pro') {
$button_class .= ' go-pro-button';
}
} else {
// Add green styling to secondary buttons
$button_class .= ' green-button-secondary';
// Special handling for Pricing buttons
if ($button['text'] === 'Pricing') {
$button_class .= ' pricing-button';
}
}
?>
<a href="<?php echo esc_url($button['url']); ?>" target="_blank" class="<?php echo esc_attr($button_class); ?>">
<?php echo esc_html($button['text']); ?>
</a>
<?php endforeach; ?>
</div>
<?php else: ?>
<div class="button-group">
<?php if (!empty($plugin['demo_url'])): ?>
<a href="<?php echo esc_url($plugin['demo_url']); ?>" class="button green-button-secondary" target="_blank">
<?php esc_html_e('View Demo', 'wp-allstars'); ?>
</a>
<?php endif; ?>
<a href="<?php echo esc_url($plugin['url']); ?>" class="button button-primary go-pro-button" target="_blank">
<?php esc_html_e('Learn More', 'wp-allstars'); ?>
</a>
</div>
<?php endif; ?>
</div>
<?php
}
/**
* Enqueue styles specific to pro plugins
*/
public static function enqueue_styles($hook) {
// Only load on the plugin settings page
if (strpos($hook, 'wp-allstars') === false) {
return;
}
// Add inline CSS for pro plugins
$custom_css = '
.wpa-pro-plugins {
padding: 15px 20px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 700px;
margin: 0 auto;
}
.wpa-pro-plugin {
background: #fff;
border: 1px solid #ddd;
padding: 24px;
border-radius: 8px;
display: flex;
flex-direction: column;
transition: all 0.2s ease;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
width: 100%;
margin-bottom: 24px;
max-width: 100%;
}
.wpa-pro-plugin:last-child {
margin-bottom: 0;
}
.wpa-pro-plugin:hover {
border-color: #2271b1;
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
.wpa-pro-plugin h3 {
margin: 0 0 12px;
font-size: 16px;
font-weight: 600;
color: #1d2327;
line-height: 1.4;
}
.wpa-pro-plugin p {
margin: 0 0 16px;
color: #50575e;
font-size: 14px;
line-height: 1.6;
}
.wpa-pro-plugin .button-group {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: auto;
justify-content: flex-start;
}
.wpa-pro-plugin .button {
text-decoration: none;
min-width: 120px;
text-align: center;
height: 30px;
line-height: 28px;
padding: 0 12px;
font-size: 13px;
font-weight: normal;
margin: 0;
border: 1px solid #0071a1 !important;
border-radius: 3px !important;
background: #f6f7f7;
color: #0071a1;
display: inline-block;
vertical-align: top;
box-shadow: none;
cursor: pointer;
}
.wpa-pro-plugin .button:hover {
background: #f0f0f1;
border-color: #0071a1;
color: #0071a1;
}
.wpa-pro-plugin .button-primary {
background: #0071a1;
border-color: #0071a1;
color: #fff;
}
.wpa-pro-plugin .button-primary:hover {
background: #006291;
border-color: #006291;
color: #fff;
}
';
wp_add_inline_style('wp-allstars-admin', $custom_css);
}
}

View File

@ -1,126 +0,0 @@
<?php
/**
* Read Me Manager Class
*
* @package WP_ALLSTARS
* @since 0.2.0
*/
if (!defined('ABSPATH')) {
exit;
}
class WP_Allstars_Readme_Manager {
/**
* Initialize the class
*/
public static function init() {
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_styles'));
}
/**
* Enqueue styles for the readme tab
*
* @param string $hook Current admin page hook
*/
public static function enqueue_styles($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
);
}
/**
* Get the readme content
*
* @return array
*/
public static function get_readme_content() {
return wp_allstars_get_readme_content();
}
/**
* Display the readme tab content
*/
public static function display_tab_content() {
$readme = self::get_readme_content();
?>
<div class="wp-allstars-settings-content tab-content" id="readme">
<div class="wpa-pro-plugins">
<div class="wpa-pro-plugin">
<div class="wp-allstars-markdown-content">
<?php echo self::parse_markdown($readme['content']); ?>
</div>
</div>
</div>
</div>
<?php
}
/**
* Parse markdown content to HTML
*
* A simple markdown parser for basic formatting
*
* @param string $markdown The markdown content
* @return string The HTML content
*/
private static function parse_markdown($markdown) {
// Replace version placeholder with actual version
$markdown = str_replace('{WP_ALLSTARS_VERSION}', WP_ALLSTARS_VERSION, $markdown);
// Headers
$markdown = preg_replace('/^### (.*?)$/m', '<h3>$1</h3>', $markdown);
$markdown = preg_replace('/^## (.*?)$/m', '<h2>$1</h2>', $markdown);
$markdown = preg_replace('/^# (.*?)$/m', '<h1>$1</h1>', $markdown);
// Bold and Italic
$markdown = preg_replace('/\*\*(.*?)\*\*/s', '<strong>$1</strong>', $markdown);
$markdown = preg_replace('/\*(.*?)\*/s', '<em>$1</em>', $markdown);
// Process lists first - identify all list items
$markdown = preg_replace('/^- (.*?)$/m', '<li class="bullet-item">$1</li>', $markdown);
$markdown = preg_replace('/^\* (.*?)$/m', '<li class="bullet-item">$1</li>', $markdown);
$markdown = preg_replace('/^\d+\. (.*?)$/m', '<li class="number-item">$1</li>', $markdown);
// Group consecutive list items into appropriate list types
// First group bullet items into unordered lists
$markdown = preg_replace('/((?:<li class="bullet-item">.*?<\/li>\n)+)/s', '<ul class="wp-allstars-ul">$1</ul>', $markdown);
// Then group numbered items into ordered lists with a special class for indentation
$markdown = preg_replace('/((?:<li class="number-item">.*?<\/li>\n)+)/s', '<ol class="wp-allstars-ol numbered-list">$1</ol>', $markdown);
// Clean up the classes from the final output
$markdown = str_replace('class="bullet-item"', '', $markdown);
$markdown = str_replace('class="number-item"', '', $markdown);
$markdown = str_replace('class="wp-allstars-ul"', 'class="wp-allstars-list"', $markdown);
$markdown = str_replace('class="wp-allstars-ol numbered-list"', 'class="wp-allstars-list numbered-list"', $markdown);
// Links
$markdown = preg_replace('/\[(.*?)\]\((.*?)\)/s', '<a href="$2" target="_blank">$1</a>', $markdown);
// Paragraphs
$markdown = preg_replace('/^(?!<[a-z]).+$/m', '<p>$0</p>', $markdown);
// Fix multiple paragraph tags
$markdown = str_replace('<p><p>', '<p>', $markdown);
$markdown = str_replace('</p></p>', '</p>', $markdown);
// Fix lists within paragraphs
$markdown = str_replace('<p><ul>', '<ul>', $markdown);
$markdown = str_replace('</ul></p>', '</ul>', $markdown);
return $markdown;
}
}
// Initialize the class
WP_Allstars_Readme_Manager::init();

View File

@ -1,168 +0,0 @@
<?php
/**
* Settings Manager Class
*
* Handles the display and management of plugin settings tabs (General and Advanced).
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
class WP_Allstars_Settings_Manager {
/**
* Initialize the class
*/
public static function init() {
// Register settings
add_action('admin_init', array(self::class, 'register_settings'));
// Enqueue scripts and styles if needed
add_action('admin_enqueue_scripts', array(self::class, 'enqueue_scripts'));
}
/**
* Register plugin settings
*/
public static function register_settings() {
// General settings
register_setting('wp_allstars_settings', 'wp_allstars_simple_setting');
// Advanced settings
register_setting('wp_allstars_settings', 'wp_allstars_auto_upload_images');
}
/**
* Enqueue scripts and styles needed for settings
*/
public static function enqueue_scripts($hook) {
// Only load on the plugin settings page
if (strpos($hook, 'wp-allstars') === false) {
return;
}
// Add inline JS for toggle functionality
$toggle_js = '
jQuery(document).ready(function($) {
// Toggle expandable settings panels
$(".wp-allstars-toggle-header").on("click", function() {
var $this = $(this);
var $settings = $this.next(".wp-allstars-toggle-settings");
var isExpanded = $this.attr("aria-expanded") === "true";
// Toggle aria-expanded attribute
$this.attr("aria-expanded", !isExpanded);
// Toggle settings visibility
$settings.slideToggle(200);
});
});
';
wp_add_inline_script('wp-allstars-admin', $toggle_js);
}
/**
* Display the general tab content
*/
public static function display_general_tab() {
?>
<div class="wp-allstars-settings-section">
<div class="wp-allstars-settings-grid">
<!-- Example of a simple toggle setting (no panel) -->
<div class="wp-setting-row">
<div class="wp-setting-header">
<div class="wp-setting-main">
<div class="wp-setting-left">
<div class="wp-toggle-switch">
<input type="checkbox"
id="wp_allstars_simple_setting"
name="wp_allstars_simple_setting"
value="1"
<?php checked(get_option('wp_allstars_simple_setting', false)); ?>
/>
<span class="wp-toggle-slider"></span>
</div>
<label for="wp_allstars_simple_setting" class="wp-setting-label">
<?php esc_html_e('Example: Simple Toggle', 'wp-allstars'); ?>
</label>
</div>
</div>
<p class="wp-setting-description">
<?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>
</div>
</div>
</div>
</div>
<?php
}
/**
* Display the advanced tab content
*/
public static function display_advanced_tab() {
?>
<div class="wp-allstars-settings-section">
<div class="wp-allstars-settings-grid">
<!-- Example of an expandable panel setting -->
<div class="wp-allstars-toggle">
<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>
<?php
}
/**
* Save settings
*/
public static function save_settings() {
// Check for nonce
if (!isset($_POST['wp_allstars_settings_nonce']) || !wp_verify_nonce($_POST['wp_allstars_settings_nonce'], 'wp_allstars_save_settings')) {
return;
}
// Save general settings
update_option('wp_allstars_simple_setting', isset($_POST['wp_allstars_simple_setting']) ? 1 : 0);
// Save advanced settings
update_option('wp_allstars_auto_upload_images', isset($_POST['wp_allstars_auto_upload_images']) ? 1 : 0);
// Add settings saved notice
add_settings_error('wp_allstars_settings', 'settings_updated', __('Settings saved.', 'wp-allstars'), 'updated');
}
}

View File

@ -1,329 +0,0 @@
<?php
/**
* WP ALLSTARS Theme Manager
*
* Manages the Theme tab functionality including:
* - Theme data retrieval and caching
* - AJAX handlers for theme browsing
* - Theme activation and installation
* - Theme UI rendering
*
* @package WP_ALLSTARS
* @since 0.2.0
*/
// If this file is called directly, abort.
if (!defined('WPINC')) {
die;
}
/**
* WP_Allstars_Theme_Manager class
*
* Provides theme discovery and management functionality
*/
class WP_Allstars_Theme_Manager {
/**
* Initialize the class and register all action hooks
*
* @return void
*/
public static function init() {
// Register AJAX handlers for theme operations
add_action('wp_ajax_wp_allstars_get_themes', array(self::class, 'ajax_get_themes'));
add_action('wp_ajax_wp_allstars_activate_theme', array(self::class, 'activate_theme'));
// Register hooks for automatic cache clearing when themes change
add_action('upgrader_process_complete', array(self::class, 'clear_theme_cache'), 10, 0);
add_action('switch_theme', array(self::class, 'clear_theme_cache'));
// Enqueue theme-specific assets when needed
add_action('admin_enqueue_scripts', array(self::class, 'enqueue_scripts'));
}
/**
* Enqueue scripts and styles for the theme tab
*
* Loads necessary WordPress core scripts and stylesheets
* required for theme browsing and installation.
*
* @param string $hook The current admin page hook
* @return void
*/
public static function enqueue_scripts($hook) {
// Only load on plugin pages
if (strpos($hook, 'wp-allstars') === false) {
return;
}
// Only load when theme tab is active
if (!isset($_GET['tab']) || $_GET['tab'] !== 'theme') {
return;
}
// Load WordPress core theme functionality
require_once ABSPATH . 'wp-admin/includes/theme.php';
// Enqueue core WordPress scripts for theme operations
wp_enqueue_script('theme-install');
wp_enqueue_script('updates');
add_thickbox();
// Enqueue theme tab specific styles
wp_enqueue_style(
'wp-allstars-admin',
plugins_url('css/wp-allstars-admin.css', dirname(__FILE__)),
array(),
WP_ALLSTARS_VERSION
);
wp_enqueue_style('wp-allstars-plugins', plugins_url('css/wp-allstars-plugins.css', dirname(__FILE__)));
// Enqueue the main admin script before adding inline script
wp_enqueue_script('wp-allstars-admin', plugins_url('js/wp-allstars-admin.js', dirname(__FILE__)), array('jquery'), '1.0.0', true);
// Localize the script with nonce data
wp_localize_script('wp-allstars-admin', 'wpAllstars', array(
'nonce' => wp_create_nonce('wp-allstars-nonce'),
'ajaxurl' => admin_url('admin-ajax.php')
));
// Add inline script for theme loading and interaction
wp_add_inline_script('wp-allstars-admin', self::get_theme_scripts());
}
/**
* Get theme scripts for inline inclusion
*/
private static function get_theme_scripts() {
return '
jQuery(document).ready(function($) {
if ($("#wpa-theme-list").length) {
var $container = $("#wpa-theme-list");
var $loadingOverlay = $container.find(".wp-allstars-loading-overlay");
// AJAX request to get themes
$.ajax({
url: wpAllstars.ajaxurl,
type: "POST",
data: {
action: "wp_allstars_get_themes",
_wpnonce: wpAllstars.nonce
},
success: function(response) {
$loadingOverlay.remove();
if (response.success) {
$container.html(response.data);
// Initialize theme handlers - use the global function from admin.js
if (typeof window.initThemeHandlers === "function") {
window.initThemeHandlers();
}
} else {
$container.html("<div class=\"notice notice-error\"><p>" + response.data + "</p></div>");
}
},
error: function(xhr, status, error) {
$loadingOverlay.remove();
$container.html("<div class=\"notice notice-error\"><p>Failed to load themes. Please try again. Error: " + error + "</p></div>");
console.error("AJAX Error:", xhr.responseText);
}
});
}
});
';
}
/**
* Display the theme tab content
*/
public static function display_tab_content() {
?>
<div class="wp-allstars-settings-content tab-content" id="theme">
<div id="wpa-theme-list" class="wpa-theme-container">
<!-- Theme content will be loaded via AJAX -->
<div class="wp-allstars-loading-overlay">
<span class="spinner is-active"></span>
<p>Loading theme data...</p>
</div>
</div>
</div>
<?php
}
/**
* Get cached theme
*/
public static function get_cached_theme() {
$cache_key = 'wp_allstars_theme_kadence';
return get_transient($cache_key);
}
/**
* Set cached theme
*/
public static function set_cached_theme($data) {
$cache_key = 'wp_allstars_theme_kadence';
set_transient($cache_key, $data, 12 * HOUR_IN_SECONDS);
}
/**
* Clear theme cache
*/
public static function clear_theme_cache() {
delete_transient('wp_allstars_theme_kadence');
}
/**
* AJAX endpoint for getting themes
*/
public static function ajax_get_themes() {
error_log('WP ALLSTARS: Theme AJAX handler started');
// Check nonce with the correct action name
if (!isset($_POST['_wpnonce'])) {
error_log('WP ALLSTARS: No nonce provided');
wp_send_json_error('No security token provided.');
return;
}
// Use verify_nonce instead of check_ajax_referer for more reliable verification
if (!wp_verify_nonce($_POST['_wpnonce'], 'wp-allstars-nonce')) {
error_log('WP ALLSTARS: Invalid nonce: ' . sanitize_text_field($_POST['_wpnonce']));
wp_send_json_error('Invalid security token sent.');
return;
}
if (!current_user_can('install_themes')) {
error_log('WP ALLSTARS: User does not have permission to install themes');
wp_send_json_error('Permission denied');
return;
}
error_log('WP ALLSTARS: Starting theme fetch process');
try {
error_log('WP ALLSTARS: Fetching theme data for kadence');
// Check if we have cached data first
$theme_data = self::get_cached_theme();
// If no cached data, fetch from API
if (empty($theme_data)) {
error_log('WP ALLSTARS: No cached theme data, fetching from API');
// Get theme data with minimal fields
$theme_data = themes_api('theme_information', array(
'slug' => 'kadence',
'fields' => array(
'sections' => false,
'description' => true,
'rating' => true,
'ratings' => false,
'downloaded' => true,
'download_link' => true,
'last_updated' => true,
'homepage' => true,
'tags' => false,
'screenshot_url' => true,
'version' => true,
'requires' => true,
'requires_php' => true,
'active_installs' => true,
'author' => true,
'preview_url' => true,
)
));
// Cache the result if successful
if (!is_wp_error($theme_data)) {
self::set_cached_theme($theme_data);
}
} else {
error_log('WP ALLSTARS: Using cached theme data');
}
if (is_wp_error($theme_data)) {
error_log('WP ALLSTARS Theme API Error: ' . $theme_data->get_error_message());
wp_send_json_error('Theme API Error: ' . $theme_data->get_error_message());
return;
}
error_log('WP ALLSTARS: Successfully fetched theme data');
// Format author data
$author = '';
if (is_string($theme_data->author)) {
$author = $theme_data->author;
} elseif (is_array($theme_data->author)) {
$author = isset($theme_data->author['display_name']) ? $theme_data->author['display_name'] : '';
}
error_log('WP ALLSTARS: Theme data retrieved, generating HTML');
// Generate custom HTML for the theme using our template partial
ob_start();
include(plugin_dir_path(dirname(__FILE__)) . 'partials/theme-panel.php');
$html = ob_get_clean();
if (empty($html)) {
error_log('WP ALLSTARS: Empty HTML generated');
wp_send_json_error('Failed to generate theme display');
return;
}
error_log('WP ALLSTARS: Successfully generated theme display, HTML length: ' . strlen($html));
wp_send_json_success($html);
exit; // Ensure we exit after sending the JSON response
} catch (Exception $e) {
error_log('WP ALLSTARS Theme loading exception: ' . $e->getMessage());
error_log('WP ALLSTARS Theme loading exception trace: ' . $e->getTraceAsString());
wp_send_json_error('Theme loading error: ' . $e->getMessage());
} catch (Error $e) {
error_log('WP ALLSTARS Theme loading error: ' . $e->getMessage());
error_log('WP ALLSTARS Theme loading error trace: ' . $e->getTraceAsString());
wp_send_json_error('Theme loading error: ' . $e->getMessage());
}
}
/**
* AJAX handler for theme activation
*/
public static function activate_theme() {
// Debug information
error_log('Theme activation AJAX request received: ' . print_r($_POST, true));
// Check nonce with the correct action name
if (!check_ajax_referer('wp-allstars-nonce', '_wpnonce', false)) {
error_log('Theme activation failed: Invalid nonce');
wp_send_json_error('Invalid security token sent.');
return;
}
if (!current_user_can('switch_themes')) {
error_log('Theme activation failed: Permission denied');
wp_send_json_error('Permission denied');
return;
}
$theme = isset($_POST['theme']) ? sanitize_text_field($_POST['theme']) : '';
if (empty($theme)) {
error_log('Theme activation failed: No theme specified');
wp_send_json_error('No theme specified');
return;
}
// Get the theme object
$theme_obj = wp_get_theme($theme);
if (!$theme_obj->exists()) {
error_log('Theme activation failed: Theme does not exist - ' . $theme);
wp_send_json_error('Theme does not exist');
return;
}
// Set the new theme
switch_theme($theme);
error_log('Theme activation success - ' . $theme);
wp_send_json_success();
}
}

View File

@ -1,168 +0,0 @@
<?php
/**
* Tools Manager Class
*
* @package WP_ALLSTARS
* @since 0.2.0
*/
if (!defined('ABSPATH')) {
exit;
}
class WP_Allstars_Tools_Manager {
/**
* Initialize the class
*/
public static function init() {
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_styles'));
}
/**
* Enqueue styles for the tools tab
*
* @param string $hook Current admin page hook
*/
public static function enqueue_styles($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 CSS for tools to match the single column layout
$custom_css = '
#tools .wpa-pro-plugins {
padding: 15px 20px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 700px;
margin: 0 auto;
}
#tools .wpa-pro-plugin {
background: #fff;
border: 1px solid #ddd;
padding: 24px;
border-radius: 8px;
display: flex;
flex-direction: column;
transition: all 0.2s ease;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
width: 100%;
margin-bottom: 24px;
max-width: 100%;
}
#tools .wpa-pro-plugin:last-child {
margin-bottom: 0;
}
#tools .wpa-pro-plugin:hover {
border-color: #2271b1;
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
#tools .wpa-pro-plugin .button-group {
justify-content: flex-start;
}
';
wp_add_inline_style('wp-allstars-admin', $custom_css);
}
/**
* Get all tools
*
* @return array
*/
public static function get_tools() {
return wp_allstars_get_tools();
}
/**
* Display the tools tab content
*/
public static function display_tab_content() {
$tools = self::get_tools();
// Sort tools alphabetically by name
uasort($tools, function($a, $b) {
return strcasecmp($a['name'], $b['name']);
});
?>
<div class="wp-allstars-settings-content tab-content" id="tools">
<div class="wpa-pro-plugins">
<?php
foreach ($tools as $tool) {
self::display_tool_card(self::sanitize_tool_data($tool));
}
?>
</div>
</div>
<?php
}
/**
* Display a single tool card
*
* @param array $tool Sanitized tool configuration
*/
private static function display_tool_card($tool) {
// Ensure we have the required fields
if (empty($tool['name'])) {
return;
}
?>
<div class="wpa-pro-plugin">
<h3><?php echo esc_html($tool['name']); ?></h3>
<?php if (!empty($tool['description'])): ?>
<p><?php echo esc_html($tool['description']); ?></p>
<?php endif; ?>
<?php if (!empty($tool['button_group']) && is_array($tool['button_group'])): ?>
<div class="button-group">
<?php foreach ($tool['button_group'] as $button): ?>
<?php if (!empty($button['url']) && !empty($button['text'])): ?>
<?php
$button_class = 'button';
if (!empty($button['primary'])) {
$button_class .= ' button-primary go-pro-button';
} else {
$button_class .= ' green-button-secondary';
}
?>
<a
href="<?php echo esc_url($button['url']); ?>"
target="_blank"
class="<?php echo esc_attr($button_class); ?>"
>
<?php echo esc_html($button['text']); ?>
</a>
<?php endif; ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php
}
/**
* Sanitize tool data
*
* @param array $tool Raw tool data
* @return array Sanitized tool data
*/
private static function sanitize_tool_data($tool) {
return array(
'name' => isset($tool['name']) ? sanitize_text_field($tool['name']) : '',
'description' => isset($tool['description']) ? sanitize_text_field($tool['description']) : '',
'button_group' => isset($tool['button_group']) ? $tool['button_group'] : array(),
);
}
}

View File

@ -1,178 +0,0 @@
<?php
/**
* Workflow Manager Class
*
* @package WP_ALLSTARS
* @since 0.2.0
*/
if (!defined('ABSPATH')) {
exit;
}
class WP_Allstars_Workflow_Manager {
/**
* Initialize the class
*/
public static function init() {
add_action('admin_init', array(__CLASS__, 'register_settings'));
}
/**
* Register workflow settings
*/
public static function register_settings() {
register_setting('wp_allstars_workflow', 'wp_allstars_workflow_options');
register_setting('wp_allstars_workflow', 'wp_allstars_auto_upload_images');
register_setting('wp_allstars_workflow', 'wp_allstars_max_width');
register_setting('wp_allstars_workflow', 'wp_allstars_max_height');
register_setting('wp_allstars_workflow', 'wp_allstars_exclude_urls');
register_setting('wp_allstars_workflow', 'wp_allstars_image_name_pattern');
register_setting('wp_allstars_workflow', 'wp_allstars_image_alt_pattern');
}
/**
* Display the workflow tab content
*/
public static function display_tab_content() {
?>
<div class="wp-allstars-settings-content tab-content" id="workflow">
<div class="wp-allstars-toggle">
<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('Enable Auto Upload Images', 'wp-allstars'); ?>
</label>
</div>
</div>
<p class="wp-setting-description">
<?php esc_html_e('Import images that have external URLs into your Media Library when saving. Consider disabling during large data imports with many external image URLs.', 'wp-allstars'); ?>
</p>
</div>
<div class="wp-allstars-toggle-settings">
<div class="wp-allstars-setting-row">
<label for="wp_allstars_max_width"><?php esc_html_e('Max Width', 'wp-allstars'); ?></label>
<input type="number"
id="wp_allstars_max_width"
name="wp_allstars_max_width"
value="<?php echo esc_attr(get_option('wp_allstars_max_width', 2560)); ?>"
/>
<p class="description"><?php esc_html_e('Maximum width for uploaded images in pixels.', 'wp-allstars'); ?></p>
</div>
<div class="wp-allstars-setting-row">
<label for="wp_allstars_max_height"><?php esc_html_e('Max Height', 'wp-allstars'); ?></label>
<input type="number"
id="wp_allstars_max_height"
name="wp_allstars_max_height"
value="<?php echo esc_attr(get_option('wp_allstars_max_height', 2560)); ?>"
/>
<p class="description"><?php esc_html_e('Maximum height for uploaded images in pixels.', 'wp-allstars'); ?></p>
</div>
<div class="wp-allstars-setting-row">
<label for="wp_allstars_exclude_urls"><?php esc_html_e('Exclude URLs', 'wp-allstars'); ?></label>
<textarea id="wp_allstars_exclude_urls"
name="wp_allstars_exclude_urls"
rows="3"
placeholder="example.com&#10;another-domain.com"
><?php echo esc_textarea(get_option('wp_allstars_exclude_urls', '')); ?></textarea>
<p class="description"><?php esc_html_e('Enter domains to exclude (one per line). Images from these domains will not be imported.', 'wp-allstars'); ?></p>
</div>
<div class="wp-allstars-setting-row">
<label for="wp_allstars_image_name"><?php esc_html_e('Image Name Pattern', 'wp-allstars'); ?></label>
<input type="text"
id="wp_allstars_image_name"
name="wp_allstars_image_name"
value="<?php echo esc_attr(get_option('wp_allstars_image_name_pattern', '%filename%')); ?>"
/>
<p class="description">
<?php esc_html_e('Available patterns:', 'wp-allstars'); ?> %filename%, %post_id%, %postname%, %timestamp%, %date%, %year%, %month%, %day%
</p>
</div>
<div class="wp-allstars-setting-row">
<label for="wp_allstars_image_alt"><?php esc_html_e('Image Alt Pattern', 'wp-allstars'); ?></label>
<input type="text"
id="wp_allstars_image_alt"
name="wp_allstars_image_alt"
value="<?php echo esc_attr(get_option('wp_allstars_image_alt_pattern', '%filename%')); ?>"
/>
<p class="description">
<?php esc_html_e('Available patterns:', 'wp-allstars'); ?> %filename%, %post_title%, %post_id%, %postname%, %timestamp%
</p>
</div>
</div>
</div>
</div>
<?php
}
/**
* Save workflow settings via AJAX
*/
public static function save_settings() {
// Verify nonce for security
check_ajax_referer('wp-allstars-nonce', 'nonce');
// Check if user has proper permissions
if (!current_user_can('manage_options')) {
wp_send_json_error('Insufficient permissions');
return;
}
$options = array();
// Auto upload images setting
$options['auto_upload_images'] = isset($_POST['auto_upload_images']) ?
(bool) $_POST['auto_upload_images'] :
false;
// Max dimensions
$options['max_width'] = isset($_POST['max_width']) ?
absint($_POST['max_width']) :
2560;
$options['max_height'] = isset($_POST['max_height']) ?
absint($_POST['max_height']) :
2560;
// Exclude URLs
$options['exclude_urls'] = isset($_POST['exclude_urls']) ?
sanitize_textarea_field($_POST['exclude_urls']) :
'';
// Name and alt patterns
$options['image_name_pattern'] = isset($_POST['image_name_pattern']) ?
sanitize_text_field($_POST['image_name_pattern']) :
'%filename%';
$options['image_alt_pattern'] = isset($_POST['image_alt_pattern']) ?
sanitize_text_field($_POST['image_alt_pattern']) :
'%filename%';
// Update the options
update_option('wp_allstars_workflow_options', $options);
// Also update individual options for backward compatibility
update_option('wp_allstars_auto_upload_images', $options['auto_upload_images']);
update_option('wp_allstars_max_width', $options['max_width']);
update_option('wp_allstars_max_height', $options['max_height']);
update_option('wp_allstars_exclude_urls', $options['exclude_urls']);
update_option('wp_allstars_image_name_pattern', $options['image_name_pattern']);
update_option('wp_allstars_image_alt_pattern', $options['image_alt_pattern']);
wp_send_json_success('Workflow settings saved');
}
}

View File

@ -0,0 +1,403 @@
// Define loadTheme in the global scope so it can be called from inline scripts
var loadTheme;
jQuery(document).ready(function($) {
// Function to show notification
function showNotification(message, $element, isError = false) {
// Remove any existing notifications
$('.seoprostack-setting-notification').remove();
// Create notification element
var $notification = $('<span class="seoprostack-setting-notification' + (isError ? ' error' : '') + '">' + message + '</span>');
// If element is provided, show notification next to it
if ($element && $element.length) {
$element.after($notification);
} else {
// Fallback to header if no element provided
$('.seoprostack-header h1').after($notification);
}
// Fade out after delay
setTimeout(function() {
$notification.fadeOut(300, function() {
$(this).remove();
});
}, 2000);
}
// Handle option updates
function updateOption(option, value) {
return $.ajax({
url: wpSeoProStack.ajaxurl,
type: 'POST',
data: {
action: 'wp_seoprostack_update_option',
option: option,
value: value,
nonce: wpSeoProStack.nonce
}
}).then(function(response) {
if (!response.success) {
throw new Error(response.data || 'Error saving setting');
}
return response;
});
}
// Toggle sections
$('.seoprostack-toggle-header').on('click', function() {
$(this).toggleClass('active');
$(this).next('.seoprostack-toggle-settings').slideToggle(300);
});
// Tabs functionality (if not using WP default tabs)
$('.seoprostack-tab-nav a').on('click', function(e) {
e.preventDefault();
var targetTab = $(this).attr('href').substring(1);
// Update active tab
$('.seoprostack-tab-nav a').removeClass('active');
$(this).addClass('active');
// Show target tab content
$('.seoprostack-tab-content').hide();
$('#' + targetTab).show();
// Update URL without refreshing
if (history.pushState) {
var newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?page=seoprostack&tab=' + targetTab;
window.history.pushState({path: newUrl}, '', newUrl);
}
});
// Pro Plugins Tab
if ($('#pro-plugins').length) {
// Category filter
$('.seoprostack-category-filter a').on('click', function(e) {
e.preventDefault();
var category = $(this).data('category');
// Update active filter
$('.seoprostack-category-filter a').removeClass('active');
$(this).addClass('active');
// Show loading
$('#seoprostack-plugins-grid').addClass('loading');
// Load plugins
$.ajax({
url: wpSeoProStack.ajaxurl,
type: 'POST',
data: {
action: 'wp_seoprostack_get_plugins',
category: category,
nonce: wpSeoProStack.nonce
},
success: function(response) {
$('#seoprostack-plugins-grid').removeClass('loading');
if (response.success) {
renderPlugins(response.data.plugins);
} else {
$('#seoprostack-plugins-grid').html('<div class="seoprostack-notice seoprostack-notice-error">' + response.data.message + '</div>');
}
},
error: function() {
$('#seoprostack-plugins-grid').removeClass('loading');
$('#seoprostack-plugins-grid').html('<div class="seoprostack-notice seoprostack-notice-error">Error connecting to server</div>');
}
});
});
// Activate plugin
$(document).on('click', '.seoprostack-activate-plugin', function(e) {
e.preventDefault();
var $button = $(this);
var plugin = $button.data('plugin');
var $card = $button.closest('.seoprostack-plugin-card');
// Show loading
$button.prop('disabled', true).text('Activating...');
// Send activation request
$.ajax({
url: wpSeoProStack.ajaxurl,
type: 'POST',
data: {
action: 'wp_seoprostack_activate_plugin',
plugin: plugin,
nonce: wpSeoProStack.nonce
},
success: function(response) {
if (response.success) {
// Update UI
$button.text('Activated').addClass('button-disabled');
$card.find('.plugin-status').removeClass('not-installed installed').addClass('active').text('Active');
} else {
$button.prop('disabled', false).text('Activate');
alert(response.data.message);
}
},
error: function() {
$button.prop('disabled', false).text('Activate');
alert('Error connecting to server');
}
});
});
// Render plugins
function renderPlugins(plugins) {
var html = '';
if (plugins.length === 0) {
html = '<div class="seoprostack-notice seoprostack-notice-info">No plugins found in this category</div>';
} else {
plugins.forEach(function(plugin) {
var statusClass = plugin.active ? 'active' : (plugin.status === 'installed' ? 'installed' : 'not-installed');
var statusText = plugin.active ? 'Active' : (plugin.status === 'installed' ? 'Installed' : 'Not Installed');
var buttonText = plugin.active ? 'Activated' : 'Activate';
var buttonDisabled = plugin.active ? ' button-disabled' : '';
html += '<div class="seoprostack-plugin-card">';
html += '<div class="seoprostack-plugin-card-header">';
html += '<span class="plugin-status ' + statusClass + '">' + statusText + '</span>';
html += '</div>';
html += '<div class="seoprostack-plugin-card-content">';
html += '<h3>' + plugin.name + ' <span class="version">v' + plugin.version + '</span></h3>';
html += '<p>' + plugin.description + '</p>';
html += '<div class="seoprostack-plugin-card-footer">';
html += '<a href="' + plugin.url + '" class="button button-secondary" target="_blank">View Details</a>';
if (!plugin.active) {
html += '<button class="button button-primary seoprostack-activate-plugin' + buttonDisabled + '" data-plugin="' + plugin.path + '">' + buttonText + '</button>';
} else {
html += '<button class="button button-primary' + buttonDisabled + '">' + buttonText + '</button>';
}
html += '</div>';
html += '</div>';
html += '</div>';
});
}
$('#seoprostack-plugins-grid').html(html);
}
// Load initial plugins
$('.seoprostack-category-filter a.active').trigger('click');
}
// Advanced Tab Form
if ($('#seoprostack-advanced-settings-form').length) {
$('#seoprostack-advanced-settings-form').on('submit', function(e) {
e.preventDefault();
var $form = $(this);
var $button = $('#seoprostack-save-advanced-settings');
var $spinner = $button.next('.spinner');
var $response = $('#advanced-settings-response');
// Show loading
$button.prop('disabled', true);
$spinner.css('visibility', 'visible');
// Get form data
var formData = $form.serializeArray();
var data = {
action: 'wp_seoprostack_save_advanced_settings',
nonce: wpSeoProStack.nonce
};
// Convert form data to proper format
$.each(formData, function(i, field) {
data[field.name] = field.value;
});
// Add checkbox fields that might not be in formData
$form.find('input[type="checkbox"]').each(function() {
var name = $(this).attr('name');
if (data[name] === undefined) {
data[name] = 'no';
}
});
// Send AJAX request
$.post(seoProStack.ajaxurl, data, function(response) {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
// Show response
if (response.success) {
$response.html('<div class="seoprostack-notice seoprostack-notice-success">' + response.data.message + '</div>');
} else {
$response.html('<div class="seoprostack-notice seoprostack-notice-error">' + response.data.message + '</div>');
}
// Hide response after delay
setTimeout(function() {
$response.find('.seoprostack-notice').fadeOut(500, function() {
$(this).remove();
});
}, 3000);
}).fail(function() {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
// Show error
$response.html('<div class="seoprostack-notice seoprostack-notice-error">Error connecting to server</div>');
});
});
}
// Tools Tab
if ($('#tools').length) {
// Database Optimization
$('#seoprostack-optimize-db').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var $spinner = $button.next('.spinner');
var $response = $('#db-optimize-response');
// Show loading
$button.prop('disabled', true);
$spinner.css('visibility', 'visible');
// Send AJAX request
$.ajax({
url: wpSeoProStack.ajaxurl,
type: 'POST',
data: {
action: 'wp_seoprostack_optimize_database',
nonce: wpSeoProStack.nonce
},
success: function(response) {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
// Show response
if (response.success) {
$response.html('<div class="seoprostack-notice seoprostack-notice-success">' + response.data.message + '</div>');
// Update stats if provided
if (response.data.stats) {
updateDbStats(response.data.stats);
}
} else {
$response.html('<div class="seoprostack-notice seoprostack-notice-error">' + response.data.message + '</div>');
}
// Hide response after delay
setTimeout(function() {
$response.find('.seoprostack-notice').fadeOut(500, function() {
$(this).remove();
});
}, 5000);
},
error: function() {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
// Show error
$response.html('<div class="seoprostack-notice seoprostack-notice-error">Error connecting to server</div>');
}
});
});
// Function to update database stats
function updateDbStats(stats) {
if (stats.total_cleaned) {
$('#db-total-cleaned').text(stats.total_cleaned);
}
if (stats.db_size_before) {
$('#db-size-before').text(stats.db_size_before);
}
if (stats.db_size_after) {
$('#db-size-after').text(stats.db_size_after);
}
if (stats.savings_percentage) {
$('#db-savings').text(stats.savings_percentage + '%');
}
}
// Generate Robots.txt
$('#seoprostack-generate-robots').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var $spinner = $button.next('.spinner');
var $response = $('#robots-response');
var $content = $('#robots-content');
// Show loading
$button.prop('disabled', true);
$spinner.css('visibility', 'visible');
// Send AJAX request
$.ajax({
url: wpSeoProStack.ajaxurl,
type: 'POST',
data: {
action: 'wp_seoprostack_generate_robots',
nonce: wpSeoProStack.nonce
},
success: function(response) {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
// Show response
if (response.success) {
$response.html('<div class="seoprostack-notice seoprostack-notice-success">' + response.data.message + '</div>');
// Display robots.txt content
if (response.data.content) {
$content.val(response.data.content);
$content.closest('.seoprostack-setting-row').show();
}
} else {
$response.html('<div class="seoprostack-notice seoprostack-notice-error">' + response.data.message + '</div>');
}
},
error: function() {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
// Show error
$response.html('<div class="seoprostack-notice seoprostack-notice-error">Error connecting to server</div>');
}
});
});
// Copy to Clipboard Functionality
$('.seoprostack-copy-to-clipboard').on('click', function(e) {
e.preventDefault();
var targetId = $(this).data('target');
var $target = $('#' + targetId);
var $button = $(this);
var originalText = $button.text();
// Copy to clipboard
$target.select();
document.execCommand('copy');
// Update button text
$button.text('Copied!');
// Reset button text
setTimeout(function() {
$button.text(originalText);
}, 2000);
});
}
});
});

View File

@ -1,387 +0,0 @@
// Define loadTheme in the global scope so it can be called from inline scripts
var loadTheme;
jQuery(document).ready(function($) {
// Function to show notification
function showNotification(message, $element, isError = false) {
// Remove any existing notifications
$('.wp-setting-notification').remove();
// Create notification element
var $notification = $('<span class="wp-setting-notification' + (isError ? ' error' : '') + '">' + message + '</span>');
// If element is provided, show notification next to it
if ($element && $element.length) {
$element.after($notification);
} else {
// Fallback to header if no element provided
$('.wp-allstars-header h1').after($notification);
}
// Fade out after delay
setTimeout(function() {
$notification.fadeOut(300, function() {
$(this).remove();
});
}, 2000);
}
// Handle option updates
function updateOption(option, value) {
return $.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'wp_allstars_update_option',
option: option,
value: value,
nonce: wpAllstars.nonce
}
}).then(function(response) {
if (!response.success) {
throw new Error(response.data || 'Error saving setting');
}
return response;
});
}
// Handle toggle switch clicks
$('.wp-toggle-switch').on('click', function(e) {
e.stopPropagation();
var $checkbox = $(this).find('input[type="checkbox"]');
var isChecked = $checkbox.is(':checked');
$checkbox.prop('checked', !isChecked).trigger('change');
});
// Prevent label clicks from toggling the checkbox directly
$('.wp-setting-label, .wp-allstars-toggle-left label').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
});
// Handle checkbox changes
$('.wp-toggle-switch input[type="checkbox"]').on('change', function(e) {
e.stopPropagation();
var $input = $(this);
var option = $input.attr('name');
var value = $input.is(':checked') ? 1 : 0;
var $label = $input.closest('.wp-setting-left, .wp-allstars-toggle-left').find('label');
updateOption(option, value)
.then(function() {
showNotification('Saved', $label);
})
.catch(function() {
showNotification('Error saving settings', $label, true);
});
});
// Handle text input changes
$('.wp-allstars-setting-row input[type="text"], .wp-allstars-setting-row input[type="number"], .wp-allstars-setting-row textarea').on('blur change', function() {
var $input = $(this);
var option = $input.attr('name');
var value = $input.val();
var $label = $input.closest('.wp-allstars-setting-row').find('label').first();
updateOption(option, value)
.then(function() {
showNotification('Saved', $label);
})
.catch(function(error) {
console.error('Error:', error);
showNotification('Error saving setting', $label, true);
});
});
// Toggle expandable panels
$('.wp-allstars-toggle-header').on('click', function(e) {
if (!$(e.target).closest('.wp-toggle-switch').length &&
!$(e.target).closest('label').length) {
var $settings = $(this).closest('.wp-allstars-toggle').find('.wp-allstars-toggle-settings');
var isExpanded = $(this).attr('aria-expanded') === 'true';
$(this).attr('aria-expanded', !isExpanded);
$settings.slideToggle(200);
}
});
// Set initial panel states
$('.wp-allstars-toggle-header').each(function() {
var $settings = $(this).closest('.wp-allstars-toggle').find('.wp-allstars-toggle-settings');
var isExpanded = $(this).attr('aria-expanded') === 'true';
if (!isExpanded) {
$settings.hide();
}
});
// Remove JavaScript-based tab switching - let the native WordPress tab links work
// Plugin category filters
if ($('#wpa-plugin-filters').length) {
$('#wpa-plugin-filters a').on('click', function(e) {
e.preventDefault();
var category = $(this).data('category');
// Update active filter
$('#wpa-plugin-filters a').removeClass('current');
$(this).addClass('current');
// Load plugins for the selected category
loadPlugins(category);
});
// Load initial plugins if we're on the recommended tab
if ($('#recommended').is(':visible') && $('#wpa-plugin-list').is(':empty')) {
loadPlugins('minimal');
}
}
// Load theme tab content if we're on the theme tab
if ($('#theme').is(':visible') && $('#wpa-theme-list').length && $('#wpa-theme-list').is(':empty')) {
loadTheme();
}
// Function to load plugins
function loadPlugins(category) {
var $container = $('#wpa-plugin-list');
var $loadingOverlay = $('<div class="wp-allstars-loading-overlay"><span class="spinner is-active"></span></div>');
// Show loading overlay
$container.css('position', 'relative').append($loadingOverlay);
// Clear existing plugins
$container.empty().append($loadingOverlay);
// AJAX request to get plugins
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'wp_allstars_get_plugins',
category: category,
_wpnonce: wpAllstars.nonce
},
success: function(response) {
// Remove loading overlay
$loadingOverlay.remove();
if (response.success) {
// Append plugins HTML
$container.html(response.data);
// Initialize plugin action buttons
initPluginActions();
// Individual plugin card spinners have been removed
} else {
// Show error message
$container.html('<div class="notice notice-error"><p>' + response.data + '</p></div>');
}
},
error: function(xhr, status, error) {
// Remove loading overlay
$loadingOverlay.remove();
// Show error message
$container.html('<div class="notice notice-error"><p>Failed to load plugins. Please try again. Error: ' + error + '</p></div>');
console.error('AJAX Error:', xhr.responseText);
}
});
}
// Theme handlers are initialized directly from the inline script
// We don't need a separate loadTheme function anymore
// Initialize plugin action buttons
function initPluginActions() {
// Remove any existing event handlers to prevent duplicates
$('.plugin-card .install-now').off('click');
$('.plugin-card .update-now').off('click');
$('.plugin-card .activate-now').off('click');
// Install plugin
$('.plugin-card .install-now').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var slug = $button.data('slug');
$button.addClass('updating-message').text('Installing...');
wp.updates.installPlugin({
slug: slug,
success: function(response) {
$button.removeClass('updating-message').addClass('updated-message').text('Installed!');
setTimeout(function() {
// Replace the button with an activate button
var $parent = $button.parent();
$button.remove();
$parent.html('<a class="button activate-now" href="' + response.activateUrl + '" data-slug="' + slug + '" aria-label="Activate ' + slug + '">Activate</a>');
// Re-initialize the event handlers
initPluginActions();
}, 1000);
},
error: function(response) {
$button.removeClass('updating-message').text('Install Now');
alert(response.errorMessage);
}
});
});
// Update plugin
$('.plugin-card .update-now').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var slug = $button.data('slug');
$button.addClass('updating-message').text('Updating...');
wp.updates.updatePlugin({
slug: slug,
success: function() {
$button.removeClass('updating-message').addClass('updated-message').text('Updated!');
setTimeout(function() {
$button.removeClass('update-now updated-message')
.addClass('button-disabled')
.text('Active');
}, 1000);
},
error: function(response) {
$button.removeClass('updating-message').text('Update Now');
alert(response.errorMessage);
}
});
});
// Activate plugin
$('.plugin-card .activate-now').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var url = $button.attr('href');
var slug = $button.data('slug');
$button.addClass('updating-message').text('Activating...');
$.ajax({
url: url,
dataType: 'html',
success: function() {
$button.removeClass('updating-message').addClass('updated-message').text('Activated!');
setTimeout(function() {
// Replace the button with an active button
var $parent = $button.parent();
$button.remove();
$parent.html('<button type="button" class="button button-disabled" disabled="disabled">Active</button>');
}, 1000);
},
error: function() {
$button.removeClass('updating-message').text('Activate');
alert('Failed to activate plugin. Please try again or activate from the Plugins page.');
}
});
});
}
// Expose initPluginActions to global scope for use in other scripts
window.initPluginActions = initPluginActions;
// Initialize theme handlers
function initThemeHandlers() {
console.log('Initializing theme handlers');
// Remove any existing event handlers to prevent duplicates
$('.theme-actions .install-now').off('click');
$('.theme-actions .activate-now').off('click');
// Install theme - use wp.updates.installTheme AJAX method
$('.theme-actions .install-now').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var slug = $button.data('slug');
var buttonText = $button.text();
$button.addClass('updating-message').attr('aria-label', wp.updates.l10n.installing);
wp.updates.installTheme({
slug: slug,
success: function(response) {
$button.removeClass('updating-message').addClass('updated-message').attr('aria-label', wp.updates.l10n.installed);
setTimeout(function() {
// Replace the button with an activate button
var $parent = $button.parent();
$button.remove();
// Create activate URL with nonce
var activateUrl = ajaxurl + '?action=wp_allstars_activate_theme&theme=' + slug + '&_wpnonce=' + wpAllstars.nonce;
$parent.prepend('<a href="' + activateUrl + '" class="button button-primary activate-now" data-slug="' + slug + '" data-name="Kadence" data-nonce="' + wpAllstars.nonce + '">Activate</a>');
// Re-initialize the event handlers
initThemeHandlers();
}, 1000);
},
error: function(response) {
$button.removeClass('updating-message').text(buttonText);
alert(response.errorMessage || 'Error installing theme');
}
});
});
// Activate theme - use AJAX
$('.theme-actions .activate-now').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var slug = $button.data('slug');
var nonce = $button.data('nonce');
var buttonText = $button.text();
$button.addClass('updating-message').attr('aria-label', 'Activating...');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'wp_allstars_activate_theme',
theme: slug,
_wpnonce: wpAllstars.nonce
},
success: function(response) {
if (response.success) {
$button.removeClass('updating-message').addClass('updated-message').attr('aria-label', 'Activated');
setTimeout(function() {
// Replace the button with an active button
var $parent = $button.parent();
$button.remove();
$parent.prepend('<button type="button" class="button button-disabled" disabled="disabled">Active</button>');
// Optionally reload the page to show the activated theme
// window.location.reload();
}, 1000);
} else {
$button.removeClass('updating-message').text(buttonText);
alert(response.data || 'Error activating theme');
}
},
error: function(xhr, status, error) {
$button.removeClass('updating-message').text(buttonText);
alert('Failed to activate theme. Please try again or activate from the Themes page. Error: ' + error);
}
});
});
}
// Expose initThemeHandlers to global scope for use in other scripts
window.initThemeHandlers = initThemeHandlers;
});

View File

@ -1,8 +1,9 @@
<?php
/**
* Theme panel template for WP Allstars
* Theme panel template for SEO Pro Stack
*
* @package WP_Allstars
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Partials
*/
// Prevent direct access
@ -24,7 +25,7 @@ if (!defined('ABSPATH')) {
$installed_theme = wp_get_theme('kadence');
$current_theme = wp_get_theme();
$is_active = ($current_theme->get_stylesheet() === 'kadence');
$nonce = wp_create_nonce('wp-allstars-nonce');
$nonce = wp_create_nonce('wp-seoprostack-nonce');
if ($is_active): ?>
<button type="button" class="button button-disabled" disabled="disabled">
@ -73,22 +74,22 @@ if (!defined('ABSPATH')) {
});
</script>
<?php endif; ?>
<a class="button button-secondary green-button-secondary preview install-theme-preview" href="<?php echo esc_url($theme_data->preview_url); ?>" target="_blank">
<a class="button button-secondary preview install-theme-preview" href="<?php echo esc_url($theme_data->preview_url); ?>" target="_blank">
<?php esc_html_e('Preview'); ?>
</a>
<a class="button button-secondary green-button-secondary" href="https://www.kadencewp.com/kadence-theme/starter-templates/" target="_blank">
<a class="button button-secondary" href="https://www.kadencewp.com/kadence-theme/starter-templates/" target="_blank">
<?php esc_html_e('Templates'); ?>
</a>
<a class="button button-secondary green-button-secondary" href="https://www.kadencewp.com/wordpress-solutions/kadence-ai/" target="_blank">
<a class="button button-secondary" href="https://www.kadencewp.com/wordpress-solutions/kadence-ai/" target="_blank">
<?php esc_html_e('Starter AI'); ?>
</a>
<a class="button button-secondary green-button-secondary" href="https://www.kadencewp.com/kadence-theme/marketplace/" target="_blank">
<a class="button button-secondary" href="https://www.kadencewp.com/kadence-theme/marketplace/" target="_blank">
<?php esc_html_e('Marketplace'); ?>
</a>
<a class="button button-secondary green-button-secondary" href="https://www.kadencewp.com/pricing/" target="_blank">
<a class="button button-secondary" href="https://www.kadencewp.com/pricing/" target="_blank">
<?php esc_html_e('Pricing'); ?>
</a>
<a class="button button-primary go-pro-button" href="https://www.kadencewp.com/kadence-theme/" target="_blank">
<a class="button button-primary" href="https://www.kadencewp.com/kadence-theme/" target="_blank">
<?php esc_html_e('Go Pro'); ?>
</a>
</div>

View File

@ -3,7 +3,7 @@
* Pro Plugins Configuration
*/
function wp_allstars_get_pro_plugins() {
function wp_seoprostack_get_pro_plugins_config() {
return array(
'magic-login-pro' => array(
'name' => 'Magic Login Pro',
@ -776,3 +776,8 @@
)
);
}
// Backward compatibility alias
function wp_allstars_get_pro_plugins_config() {
return wp_seoprostack_get_pro_plugins_config();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,132 @@
<?php
/**
* The Advanced Settings AJAX handler.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/AJAX
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Advanced Settings AJAX handler.
*/
class SEOProStack_AJAX_Advanced {
/**
* Initialize the AJAX handlers.
*/
public function init() {
add_action('wp_ajax_seoprostack_save_advanced_settings', array($this, 'save_advanced_settings'));
add_action('wp_ajax_seoprostack_optimize_database', array($this, 'optimize_database'));
}
/**
* Save advanced settings.
*/
public function save_advanced_settings() {
// Verify nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'seoprostack_ajax_nonce')) {
wp_send_json_error(array('message' => 'Security check failed'));
}
// Check capabilities
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => 'You do not have permission to change settings'));
}
// Get settings
$settings = array(
'disable_emojis' => isset($_POST['disable_emojis']) ? sanitize_text_field($_POST['disable_emojis']) : 'no',
'disable_embeds' => isset($_POST['disable_embeds']) ? sanitize_text_field($_POST['disable_embeds']) : 'no',
'remove_query_strings' => isset($_POST['remove_query_strings']) ? sanitize_text_field($_POST['remove_query_strings']) : 'no',
'disable_xmlrpc' => isset($_POST['disable_xmlrpc']) ? sanitize_text_field($_POST['disable_xmlrpc']) : 'no',
'remove_shortlink' => isset($_POST['remove_shortlink']) ? sanitize_text_field($_POST['remove_shortlink']) : 'no',
'remove_rsd_link' => isset($_POST['remove_rsd_link']) ? sanitize_text_field($_POST['remove_rsd_link']) : 'no',
'remove_wlwmanifest_link' => isset($_POST['remove_wlwmanifest_link']) ? sanitize_text_field($_POST['remove_wlwmanifest_link']) : 'no',
'disable_self_pingbacks' => isset($_POST['disable_self_pingbacks']) ? sanitize_text_field($_POST['disable_self_pingbacks']) : 'no',
'disable_feed_links' => isset($_POST['disable_feed_links']) ? sanitize_text_field($_POST['disable_feed_links']) : 'no',
'remove_rest_api_links' => isset($_POST['remove_rest_api_links']) ? sanitize_text_field($_POST['remove_rest_api_links']) : 'no',
'minify_html' => isset($_POST['minify_html']) ? sanitize_text_field($_POST['minify_html']) : 'no',
'minify_css' => isset($_POST['minify_css']) ? sanitize_text_field($_POST['minify_css']) : 'no',
'minify_js' => isset($_POST['minify_js']) ? sanitize_text_field($_POST['minify_js']) : 'no'
);
// Save settings
update_option('seoprostack_advanced_settings', $settings);
// Flush rewrite rules if necessary
if (isset($settings['disable_feed_links']) && $settings['disable_feed_links'] === 'yes') {
flush_rewrite_rules();
}
// Send response
wp_send_json_success(array('message' => 'Settings saved successfully'));
}
/**
* Optimize database.
*/
public function optimize_database() {
global $wpdb;
// Verify nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'seoprostack_ajax_nonce')) {
wp_send_json_error(array('message' => 'Security check failed'));
}
// Check capabilities
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => 'You do not have permission to optimize database'));
}
// Tables to optimize
$tables = $wpdb->get_col("SHOW TABLES LIKE '{$wpdb->prefix}%'");
$optimized = 0;
$failed = 0;
foreach ($tables as $table) {
$result = $wpdb->query("OPTIMIZE TABLE $table");
if ($result === false) {
$failed++;
} else {
$optimized++;
}
}
// Delete post revisions
$deleted_revisions = $wpdb->query("DELETE FROM $wpdb->posts WHERE post_type = 'revision'");
// Delete auto drafts
$deleted_drafts = $wpdb->query("DELETE FROM $wpdb->posts WHERE post_status = 'auto-draft'");
// Delete trashed posts
$deleted_trash = $wpdb->query("DELETE FROM $wpdb->posts WHERE post_status = 'trash'");
// Delete spam comments
$deleted_spam = $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_approved = 'spam'");
// Delete trashed comments
$deleted_trash_comments = $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_approved = 'trash'");
// Delete expired transients
$deleted_transients = $wpdb->query("DELETE FROM $wpdb->options WHERE option_name LIKE '_transient_%' AND option_name NOT LIKE '_transient_timeout_%'");
// Send response
wp_send_json_success(array(
'message' => sprintf(
'Database optimization complete. %d tables optimized, %d revisions deleted, %d auto-drafts deleted, %d trash posts deleted, %d spam comments deleted, %d trash comments deleted, %d expired transients deleted.',
$optimized,
$deleted_revisions ? $deleted_revisions : 0,
$deleted_drafts ? $deleted_drafts : 0,
$deleted_trash ? $deleted_trash : 0,
$deleted_spam ? $deleted_spam : 0,
$deleted_trash_comments ? $deleted_trash_comments : 0,
$deleted_transients ? $deleted_transients : 0
)
));
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
* AJAX handler for plugin-related functionality.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/AJAX
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* AJAX handler for plugins.
*/
class SEOProStack_AJAX_Plugins {
/**
* Get list of installed plugins.
*/
public function get_plugins() {
// Check nonce
if (!check_ajax_referer('seoprostack-nonce', 'nonce', false)) {
wp_send_json_error('Invalid security token sent.');
return;
}
// Check permissions
if (!current_user_can('manage_options')) {
wp_send_json_error('You do not have permission to view plugins.');
return;
}
$installed_plugins = get_plugins();
$active_plugins = get_option('active_plugins');
$plugin_list = array();
// Create the plugins array
foreach ($installed_plugins as $path => $plugin) {
// Skip the SEO Pro Stack plugin
if (strpos($path, 'wp-seoprostack-plugin') !== false) {
continue;
}
$is_active = in_array($path, $active_plugins);
$plugin_slug = explode('/', $path)[0];
$plugin_list[] = array(
'name' => $plugin['Name'],
'slug' => $plugin_slug,
'version' => $plugin['Version'],
'active' => $is_active,
'path' => $path
);
}
// Sort plugins alphabetically
usort($plugin_list, function ($a, $b) {
return strcasecmp($a['name'], $b['name']);
});
wp_send_json_success($plugin_list);
}
}

View File

@ -0,0 +1,194 @@
<?php
/**
* The Pro Plugins AJAX handler.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/AJAX
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Pro Plugins AJAX handler.
*/
class SEOProStack_AJAX_Pro_Plugins {
/**
* Initialize the AJAX handlers.
*/
public function init() {
add_action('wp_ajax_seoprostack_get_pro_plugins', array($this, 'get_pro_plugins'));
add_action('wp_ajax_seoprostack_activate_plugin', array($this, 'activate_plugin'));
}
/**
* Get the list of pro plugins.
*/
public function get_pro_plugins() {
// Verify nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'seoprostack_ajax_nonce')) {
wp_send_json_error(array('message' => 'Security check failed'));
}
// Get category filter
$category = isset($_POST['category']) ? sanitize_text_field($_POST['category']) : 'all';
// Plugin data
$plugins = $this->get_plugin_data($category);
// Send response
wp_send_json_success(array('plugins' => $plugins));
}
/**
* Activate a plugin.
*/
public function activate_plugin() {
// Verify nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'seoprostack_ajax_nonce')) {
wp_send_json_error(array('message' => 'Security check failed'));
}
// Check capabilities
if (!current_user_can('activate_plugins')) {
wp_send_json_error(array('message' => 'You do not have permission to activate plugins'));
}
// Get plugin path
if (!isset($_POST['plugin'])) {
wp_send_json_error(array('message' => 'No plugin specified'));
}
$plugin = sanitize_text_field($_POST['plugin']);
// Activate the plugin
$result = activate_plugin($plugin);
if (is_wp_error($result)) {
wp_send_json_error(array('message' => $result->get_error_message()));
} else {
wp_send_json_success(array('message' => 'Plugin activated successfully'));
}
}
/**
* Get the plugin data based on category.
*
* @param string $category The plugin category.
* @return array The plugin data.
*/
private function get_plugin_data($category) {
$plugins = array(
array(
'name' => 'Rank Math SEO',
'version' => '1.0.123',
'description' => 'The most advanced SEO plugin for WordPress that helps you optimize your website for search engines.',
'url' => 'https://rankmath.com/',
'status' => 'not-installed',
'active' => false,
'path' => 'rank-math-seo/rank-math.php',
'category' => 'seo'
),
array(
'name' => 'WP Rocket',
'version' => '3.14.4',
'description' => 'The best WordPress caching plugin to speed up your website in a few clicks.',
'url' => 'https://wp-rocket.me/',
'status' => 'not-installed',
'active' => false,
'path' => 'wp-rocket/wp-rocket.php',
'category' => 'performance'
),
array(
'name' => 'MonsterInsights',
'version' => '8.14.0',
'description' => 'The best Google Analytics plugin for WordPress that connects your website with Google Analytics.',
'url' => 'https://www.monsterinsights.com/',
'status' => 'not-installed',
'active' => false,
'path' => 'google-analytics-for-wordpress/googleanalytics.php',
'category' => 'analytics'
),
array(
'name' => 'Yoast SEO',
'version' => '21.2',
'description' => 'The first true all-in-one SEO solution for WordPress, including on-page content analysis, XML sitemaps and much more.',
'url' => 'https://yoast.com/wordpress/plugins/seo/',
'status' => 'not-installed',
'active' => false,
'path' => 'wordpress-seo/wp-seo.php',
'category' => 'seo'
),
array(
'name' => 'WP Cloudflare Super Page Cache',
'version' => '4.7.0',
'description' => 'Speed up your website by implementing full page caching using Cloudflare.',
'url' => 'https://wordpress.org/plugins/wp-cloudflare-page-cache/',
'status' => 'not-installed',
'active' => false,
'path' => 'wp-cloudflare-page-cache/wp-cloudflare-super-page-cache.php',
'category' => 'performance'
),
array(
'name' => 'ExactMetrics',
'version' => '7.14.1',
'description' => 'Google Analytics Dashboard for WordPress. See how visitors find and use your website.',
'url' => 'https://www.exactmetrics.com/',
'status' => 'not-installed',
'active' => false,
'path' => 'google-analytics-dashboard-for-wp/gadwp.php',
'category' => 'analytics'
),
array(
'name' => 'SEOPress',
'version' => '7.2.2',
'description' => 'Boost your SEO with SEOPress, a simple, fast and powerful WordPress SEO plugin.',
'url' => 'https://www.seopress.org/',
'status' => 'not-installed',
'active' => false,
'path' => 'wp-seopress/seopress.php',
'category' => 'seo'
),
array(
'name' => 'WP-Optimize',
'version' => '3.2.19',
'description' => 'A comprehensive plugin with database clean-up, image compression and page caching features.',
'url' => 'https://getwpo.com/',
'status' => 'not-installed',
'active' => false,
'path' => 'wp-optimize/wp-optimize.php',
'category' => 'performance'
),
array(
'name' => 'Fathom Analytics',
'version' => '3.2.1',
'description' => 'Simple, privacy-focused website analytics that doesn\'t compromise visitor privacy.',
'url' => 'https://usefathom.com/',
'status' => 'not-installed',
'active' => false,
'path' => 'fathom-analytics-wordpress-plugin/fathom-analytics.php',
'category' => 'analytics'
)
);
// Update plugin status (check if installed and active)
foreach ($plugins as $key => $plugin) {
if (file_exists(WP_PLUGIN_DIR . '/' . $plugin['path'])) {
$plugins[$key]['status'] = 'installed';
$plugins[$key]['active'] = is_plugin_active($plugin['path']);
}
}
// Filter by category if needed
if ($category !== 'all') {
$plugins = array_filter($plugins, function($plugin) use ($category) {
return $plugin['category'] === $category;
});
}
return array_values($plugins);
}
}

View File

@ -0,0 +1,119 @@
<?php
/**
* AJAX handler for settings functionality.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/AJAX
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* AJAX handler for settings.
*/
class SEOProStack_AJAX_Settings {
/**
* Initialize the class
*/
public function __construct() {
add_action('wp_ajax_seoprostack_update_option', array($this, 'update_option'));
add_action('wp_ajax_seoprostack_get_options', array($this, 'get_options'));
}
/**
* Update a plugin option via AJAX.
*/
public function update_option() {
// Check nonce
if (!check_ajax_referer('seoprostack-nonce', 'nonce', false)) {
wp_send_json_error(array(
'message' => 'Invalid security token sent.'
));
return;
}
// Check permissions
if (!current_user_can('manage_options')) {
wp_send_json_error(array(
'message' => 'You do not have permission to update settings.'
));
return;
}
// Get option data
$option_group = isset($_POST['option_group']) ? sanitize_text_field($_POST['option_group']) : '';
$option_name = isset($_POST['option_name']) ? sanitize_text_field($_POST['option_name']) : '';
$option_value = isset($_POST['option_value']) ? sanitize_text_field($_POST['option_value']) : '';
if (empty($option_group) || empty($option_name)) {
wp_send_json_error(array(
'message' => 'Missing required parameters.'
));
return;
}
// Get current option values
$options = get_option($option_group, array());
// Update value
$options[$option_name] = $option_value;
// Save updated options
$result = update_option($option_group, $options);
if ($result) {
wp_send_json_success(array(
'message' => 'Option updated successfully',
'option_group' => $option_group,
'option_name' => $option_name,
'option_value' => $option_value
));
} else {
wp_send_json_error(array(
'message' => 'Failed to update option or no changes were made.'
));
}
}
/**
* Get plugin options via AJAX.
*/
public function get_options() {
// Check nonce
if (!check_ajax_referer('seoprostack-nonce', 'nonce', false)) {
wp_send_json_error(array(
'message' => 'Invalid security token sent.'
));
return;
}
// Check permissions
if (!current_user_can('manage_options')) {
wp_send_json_error(array(
'message' => 'You do not have permission to retrieve settings.'
));
return;
}
// Get option group
$option_group = isset($_POST['option_group']) ? sanitize_text_field($_POST['option_group']) : '';
if (empty($option_group)) {
wp_send_json_error(array(
'message' => 'Missing required parameters.'
));
return;
}
// Get options
$options = get_option($option_group, array());
wp_send_json_success(array(
'options' => $options
));
}
}

View File

@ -0,0 +1,93 @@
<?php
/**
* AJAX handler for theme-related functionality.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/AJAX
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* AJAX handler for themes.
*/
class SEOProStack_AJAX_Themes {
/**
* Get list of available themes.
*/
public function get_themes() {
// Check nonce
if (!check_ajax_referer('seoprostack-nonce', 'nonce', false)) {
wp_send_json_error('Invalid security token sent.');
return;
}
// Check permissions
if (!current_user_can('manage_options')) {
wp_send_json_error('You do not have permission to view themes.');
return;
}
$themes = wp_get_themes();
$current_theme = wp_get_theme();
$theme_list = array();
foreach ($themes as $theme_slug => $theme_obj) {
$theme_list[] = array(
'name' => $theme_obj->get('Name'),
'version' => $theme_obj->get('Version'),
'description' => $theme_obj->get('Description'),
'author' => $theme_obj->get('Author'),
'slug' => $theme_slug,
'active' => ($current_theme->get_stylesheet() === $theme_slug),
'screenshot' => $theme_obj->get_screenshot(),
);
}
// Sort themes - active first, then alphabetically
usort($theme_list, function ($a, $b) {
if ($a['active'] && !$b['active']) return -1;
if (!$a['active'] && $b['active']) return 1;
return strcasecmp($a['name'], $b['name']);
});
wp_send_json_success($theme_list);
}
/**
* Activate a theme.
*/
public function activate_theme() {
// Check nonce
if (!check_ajax_referer('seoprostack-nonce', 'nonce', false)) {
wp_send_json_error('Invalid security token sent.');
return;
}
// Check permissions
if (!current_user_can('switch_themes')) {
wp_send_json_error('You do not have permission to switch themes.');
return;
}
$theme_slug = sanitize_text_field($_POST['theme']);
// Check if theme exists
$themes = wp_get_themes();
if (!isset($themes[$theme_slug])) {
wp_send_json_error('Theme does not exist.');
return;
}
// Activate theme
switch_theme($theme_slug);
wp_send_json_success(array(
'message' => sprintf('Theme "%s" has been activated.', $themes[$theme_slug]->get('Name')),
));
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
* The Tools AJAX handler.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/AJAX
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Tools AJAX handler.
*/
class SEOProStack_AJAX_Tools {
/**
* Initialize the AJAX handlers.
*/
public function init() {
add_action('wp_ajax_seoprostack_generate_robots', array($this, 'generate_robots'));
}
/**
* Generate robots.txt file content.
*/
public function generate_robots() {
// Verify nonce
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'seoprostack_ajax_nonce')) {
wp_send_json_error(array('message' => 'Security check failed'));
}
// Check capabilities
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => 'You do not have permission to generate robots.txt'));
}
// Generate robots.txt content
$site_url = get_home_url();
$parsed_url = parse_url($site_url);
$host = $parsed_url['host'];
$content = "# SEO Pro Stack generated robots.txt\n";
$content .= "# Generated on: " . date('Y-m-d H:i:s') . "\n\n";
$content .= "User-agent: *\n";
// Disallow WordPress admin
$content .= "Disallow: /wp-admin/\n";
// Allow assets and ajax
$content .= "Allow: /wp-admin/admin-ajax.php\n";
$content .= "Allow: /wp-includes/*.js\n";
$content .= "Allow: /wp-includes/*.css\n";
$content .= "Allow: /wp-content/uploads/\n";
// Disallow common WordPress files and directories
$content .= "Disallow: /wp-includes/\n";
$content .= "Disallow: /readme.html\n";
$content .= "Disallow: /license.txt\n";
$content .= "Disallow: /xmlrpc.php\n";
$content .= "Disallow: /wp-json/\n";
// Add sitemap if Yoast SEO or other SEO plugin is active
if (function_exists('wpseo_init') || defined('AIOSEO_VERSION') || defined('RANK_MATH_VERSION')) {
$content .= "\n# XML Sitemap\n";
$content .= "Sitemap: " . trailingslashit($site_url) . "sitemap_index.xml\n";
}
// Send response
wp_send_json_success(array(
'message' => 'Robots.txt content generated successfully.',
'content' => $content
));
}
}

View File

@ -0,0 +1,193 @@
<?php
/**
* The admin settings page class.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The admin settings page class.
*/
class SEOProStack_Settings_Page {
/**
* Register the settings page.
*/
public function add_menu_page() {
add_options_page(
'SEO Pro Stack Settings', // Page title
'SEO Pro Stack', // Menu title
'manage_options', // Capability
'seoprostack', // Menu slug
array($this, 'render_settings_page') // Function to display the page
);
}
/**
* Register settings.
*/
public function register_settings() {
register_setting('seoprostack_settings', 'seoprostack_workflow_options');
register_setting('seoprostack_settings', 'seoprostack_advanced_options');
}
/**
* Render the settings page.
*/
public function render_settings_page() {
$active_tab = isset($_GET['tab']) ? sanitize_key($_GET['tab']) : 'general';
$tabs = $this->get_tabs();
?>
<div class="wrap seoprostack-wrap">
<div class="seoprostack-header">
<h1><?php echo esc_html('SEO Pro Stack'); ?></h1>
<p class="seoprostack-description"><?php echo esc_html('Speed up your WordPress site with our optimization tools.'); ?></p>
</div>
<div class="seoprostack-settings-container">
<div class="seoprostack-nav">
<h2 class="nav-tab-wrapper">
<?php foreach ($tabs as $tab_id => $tab) : ?>
<a href="?page=seoprostack&tab=<?php echo esc_attr($tab_id); ?>"
class="nav-tab <?php echo $active_tab === $tab_id ? 'nav-tab-active' : ''; ?>">
<?php echo esc_html($tab['label']); ?>
</a>
<?php endforeach; ?>
</h2>
</div>
<div class="seoprostack-settings-content">
<?php
if (isset($tabs[$active_tab]) && isset($tabs[$active_tab]['callback'])) {
call_user_func($tabs[$active_tab]['callback']);
}
?>
</div>
</div>
</div>
<?php
}
/**
* Get all available tabs.
*
* @return array Array of tab configurations.
*/
private function get_tabs() {
$tabs = array(
'general' => array(
'label' => __('General', 'seoprostack'),
'callback' => array($this, 'render_general_tab'),
),
'advanced' => array(
'label' => __('Advanced', 'seoprostack'),
'callback' => array($this, 'render_advanced_tab'),
),
'workflow' => array(
'label' => __('Workflow', 'seoprostack'),
'callback' => array($this, 'render_workflow_tab'),
),
'recommended' => array(
'label' => __('Free Plugins', 'seoprostack'),
'callback' => array($this, 'render_recommended_plugins_tab'),
),
'pro' => array(
'label' => __('Pro Plugins', 'seoprostack'),
'callback' => array($this, 'render_pro_plugins_tab'),
),
'theme' => array(
'label' => __('Theme', 'seoprostack'),
'callback' => array($this, 'render_theme_tab'),
),
'hosting' => array(
'label' => __('Hosting', 'seoprostack'),
'callback' => array($this, 'render_hosting_tab'),
),
'tools' => array(
'label' => __('Tools', 'seoprostack'),
'callback' => array($this, 'render_tools_tab'),
),
);
return $tabs;
}
/**
* Render the General tab.
*/
public function render_general_tab() {
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/tabs/class-seoprostack-tab-general.php';
$tab = new SEOProStack_Tab_General();
$tab->render();
}
/**
* Render the Advanced tab.
*/
public function render_advanced_tab() {
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/tabs/class-seoprostack-tab-advanced.php';
$tab = new SEOProStack_Tab_Advanced();
$tab->render();
}
/**
* Render the Workflow tab.
*/
public function render_workflow_tab() {
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/tabs/class-seoprostack-tab-workflow.php';
$tab = new SEOProStack_Tab_Workflow();
$tab->render();
}
/**
* Render the Recommended Plugins tab.
*/
public function render_recommended_plugins_tab() {
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/tabs/class-seoprostack-tab-recommended-plugins.php';
$tab = new SEOProStack_Tab_Recommended_Plugins();
$tab->render();
}
/**
* Render the Pro Plugins tab.
*/
public function render_pro_plugins_tab() {
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/tabs/class-seoprostack-tab-pro-plugins.php';
$tab = new SEOProStack_Tab_Pro_Plugins();
$tab->render();
}
/**
* Render the Theme tab.
*/
public function render_theme_tab() {
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/tabs/class-seoprostack-tab-theme.php';
$tab = new SEOProStack_Tab_Theme();
$tab->render();
}
/**
* Render the Hosting tab.
*/
public function render_hosting_tab() {
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/tabs/class-seoprostack-tab-hosting.php';
$tab = new SEOProStack_Tab_Hosting();
$tab->render();
}
/**
* Render the Tools tab.
*/
public function render_tools_tab() {
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings/tabs/class-seoprostack-tab-tools.php';
$tab = new SEOProStack_Tab_Tools();
$tab->render();
}
}

View File

@ -1,14 +1,32 @@
<?php
/**
* Hosting providers data for WP ALLSTARS plugin
* Hosting providers data for SEO Pro Stack
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Data
*/
// Define hosting providers
function wp_allstars_get_hosting_providers() {
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* Define hosting providers
*
* @return array Array of hosting providers with their details
*/
function wp_seoprostack_get_hosting_providers() {
return array(
'closte' => array(
'name' => 'Closte',
'description' => 'Managed WordPress hosting with advanced performance optimization and auto-scaling.',
'features' => array(
'Auto-scaling architecture',
'Global CDN included',
'Advanced caching',
'Free SSL certificates'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -24,6 +42,12 @@ function wp_allstars_get_hosting_providers() {
'cloudron' => array(
'name' => 'Cloudron',
'description' => 'Self-hosted platform that makes it easy to run web applications like WordPress on your server.',
'features' => array(
'One-click installation',
'Automatic updates',
'Built-in backups',
'SSL certificate management'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -39,6 +63,12 @@ function wp_allstars_get_hosting_providers() {
'hostinger' => array(
'name' => 'Hostinger',
'description' => 'Affordable WordPress hosting with good performance and user-friendly management tools.',
'features' => array(
'Free domain name',
'Managed WordPress features',
'LiteSpeed cache',
'Weekly backups'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -54,6 +84,12 @@ function wp_allstars_get_hosting_providers() {
'hetzner' => array(
'name' => 'Hetzner Cloud',
'description' => 'High-performance cloud servers with excellent price-to-performance ratio for self-managed WordPress hosting.',
'features' => array(
'Scalable cloud instances',
'Per-minute billing',
'Snapshots and backups',
'Global data centers'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -69,6 +105,12 @@ function wp_allstars_get_hosting_providers() {
'simplehost' => array(
'name' => 'SimpleHost',
'description' => 'Streamlined WordPress hosting with a focus on simplicity and performance.',
'features' => array(
'Simplified hosting dashboard',
'Pre-optimized WordPress',
'Automated backups',
'Email hosting included'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -84,6 +126,12 @@ function wp_allstars_get_hosting_providers() {
'cloudflare' => array(
'name' => 'Cloudflare',
'description' => 'Global cloud platform that provides CDN, security, and performance optimization services.',
'features' => array(
'Global CDN network',
'DDoS protection',
'Web application firewall',
'Performance optimization'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -99,6 +147,12 @@ function wp_allstars_get_hosting_providers() {
'spaceship' => array(
'name' => 'Spaceship',
'description' => 'Modern hosting platform with advanced features for WordPress sites.',
'features' => array(
'Advanced WordPress tools',
'Optimized for speed',
'Developer-friendly features',
'Smart caching system'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -110,6 +164,12 @@ function wp_allstars_get_hosting_providers() {
'101domain' => array(
'name' => '101Domain',
'description' => 'Domain registration and management service with support for hundreds of TLDs.',
'features' => array(
'Extensive TLD selection',
'Domain privacy protection',
'Expert domain support',
'Bulk domain management'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -121,6 +181,12 @@ function wp_allstars_get_hosting_providers() {
'namecheap' => array(
'name' => 'Namecheap',
'description' => 'Domain registrar and web hosting provider with competitive pricing and good support.',
'features' => array(
'Free WhoisGuard protection',
'Competitive domain pricing',
'Reliable hosting services',
'Excellent support'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -136,6 +202,12 @@ function wp_allstars_get_hosting_providers() {
'updownio' => array(
'name' => 'Updown.io',
'description' => 'Simple and affordable website monitoring service with uptime checks and performance metrics.',
'features' => array(
'Real-time monitoring',
'Performance metrics',
'Notification alerts',
'Detailed reports'
),
'button_group' => array(
array(
'text' => 'Home Page',
@ -147,21 +219,11 @@ function wp_allstars_get_hosting_providers() {
'url' => 'https://updown.io/pricing'
)
)
),
'coolify' => array(
'name' => 'Coolify',
'description' => 'Self-hostable Heroku & Netlify alternative for developers. Deploy your apps, databases, and services with ease.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://coolify.io/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://coolify.io/pricing/'
)
)
)
);
}
// Alias for backward compatibility with the old codebase
function wp_allstars_get_hosting_providers() {
return wp_seoprostack_get_hosting_providers();
}

View File

@ -1,10 +1,22 @@
<?php
/**
* Recommended plugins data for WP ALLSTARS plugin
* Recommended plugins data for SEO Pro Stack
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Data
*/
// Define recommended plugins
function wp_allstars_get_recommended_plugins() {
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* Define recommended plugins
*
* @return array Array of recommended plugins categorized by use case
*/
function wp_seoprostack_get_recommended_plugins() {
return array(
'minimal' => array(
'antispam-bee',
@ -159,3 +171,13 @@ function wp_allstars_get_recommended_plugins() {
)
);
}
// Alias for backward compatibility with the old codebase
function wp_allstars_get_recommended_plugins() {
return wp_seoprostack_get_recommended_plugins();
}
// Alias for backward compatibility with the new codebase
function seoprostack_get_recommended_plugins() {
return wp_seoprostack_get_recommended_plugins();
}

View File

@ -1,10 +1,22 @@
<?php
/**
* Tools data for WP ALLSTARS plugin
* Tools data for SEO Pro Stack
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Data
*/
// Define tools
function wp_allstars_get_tools() {
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* Define tools
*
* @return array Array of tools with their details
*/
function wp_seoprostack_get_tools() {
return array(
'advise' => array(
'name' => 'Advise.so',
@ -171,83 +183,6 @@ function wp_allstars_get_tools() {
)
)
),
'pixelmator' => array(
'name' => 'Pixelmator Pro',
'description' => 'Professional image editing software for Mac with powerful tools and an intuitive interface.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.pixelmator.com/pro/',
'primary' => true
)
)
),
'upscayl' => array(
'name' => 'Upscayl',
'description' => 'Open-source AI image upscaler that enhances and enlarges images with improved quality.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://upscayl.org/',
'primary' => true
)
)
),
'sitesucker' => array(
'name' => 'SiteSucker',
'description' => 'Website downloading tool that allows you to save entire websites for offline viewing.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://ricks-apps.com/osx/sitesucker/index.html',
'primary' => true
)
)
),
'virustotal' => array(
'name' => 'VirusTotal',
'description' => 'Free service that analyzes files and URLs for viruses, worms, trojans, and other malicious content.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.virustotal.com/',
'primary' => true
)
)
),
'transmit' => array(
'name' => 'Transmit',
'description' => 'File transfer client for macOS with support for FTP, SFTP, WebDAV, and cloud services.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://panic.com/transmit/',
'primary' => true
)
)
),
'iterm2' => array(
'name' => 'iTerm2',
'description' => 'Terminal emulator for macOS with advanced features beyond the default Terminal app.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://iterm2.com/',
'primary' => true
)
)
),
'cloudron' => array(
'name' => 'Cloudron',
'description' => 'Self-hosted platform that makes it easy to run web applications like WordPress on your server.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.cloudron.io/',
'primary' => true
)
)
),
'urlmonitor' => array(
'name' => 'URL Monitor',
'description' => 'Website monitoring service that tracks uptime, performance, and alerts you to issues.',
@ -325,50 +260,6 @@ function wp_allstars_get_tools() {
)
)
),
'muraena' => array(
'name' => 'Muraena AI',
'description' => 'AI-powered writing assistant for creating and optimizing content.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://muraena.ai/',
'primary' => true
)
)
),
'googlebusiness' => array(
'name' => 'Google Business Profile',
'description' => 'Free tool to manage your business presence on Google Search and Maps.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://business.google.com/',
'primary' => true
)
)
),
'chatgptdetector' => array(
'name' => 'ChatGPT Detector',
'description' => 'Tool to detect AI-generated content from models like ChatGPT.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://textvisualization.app/chatgpt-detector/',
'primary' => true
)
)
),
'zerogpt' => array(
'name' => 'ZeroGPT',
'description' => 'AI content detector that identifies text generated by AI models.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://zerogpt.tools/',
'primary' => true
)
)
),
'zerogptplus' => array(
'name' => 'ZeroGPT Plus',
'description' => 'Advanced AI content detector with improved accuracy and additional features.',
@ -402,22 +293,6 @@ function wp_allstars_get_tools() {
)
)
),
'searchatlas' => array(
'name' => 'Search Atlas',
'description' => 'Comprehensive SEO platform with keyword research, rank tracking, and content optimization tools.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://searchatlas.com/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://searchatlas.com/pricing/',
'primary' => false
)
)
),
'seoptimer' => array(
'name' => 'SEOptimer',
'description' => 'Website audit tool that provides SEO, usability, and performance recommendations.',
@ -440,61 +315,6 @@ function wp_allstars_get_tools() {
)
)
),
'appsumo' => array(
'name' => 'AppSumo',
'description' => 'Marketplace for discounted digital products and services for entrepreneurs.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://appsumo.com/',
'primary' => true
)
)
),
'screenstudio' => array(
'name' => 'Screen Studio',
'description' => 'Screen recording software with automatic editing and professional results.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://screen.studio/',
'primary' => true
)
)
),
'screenflow' => array(
'name' => 'ScreenFlow',
'description' => 'Professional screen recording and video editing software for macOS.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.telestream.net/screenflow/overview.htm',
'primary' => true
)
)
),
'acronis' => array(
'name' => 'Acronis Cyber Protect Connect',
'description' => 'Remote desktop and support solution for secure access to remote computers.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.acronis.com/en-us/products/cyber-protect-connect/',
'primary' => true
)
)
),
'espocrm' => array(
'name' => 'EspoCRM',
'description' => 'Open-source customer relationship management (CRM) application.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.espocrm.com/',
'primary' => true
)
)
),
'libreoffice' => array(
'name' => 'LibreOffice',
'description' => 'Free and open-source office suite compatible with Microsoft Office formats.',
@ -541,3 +361,13 @@ function wp_allstars_get_tools() {
),
);
}
// Alias for backward compatibility with the old codebase
function wp_allstars_get_tools() {
return wp_seoprostack_get_tools();
}
// Alias for backward compatibility with the new codebase
function seoprostack_get_tools() {
return wp_seoprostack_get_tools();
}

View File

@ -0,0 +1,159 @@
<?php
/**
* The Advanced tab for plugin settings.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Tabs
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Advanced tab for plugin settings.
*/
class SEOProStack_Tab_Advanced {
/**
* Render the tab content.
*/
public function render() {
// Get current settings
$settings = get_option('seoprostack_advanced_settings', array(
'disable_emojis' => 'yes',
'disable_embeds' => 'yes',
'remove_query_strings' => 'no',
'disable_xmlrpc' => 'yes',
'remove_shortlink' => 'yes',
'remove_rsd_link' => 'yes',
'remove_wlwmanifest_link' => 'yes',
'disable_self_pingbacks' => 'yes',
'disable_feed_links' => 'no',
'remove_rest_api_links' => 'no',
'minify_html' => 'no',
'minify_css' => 'no',
'minify_js' => 'no'
));
?>
<div class="seoprostack-settings-content tab-content" id="advanced">
<div class="seoprostack-setting-section">
<h2><?php esc_html_e('Advanced Settings', 'seoprostack'); ?></h2>
<p class="description"><?php esc_html_e('These settings help optimize your WordPress site for better performance. Use with caution and test thoroughly after making changes.', 'seoprostack'); ?></p>
<div id="advanced-settings-response"></div>
<form id="seoprostack-advanced-settings-form">
<div class="seoprostack-toggle">
<div class="seoprostack-toggle-header">
<div class="seoprostack-toggle-main">
<div class="seoprostack-toggle-left">
<h3><?php esc_html_e('WordPress Cleanup', 'seoprostack'); ?></h3>
<p><?php esc_html_e('Remove unnecessary code from WordPress header', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-toggle-right">
<label class="wp-toggle-switch">
<input type="checkbox" class="seoprostack-toggle-switch" <?php checked(true, true); ?>>
<span class="toggle-label"></span>
</label>
</div>
</div>
</div>
<div class="seoprostack-toggle-settings" style="display: block;">
<div class="seoprostack-setting-row">
<label class="seoprostack-checkbox-label">
<input type="checkbox" name="disable_emojis" value="yes" <?php checked('yes', $settings['disable_emojis']); ?>>
<?php esc_html_e('Disable WordPress Emojis', 'seoprostack'); ?>
</label>
<p class="description"><?php esc_html_e('Removes the WordPress emoji script and related code from loading on your site.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-setting-row">
<label class="seoprostack-checkbox-label">
<input type="checkbox" name="disable_embeds" value="yes" <?php checked('yes', $settings['disable_embeds']); ?>>
<?php esc_html_e('Disable WordPress Embeds', 'seoprostack'); ?>
</label>
<p class="description"><?php esc_html_e('Disables the WordPress embed functionality, removing the related JavaScript file.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-setting-row">
<label class="seoprostack-checkbox-label">
<input type="checkbox" name="remove_query_strings" value="yes" <?php checked('yes', $settings['remove_query_strings']); ?>>
<?php esc_html_e('Remove Query Strings from Static Resources', 'seoprostack'); ?>
</label>
<p class="description"><?php esc_html_e('Removes query strings from static resources like CSS and JavaScript files, improving caching.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-setting-row">
<label class="seoprostack-checkbox-label">
<input type="checkbox" name="disable_xmlrpc" value="yes" <?php checked('yes', $settings['disable_xmlrpc']); ?>>
<?php esc_html_e('Disable XML-RPC', 'seoprostack'); ?>
</label>
<p class="description"><?php esc_html_e('Disables the XML-RPC API, which could be a security vulnerability if not used.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-setting-row">
<label class="seoprostack-checkbox-label">
<input type="checkbox" name="remove_shortlink" value="yes" <?php checked('yes', $settings['remove_shortlink']); ?>>
<?php esc_html_e('Remove Shortlink', 'seoprostack'); ?>
</label>
<p class="description"><?php esc_html_e('Removes the shortlink tag from the header.', 'seoprostack'); ?></p>
</div>
</div>
</div>
<div class="seoprostack-toggle">
<div class="seoprostack-toggle-header">
<div class="seoprostack-toggle-main">
<div class="seoprostack-toggle-left">
<h3><?php esc_html_e('Performance Optimization', 'seoprostack'); ?></h3>
<p><?php esc_html_e('Enable additional performance optimizations', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-toggle-right">
<label class="wp-toggle-switch">
<input type="checkbox" class="seoprostack-toggle-switch" <?php checked(true, true); ?>>
<span class="toggle-label"></span>
</label>
</div>
</div>
</div>
<div class="seoprostack-toggle-settings" style="display: block;">
<div class="seoprostack-setting-row">
<label class="seoprostack-checkbox-label">
<input type="checkbox" name="minify_html" value="yes" <?php checked('yes', $settings['minify_html']); ?>>
<?php esc_html_e('Minify HTML', 'seoprostack'); ?>
</label>
<p class="description"><?php esc_html_e('Removes unnecessary whitespace from HTML to reduce file size.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-setting-row">
<label class="seoprostack-checkbox-label">
<input type="checkbox" name="minify_css" value="yes" <?php checked('yes', $settings['minify_css']); ?>>
<?php esc_html_e('Minify CSS', 'seoprostack'); ?>
</label>
<p class="description"><?php esc_html_e('Combines and minifies CSS files to reduce HTTP requests and file size.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-setting-row">
<label class="seoprostack-checkbox-label">
<input type="checkbox" name="minify_js" value="yes" <?php checked('yes', $settings['minify_js']); ?>>
<?php esc_html_e('Minify JavaScript', 'seoprostack'); ?>
</label>
<p class="description"><?php esc_html_e('Combines and minifies JavaScript files to reduce HTTP requests and file size.', 'seoprostack'); ?></p>
</div>
</div>
</div>
<div class="seoprostack-setting-actions">
<button type="submit" class="button button-primary" id="seoprostack-save-advanced-settings">
<?php esc_html_e('Save Advanced Settings', 'seoprostack'); ?>
</button>
<span class="spinner"></span>
</div>
</form>
</div>
</div>
<?php
}
}

View File

@ -0,0 +1,62 @@
<?php
/**
* The General tab for plugin settings.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Tabs
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The General tab for plugin settings.
*/
class SEOProStack_Tab_General {
/**
* Render the tab content.
*/
public function render() {
?>
<div class="seoprostack-settings-content tab-content" id="general">
<div class="seoprostack-settings-section">
<h2><?php esc_html_e('Welcome to SEO Pro Stack', 'seoprostack'); ?></h2>
<p><?php esc_html_e('SEO Pro Stack helps you optimize your WordPress site for better search engine rankings and faster performance.', 'seoprostack'); ?></p>
<div class="seoprostack-welcome-cards">
<div class="seoprostack-card">
<div class="seoprostack-card-icon dashicons dashicons-performance"></div>
<h3><?php esc_html_e('Optimize Performance', 'seoprostack'); ?></h3>
<p><?php esc_html_e('Speed up your site with our performance optimization tools.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-card">
<div class="seoprostack-card-icon dashicons dashicons-admin-plugins"></div>
<h3><?php esc_html_e('Recommended Plugins', 'seoprostack'); ?></h3>
<p><?php esc_html_e('Discover plugins that enhance your site\'s SEO and performance.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-card">
<div class="seoprostack-card-icon dashicons dashicons-admin-appearance"></div>
<h3><?php esc_html_e('Theme Optimization', 'seoprostack'); ?></h3>
<p><?php esc_html_e('Find and activate SEO-friendly themes for your site.', 'seoprostack'); ?></p>
</div>
</div>
<div class="seoprostack-quick-start">
<h3><?php esc_html_e('Quick Start Guide', 'seoprostack'); ?></h3>
<ol>
<li><?php esc_html_e('Configure auto-upload settings in the Workflow tab', 'seoprostack'); ?></li>
<li><?php esc_html_e('Explore recommended plugins in the Free Plugins tab', 'seoprostack'); ?></li>
<li><?php esc_html_e('Check out premium plugins in the Pro Plugins tab', 'seoprostack'); ?></li>
<li><?php esc_html_e('Find an SEO-optimized theme in the Theme tab', 'seoprostack'); ?></li>
</ol>
</div>
</div>
</div>
<?php
}
}

View File

@ -0,0 +1,692 @@
<?php
/**
* The Hosting tab for plugin settings.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Tabs
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Hosting tab for plugin settings.
* Self-contained class with integrated data and functionality
*/
class SEOProStack_Tab_Hosting {
/**
* Tab identifier
*
* @var string
*/
private $tab_id = 'hosting';
/**
* Initialize the class.
* Register any hooks or actions here.
*/
/**
* Hosting providers data
*
* @var array
*/
private $hosting_providers;
/**
* Server information
*
* @var array
*/
private $server_info;
public function __construct() {
// Initialize the hosting providers data
$this->hosting_providers = $this->get_hosting_providers();
$this->server_info = $this->get_server_info();
}
/**
* Get the tab ID
*
* @return string The tab ID
*/
public function get_tab_id() {
return $this->tab_id;
}
/**
* Get the tab title
*
* @return string The tab title
*/
public function get_title() {
return __('Hosting', 'seoprostack');
}
/**
* Get server information
*
* @return array Server information
*/
private function get_server_info() {
global $wpdb;
$server_info = array();
// PHP Version
$server_info['php_version'] = array(
'label' => __('PHP Version', 'seoprostack'),
'value' => phpversion(),
'recommendation' => __('PHP 8.0 or higher recommended', 'seoprostack')
);
// MySQL Version
$server_info['mysql_version'] = array(
'label' => __('MySQL Version', 'seoprostack'),
'value' => $wpdb->db_version(),
'recommendation' => __('MySQL 8.0 or higher recommended', 'seoprostack')
);
// Server Software
$server_info['server_software'] = array(
'label' => __('Server Software', 'seoprostack'),
'value' => $_SERVER['SERVER_SOFTWARE'] ?? __('Unknown', 'seoprostack'),
'recommendation' => ''
);
// PHP Memory Limit
$memory_limit = ini_get('memory_limit');
$server_info['php_memory_limit'] = array(
'label' => __('PHP Memory Limit', 'seoprostack'),
'value' => $memory_limit,
'recommendation' => __('256M or higher recommended', 'seoprostack')
);
// Max Upload Size
$upload_max_filesize = ini_get('upload_max_filesize');
$server_info['upload_max_filesize'] = array(
'label' => __('Max Upload Size', 'seoprostack'),
'value' => $upload_max_filesize,
'recommendation' => __('64M or higher recommended', 'seoprostack')
);
return $server_info;
}
/**
* Get hosting providers
*
* @return array The hosting providers data
*/
private function get_hosting_providers() {
return array(
'kinsta' => array(
'name' => 'Kinsta',
'description' => 'Premium WordPress hosting with excellent performance, security, and customer support.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://kinsta.com/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://kinsta.com/plans/'
)
)
),
'wpengine' => array(
'name' => 'WP Engine',
'description' => 'Managed WordPress hosting provider with solid performance and security features.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://wpengine.com/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://wpengine.com/plans/'
)
)
),
'siteground' => array(
'name' => 'SiteGround',
'description' => 'Popular WordPress hosting with good performance and customer support.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.siteground.com/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.siteground.com/wordpress-hosting.htm'
)
)
),
'hostinger' => array(
'name' => 'Hostinger',
'description' => 'Affordable WordPress hosting with good performance and user-friendly management tools.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.hostinger.com/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.hostinger.com/wordpress-hosting'
)
)
),
'hetzner' => array(
'name' => 'Hetzner Cloud',
'description' => 'High-performance cloud servers with excellent price-to-performance ratio for self-managed WordPress hosting.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.hetzner.com/cloud/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.hetzner.com/cloud#pricing'
)
)
),
'simplehost' => array(
'name' => 'SimpleHost',
'description' => 'Streamlined WordPress hosting with a focus on simplicity and performance.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://simplehost.so/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://simplehost.so/#pricing'
)
)
),
'cloudflare' => array(
'name' => 'Cloudflare',
'description' => 'Global cloud platform that provides CDN, security, and performance optimization services.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.cloudflare.com/en-gb/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.cloudflare.com/en-gb/plans/'
)
)
),
'spaceship' => array(
'name' => 'Spaceship',
'description' => 'Modern hosting platform with advanced features for WordPress sites.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.spaceship.com/',
'primary' => true
)
)
),
'101domain' => array(
'name' => '101Domain',
'description' => 'Domain registration and management service with support for hundreds of TLDs.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.101domain.com/',
'primary' => true
)
)
),
'namecheap' => array(
'name' => 'Namecheap',
'description' => 'Domain registrar and web hosting provider with competitive pricing and good support.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.namecheap.com/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.namecheap.com/hosting/shared/'
)
)
),
'updownio' => array(
'name' => 'Updown.io',
'description' => 'Simple and affordable website monitoring service with uptime checks and performance metrics.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://updown.io/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://updown.io/pricing'
)
)
)
);
}
/**
* Get the tab description
*
* @return string The tab description
*/
public function get_description() {
return __('Details about your current hosting environment and recommendations for improvement.', 'seoprostack');
}
/**
* Get additional hosting providers for specialized cases
*
* @return array Array of additional hosting providers
*/
private function get_additional_hosting_providers() {
return array(
'closte' => array(
'name' => 'Closte',
'description' => 'Managed WordPress hosting with advanced performance optimization and auto-scaling.',
'features' => array(
'Auto-scaling architecture',
'Global CDN included',
'Advanced caching',
'Free SSL certificates'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://closte.com/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://closte.com/pricing'
)
)
),
'cloudron' => array(
'name' => 'Cloudron',
'description' => 'Self-hosted platform that makes it easy to run web applications like WordPress on your server.',
'features' => array(
'One-click installation',
'Automatic updates',
'Built-in backups',
'SSL certificate management'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.cloudron.io/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.cloudron.io/pricing.html'
)
)
),
'hostinger' => array(
'name' => 'Hostinger',
'description' => 'Affordable WordPress hosting with good performance and user-friendly management tools.',
'features' => array(
'Free domain name',
'Managed WordPress features',
'LiteSpeed cache',
'Weekly backups'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.hostinger.com/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.hostinger.com/wordpress-hosting'
)
)
),
'hetzner' => array(
'name' => 'Hetzner Cloud',
'description' => 'High-performance cloud servers with excellent price-to-performance ratio for self-managed WordPress hosting.',
'features' => array(
'Scalable cloud instances',
'Per-minute billing',
'Snapshots and backups',
'Global data centers'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.hetzner.com/cloud/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.hetzner.com/cloud#pricing'
)
)
),
'simplehost' => array(
'name' => 'SimpleHost',
'description' => 'Streamlined WordPress hosting with a focus on simplicity and performance.',
'features' => array(
'Simplified hosting dashboard',
'Pre-optimized WordPress',
'Automated backups',
'Email hosting included'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://simplehost.so/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://simplehost.so/#pricing'
)
)
),
'cloudflare' => array(
'name' => 'Cloudflare',
'description' => 'Global cloud platform that provides CDN, security, and performance optimization services.',
'features' => array(
'Global CDN network',
'DDoS protection',
'Web application firewall',
'Performance optimization'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.cloudflare.com/en-gb/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.cloudflare.com/en-gb/plans/'
)
)
),
'spaceship' => array(
'name' => 'Spaceship',
'description' => 'Modern hosting platform with advanced features for WordPress sites.',
'features' => array(
'Advanced WordPress tools',
'Optimized for speed',
'Developer-friendly features',
'Smart caching system'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.spaceship.com/',
'primary' => true
)
)
),
'101domain' => array(
'name' => '101Domain',
'description' => 'Domain registration and management service with support for hundreds of TLDs.',
'features' => array(
'Extensive TLD selection',
'Domain privacy protection',
'Expert domain support',
'Bulk domain management'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.101domain.com/',
'primary' => true
)
)
),
'namecheap' => array(
'name' => 'Namecheap',
'description' => 'Domain registrar and web hosting provider with competitive pricing and good support.',
'features' => array(
'Free WhoisGuard protection',
'Competitive domain pricing',
'Reliable hosting services',
'Excellent support'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.namecheap.com/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://www.namecheap.com/hosting/shared/'
)
)
),
'updownio' => array(
'name' => 'Updown.io',
'description' => 'Simple and affordable website monitoring service with uptime checks and performance metrics.',
'features' => array(
'Real-time monitoring',
'Performance metrics',
'Notification alerts',
'Detailed reports'
),
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://updown.io/',
'primary' => true
),
array(
'text' => 'Pricing',
'url' => 'https://updown.io/pricing'
)
)
)
);
}
/**
* Render the tab content.
*/
public function render() {
// Use the self-contained data
$server_info = $this->server_info;
$hosting_providers = $this->hosting_providers;
echo '<div class="tab-content" id="' . esc_attr($this->tab_id) . '">;
if (function_exists('wp_seoprostack_get_hosting_providers') && empty($GLOBALS['_wp_seoprostack_hosting_loaded'])) {
// Optional: merge with any providers from the external function to ensure none are lost
$external_providers = wp_seoprostack_get_hosting_providers();
$hosting_providers = array_merge($external_providers, $hosting_providers);
$GLOBALS['_wp_seoprostack_hosting_loaded'] = true;
}
?>
<div class="seoprostack-settings-content tab-content" id="<?php echo esc_attr($this->get_tab_id()); ?>">
<div class="seoprostack-setting-section">
<h2><?php esc_html_e('Hosting Information', 'seoprostack'); ?></h2>
<p class="description"><?php echo esc_html($this->get_description()); ?></p>
<div class="seoprostack-server-info">
<h3><?php esc_html_e('Server Environment', 'seoprostack'); ?></h3>
<table class="seoprostack-info-table">
<tr>
<th><?php esc_html_e('PHP Version', 'seoprostack'); ?></th>
<td>
<?php echo esc_html($server_info['php_version']); ?>
<?php echo $this->get_status_icon($server_info['php_status']); ?>
</td>
<td class="seoprostack-info-note">
<?php echo esc_html($server_info['php_note']); ?>
</td>
</tr>
<tr>
<th><?php esc_html_e('MySQL Version', 'seoprostack'); ?></th>
<td>
<?php echo esc_html($server_info['mysql_version']); ?>
<?php echo $this->get_status_icon($server_info['mysql_status']); ?>
</td>
<td class="seoprostack-info-note">
<?php echo esc_html($server_info['mysql_note']); ?>
</td>
</tr>
<tr>
<th><?php esc_html_e('WordPress Version', 'seoprostack'); ?></th>
<td>
<?php echo esc_html($server_info['wp_version']); ?>
<?php echo $this->get_status_icon($server_info['wp_status']); ?>
</td>
<td class="seoprostack-info-note">
<?php echo esc_html($server_info['wp_note']); ?>
</td>
</tr>
<tr>
<th><?php esc_html_e('Memory Limit', 'seoprostack'); ?></th>
<td>
<?php echo esc_html($server_info['memory_limit']); ?>
<?php echo $this->get_status_icon($server_info['memory_status']); ?>
</td>
<td class="seoprostack-info-note">
<?php echo esc_html($server_info['memory_note']); ?>
</td>
</tr>
<tr>
<th><?php esc_html_e('Max Execution Time', 'seoprostack'); ?></th>
<td>
<?php echo esc_html($server_info['max_execution_time']); ?> seconds
<?php echo $this->get_status_icon($server_info['execution_status']); ?>
</td>
<td class="seoprostack-info-note">
<?php echo esc_html($server_info['execution_note']); ?>
</td>
</tr>
</table>
</div>
<div class="seoprostack-hosting-recommendations">
<h3><?php esc_html_e('Recommended Hosting Providers', 'seoprostack'); ?></h3>
<p><?php esc_html_e('These hosting providers offer excellent performance for WordPress sites and are recommended for optimal SEO results.', 'seoprostack'); ?></p>
<div class="seoprostack-hosting-grid">
<?php foreach ($hosting_providers as $key => $provider) : ?>
<div class="seoprostack-hosting-card">
<div class="seoprostack-hosting-card-header">
<h4><?php echo esc_html($provider['name']); ?></h4>
</div>
<div class="seoprostack-hosting-card-content">
<p><?php echo esc_html($provider['description']); ?></p>
<?php if (!empty($provider['features'])) : ?>
<ul class="seoprostack-hosting-features">
<?php foreach ($provider['features'] as $feature) : ?>
<li><?php echo esc_html($feature); ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
<div class="seoprostack-hosting-card-footer">
<?php foreach ($provider['button_group'] as $button) : ?>
<a href="<?php echo esc_url($button['url']); ?>" class="seoprostack-button<?php echo ($button['primary']) ? ' primary' : ''; ?>" target="_blank">
<?php echo esc_html($button['text']); ?>
</a>
<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<?php
}
/**
* Get server information.
*
* @return array Server information.
*/
private function get_server_info() {
global $wpdb;
// PHP version
$php_version = phpversion();
$php_status = version_compare($php_version, '7.4', '>=') ? 'good' : (version_compare($php_version, '7.0', '>=') ? 'warning' : 'bad');
$php_note = version_compare($php_version, '7.4', '>=') ? __('Your PHP version is up to date.', 'seoprostack') : __('We recommend PHP 7.4 or higher for optimal performance and security.', 'seoprostack');
// MySQL version
$mysql_version = $wpdb->db_version();
$mysql_status = version_compare($mysql_version, '5.6', '>=') ? 'good' : 'warning';
$mysql_note = version_compare($mysql_version, '5.6', '>=') ? __('Your MySQL version is sufficient.', 'seoprostack') : __('We recommend MySQL 5.6 or higher for better performance.', 'seoprostack');
// WordPress version
$wp_version = get_bloginfo('version');
$wp_status = version_compare($wp_version, '5.8', '>=') ? 'good' : (version_compare($wp_version, '5.5', '>=') ? 'warning' : 'bad');
$wp_note = version_compare($wp_version, '5.8', '>=') ? __('Your WordPress version is up to date.', 'seoprostack') : __('We recommend updating to the latest version of WordPress.', 'seoprostack');
// Memory limit
$memory_limit = ini_get('memory_limit');
$memory_limit_bytes = wp_convert_hr_to_bytes($memory_limit);
$memory_status = $memory_limit_bytes >= 256 * 1024 * 1024 ? 'good' : ($memory_limit_bytes >= 128 * 1024 * 1024 ? 'warning' : 'bad');
$memory_note = $memory_limit_bytes >= 256 * 1024 * 1024 ? __('Your memory limit is sufficient.', 'seoprostack') : __('We recommend a memory limit of at least 256MB.', 'seoprostack');
// Max execution time
$max_execution_time = ini_get('max_execution_time');
$execution_status = $max_execution_time >= 180 || $max_execution_time == 0 ? 'good' : ($max_execution_time >= 60 ? 'warning' : 'bad');
$execution_note = $max_execution_time >= 180 || $max_execution_time == 0 ? __('Your max execution time is sufficient.', 'seoprostack') : __('We recommend a max execution time of at least 180 seconds.', 'seoprostack');
return array(
'php_version' => $php_version,
'php_status' => $php_status,
'php_note' => $php_note,
'mysql_version' => $mysql_version,
'mysql_status' => $mysql_status,
'mysql_note' => $mysql_note,
'wp_version' => $wp_version,
'wp_status' => $wp_status,
'wp_note' => $wp_note,
'memory_limit' => $memory_limit,
'memory_status' => $memory_status,
'memory_note' => $memory_note,
'max_execution_time' => $max_execution_time,
'execution_status' => $execution_status,
'execution_note' => $execution_note
);
}
/**
* Get a status icon based on the status.
*
* @param string $status Status (good, warning, or bad).
* @return string Status icon HTML.
*/
private function get_status_icon($status) {
switch ($status) {
case 'good':
return '<span class="seoprostack-status-icon good dashicons dashicons-yes-alt"></span>';
case 'warning':
return '<span class="seoprostack-status-icon warning dashicons dashicons-warning"></span>';
case 'bad':
return '<span class="seoprostack-status-icon bad dashicons dashicons-dismiss"></span>';
default:
return '';
}
}
}

View File

@ -0,0 +1,176 @@
<?php
/**
* The Pro Plugins tab for plugin settings.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Tabs
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Pro Plugins tab for plugin settings.
*/
class SEOProStack_Tab_Pro_Plugins {
/**
* Render the tab content.
*/
public function render() {
?>
<div class="seoprostack-settings-content tab-content" id="pro-plugins">
<div class="seoprostack-setting-section">
<h2><?php esc_html_e('Premium WordPress Plugins', 'seoprostack'); ?></h2>
<p class="description"><?php esc_html_e('These premium plugins enhance your WordPress site with advanced features and functionality.', 'seoprostack'); ?></p>
<div class="seoprostack-plugin-filters" id="seoprostack-plugin-filters">
<a href="#" class="button current" data-category="all"><?php esc_html_e('All', 'seoprostack'); ?></a>
<a href="#" class="button" data-category="seo"><?php esc_html_e('SEO', 'seoprostack'); ?></a>
<a href="#" class="button" data-category="performance"><?php esc_html_e('Performance', 'seoprostack'); ?></a>
<a href="#" class="button" data-category="analytics"><?php esc_html_e('Analytics', 'seoprostack'); ?></a>
</div>
<div class="seoprostack-loading" style="text-align: center; padding: 30px; display: none;">
<span class="spinner is-active"></span>
<p><?php esc_html_e('Loading plugins...', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-plugin-list" id="seoprostack-plugin-list">
<!-- Plugins will be loaded here via AJAX -->
</div>
<div class="seoprostack-no-plugins" style="display: none;">
<p><?php esc_html_e('No plugins found matching your criteria.', 'seoprostack'); ?></p>
</div>
</div>
<script type="text/javascript">
jQuery(document).ready(function($) {
// Function to load plugins
function loadProPlugins(category) {
var $container = $('#seoprostack-plugin-list');
var $loading = $('.seoprostack-loading');
var $noPlugins = $('.seoprostack-no-plugins');
// Reset container and show loading
$container.empty();
$noPlugins.hide();
$loading.show();
// Make AJAX request
$.ajax({
url: seoProStack.ajaxurl,
type: 'POST',
data: {
action: 'seoprostack_get_pro_plugins',
category: category,
nonce: seoProStack.nonce
},
success: function(response) {
$loading.hide();
if (response.success && response.data.plugins && response.data.plugins.length > 0) {
// Render plugins
$.each(response.data.plugins, function(index, plugin) {
var $pluginCard = $('<div class="seoprostack-plugin-card" />');
// Plugin header
var $header = $('<div class="seoprostack-plugin-header" />');
$header.append('<h3>' + plugin.name + '</h3>');
$header.append('<span class="seoprostack-plugin-version">v' + plugin.version + '</span>');
$pluginCard.append($header);
// Plugin content
var $content = $('<div class="seoprostack-plugin-content" />');
$content.append('<p>' + plugin.description + '</p>');
// Plugin actions
var $actions = $('<div class="seoprostack-plugin-actions" />');
if (plugin.status === 'installed') {
if (plugin.active) {
$actions.append('<span class="button button-disabled">Active</span>');
} else {
$actions.append('<a href="#" class="button activate-plugin" data-plugin="' + plugin.path + '">Activate</a>');
}
} else {
$actions.append('<a href="' + plugin.url + '" class="button button-primary" target="_blank">Get Plugin</a>');
}
$content.append($actions);
$pluginCard.append($content);
// Add card to container
$container.append($pluginCard);
});
} else {
$noPlugins.show();
}
},
error: function() {
$loading.hide();
$noPlugins.show();
}
});
}
// Handle category filter clicks
$('#seoprostack-plugin-filters a').on('click', function(e) {
e.preventDefault();
// Update active filter
$('#seoprostack-plugin-filters a').removeClass('current');
$(this).addClass('current');
// Load plugins
var category = $(this).data('category');
loadProPlugins(category);
});
// Load initial plugins
loadProPlugins('all');
// Delegate plugin activation
$(document).on('click', '.activate-plugin', function(e) {
e.preventDefault();
var $button = $(this);
var pluginPath = $button.data('plugin');
$button.text('Activating...').addClass('updating-message');
$.ajax({
url: seoProStack.ajaxurl,
type: 'POST',
data: {
action: 'seoprostack_activate_plugin',
plugin: pluginPath,
nonce: seoProStack.nonce
},
success: function(response) {
if (response.success) {
$button.removeClass('updating-message')
.removeClass('activate-plugin')
.addClass('button-disabled')
.text('Active')
.prop('disabled', true);
} else {
$button.removeClass('updating-message').text('Activate');
alert(response.data.message || 'Error activating plugin');
}
},
error: function() {
$button.removeClass('updating-message').text('Activate');
alert('Error connecting to server');
}
});
});
});
</script>
</div>
<?php
}
}

View File

@ -0,0 +1,617 @@
<?php
/**
* The Recommended Plugins tab for plugin settings.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Tabs
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Recommended Plugins tab for plugin settings.
* Self-contained class with integrated data and functionality
*/
class SEOProStack_Tab_Recommended_Plugins {
/**
* Tab identifier
*
* @var string
*/
private $tab_id = 'recommended-plugins';
/**
* Plugin details cache.
*
* @var array
*/
private $plugin_details = array();
/**
* Initialize the class.
* Register any hooks or actions here.
*/
public function __construct() {
// Register AJAX handler for plugin installation
add_action('wp_ajax_seoprostack_install_plugins', array($this, 'ajax_install_plugins'));
// Define plugin names and descriptions for common plugins
$this->plugin_details = array(
'wordpress-seo' => array(
'name' => 'Yoast SEO (Free)',
'description' => 'The #1 WordPress SEO plugin that helps you with content optimization, XML sitemaps, and more.'
),
'autoptimize' => array(
'name' => 'Autoptimize',
'description' => 'Optimizes your website, concatenating scripts and styles, minifying and compressing them.'
),
'wp-fastest-cache' => array(
'name' => 'WP Fastest Cache',
'description' => 'This plugin creates static html files from your dynamic WordPress site to speed up your website.'
),
'updraftplus' => array(
'name' => 'UpdraftPlus',
'description' => 'Backup your website with ease, including files and database, and restore with one click.'
),
'google-site-kit' => array(
'name' => 'Site Kit by Google',
'description' => 'Get insights from multiple Google products directly in your WordPress dashboard.'
),
'wordfence' => array(
'name' => 'Wordfence Security',
'description' => 'Protect your site from malicious hackers with firewall and malware scanner.'
),
'rank-math-seo' => array(
'name' => 'Rank Math SEO',
'description' => 'SEO plugin that helps you rank higher in search engines with its powerful features and easy-to-use interface.'
),
'all-in-one-seo-pack' => array(
'name' => 'All in One SEO Pack',
'description' => 'Complete SEO solution for WordPress including on-page SEO optimization, XML sitemaps and more.'
),
'compressx' => array(
'name' => 'CompressX',
'description' => 'Comprehensive image optimization plugin for WordPress that improves page load speed.'
),
'wp-rocket' => array(
'name' => 'WP Rocket',
'description' => 'Premium caching plugin that improves site performance and page loading speed.'
),
'contact-form-7' => array(
'name' => 'Contact Form 7',
'description' => 'Simple but flexible contact form plugin with extensive customization options.'
)
);
}
/**
* Get the tab ID
*
* @return string The tab ID
*/
public function get_tab_id() {
return $this->tab_id;
}
/**
* Get the tab title
*
* @return string The tab title
*/
public function get_title() {
return __('Recommended Plugins', 'seoprostack');
}
/**
* Get the tab description
*
* @return string The tab description
*/
public function get_description() {
return __('These free plugins work well with SEO Pro Stack to enhance your WordPress site.', 'seoprostack');
}
/**
* Get recommended plugins
* This internalizes the data previously retrieved from wp_seoprostack_get_recommended_plugins()
*
* @return array Array of recommended plugins categorized by use case
*/
public function get_recommended_plugins() {
return array(
'minimal' => array(
'antispam-bee',
'compressx',
'fluent-smtp',
'kadence-blocks',
'simple-cloudflare-turnstile'
),
'admin' => array(
'admin-bar-dashboard-control',
'codepress-admin-columns',
'admin-menu-editor',
'hide-admin-notices',
'mainwp-child',
'mainwp-child-reports',
'magic-login',
'manage-notification-emails',
'plugin-groups',
'plugin-toggle'
),
'affiliates' => array(
'pretty-links',
'simple-urls',
'slicewp'
),
'ai' => array(
'ai-engine',
),
'cms' => array(
'auto-post-scheduler',
'block-options',
'bookmark-card',
'browser-shots',
'bulk-actions-select-all',
'bulk-edit-categories-tags',
'bulk-edit-user-profiles-in-spreadsheet',
'carbon-copy',
'code-block-pro',
'iframe-block',
'ics-calendar',
'mammoth-docx-converter',
'nav-menu-roles',
'ninja-tables',
'post-draft-preview',
'post-type-switcher',
'simple-custom-post-order',
'simple-icons',
'sticky-posts-switch',
'term-management-tools',
'the-paste',
'ultimate-addons-for-gutenberg',
'wikipedia-preview',
'wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages'
),
'compliance' => array(
'avatar-privacy',
'complianz-gdpr',
'complianz-terms-conditions',
'really-simple-ssl'
),
'crm' => array(
'fluent-boards',
'fluent-booking',
'fluent-community',
'fluent-crm',
'fluentform',
'fluentforms-pdf',
'fluentform-block',
'fluent-support'
),
'ecommerce' => array(
'woocommerce',
'woo-bulk-edit-products',
'woo-coupons-bulk-editor',
'woocommerce-gateway-gocardless',
'kadence-woocommerce-email-designer',
'pymntpl-paypal-woocommerce',
'woo-stripe-payment'
),
'lms' => array(
'fluent-community',
'masterstudy-lms-learning-management-system',
'tutor'
),
'media' => array(
'easy-watermark',
'enable-media-replace',
'image-copytrack',
'imsanity',
'media-file-renamer',
'safe-svg'
),
'seo' => array(
'burst-statistics',
'pretty-link',
'revive-so',
'seo-by-rank-math',
'syndication-links',
'ultimate-410',
'webmention'
),
'setup' => array(
'kadence-starter-templates',
'wordpress-importer'
),
'social' => array(
'bit-social',
'easy-video-reviews',
'social-engine',
'wp-social-ninja',
'wp-social-reviews'
),
'speed' => array(
'disable-wordpress-updates',
'flying-analytics',
'flying-pages',
'flying-scripts',
'freesoul-deactivate-plugins',
'index-wp-mysql-for-speed',
'litespeed-cache',
'performant-translations',
'wp-optimize',
'wp-widget-disable'
),
'translation' => array(
'hreflang-manager-lite',
'performant-translations',
'translatepress-multilingual'
),
'advanced' => array(
'acf-better-search',
'advanced-custom-fields',
'automatorwp',
'bit-pi',
'bit-integrations',
'code-snippets',
'easy-code-manager',
'favorites',
'remove-cpt-base',
'remove-old-slugspermalinks',
'secure-custom-fields',
'yellow-pencil-visual-theme-customizer'
),
'debug' => array(
'advanced-database-cleaner',
'debug-log-manager',
'gotmls',
'query-monitor',
'string-locator',
'user-switching',
'wp-crontrol'
)
);
}
/**
* Render the tab content.
*/
public function render() {
// Get recommended plugins from the internal method
$recommended_plugins = $this->get_recommended_plugins();
// For backward compatibility, make recommended plugins available through global function
if (function_exists('wp_seoprostack_get_recommended_plugins') && empty($GLOBALS['_wp_seoprostack_recommended_plugins_loaded'])) {
// Optional: merge with any plugins from the external function to ensure none are lost
$external_plugins = wp_seoprostack_get_recommended_plugins();
$recommended_plugins = array_merge_recursive($external_plugins, $recommended_plugins);
$GLOBALS['_wp_seoprostack_recommended_plugins_loaded'] = true;
}
?>
<div class="seoprostack-settings-content tab-content" id="<?php echo esc_attr($this->get_tab_id()); ?>">
<div class="seoprostack-setting-section">
<h2><?php esc_html_e('Recommended Free Plugins', 'seoprostack'); ?></h2>
<p class="description"><?php echo esc_html($this->get_description()); ?></p>
<?php
// Display SEO plugins section
if (!empty($recommended_plugins['seo'])) {
echo '<h3>' . esc_html__('SEO Plugins', 'seoprostack') . '</h3>';
echo '<div class="seoprostack-plugin-grid">';
foreach ($recommended_plugins['seo'] as $plugin_slug) {
$this->render_plugin_card($plugin_slug);
}
echo '</div>';
}
// Display Cache plugins section
if (!empty($recommended_plugins['speed'])) {
echo '<h3>' . esc_html__('Cache & Performance', 'seoprostack') . '</h3>';
echo '<div class="seoprostack-plugin-grid">';
foreach ($recommended_plugins['speed'] as $plugin_slug) {
$this->render_plugin_card($plugin_slug);
}
echo '</div>';
}
// Display Security plugins section
if (!empty($recommended_plugins['security'])) {
echo '<h3>' . esc_html__('Security', 'seoprostack') . '</h3>';
echo '<div class="seoprostack-plugin-grid">';
foreach ($recommended_plugins['security'] as $plugin_slug) {
$this->render_plugin_card($plugin_slug);
}
echo '</div>';
}
// Display Image optimization plugins section
if (!empty($recommended_plugins['media'])) {
echo '<h3>' . esc_html__('Image Optimization', 'seoprostack') . '</h3>';
echo '<div class="seoprostack-plugin-grid">';
foreach ($recommended_plugins['media'] as $plugin_slug) {
$this->render_plugin_card($plugin_slug);
}
echo '</div>';
}
// Display Backup plugins section
if (!empty($recommended_plugins['backup'])) {
echo '<h3>' . esc_html__('Backup & Migration', 'seoprostack') . '</h3>';
echo '<div class="seoprostack-plugin-grid">';
foreach ($recommended_plugins['backup'] as $plugin_slug) {
$this->render_plugin_card($plugin_slug);
}
echo '</div>';
}
?>
<div class="seoprostack-bulk-actions">
<button class="button button-primary" id="seoprostack-install-selected">
<?php esc_html_e('Install Selected Plugins', 'seoprostack'); ?>
</button>
<span class="spinner"></span>
</div>
<div id="seoprostack-install-response"></div>
<script type="text/javascript">
jQuery(document).ready(function($) {
// Handle bulk installation
$('#seoprostack-install-selected').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var $spinner = $button.next('.spinner');
var $response = $('#seoprostack-install-response');
var selected = [];
// Get selected plugins
$('.seoprostack-plugin-check:checked').each(function() {
selected.push($(this).val());
});
if (selected.length === 0) {
$response.html('<div class="seoprostack-notice seoprostack-notice-warning">Please select at least one plugin to install</div>');
return;
}
// Show loading
$button.prop('disabled', true);
$spinner.css('visibility', 'visible');
$response.html('<div class="seoprostack-notice seoprostack-notice-loading">Installing plugins...</div>');
// Send AJAX request
$.ajax({
url: wpSeoProStack.ajaxurl,
type: 'POST',
data: {
action: 'seoprostack_install_plugins',
plugins: selected,
nonce: wpSeoProStack.nonce
},
success: function(response) {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
if (response.success) {
var html = '<div class="seoprostack-notice seoprostack-notice-success">';
html += '<p>Installation completed:</p><ul>';
$.each(response.data.installed, function(i, plugin) {
html += '<li>' + plugin + ' installed and activated successfully</li>';
// Update UI
$('.seoprostack-plugin-card[data-slug="' + plugin + '"]')
.find('.plugin-status')
.removeClass('not-installed')
.addClass('active')
.text('Active');
});
if (response.data.failed.length > 0) {
html += '</ul><p>Installation failed:</p><ul>';
$.each(response.data.failed, function(i, fail) {
html += '<li>' + fail.plugin + ': ' + fail.message + '</li>';
});
}
html += '</ul></div>';
$response.html(html);
} else {
$response.html('<div class="seoprostack-notice seoprostack-notice-error">' + response.data.message + '</div>');
}
},
error: function() {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
// Show error
$response.html('<div class="seoprostack-notice seoprostack-notice-error">Error connecting to server</div>');
}
});
});
});
</script>
</div>
</div>
<?php
}
/**
* Render a plugin card.
*
* @param string $slug The plugin slug.
*/
private function render_plugin_card($slug) {
// Get plugin details
$name = isset($this->plugin_details[$slug]['name']) ? $this->plugin_details[$slug]['name'] : $this->get_readable_name($slug);
$description = isset($this->plugin_details[$slug]['description']) ? $this->plugin_details[$slug]['description'] : '';
// Check if plugin is installed and active
$status = 'not-installed';
$status_text = 'Not Installed';
if (file_exists(WP_PLUGIN_DIR . '/' . $slug)) {
$status = 'installed';
$status_text = 'Installed';
include_once ABSPATH . 'wp-admin/includes/plugin.php';
if (is_plugin_active($slug . '/' . $slug . '.php') || is_plugin_active($slug . '/index.php')) {
$status = 'active';
$status_text = 'Active';
}
}
?>
<div class="seoprostack-plugin-card" data-slug="<?php echo esc_attr($slug); ?>">
<div class="seoprostack-plugin-card-header">
<label class="seoprostack-checkbox-container">
<input type="checkbox" class="seoprostack-plugin-check" value="<?php echo esc_attr($slug); ?>" <?php disabled($status === 'active', true); ?>>
<span class="seoprostack-checkbox-checkmark"></span>
</label>
<span class="plugin-status <?php echo esc_attr($status); ?>"><?php echo esc_html($status_text); ?></span>
</div>
<div class="seoprostack-plugin-card-content">
<h3><?php echo esc_html($name); ?></h3>
<?php if (!empty($description)) : ?>
<p><?php echo esc_html($description); ?></p>
<?php endif; ?>
<div class="seoprostack-plugin-card-footer">
<a href="https://wordpress.org/plugins/<?php echo esc_attr($slug); ?>/" class="button button-secondary" target="_blank">
<?php esc_html_e('View Details', 'seoprostack'); ?>
</a>
</div>
</div>
</div>
<?php
}
/**
* Get a readable name from a plugin slug.
*
* @param string $slug The plugin slug.
* @return string The readable name.
*/
private function get_readable_name($slug) {
$name = str_replace(array('-', '_'), ' ', $slug);
return ucwords($name);
}
/**
* AJAX handler for plugin installation
*/
public function ajax_install_plugins() {
// Check nonce for security
check_ajax_referer('wp-seoprostack-nonce', 'nonce');
// Ensure user has permission
if (!current_user_can('install_plugins')) {
wp_send_json_error(array('message' => __('You do not have permission to install plugins.', 'seoprostack')));
}
// Get selected plugins
$plugins = isset($_POST['plugins']) ? (array) $_POST['plugins'] : array();
if (empty($plugins)) {
wp_send_json_error(array('message' => __('No plugins selected.', 'seoprostack')));
}
// Include required files for plugin installation
require_once ABSPATH . 'wp-admin/includes/plugin.php';
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
// Set up the upgrader
$skin = new WP_Ajax_Upgrader_Skin();
$upgrader = new Plugin_Upgrader($skin);
$installed = array();
$failed = array();
// Install and activate each plugin
foreach ($plugins as $plugin) {
// Skip if already active
if (is_plugin_active($plugin . '/' . $plugin . '.php') || is_plugin_active($plugin . '/index.php')) {
continue;
}
// Get plugin info from wordpress.org
$api = plugins_api('plugin_information', array(
'slug' => $plugin,
'fields' => array(
'short_description' => false,
'sections' => false,
'requires' => false,
'rating' => false,
'ratings' => false,
'downloaded' => false,
'last_updated' => false,
'added' => false,
'tags' => false,
'compatibility' => false,
'homepage' => false,
'donate_link' => false,
),
));
if (is_wp_error($api)) {
$failed[] = array(
'plugin' => $plugin,
'message' => $api->get_error_message()
);
continue;
}
// Install the plugin
$result = $upgrader->install($api->download_link);
if (is_wp_error($result)) {
$failed[] = array(
'plugin' => $plugin,
'message' => $result->get_error_message()
);
continue;
}
if ($result === false) {
$failed[] = array(
'plugin' => $plugin,
'message' => __('Failed to install plugin.', 'seoprostack')
);
continue;
}
// Activate the plugin
$activate = activate_plugin(WP_PLUGIN_DIR . '/' . $plugin . '/' . $plugin . '.php');
if (is_wp_error($activate)) {
// Try alternative file path
$activate = activate_plugin(WP_PLUGIN_DIR . '/' . $plugin . '/index.php');
if (is_wp_error($activate)) {
$failed[] = array(
'plugin' => $plugin,
'message' => $activate->get_error_message()
);
continue;
}
}
$installed[] = $plugin;
}
// Send success response
wp_send_json_success(array(
'installed' => $installed,
'failed' => $failed
));
}
}

View File

@ -0,0 +1,92 @@
<?php
/**
* The Theme tab for plugin settings.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Tabs
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Theme tab for plugin settings.
*/
class SEOProStack_Tab_Theme {
/**
* Render the tab content.
*/
public function render() {
// Get current theme
$current_theme = wp_get_theme();
?>
<div class="seoprostack-settings-content tab-content" id="theme">
<div class="seoprostack-setting-section">
<h2><?php esc_html_e('Theme Recommendations', 'seoprostack'); ?></h2>
<p class="description"><?php esc_html_e('These themes are fast, SEO-friendly, and work well with SEO Pro Stack.', 'seoprostack'); ?></p>
<div class="seoprostack-theme-info">
<h3><?php esc_html_e('Your Current Theme', 'seoprostack'); ?></h3>
<div class="seoprostack-current-theme">
<?php if ($current_theme->get_screenshot()) : ?>
<div class="seoprostack-theme-screenshot">
<img src="<?php echo esc_url($current_theme->get_screenshot()); ?>" alt="<?php echo esc_attr($current_theme->display('Name')); ?>">
</div>
<?php endif; ?>
<div class="seoprostack-theme-details">
<h4><?php echo esc_html($current_theme->display('Name')); ?></h4>
<div class="seoprostack-theme-version"><?php printf(esc_html__('Version: %s', 'seoprostack'), $current_theme->display('Version')); ?></div>
<div class="seoprostack-theme-author"><?php printf(esc_html__('By %s', 'seoprostack'), $current_theme->display('Author')); ?></div>
<p class="description"><?php echo esc_html($current_theme->display('Description')); ?></p>
</div>
</div>
</div>
<div class="seoprostack-recommended-themes">
<h3><?php esc_html_e('Recommended Themes', 'seoprostack'); ?></h3>
<div class="seoprostack-theme-grid">
<!-- Astra Theme -->
<div class="seoprostack-theme-card">
<div class="seoprostack-theme-card-header">
<img src="<?php echo esc_url(SEOPROSTACK_PLUGIN_URL . 'admin/images/themes/astra.jpg'); ?>" alt="Astra Theme">
</div>
<div class="seoprostack-theme-card-content">
<h4>Astra</h4>
<p><?php esc_html_e('Fast, lightweight and customizable WordPress theme suitable for blogs, personal portfolios and business websites.', 'seoprostack'); ?></p>
<a href="https://wpastra.com/" class="button" target="_blank"><?php esc_html_e('Learn More', 'seoprostack'); ?></a>
</div>
</div>
<!-- GeneratePress Theme -->
<div class="seoprostack-theme-card">
<div class="seoprostack-theme-card-header">
<img src="<?php echo esc_url(SEOPROSTACK_PLUGIN_URL . 'admin/images/themes/generatepress.jpg'); ?>" alt="GeneratePress Theme">
</div>
<div class="seoprostack-theme-card-content">
<h4>GeneratePress</h4>
<p><?php esc_html_e('Lightweight WordPress theme focused on speed, stability, and accessibility.', 'seoprostack'); ?></p>
<a href="https://generatepress.com/" class="button" target="_blank"><?php esc_html_e('Learn More', 'seoprostack'); ?></a>
</div>
</div>
<!-- Kadence Theme -->
<div class="seoprostack-theme-card">
<div class="seoprostack-theme-card-header">
<img src="<?php echo esc_url(SEOPROSTACK_PLUGIN_URL . 'admin/images/themes/kadence.jpg'); ?>" alt="Kadence Theme">
</div>
<div class="seoprostack-theme-card-content">
<h4>Kadence</h4>
<p><?php esc_html_e('Fast, lightweight, and extremely customizable WordPress theme.', 'seoprostack'); ?></p>
<a href="https://www.kadencewp.com/kadence-theme/" class="button" target="_blank"><?php esc_html_e('Learn More', 'seoprostack'); ?></a>
</div>
</div>
</div>
</div>
</div>
</div>
<?php
}
}

View File

@ -0,0 +1,299 @@
<?php
/**
* The Tools tab for plugin settings.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Tabs
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Tools tab for plugin settings.
* Self-contained class with integrated data and functionality
*/
class SEOProStack_Tab_Tools {
/**
* Tab identifier
*
* @var string
*/
private $tab_id = 'tools';
/**
* Initialize the class.
* Register any hooks or actions here.
*/
public function __construct() {
// Register AJAX handler for database optimization
add_action('wp_ajax_seoprostack_optimize_database', array($this, 'ajax_optimize_database'));
}
/**
* Get the tab ID
*
* @return string The tab ID
*/
public function get_tab_id() {
return $this->tab_id;
}
/**
* Get the tab title
*
* @return string The tab title
*/
public function get_title() {
return __('Tools', 'seoprostack');
}
/**
* Get the tab description
*
* @return string The tab description
*/
public function get_description() {
return __('Useful tools and resources to help improve your website\'s SEO and performance.', 'seoprostack');
}
/**
* Get the tools data
* This internalizes the data previously retrieved from wp_seoprostack_get_tools()
*
* @return array Array of tools with their details
*/
public function get_tools() {
return array(
'advise' => array(
'name' => 'Advise.so',
'description' => 'Accelerate website growth with AI-powered content optimization and topic recommendations.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://advise.so/',
'primary' => true
),
array(
'text' => 'App',
'url' => 'https://app.advise.so/'
)
)
),
'seoutils' => array(
'name' => 'SEO Utils',
'description' => 'Rich collection of online SEO tools for keyword research, SERP analysis, and content optimization.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://seoutils.com/',
'primary' => true
)
)
),
'dataforseo' => array(
'name' => 'DataForSEO',
'description' => 'Comprehensive SEO APIs for rank tracking, SERP analysis, and keyword research.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://dataforseo.com/',
'primary' => true
),
array(
'text' => 'Dashboard',
'url' => 'https://app.dataforseo.com/'
)
)
),
// For brevity, I'm including only a few tools here
// In production, you would include all tools or dynamically load them
'ahrefs' => array(
'name' => 'Ahrefs',
'description' => 'Comprehensive SEO toolset for backlink analysis, keyword research, and competitor analysis.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://ahrefs.com/',
'primary' => true
),
array(
'text' => 'Dashboard',
'url' => 'https://app.ahrefs.com/'
)
)
),
'localrank' => array(
'name' => 'LocalRank',
'description' => 'Track keyword rankings for multiple locations to better understand local SEO performance.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://app.localrank.io/',
'primary' => true
)
)
),
// Additional tools would be listed here...
);
}
/**
* Render the tab content.
*/
public function render() {
// Get tools from the internal method
$tools = $this->get_tools();
// For backward compatibility, make tools available through the global function
if (function_exists('wp_seoprostack_get_tools') && empty($GLOBALS['_wp_seoprostack_tools_loaded'])) {
// Optional: merge with any tools from the external function to ensure none are lost
$external_tools = wp_seoprostack_get_tools();
$tools = array_merge($external_tools, $tools);
$GLOBALS['_wp_seoprostack_tools_loaded'] = true;
}
?>
<div class="seoprostack-settings-content tab-content" id="<?php echo esc_attr($this->get_tab_id()); ?>">
<div class="seoprostack-setting-section">
<h2><?php esc_html_e('SEO Tools', 'seoprostack'); ?></h2>
<p class="description"><?php echo esc_html($this->get_description()); ?></p>
<div class="seoprostack-tools-grid">
<?php foreach ($tools as $key => $tool) : ?>
<div class="seoprostack-tool-card">
<div class="seoprostack-tool-card-header">
<span class="dashicons dashicons-admin-tools"></span>
</div>
<div class="seoprostack-tool-card-content">
<h3><?php echo esc_html($tool['name']); ?></h3>
<p><?php echo esc_html($tool['description']); ?></p>
<?php if (!empty($tool['button_group'])) : ?>
<?php foreach ($tool['button_group'] as $button) : ?>
<a href="<?php echo esc_url($button['url']); ?>" class="button<?php echo ($button['primary']) ? ' button-primary' : ''; ?>" target="_blank">
<?php echo esc_html($button['text']); ?>
</a>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="seoprostack-setting-section">
<h3><?php esc_html_e('Database Optimization', 'seoprostack'); ?></h3>
<p class="description"><?php esc_html_e('Clean up your WordPress database to improve performance.', 'seoprostack'); ?></p>
<div id="seoprostack-db-cleanup-response"></div>
<div class="seoprostack-db-actions">
<button type="button" class="button button-primary" id="seoprostack-optimize-db">
<?php esc_html_e('Optimize Database', 'seoprostack'); ?>
</button>
<span class="spinner"></span>
</div>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('#seoprostack-optimize-db').on('click', function(e) {
e.preventDefault();
var $button = $(this);
var $spinner = $button.next('.spinner');
var $response = $('#seoprostack-db-cleanup-response');
// Show loading
$button.prop('disabled', true);
$spinner.css('visibility', 'visible');
// Send AJAX request
$.ajax({
url: wpSeoProStack.ajaxurl,
type: 'POST',
data: {
action: 'seoprostack_optimize_database',
nonce: wpSeoProStack.nonce
},
success: function(response) {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
if (response.success) {
$response.html('<div class="seoprostack-notice seoprostack-notice-success">' + response.data.message + '</div>');
} else {
$response.html('<div class="seoprostack-notice seoprostack-notice-error">' + response.data.message + '</div>');
}
},
error: function() {
// Hide loading
$button.prop('disabled', false);
$spinner.css('visibility', 'hidden');
// Show error
$response.html('<div class="seoprostack-notice seoprostack-notice-error">Error connecting to server</div>');
}
});
});
});
</script>
</div>
</div>
</div>
<?php
}
/**
* AJAX handler for database optimization
*/
public function ajax_optimize_database() {
// Check nonce for security
check_ajax_referer('wp-seoprostack-nonce', 'nonce');
// Ensure user has permission
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('You do not have permission to perform this action.', 'seoprostack')));
}
global $wpdb;
// Optimize database tables
$tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
$optimized = 0;
foreach ($tables as $table) {
if (0 === strpos($table[0], $wpdb->prefix)) {
$wpdb->query("OPTIMIZE TABLE {$table[0]}");
$optimized++;
}
}
// Clean up post revisions
$deleted_revisions = $wpdb->query("DELETE FROM $wpdb->posts WHERE post_type = 'revision'");
// Clean up auto drafts
$deleted_drafts = $wpdb->query("DELETE FROM $wpdb->posts WHERE post_status = 'auto-draft'");
// Clean up orphaned postmeta
$deleted_postmeta = $wpdb->query("
DELETE pm
FROM $wpdb->postmeta pm
LEFT JOIN $wpdb->posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL
");
// Send success response
wp_send_json_success(array(
'message' => sprintf(
__('Database optimization complete. Optimized %d tables, deleted %d revisions, %d auto-drafts, and %d orphaned postmeta entries.', 'seoprostack'),
$optimized,
$deleted_revisions,
$deleted_drafts,
$deleted_postmeta
)
));
}
}

View File

@ -0,0 +1,132 @@
<?php
/**
* The Workflow tab for plugin settings.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Admin/Settings/Tabs
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The Workflow tab for plugin settings.
*/
class SEOProStack_Tab_Workflow {
/**
* Render the tab content.
*/
public function render() {
$options = get_option('seoprostack_workflow_options', array(
'auto_upload_images' => true,
'max_width' => 1200,
'max_height' => 1200,
'exclude_urls' => '',
'image_name_pattern' => '%filename%',
'image_alt_pattern' => '%filename%'
));
?>
<div class="seoprostack-settings-content tab-content" id="workflow">
<form method="post" action="options.php" id="seoprostack-workflow-form">
<?php settings_fields('seoprostack_settings'); ?>
<div class="seoprostack-setting-section">
<h2><?php esc_html_e('Image Auto-Upload Settings', 'seoprostack'); ?></h2>
<p class="description"><?php esc_html_e('Configure how external images are automatically uploaded to your media library.', 'seoprostack'); ?></p>
<div class="seoprostack-toggle">
<div class="seoprostack-toggle-header">
<div class="seoprostack-toggle-main">
<div class="seoprostack-toggle-left">
<div class="wp-toggle-switch">
<input type="checkbox"
id="auto_upload_images"
name="seoprostack_workflow_options[auto_upload_images]"
value="1"
<?php checked(isset($options['auto_upload_images']) ? $options['auto_upload_images'] : true); ?>
/>
<label for="auto_upload_images" class="toggle-label"></label>
</div>
<label for="auto_upload_images">
<?php esc_html_e('Enable Auto Upload Images', 'seoprostack'); ?>
</label>
</div>
</div>
<p class="seoprostack-setting-description">
<?php esc_html_e('Import images that have external URLs into your Media Library when saving content. Consider disabling during large data imports with many external image URLs.', 'seoprostack'); ?>
</p>
</div>
<div class="seoprostack-toggle-settings">
<div class="seoprostack-setting-row">
<label for="max_width"><?php esc_html_e('Max Width', 'seoprostack'); ?></label>
<input type="number"
id="max_width"
name="seoprostack_workflow_options[max_width]"
value="<?php echo esc_attr(isset($options['max_width']) ? $options['max_width'] : 1200); ?>"
/>
<p class="description"><?php esc_html_e('Maximum width for uploaded images in pixels.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-setting-row">
<label for="max_height"><?php esc_html_e('Max Height', 'seoprostack'); ?></label>
<input type="number"
id="max_height"
name="seoprostack_workflow_options[max_height]"
value="<?php echo esc_attr(isset($options['max_height']) ? $options['max_height'] : 1200); ?>"
/>
<p class="description"><?php esc_html_e('Maximum height for uploaded images in pixels.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-setting-row">
<label for="exclude_urls"><?php esc_html_e('Exclude URLs', 'seoprostack'); ?></label>
<textarea id="exclude_urls"
name="seoprostack_workflow_options[exclude_urls]"
rows="3"
class="large-text"
><?php echo esc_textarea(isset($options['exclude_urls']) ? $options['exclude_urls'] : ''); ?></textarea>
<p class="description"><?php esc_html_e('Enter domains to exclude (one per line). Images from these domains will not be imported.', 'seoprostack'); ?></p>
</div>
<div class="seoprostack-setting-row">
<label for="image_name_pattern"><?php esc_html_e('Image Name Pattern', 'seoprostack'); ?></label>
<input type="text"
id="image_name_pattern"
name="seoprostack_workflow_options[image_name_pattern]"
value="<?php echo esc_attr(isset($options['image_name_pattern']) ? $options['image_name_pattern'] : '%filename%'); ?>"
class="regular-text"
/>
<p class="description">
<?php esc_html_e('Available patterns:', 'seoprostack'); ?> %filename%, %post_id%, %postname%, %timestamp%, %date%, %year%, %month%, %day%
</p>
</div>
<div class="seoprostack-setting-row">
<label for="image_alt_pattern"><?php esc_html_e('Image Alt Pattern', 'seoprostack'); ?></label>
<input type="text"
id="image_alt_pattern"
name="seoprostack_workflow_options[image_alt_pattern]"
value="<?php echo esc_attr(isset($options['image_alt_pattern']) ? $options['image_alt_pattern'] : '%filename%'); ?>"
class="regular-text"
/>
<p class="description">
<?php esc_html_e('Available patterns:', 'seoprostack'); ?> %filename%, %post_title%, %post_id%, %postname%, %timestamp%
</p>
</div>
</div>
</div>
<div class="seoprostack-setting-actions">
<button type="submit" class="button button-primary">
<?php esc_html_e('Save Changes', 'seoprostack'); ?>
</button>
</div>
</div>
</form>
</div>
<?php
}
}

View File

@ -2,20 +2,24 @@
/**
* Auto Upload Images functionality
*
* @package WP_ALLSTARS
* @since 0.2.0
* @package SEO_Pro_Stack
* @deprecated 1.0.0 Use the class in includes/features/auto-upload/class-seoprostack-auto-upload.php instead
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
class WP_Allstars_Auto_Upload {
/**
* @deprecated 1.0.0 Use SEOProStack_Auto_Upload instead
*/
class SEOProStack_Auto_Upload_Legacy {
/**
* Initialize the class
*/
public function __construct() {
add_filter('content_save_pre', array($this, 'process_content'));
add_filter('content_save_pre', array($this, 'process_content'), 10, 1);
add_action('wp_allstars_image_upload_error', array($this, 'log_error'), 10, 2);
}
@ -62,8 +66,7 @@ class WP_Allstars_Auto_Upload {
return str_replace($url, $local_url, $matches[0]);
}
} catch (Exception $e) {
// Trigger error action for logging
do_action('wp_allstars_image_upload_error', esc_url($url), $e->getMessage());
do_action('wp_allstars_image_upload_error', $url, $e->getMessage());
}
return $matches[0];
@ -86,12 +89,11 @@ class WP_Allstars_Auto_Upload {
*
* @param string $url External image URL
* @return string|false Local URL on success, false on failure
* @throws Exception If download or upload fails
*/
private function upload_image($url) {
$file_array = array(
'name' => sanitize_file_name(basename($url))
);
// Get file info
$file_array = array();
$file_array['name'] = basename($url);
// Download file to temp location
$file_array['tmp_name'] = download_url($url);
@ -100,18 +102,17 @@ class WP_Allstars_Auto_Upload {
throw new Exception('Failed to download image: ' . $file_array['tmp_name']->get_error_message());
}
// Check file type for security
// Check file type
$wp_filetype = wp_check_filetype_and_ext($file_array['tmp_name'], $file_array['name']);
if (!$wp_filetype['type']) {
unlink($file_array['tmp_name']);
throw new Exception('Invalid file type');
}
// Upload the file to media library
// Upload the file
$attachment_id = media_handle_sideload($file_array, 0);
if (is_wp_error($attachment_id)) {
unlink($file_array['tmp_name']);
throw new Exception('Failed to upload image: ' . $attachment_id->get_error_message());
}
@ -125,12 +126,10 @@ class WP_Allstars_Auto_Upload {
* @param string $error Error message
*/
public function log_error($url, $error) {
if (WP_DEBUG) {
error_log(sprintf(
'[WP ALLSTARS] Auto Upload Images Error - URL: %s, Error: %s',
esc_url_raw($url),
sanitize_text_field($error)
'[SEO Pro Stack] Auto Upload Images Error - URL: %s, Error: %s',
$url,
$error
));
}
}
}

View File

@ -1,60 +0,0 @@
<?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

@ -0,0 +1,69 @@
<?php
/**
* Autoloader for SEO Pro Stack plugin.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Core
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* Class SEOProStack_Autoloader
*
* Handles autoloading of plugin classes.
*/
class SEOProStack_Autoloader {
/**
* Register the autoloader
*/
public static function register() {
spl_autoload_register(array(self::class, 'autoload'));
}
/**
* Autoload a class file based on its name
*
* @param string $class_name The name of the class to load.
*/
public static function autoload($class_name) {
// Check if the class should be loaded by this autoloader
if (false === strpos($class_name, 'SEOProStack')) {
return;
}
// Convert class name to filename
$file_path = str_replace('SEOProStack_', '', $class_name);
$file_path = str_replace('_', '-', $file_path);
$file_path = strtolower($file_path);
// Add 'class-' prefix
$file_path = 'class-' . $file_path . '.php';
// Base paths to check for classes
$base_paths = array(
SEOPROSTACK_PLUGIN_DIR . 'includes/',
SEOPROSTACK_PLUGIN_DIR . 'includes/core/',
SEOPROSTACK_PLUGIN_DIR . 'includes/features/',
SEOPROSTACK_PLUGIN_DIR . 'includes/features/auto-upload/',
SEOPROSTACK_PLUGIN_DIR . 'admin/',
SEOPROSTACK_PLUGIN_DIR . 'admin/settings/',
SEOPROSTACK_PLUGIN_DIR . 'admin/settings/ajax/',
SEOPROSTACK_PLUGIN_DIR . 'admin/settings/tabs/',
);
// Try to find and load the file
foreach ($base_paths as $base_path) {
$full_path = $base_path . $file_path;
if (file_exists($full_path)) {
require_once $full_path;
return;
}
}
}
}
SEOProStack_Autoloader::register();

View File

@ -0,0 +1,102 @@
<?php
/**
* Register all actions and filters for the plugin.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Core
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* Register all actions and filters for the plugin.
*/
class SEOProStack_Loader {
/**
* The array of actions registered with WordPress.
*
* @var array $actions The actions registered with WordPress.
*/
protected $actions;
/**
* The array of filters registered with WordPress.
*
* @var array $filters The filters registered with WordPress.
*/
protected $filters;
/**
* Initialize the collections used to maintain the actions and filters.
*/
public function __construct() {
$this->actions = array();
$this->filters = array();
}
/**
* Add a new action to the collection.
*
* @param string $hook The name of the WordPress action that is being registered.
* @param object $component A reference to the instance of the object.
* @param string $callback The name of the function definition on the component.
* @param int $priority Optional. The priority at which the function should be fired. Default is 10.
* @param int $accepted_args Optional. The number of arguments that should be passed to the callback. Default is 1.
*/
public function add_action($hook, $component, $callback, $priority = 10, $accepted_args = 1) {
$this->actions = $this->add($this->actions, $hook, $component, $callback, $priority, $accepted_args);
}
/**
* Add a new filter to the collection.
*
* @param string $hook The name of the WordPress filter that is being registered.
* @param object $component A reference to the instance of the object.
* @param string $callback The name of the function definition on the component.
* @param int $priority Optional. The priority at which the function should be fired. Default is 10.
* @param int $accepted_args Optional. The number of arguments that should be passed to the callback. Default is 1.
*/
public function add_filter($hook, $component, $callback, $priority = 10, $accepted_args = 1) {
$this->filters = $this->add($this->filters, $hook, $component, $callback, $priority, $accepted_args);
}
/**
* A utility function that is used to register the actions and hooks.
*
* @param array $hooks The collection of hooks that is being registered.
* @param string $hook The name of the WordPress filter that is being registered.
* @param object $component A reference to the instance of the object.
* @param string $callback The name of the function definition on the component.
* @param int $priority The priority at which the function should be fired.
* @param int $accepted_args The number of arguments that should be passed to the callback.
* @return array The collection of actions and filters registered.
*/
private function add($hooks, $hook, $component, $callback, $priority, $accepted_args) {
$hooks[] = array(
'hook' => $hook,
'component' => $component,
'callback' => $callback,
'priority' => $priority,
'accepted_args' => $accepted_args,
);
return $hooks;
}
/**
* Register the filters and actions with WordPress.
*/
public function run() {
foreach ($this->filters as $hook) {
add_filter($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']);
}
foreach ($this->actions as $hook) {
add_action($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']);
}
}
}

View File

@ -0,0 +1,69 @@
<?php
/**
* The core plugin class.
*
* @package SEO_Pro_Stack
* @subpackage SEO_Pro_Stack/Core
*/
// If this file is called directly, abort.
if (!defined('ABSPATH')) {
exit;
}
/**
* The core plugin class.
*/
class SEOProStack_Plugin {
/**
* The loader that's responsible for maintaining and registering all hooks.
*
* @var SEOProStack_Loader $loader Maintains and registers all hooks.
*/
protected $loader;
/**
* Define the core functionality of the plugin.
*/
public function __construct() {
$this->load_dependencies();
$this->define_admin_hooks();
$this->define_features();
}
/**
* Load the required dependencies for this plugin.
*/
private function load_dependencies() {
// The class responsible for orchestrating the actions and filters
require_once SEOPROSTACK_PLUGIN_DIR . 'includes/core/class-seoprostack-loader.php';
$this->loader = new SEOProStack_Loader();
}
/**
* Register all of the hooks related to the admin area.
*/
private function define_admin_hooks() {
// Admin functionality
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/class-seoprostack-admin.php';
$admin = new SEOProStack_Admin();
$admin->initialize();
}
/**
* Register all of the hooks related to plugin features.
*/
private function define_features() {
// Auto Upload feature
require_once SEOPROSTACK_PLUGIN_DIR . 'includes/features/auto-upload/class-seoprostack-auto-upload.php';
$auto_upload = new SEOProStack_Auto_Upload();
}
/**
* Run the loader to execute all of the hooks with WordPress.
*/
public function run() {
$this->loader->run();
}
}

View File

@ -0,0 +1,136 @@
<?php
/**
* Auto Upload Images functionality
*
* @package SEO_Pro_Stack
*/
class SEOProStack_Auto_Upload {
/**
* Initialize the class
*/
public function __construct() {
add_filter('content_save_pre', array($this, 'process_content'), 10, 1);
// New action name
add_action('wp_seoprostack_image_upload_error', array($this, 'log_error'), 10, 2);
// Backward compatibility
add_action('wp_allstars_image_upload_error', array($this, 'log_error'), 10, 2);
}
/**
* Process content for external images
*
* @param string $content The post content
* @return string Modified content with local image URLs
*/
public function process_content($content) {
// Check if auto upload is enabled - support both option names for backward compatibility
$seoprostack_options = get_option('wp_seoprostack_workflow_options', null);
$allstars_options = get_option('wp_allstars_workflow_options', array('auto_upload_images' => false));
// Use new options if they exist, otherwise fall back to old options
$options = $seoprostack_options !== null ? $seoprostack_options : $allstars_options;
if (!$options['auto_upload_images']) {
return $content;
}
// Regular expression to find image URLs
$pattern = '/<img[^>]+src=[\'"]([^\'"]+)[\'"][^>]*>/i';
return preg_replace_callback($pattern, array($this, 'process_image_url'), $content);
}
/**
* Process individual image URL
*
* @param array $matches Regex matches
* @return string Updated img tag
*/
private function process_image_url($matches) {
if (empty($matches[1])) {
return $matches[0];
}
$url = $matches[1];
// Skip if already a local URL
if ($this->is_local_url($url)) {
return $matches[0];
}
try {
$local_url = $this->upload_image($url);
if ($local_url) {
return str_replace($url, $local_url, $matches[0]);
}
} catch (Exception $e) {
// Fire both actions for backward compatibility
do_action('wp_seoprostack_image_upload_error', $url, $e->getMessage());
do_action('wp_allstars_image_upload_error', $url, $e->getMessage());
}
return $matches[0];
}
/**
* Check if URL is local
*
* @param string $url URL to check
* @return boolean
*/
private function is_local_url($url) {
$site_url = parse_url(get_site_url(), PHP_URL_HOST);
$image_host = parse_url($url, PHP_URL_HOST);
return $site_url === $image_host;
}
/**
* Upload external image to media library
*
* @param string $url External image URL
* @return string|false Local URL on success, false on failure
*/
private function upload_image($url) {
// Get file info
$file_array = array();
$file_array['name'] = basename($url);
// Download file to temp location
$file_array['tmp_name'] = download_url($url);
if (is_wp_error($file_array['tmp_name'])) {
throw new Exception('Failed to download image: ' . $file_array['tmp_name']->get_error_message());
}
// Check file type
$wp_filetype = wp_check_filetype_and_ext($file_array['tmp_name'], $file_array['name']);
if (!$wp_filetype['type']) {
unlink($file_array['tmp_name']);
throw new Exception('Invalid file type');
}
// Upload the file
$attachment_id = media_handle_sideload($file_array, 0);
if (is_wp_error($attachment_id)) {
throw new Exception('Failed to upload image: ' . $attachment_id->get_error_message());
}
return wp_get_attachment_url($attachment_id);
}
/**
* Log errors to WordPress debug log
*
* @param string $url URL that failed
* @param string $error Error message
*/
public function log_error($url, $error) {
error_log(sprintf(
'[SEO Pro Stack] Auto Upload Images Error - URL: %s, Error: %s',
$url,
$error
));
}
}

View File

@ -1,126 +0,0 @@
<?php
/**
* WP ALLSTARS Plugin
*
* A comprehensive WordPress optimization and management tool designed to enhance
* site performance, improve workflow, and provide recommendations for plugins and hosting.
*
* @package WP_ALLSTARS
* @version v0.2.3.1
*
* Plugin Name: WP Allstars
* Plugin URI: https://wpallstars.com
* Description: A superstar stack of premium WordPress functionality, designed for SEO pros.
* Author: Marcus Quinn
* Author URI: https://wpallstars.com
* Text Domain: wp-allstars
* Domain Path: /languages
* @version v0.2.3.1
*
* 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
* the Free Software Foundation, either version 2 of the License, or
* any later version.
* Version: v0.2.3.1 (Beta)
*
* WP Allstars is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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.
*/
if (!defined('WPINC')) {
exit;
}
define('WP_ALLSTARS_VERSION', 'v0.2.3.1');
/**
* 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;
}
/**
* 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
*/
function wp_allstars_activate() {
// Setup initial config
}
register_activation_hook(__FILE__, 'wp_allstars_activate');
// Core includes
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-auto-upload.php');
// Admin includes
if (is_admin()) {
$admin_includes = array(
'admin/includes/class-admin-manager.php',
'admin/includes/class-settings-manager.php',
'admin/includes/class-theme-manager.php',
'admin/includes/class-workflow-manager.php',
'admin/includes/class-tools-manager.php',
'admin/includes/class-hosting-manager.php',
'admin/includes/class-pro-plugins-manager.php',
'admin/includes/class-plugin-manager.php',
'admin/includes/class-free-plugins-manager.php',
'admin/includes/class-readme-manager.php'
);
foreach ($admin_includes as $file) {
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . $file);
}
// Settings and data
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'admin/data/pro-plugins.php');
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'admin/data/readme.php');
// Admin settings
wp_allstars_require_if_exists(plugin_dir_path(__FILE__) . 'admin/settings.php');
}
/**
* Auto Upload feature initialization
*
* Initialize the Auto Upload feature when a user is logged in
*/
function wp_allstars_init_auto_upload() {
// Only initialize for logged-in users
if (is_user_logged_in()) {
new WP_Allstars_Auto_Upload();
}
}
add_action('init', 'wp_allstars_init_auto_upload');
/**
* Initialize core plugin classes
*/
$wp_allstars_auto_upload = new WP_Allstars_Auto_Upload();

93
wp-seoprostack-plugin.php Normal file
View File

@ -0,0 +1,93 @@
<?php
/**
* Plugin Name: SEO Pro Stack
* Plugin URI: https://www.seoprostack.com
* Description: SEO Pro Stack Plugin for WordPress. Speed Matters.
* Version: 1.0.0
* Author: SEO Pro Stack
* Author URI: https://www.seoprostack.com
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: seoprostack
* Domain Path: /languages
* Requires at least: 5.0
* Requires PHP: 7.2
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
// Define plugin version - extract from plugin header
if (!function_exists('get_plugin_data')) {
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
}
// Define the version constant - first try get_plugin_data() if available,
// otherwise fall back to direct string extraction
if (function_exists('get_plugin_data')) {
$plugin_data = get_plugin_data(__FILE__, false, false);
define('SEOPROSTACK_VERSION', $plugin_data['Version']);
} else {
// Manual extraction as fallback
$plugin_file = file_get_contents(__FILE__);
preg_match('/Version:\s*([^\s]+)/i', $plugin_file, $matches);
define('SEOPROSTACK_VERSION', isset($matches[1]) ? $matches[1] : '1.0.0');
}
define('SEOPROSTACK_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('SEOPROSTACK_PLUGIN_URL', plugin_dir_url(__FILE__));
define('SEOPROSTACK_PLUGIN_BASENAME', plugin_basename(__FILE__));
// Activation hook
function seoprostack_activate() {
// Add activation logic later if needed
}
register_activation_hook( __FILE__, 'seoprostack_activate' );
// Load core functionality
require_once SEOPROSTACK_PLUGIN_DIR . 'includes/features/auto-upload/class-seoprostack-auto-upload.php';
// Load admin UI and configurations
if ( is_admin() ) {
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/pro-plugins-config.php';
require_once SEOPROSTACK_PLUGIN_DIR . 'admin/settings.php';
}
// Admin assets
function seoprostack_admin_assets() {
// Enqueue styles
wp_enqueue_style(
'seoprostack-admin',
SEOPROSTACK_PLUGIN_URL . 'admin/css/seoprostack-admin.css',
array(),
SEOPROSTACK_VERSION
);
// Enqueue WordPress updates script for theme installation
wp_enqueue_script('updates');
wp_enqueue_script(
'seoprostack-admin',
SEOPROSTACK_PLUGIN_URL . 'admin/js/seoprostack-admin.js',
array('jquery', 'updates'),
SEOPROSTACK_VERSION,
true
);
// Localize script for AJAX
$ajax_data = array(
'ajaxurl' => admin_url('admin-ajax.php'),
'adminUrl' => admin_url(),
'nonce' => wp_create_nonce('seoprostack-nonce'),
'updateNonce' => wp_create_nonce('updates')
);
wp_localize_script('seoprostack-admin', 'wpSeoProStack', $ajax_data);
}
add_action('admin_enqueue_scripts', 'seoprostack_admin_assets');
// Initialize classes
$seoprostack_auto_upload = new SEOProStack_Auto_Upload();