150 Commits

Author SHA1 Message Date
ee5881ab57 Fix admin color scheme toggle to work consistently in both directions 2025-03-25 03:06:40 +00:00
c841430181 Improve admin color scheme update with immediate stylesheet replacement 2025-03-25 03:04:21 +00:00
0626754925 Fix admin color scheme toggle to work reliably for both on and off states 2025-03-25 03:01:55 +00:00
223b0f6922 Update Modern Admin Colors description and fix color scheme toggle functionality 2025-03-25 02:57:25 +00:00
1654355939 Update description for Modern Admin Colors feature 2025-03-25 02:54:55 +00:00
4f6625136d Add live admin color scheme switching without page refresh 2025-03-25 02:53:30 +00:00
5edc8c8467 Add Modern Admin Colors feature to customize admin color scheme 2025-03-25 02:51:34 +00:00
b74d8112ca Update plugin version to v0.2.3 2025-03-25 02:43:08 +00:00
05ff272b51 Improve theme install/activate buttons: maintain button size and use spinner animation 2025-03-25 02:34:40 +00:00
e19dfecd6c Fix AJAX functionality for theme Install and Activate buttons 2025-03-25 02:31:50 +00:00
ff306ed32c Fix AJAX functionality for Install Now and Activate buttons 2025-03-25 02:29:01 +00:00
bcb4a7e05b Add Search Atlas to Tools section 2025-03-25 02:25:25 +00:00
0d3c497b23 Update plugin version to v0.2.2 2025-03-25 02:21:06 +00:00
e2bfefc6f6 Change plugin tiles max-width from 700px to 660px 2025-03-25 02:18:54 +00:00
5652ae2ad3 Set plugin tiles to max 700px width while keeping subnav at 900px 2025-03-25 02:17:18 +00:00
394cefa3cf Apply direct and specific 900px width styles to free plugins nav and container 2025-03-25 02:15:21 +00:00
d9a06e3813 Remove grey line from sub-nav panel and fix 900px width issues 2025-03-25 02:13:15 +00:00
f5a17e343e Fix secondary navigation rollover border and width consistently 2025-03-25 02:10:44 +00:00
63c2b7231a Fix secondary nav bottom border and increase max-width to 900px 2025-03-25 02:08:31 +00:00
e1e8e19946 Add rollover underline styling to free plugins secondary navigation to match main tabs 2025-03-25 02:05:24 +00:00
291cbe34f5 Make free plugins secondary navigation max-width match other tabs (700px) 2025-03-25 02:03:19 +00:00
62f368756a Fix missing hover effects for hosting and tools tiles to match Pro Plugins section 2025-03-25 02:01:38 +00:00
4153564acb Fix extra gap above workflow tab content to match other tabs 2025-03-25 01:59:08 +00:00
7eef6caab8 Fix workflow tab 'Enable Auto Upload Images' panel width and styling to match other tabs 2025-03-25 01:57:57 +00:00
d464d4cbe8 Fix workflow tab content width to be consistent with other tabs 2025-03-25 01:56:10 +00:00
817b564813 Fix content width consistency across tabs - ensure all tabs have 700px content width 2025-03-25 01:54:03 +00:00
4f88de74f6 Fix width issues and field notifications 2025-03-25 01:51:33 +00:00
2998604468 Align buttons to left, fix readme panel width, and ensure consistent 700px width for all tab content 2025-03-25 01:40:21 +00:00
d89ecc5548 Fix single column layout for Pro Plugins, Hosting, and Tools tabs with inline CSS 2025-03-25 01:36:37 +00:00
89009dca92 Convert Pro Plugins, Hosting, and Tools tabs to single column layout 2025-03-25 01:34:19 +00:00
a374f26e34 Adjust Free Plugins top padding to 15px for better spacing 2025-03-25 01:32:14 +00:00
d9b136f925 Reduce top padding from 25px to 10px in Free Plugins section 2025-03-25 01:31:31 +00:00
576d79b1e7 Add 25px gap before plugin tiles in Free Plugins section 2025-03-25 01:29:30 +00:00
a467a6aa10 Remove duplicate 'Read Me' title from readme tab content 2025-03-25 01:27:58 +00:00
1f885f1745 Increase tab spacing to a consistent 25px across all tabs 2025-03-25 01:26:06 +00:00
2158855a1a Refactor tab spacing to be consistent across all tabs by centralizing margin settings 2025-03-25 01:24:25 +00:00
233006f155 Fix tab spacing inconsistencies 2025-03-25 01:22:33 +00:00
4e951f1fb7 Include Workflow tab in spacing fix to ensure consistent layout 2025-03-25 01:21:01 +00:00
fd78d35186 Fix inconsistent spacing in General, Advanced, and Read Me tabs 2025-03-25 01:19:27 +00:00
fba03d6e43 Revert tab spacing changes that caused content to appear under wrong tabs 2025-03-25 01:17:44 +00:00
9b307f1b9d Standardize spacing between tabs and content across all tab types 2025-03-25 01:15:53 +00:00
894a31d5b6 Set top content padding to 25px to increase space between main and secondary tabs 2025-03-25 01:13:47 +00:00
01740ed72c Reduce spacing between main tab and secondary tabs 2025-03-25 01:12:42 +00:00
bbb0dc377a Restore original gap between subcategory tabs and plugin content 2025-03-25 01:11:52 +00:00
8e6371fe9d Revert changes to layout and compatibility text positioning 2025-03-25 01:10:29 +00:00
d9413aff1c Reduce gap between subcategory filters and plugin content to zero 2025-03-25 01:09:04 +00:00
f1c3087900 Reduce tab content top padding to close gap between tabs and plugins 2025-03-25 01:07:18 +00:00
2d644e9c37 Fix compatibility text positioning using transform instead of margin 2025-03-25 01:05:50 +00:00
fbb4cb69ba Reduce gap between subcategory tabs and plugin content by 10px 2025-03-25 01:04:33 +00:00
7a3b8a948f Move compatibility text another 10px to the left 2025-03-25 01:03:13 +00:00
d8130b1e19 Move compatibility text further left by increasing margin-right to 35px 2025-03-25 01:02:01 +00:00
b069bf3f3c Reduce gap between filter nav bar and results to be consistent with other tabs 2025-03-25 00:59:23 +00:00
ba0878b230 Update theme tiles to be constrained to max-width of 800px 2025-03-25 00:57:40 +00:00
4f391f0cda Fix responsive navigation: make top tabs and filter links wrap properly at smaller window widths 2025-03-25 00:55:46 +00:00
d5a4a29ae9 Fix compatibility text alignment using margin-right instead of padding-left 2025-03-25 00:54:10 +00:00
daccb54342 Double padding-left for compatibility text to move it further left 2025-03-25 00:53:05 +00:00
90f6969e1b Move compatibility text 25px to the left instead of right 2025-03-25 00:52:00 +00:00
f7b8629926 Move compatibility text 25px to the right for better alignment 2025-03-25 00:50:52 +00:00
aac7ac1195 Fix inconsistent tile width between 1086px and 1400px window widths 2025-03-25 00:47:54 +00:00
6528d8e79a Make plugin layout consistent for all screen widths based on 768px layout 2025-03-25 00:45:29 +00:00
21b0ef599d Fix text overlap on desktop screens by increasing content margins and button width 2025-03-25 00:41:58 +00:00
5f45ea85fa Fix mobile layout and text wrapping: prevent button overlap, improve text wrapping on desktop, fix mobile responsiveness 2025-03-25 00:39:30 +00:00
c3d1aff49f Refine single column plugin layout: full-width nav, fix descriptions, right-align compatibility text, transparent loading spinner 2025-03-25 00:36:08 +00:00
d389f92bd6 Update plugin tile layout to single centered column with max width 700px 2025-03-25 00:28:19 +00:00
23c5d0adce Improve free plugins tile layout: Implement consistent grid layout matching pro plugins section, add responsive design with breakpoints, improve spacing and alignment, standardize styling, fix mobile layout, add hover effects 2025-03-25 00:15:09 +00:00
1384145138 Align plugin description text with plugin name 2025-03-25 00:03:52 +00:00
169b226a39 Fix Free Plugins grid centering with improved flexbox layout 2025-03-24 23:50:09 +00:00
69ad1d55a7 Improve Free Plugins grid: center tiles and fix text alignment 2025-03-24 23:48:33 +00:00
42150fe694 Simplify Free Plugins grid with clean, centered tile layout 2025-03-24 23:43:37 +00:00
6040c1b5bd Fix: Increase plugin card padding and improve responsive grid layout 2025-03-24 23:34:18 +00:00
1224937955 Fix: Improve Free Plugins grid layout with consistent spacing and card styling 2025-03-24 23:29:13 +00:00
34b09de04e Fix: Position notification badges 3px higher with transform translateY 2025-03-24 23:24:27 +00:00
41adfb56e4 Fix: Move notification badges up by 3px for better vertical alignment 2025-03-24 23:21:41 +00:00
f03da91142 Fix: Properly align accordion panel borders to prevent overflow 2025-03-24 23:19:06 +00:00
69623d2660 Fix: Remove horizontal gaps in accordion content panels 2025-03-24 23:15:20 +00:00
e90f6168ed Fix: Improve accordion box styling and plugin card layouts with proper vertical gutters 2025-03-24 23:12:39 +00:00
eb768d9090 Fix: Properly target all settings rows, add plugin tile gutters, improve responsive padding 2025-03-24 23:08:45 +00:00
1b548a59e2 Fix: Improve targeting for General/Advanced tabs, add 75% breakpoint, add gutters to Free Plugin tiles 2025-03-24 23:01:01 +00:00
03d9511f4b Improve settings layout: fix text overlap with chevrons, standardize width across tabs, enhance responsive behavior 2025-03-24 22:57:33 +00:00
2b01f3523f Fix: Target individual setting rows to limit width to 50% on desktop 2025-03-24 22:48:08 +00:00
016f6000a6 Limit settings width to 50% in General, Advanced, and Workflow tabs to match readme panel 2025-03-24 22:45:33 +00:00
1cf243d5e1 Fine-tune numbered list indentation - move 2px to the right 2025-03-24 22:35:36 +00:00
09aebfcc98 Fix numbered list indentation to match bullet lists with dedicated class and targeted CSS 2025-03-24 22:33:07 +00:00
e00c627410 Adjust numbered list indentation to match bullet list indentation 2025-03-24 22:31:06 +00:00
c16e1d62fd Comprehensive fix for list styling in readme with improved markdown parser and CSS 2025-03-24 22:29:01 +00:00
ad2aba88a3 Enhance list styling to ensure consistent display across all readme sections 2025-03-24 22:24:31 +00:00
4de39fbd85 Reduce left padding for numbered lists to visually align with bullet lists 2025-03-24 22:21:40 +00:00
ea881f7691 Standardize bullet and numbered list styling with consistent indentation and spacing 2025-03-24 22:19:26 +00:00
19cd4d3355 Add support for numbered lists in Read Me tab with consistent styling 2025-03-24 22:17:38 +00:00
5a28089043 Fix bullet list styling on Read Me tab with proper bullets and reduced line spacing 2025-03-24 22:15:57 +00:00
9cd079206f Fix Pricing buttons to always use green styling with dedicated class and CSS rules 2025-03-24 22:11:04 +00:00
a82bd8b3f4 Fix secondary button borders to ensure all are green with more specific CSS selectors 2025-03-24 22:08:04 +00:00
7c6afdc8c7 Fix button styling: green borders on all secondary buttons, vertical text alignment, and blue version text 2025-03-24 22:05:55 +00:00
f8c098b5a1 Update CSS to ensure secondary buttons on all tabs have green borders 2025-03-24 22:03:00 +00:00
1eb732684b Add green styling to secondary buttons and Visit Website button across the plugin 2025-03-24 22:00:08 +00:00
a4b594c0e2 Update Go Pro buttons to use darker green colors with consistent hover states 2025-03-24 21:52:39 +00:00
5f90586044 Add hover effect for Go Pro buttons to make green darker on hover 2025-03-24 21:45:09 +00:00
a2b7ba6d72 Rename About tab to Read Me and display README.md content 2025-03-24 21:37:09 +00:00
e83dbcfff7 Center About panel and make it responsive 2025-03-24 21:32:15 +00:00
28f87f689e Add About tab with markdown support 2025-03-24 21:30:03 +00:00
5f195f8cfb Remove duplicate margin from plugin table to fix spacing 2025-03-24 21:18:48 +00:00
d2e8cc858c Add direct inline style to set 22px spacing between filter menu and plugin content 2025-03-24 21:16:53 +00:00
dc6b1a046f Set consistent 22px top margin on plugin browser container 2025-03-24 21:10:25 +00:00
221eefab9e Reduce filter menu bottom margin from 25px to 22px for consistent spacing 2025-03-24 21:07:27 +00:00
a81b6ac5a7 Fix double padding issue in tab content spacing 2025-03-24 21:05:24 +00:00
634f29eee7 Refactor tab content spacing for consistent 22px gap across all sections 2025-03-24 21:02:48 +00:00
e94a1d902d Fix theme list spacing by adding !important to margin-top rule 2025-03-24 20:59:50 +00:00
1c477aa0f2 Standardize tab-to-content spacing to consistent 22px throughout plugin 2025-03-24 20:55:14 +00:00
9108a5345c Increase gap between tabs and content by 2px (padding-top: 20px → 22px) 2025-03-24 20:51:40 +00:00
16d0d5e2ef Increase gap between tabs and content by 2px (padding-top: 20px → 22px) 2025-03-24 20:51:27 +00:00
8fa4b67da9 Preserve previous category order in dynamically generated Free Plugins menu 2025-03-24 20:43:14 +00:00
673d4a60fd Make Free Plugins filter menu dynamically generated from data file 2025-03-24 20:40:52 +00:00
4d671d5901 Update Free Plugins filter menu to show all available categories 2025-03-24 20:38:51 +00:00
0c96faaf60 Fix loading spinner positioning on Free Plugins tab 2025-03-24 20:34:15 +00:00
83d7debe54 Fix security token verification in Free Plugins tab 2025-03-24 20:28:33 +00:00
ccc57dc72b Fix duplicate loading spinners in Free Plugins tab 2025-03-24 20:26:28 +00:00
f0d00accaf Fix Free Plugins tab HTML structure and JS selectors 2025-03-24 20:02:40 +00:00
19e6455abb Fix free plugins tab loading and settings toggle error 2025-03-24 19:59:15 +00:00
f7fb0c6545 Restore original pro-plugins configuration data with updated function name 2025-03-24 18:58:15 +00:00
9e1c077080 Refactor plugin structure:
- Rename pro-plugins-config.php to data/pro-plugins.php
- Rename recommended-plugins.php to free-plugins.php
- Rename class-recommended-plugins-manager.php to class-free-plugins-manager.php
- Update all references throughout the codebase
- Add enhanced hover effects to Go Pro buttons
2025-03-24 18:42:24 +00:00
4bbcbe3d12 Fix: Update admin menu registration to use correct class method 2025-03-24 18:11:02 +00:00
46696eff87 Fix: Resolve critical error by restoring pro plugins function and required includes 2025-03-24 18:06:04 +00:00
8cef4c8868 Code cleanup: Improved documentation and removed backward compatibility code 2025-03-24 18:04:15 +00:00
da5d08587c UI Improvements: Center-aligned tabs and filters, standardized button styles 2025-03-24 17:55:29 +00:00
c2276f4ebd Fix: Ensure consistent padding in Theme tab matching other tabs 2025-03-24 17:45:52 +00:00
b267156b68 Fix: Ensure consistent padding across all tab content areas 2025-03-24 17:43:14 +00:00
ddd64643c4 Fix: Ensure consistent padding and wrapper structure across all tabs 2025-03-24 17:36:48 +00:00
ddd2846171 Fix: Add proper tab content padding and fix Theme tab loading issues 2025-03-24 17:30:23 +00:00
4fe9d45eba Fix: Restore original tab order and fix method name mismatches to resolve critical errors 2025-03-24 17:24:44 +00:00
ad489bddb5 Refactor: Clean up settings.php by removing all HTML content and properly delegating to Admin Manager class 2025-03-24 17:19:25 +00:00
5fdc3e277c refactor: move script and style enqueuing to Admin Manager class 2025-03-24 17:09:11 +00:00
096c9be284 refactor: move settings registration to Admin Manager class 2025-03-24 17:07:41 +00:00
2b4e3cecd3 refactor: move AJAX option handler to Admin Manager class 2025-03-24 17:06:09 +00:00
d280ec197b refactor: create Admin Manager class and move menu registration 2025-03-24 17:04:22 +00:00
5352b38348 refactor: move Recommended Plugins tab to WP_Allstars_Recommended_Plugins_Manager class 2025-03-24 16:31:46 +00:00
2405f98eb8 refactor: move Hosting tab functionality to WP_Allstars_Hosting_Manager class 2025-03-24 16:17:31 +00:00
24ffdf8950 fix: theme tab loading by properly enqueuing required scripts 2025-03-24 16:11:50 +00:00
93c3290b63 refactor: move Theme tab functionality to WP_Allstars_Theme_Manager class 2025-03-24 16:07:11 +00:00
436a829646 ui: move Theme tab before Free Plugins tab in navigation 2025-03-24 16:00:11 +00:00
20fb06a29e fix: tools tab styling issues by making CSS classes consistent 2025-03-24 15:57:47 +00:00
8fa2b00d7a refactor: move Settings and Tools tabs to dedicated classes
- Created WP_Allstars_Settings_Manager class to handle General and Advanced tabs
- Created WP_Allstars_Tools_Manager class to handle Tools tab functionality
- Moved inline CSS to properly enqueued styles
- Further reduced code duplication in settings.php
- Improved code organization with OOP principles
2025-03-24 15:52:16 +00:00
f0ffa7e552 refactor: move Pro Plugins section to dedicated class
- Created new WP_Allstars_Pro_Plugins_Manager class to handle all Pro Plugins functionality
- Moved styling from inline CSS to properly enqueued styles
- Improved code organization by separating concerns
- Reduced code duplication in settings.php
2025-03-24 15:38:44 +00:00
55d092d568 Remove 'Version' prefix from version display in admin header 2025-03-24 15:19:54 +00:00
1b02e8eb24 Update version to v0.2.0 (Beta) 2025-03-24 15:18:27 +00:00
c8835de92f Fix theme tab critical error by adding required content section 2025-03-24 15:15:36 +00:00
d9c710969b Update plugin card button styling for consistent UI 2025-03-24 14:53:42 +00:00
2c68b66dbc Fix plugin display issues in the Plugin Manager class 2025-03-24 14:40:05 +00:00
9b0e7acd2d Refactor plugin functionality into Plugin Manager class 2025-03-24 14:17:09 +00:00
930530cc96 Add Coolify to hosting providers 2025-03-24 14:04:48 +00:00
ecd3887bb9 Restructure data arrays into separate files for improved maintainability 2025-03-24 13:57:41 +00:00
25 changed files with 4790 additions and 2257 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

@ -33,7 +33,7 @@
}
.wp-allstars-version {
color: #d35400; /* Updated to dark orange */
color: #0073aa; /* Changed to WordPress blue */
font-size: 13px;
font-weight: 400;
}
@ -48,6 +48,11 @@
position: sticky;
top: 32px;
z-index: 100;
text-align: center; /* Center align the tabs */
display: flex;
flex-wrap: wrap; /* Enable wrapping */
justify-content: center; /* Ensure better centering for tabs */
margin-bottom: 25px !important; /* Increase from 15px to 25px for all tabs */
}
.nav-tab {
@ -83,6 +88,27 @@
font-weight: 600;
}
/* Responsive nav tabs */
@media screen and (max-width: 782px) {
.nav-tab-wrapper,
.wrap h2.nav-tab-wrapper {
padding: 0 10px;
}
.nav-tab {
padding: 10px 15px;
font-size: 13px;
line-height: 1.8;
}
}
@media screen and (max-width: 600px) {
.nav-tab {
padding: 8px 12px;
font-size: 12px;
}
}
/* Base Toggle Switch Component */
.wp-toggle-switch {
position: relative;
@ -137,6 +163,39 @@ input:checked + .wp-toggle-slider:before {
transform: translateX(16px);
}
/* Tab Content Area - GLOBAL SETTINGS - All tab spacing should inherit from here */
.wp-allstars-tab-content {
padding-top: 0 !important; /* Remove all padding-top from tab content */
}
/* Reset all tab content padding */
.wp-allstars-settings-content {
padding-top: 0 !important;
}
/* Remove previous spacing attempts */
#general .wp-allstars-settings-section,
#advanced .wp-allstars-settings-section,
#readme .wp-allstars-settings-section,
#workflow .wp-allstars-settings-section,
#theme .wp-allstars-settings-section,
#recommended .wp-allstars-settings-section,
#pro .wp-allstars-settings-section,
#hosting .wp-allstars-settings-section,
#tools .wp-allstars-settings-section {
padding-top: 0 !important;
margin-top: 0 !important;
}
/* Apply consistent spacing to the container for all tab types */
.wp-allstars-settings-section,
.wpa-plugin-container,
.wpa-pro-plugins,
.wp-allstars-markdown-content {
padding-top: 0 !important;
margin-top: 0 !important;
}
/* Base Setting Styles (Shared between simple and expandable) */
.wp-setting-base,
.wp-setting-row,
@ -302,7 +361,7 @@ input:checked + .wp-toggle-slider:before {
/* Settings Container */
.wpa-settings-content {
margin-top: 20px;
margin-top: 22px;
padding: 0 20px;
}
@ -354,7 +413,7 @@ input:checked + .wp-toggle-slider:before {
/* Plugin List Container */
.wp-list-table-container {
margin-top: 20px;
margin-top: 22px;
padding: 0 20px;
position: relative;
min-height: 400px;
@ -492,10 +551,12 @@ input:checked + .wp-toggle-slider:before {
/* Theme Container */
#wpa-theme-list {
margin-top: 20px;
margin-top: 0;
padding: 0 20px;
position: relative;
min-height: 400px;
max-width: 800px;
margin: 0 auto;
}
/* Theme Card Styles - Scoped to our plugin only */
@ -508,6 +569,7 @@ input:checked + .wp-toggle-slider:before {
margin-bottom: 20px;
overflow: hidden;
transition: all 0.2s ease;
width: 100%;
}
.theme-card:hover {
@ -561,6 +623,31 @@ input:checked + .wp-toggle-slider:before {
gap: 8px;
}
/* Fix theme buttons to maintain consistent size and prevent layout jumps */
.theme-actions .button {
min-width: 80px !important;
text-align: center !important;
position: relative !important;
padding-left: 12px !important;
padding-right: 12px !important;
}
/* Style for the updating message with spinner */
.theme-actions .button.updating-message:before,
.theme-actions .button.updated-message:before {
margin-top: 0 !important;
padding-right: 3px !important;
vertical-align: bottom !important;
}
/* Style theme actions container spacing */
.theme-actions {
display: flex !important;
flex-wrap: wrap !important;
gap: 8px !important;
padding: 15px !important;
}
/* Responsive Adjustments */
@media screen and (max-width: 1200px) {
.plugin-card .name,
@ -645,6 +732,7 @@ input:checked + .wp-toggle-slider:before {
height: 20px;
box-sizing: border-box;
position: relative;
transform: translateY(-3px);
}
.wp-setting-notification.error {
@ -665,7 +753,7 @@ input:checked + .wp-toggle-slider:before {
.wp-allstars-setting-row label .wp-setting-notification {
position: absolute;
right: -60px;
top: -2px;
top: -5px;
transform: translateY(0);
line-height: 1.4;
}
@ -694,13 +782,13 @@ input:checked + .wp-toggle-slider:before {
z-index: 1;
}
/* Panel styles for Pro Plugins, Hosting, and Tools tabs */
/* Panel styles for Pro Plugins, Hosting, and Tools tabs - Single Column Layout */
.wpa-pro-plugins {
padding: 20px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));
gap: 24px;
max-width: 1920px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 700px; /* Match Free Plugins max-width */
margin: 0 auto;
}
@ -713,6 +801,13 @@ input:checked + .wp-toggle-slider:before {
flex-direction: column;
transition: all 0.2s ease;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
width: 100%; /* Full width of container */
margin-bottom: 24px; /* Match Free Plugins spacing */
max-width: 100%; /* Ensure it doesn't exceed container */
}
.wpa-pro-plugin:last-child {
margin-bottom: 0;
}
.wpa-pro-plugin:hover {
@ -740,6 +835,7 @@ input:checked + .wp-toggle-slider:before {
flex-wrap: wrap;
gap: 8px;
margin-top: auto;
justify-content: flex-end; /* Right-align buttons like Free Plugins */
}
.wpa-pro-plugin .button {
@ -780,10 +876,16 @@ input:checked + .wp-toggle-slider:before {
color: #fff;
}
/* Adjust spacing between pro plugins content and tabs navigation */
#pro .wpa-pro-plugins,
#hosting .wpa-pro-plugins,
#tools .wpa-pro-plugins {
padding-top: 15px; /* Match Free Plugins padding */
}
/* Simplify media queries since we're using single column at all widths */
@media screen and (max-width: 960px) {
.wpa-pro-plugins {
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
gap: 20px;
padding: 16px;
}
.wpa-pro-plugin {
@ -793,14 +895,682 @@ input:checked + .wp-toggle-slider:before {
@media screen and (max-width: 782px) {
.wpa-pro-plugins {
grid-template-columns: 1fr;
gap: 16px;
padding: 12px;
}
.wpa-pro-plugin {
padding: 16px;
}
.wpa-pro-plugin .button {
}
/* Markdown Content Styles for About Tab */
.wp-allstars-markdown-content {
line-height: 1.6;
color: #333;
padding: 0 20px 20px 20px !important; /* No top padding, consistent with other containers */
}
.wp-allstars-markdown-content h1 {
font-size: 2em;
margin: 0.67em 0;
border-bottom: 1px solid #eaecef;
padding-bottom: 0.3em;
}
.wp-allstars-markdown-content h2 {
font-size: 1.5em;
margin: 0.83em 0;
border-bottom: 1px solid #eaecef;
padding-bottom: 0.3em;
}
.wp-allstars-markdown-content h3 {
font-size: 1.25em;
margin: 1em 0;
}
.wp-allstars-markdown-content ul {
padding-left: 2em;
margin: 1em 0;
}
.wp-allstars-markdown-content li {
margin: 0.5em 0;
}
.wp-allstars-markdown-content a {
color: #0073aa;
text-decoration: none;
}
.wp-allstars-markdown-content a:hover {
color: #00a0d2;
text-decoration: underline;
}
.wp-allstars-markdown-content p {
margin: 1em 0;
}
/* Go Pro Button Styles */
.button.button-primary[style*="background-color: #27ae60"],
.theme-install-actions .button.button-primary,
.wpa-pro-plugin .button-group .button.button-primary,
.go-pro-button {
transition: all 0.3s ease !important;
background-color: #219653 !important; /* Darker green */
border-color: #1e874b !important; /* Even darker for border */
color: #ffffff !important;
}
.button.button-primary[style*="background-color: #27ae60"]:hover,
.theme-install-actions .button.button-primary:hover,
.wpa-pro-plugin .button-group .button.button-primary:hover,
.go-pro-button:hover {
background-color: #1b7b42 !important; /* Even darker green on hover */
border-color: #186a39 !important; /* Darkest for border */
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2) !important;
}
/* Green Secondary Button Styles */
.green-button-secondary,
.green-visit-website,
#pro .button-group .button.button-secondary,
#hosting .button-group .button.button-secondary,
#tools .button-group .button.button-secondary,
#readme .button-group .button.button-secondary,
#pro .button.button-secondary,
#hosting .button.button-secondary,
#tools .button.button-secondary,
#readme .button.button-secondary,
.button.button-secondary,
/* More specific selectors to override WP defaults */
.wp-allstars-tabs-wrapper .button.button-secondary,
.wp-allstars-settings-content .button.button-secondary,
.wpa-pro-plugins .button.button-secondary,
.wpa-pro-plugin .button.button-secondary,
body.wp-admin .button.button-secondary {
transition: all 0.3s ease !important;
color: #219653 !important; /* Darker green */
border-color: #219653 !important; /* Darker green */
background-color: transparent !important;
}
.green-button-secondary:hover,
.green-visit-website:hover,
#pro .button-group .button.button-secondary:hover,
#hosting .button-group .button.button-secondary:hover,
#tools .button-group .button.button-secondary:hover,
#readme .button-group .button.button-secondary:hover,
#pro .button.button-secondary:hover,
#hosting .button.button-secondary:hover,
#tools .button.button-secondary:hover,
#readme .button.button-secondary:hover,
.button.button-secondary:hover,
.wp-allstars-tabs-wrapper .button.button-secondary:hover,
.wp-allstars-settings-content .button.button-secondary:hover,
.wpa-pro-plugins .button.button-secondary:hover,
.wpa-pro-plugin .button.button-secondary:hover,
body.wp-admin .button.button-secondary:hover {
color: #1b7b42 !important; /* Even darker green on hover */
border-color: #1b7b42 !important; /* Even darker green on hover */
background-color: rgba(33, 150, 83, 0.05) !important; /* Very light green background */
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) !important;
}
/* Button text vertical alignment */
.button, .button-primary, .button-secondary {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
}
/* Specific styling for Pricing buttons */
.pricing-button,
a.button.pricing-button,
body.wp-admin .button.pricing-button,
#pro a.button.pricing-button,
#hosting a.button.pricing-button,
#tools a.button.pricing-button,
#readme a.button.pricing-button {
color: #219653 !important;
border-color: #219653 !important;
background-color: transparent !important;
}
.pricing-button:hover,
a.button.pricing-button:hover,
body.wp-admin .button.pricing-button:hover,
#pro a.button.pricing-button:hover,
#hosting a.button.pricing-button:hover,
#tools a.button.pricing-button:hover,
#readme a.button.pricing-button:hover {
color: #1b7b42 !important;
border-color: #1b7b42 !important;
background-color: rgba(33, 150, 83, 0.05) !important;
}
/* Limit width of content in all main tabs */
.wp-allstars-tab-content .wp-allstars-settings-section,
#readme .wpa-pro-plugins {
display: block;
padding: 20px;
}
/* Target the specific setting rows to limit their width */
.wp-allstars-tab-content .wp-setting-row,
.wp-allstars-tab-content .wp-allstars-toggle,
#readme .wpa-pro-plugin {
max-width: 700px; /* Change from 50% to match global 700px width */
margin: 0 auto 20px auto;
box-sizing: border-box;
padding: 0;
}
/* Filter navigation - container at max-width to match other tabs */
#wpa-plugin-filters {
max-width: 900px !important;
margin: 0 auto 25px auto !important;
box-sizing: border-box;
padding: 15px;
border-radius: 8px;
background: #fff;
}
/* Filter links should be centered within container */
#wpa-plugin-filters .filter-links {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
margin: 0;
padding-bottom: 0;
}
/* Style the filter links similar to main tabs with proper border */
#wpa-plugin-filters .filter-links a {
margin: 0;
padding: 10px 15px;
font-size: 14px;
line-height: 1.6;
font-weight: 400;
background: transparent;
color: #50575e;
text-decoration: none;
white-space: nowrap;
border: none;
border-bottom: 2px solid transparent;
display: inline-block;
transition: all 0.2s ease;
}
#wpa-plugin-filters .filter-links a:hover,
#wpa-plugin-filters .filter-links a:focus {
color: #2271b1;
background: transparent;
border-bottom: 2px solid #2271b1;
}
#wpa-plugin-filters .filter-links a.current {
border-bottom: 2px solid #2271b1;
background: transparent;
color: #2271b1;
font-weight: 600;
}
/* Override max-width for free plugins specific elements */
#wpa-plugin-filters,
#recommended .wpa-plugin-container {
max-width: 900px !important;
width: 100% !important;
}
/* Free Plugins - Single Column Centered Layout */
#recommended .wpa-plugin-container {
padding: 15px 20px 20px 20px !important;
display: flex;
flex-direction: column;
align-items: center;
margin: 0 auto;
}
/* Use consistent layout similar to 768px width for all screen sizes */
#recommended .plugin-card {
width: 100%;
margin: 0 0 24px 0;
padding: 24px;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
background: #fff;
transition: all 0.2s ease;
display: flex;
flex-direction: column;
position: relative;
}
#recommended .plugin-card:last-child {
margin-bottom: 0;
}
#recommended .plugin-card:hover {
border-color: #2271b1;
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
#recommended .plugin-card-top {
padding: 0;
min-height: auto;
flex-grow: 1;
}
#recommended .plugin-card .plugin-icon {
position: relative;
float: left;
width: 64px;
height: 64px;
margin: 0 20px 15px 0;
}
#recommended .plugin-card .name,
#recommended .plugin-card .desc {
margin-left: 84px;
margin-right: 0; /* Full width content */
}
#recommended .plugin-card .name h3 {
margin: 0 0 12px;
font-size: 16px;
font-weight: 600;
color: #1d2327;
line-height: 1.4;
word-wrap: break-word;
}
#recommended .plugin-card .desc {
margin-top: 0;
color: #50575e;
font-size: 14px;
line-height: 1.6;
margin-bottom: 20px;
}
/* Position action links below content, not absolute */
#recommended .plugin-card .action-links {
position: relative;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
gap: 8px;
padding: 0;
margin-top: 10px;
}
#recommended .plugin-card .plugin-action-buttons {
margin: 0;
float: none;
width: auto;
}
#recommended .plugin-card .plugin-action-buttons .button {
width: auto;
min-width: 120px;
text-align: center;
}
/* Plugin card bottom with right-aligned compatibility text */
#recommended .plugin-card .plugin-card-bottom {
background: #f6f7f7;
padding: 15px 20px;
border-top: 1px solid #ddd;
text-align: right;
margin-top: auto;
}
/* Style compatibility message */
#recommended .plugin-card .column-compatibility {
text-align: center;
font-size: 13px;
color: #00a32a;
margin: 5px 0;
}
/* Loading spinner without background */
.wpa-loading-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: transparent;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
}
/* Extra small screens only */
@media screen and (max-width: 480px) {
#recommended .plugin-card {
padding-top: 80px; /* Add space for icon */
}
#recommended .plugin-card .name,
#recommended .plugin-card .desc {
margin-left: 0;
}
#recommended .plugin-card .plugin-icon {
position: absolute;
top: 16px;
left: 16px;
float: none;
}
#recommended .plugin-card .action-links {
flex-direction: column;
align-items: stretch;
}
#recommended .plugin-card .plugin-action-buttons {
width: 100%;
}
#recommended .plugin-card .plugin-action-buttons .button {
width: 100%;
}
}
/* Center the plugin container */
#recommended #the-list {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
/* Explicitly target readme content */
#readme .wp-allstars-markdown-content {
padding: 0 20px 20px 20px !important; /* No top padding, consistent with other containers */
}
/* Prevent text from overlapping dropdown chevron icon */
.wp-allstars-toggle-header {
position: relative;
padding: 15px;
padding-right: 40px; /* Make room for chevron */
}
.wp-allstars-toggle-header::after {
right: 15px;
z-index: 1; /* Ensure chevron stays above text */
}
/* Fix gaps in advanced settings accordion */
.wp-allstars-toggle-settings {
padding: 15px 0;
margin: 0;
background-color: #f8f8f8;
border-top: 1px solid #ddd;
width: calc(100% - 2px); /* Account for parent border */
margin-left: 1px; /* Center within parent borders */
box-sizing: border-box;
}
.wp-allstars-setting-row {
margin-bottom: 15px;
padding: 0 15px;
}
.wp-allstars-setting-row:last-child {
margin-bottom: 0;
}
/* Remove side gaps in text inputs and textareas */
.wp-allstars-toggle-settings input[type="text"],
.wp-allstars-toggle-settings textarea {
width: 100%;
max-width: 100%;
box-sizing: border-box;
}
/* Ensure text doesn't overflow */
.wp-setting-label,
.wp-allstars-toggle-header label,
.wp-setting-description {
white-space: normal;
word-wrap: break-word;
padding-right: 25px;
max-width: calc(100% - 40px); /* Ensure space for the chevron */
}
/* First breakpoint - 75% width */
@media screen and (max-width: 1400px) {
#readme .wp-allstars-markdown-content {
padding: 15px;
}
}
/* Second breakpoint - 100% width */
@media screen and (max-width: 1100px) {
#readme .wp-allstars-markdown-content {
padding: 10px;
}
}
/* Readme list styling */
#readme .wp-allstars-markdown-content ul.wp-allstars-list,
#readme .wp-allstars-markdown-content ul {
padding-left: 25px;
margin: 10px 0;
list-style-type: disc;
}
#readme .wp-allstars-markdown-content ol.wp-allstars-list,
#readme .wp-allstars-markdown-content ol {
padding-left: 25px; /* Same as bullets */
margin: 10px 0;
list-style-type: decimal;
}
/* Special styling for numbered lists to align with bullet lists */
#readme .wp-allstars-markdown-content ol.numbered-list {
padding-left: 21px; /* Moved 2px to the right as requested */
}
#readme .wp-allstars-markdown-content ol.numbered-list li {
margin-left: 4px; /* Fine-tune the alignment */
}
#readme .wp-allstars-markdown-content li {
margin-bottom: 5px;
line-height: 1.4;
display: list-item !important;
padding-left: 5px; /* Add consistent padding for all list items */
}
/* Ensure consistent spacing for all lists across sections */
#readme .wp-allstars-markdown-content h2 + ul,
#readme .wp-allstars-markdown-content h3 + ul,
#readme .wp-allstars-markdown-content p + ul,
#readme .wp-allstars-markdown-content h2 + ol,
#readme .wp-allstars-markdown-content h3 + ol,
#readme .wp-allstars-markdown-content p + ol,
#readme .wp-allstars-markdown-content h2 + .wp-allstars-list,
#readme .wp-allstars-markdown-content h3 + .wp-allstars-list,
#readme .wp-allstars-markdown-content p + .wp-allstars-list {
margin-top: 10px;
margin-bottom: 15px;
}
/* Additional fix for specific sections that need help */
#readme .wp-allstars-markdown-content h2 + ul,
#readme .wp-allstars-markdown-content h3 + ul {
padding-left: 25px !important;
margin-left: 0 !important;
list-style-type: disc !important;
}
/* Global setting for all content panels width - apply to ALL tabs */
.wp-allstars-settings-content,
.wp-allstars-tab-content > div,
.wp-allstars-settings-section,
.wpa-pro-plugins,
.wpa-pro-plugin,
#wpa-plugin-list,
#wpa-theme-list,
.wp-allstars-markdown-content,
.wpa-plugin-container,
#readme .wpa-pro-plugin,
.wp-allstars-toggle {
max-width: 700px !important;
margin-left: auto !important;
margin-right: auto !important;
width: 100% !important;
box-sizing: border-box !important;
}
/* Fix specific tab content - ensure all sections use the same width */
#general .wp-setting-row,
#general .wp-allstars-toggle,
#advanced .wp-setting-row,
#advanced .wp-allstars-toggle,
#workflow .wp-setting-row,
#workflow .wp-allstars-toggle,
#readme .wp-allstars-markdown-content {
max-width: 700px !important;
width: 100% !important;
box-sizing: border-box !important;
margin-left: auto !important;
margin-right: auto !important;
}
/* Specific fix for workflow tab container */
#workflow.wp-allstars-settings-content,
#workflow .wp-allstars-toggle {
max-width: 700px !important;
width: 100% !important;
margin-left: auto !important;
margin-right: auto !important;
box-sizing: border-box !important;
}
/* Fix to ensure consistent tab structure - "Enable Auto Upload Images" panel */
#workflow.tab-content {
padding: 0 20px 20px 20px !important; /* Changed from 20px to 0 20px 20px 20px to remove top padding */
}
/* Fix spacing in workflow tab to match other tabs */
#workflow .wp-allstars-toggle {
margin-bottom: 15px !important;
}
/* Consistent padding for toggle headers across all tabs */
#workflow .wp-allstars-toggle-header,
#general .wp-setting-header,
#advanced .wp-allstars-toggle-header {
padding: 15px !important;
}
/* Ensure consistent hover styles across all tab tile layouts */
.wpa-pro-plugin:hover,
#pro .wpa-pro-plugin:hover,
#hosting .wpa-pro-plugin:hover,
#tools .wpa-pro-plugin:hover,
#recommended .plugin-card:hover {
border-color: #2271b1 !important;
box-shadow: 0 2px 6px rgba(0,0,0,0.15) !important;
transition: all 0.2s ease !important;
}
/* Direct override for free plugins tab width - setting the tab content container to 900px */
#recommended.wp-allstars-settings-content,
#recommended.tab-content {
max-width: 900px !important;
width: 100% !important;
}
/* Target the specific filter container directly with !important */
#wpa-plugin-filters {
max-width: 900px !important;
width: 900px !important;
margin-left: auto !important;
margin-right: auto !important;
box-sizing: border-box !important;
padding: 15px !important;
border-radius: 8px !important;
background: #fff !important;
}
/* Filter links should be centered within container */
#wpa-plugin-filters .filter-links {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
margin: 0;
padding-bottom: 0;
}
/* Style the filter links similar to main tabs with proper border */
#wpa-plugin-filters .filter-links a {
margin: 0;
padding: 10px 15px;
font-size: 14px;
line-height: 1.6;
font-weight: 400;
background: transparent;
color: #50575e;
text-decoration: none;
white-space: nowrap;
border: none;
border-bottom: 2px solid transparent;
display: inline-block;
transition: all 0.2s ease;
}
#wpa-plugin-filters .filter-links a:hover,
#wpa-plugin-filters .filter-links a:focus {
color: #2271b1;
background: transparent;
border-bottom: 2px solid #2271b1;
}
#wpa-plugin-filters .filter-links a.current {
border-bottom: 2px solid #2271b1;
background: transparent;
color: #2271b1;
font-weight: 600;
}
/* Target the plugin container directly with !important for 900px width */
#recommended .wpa-plugin-container,
#wpa-plugin-list.wpa-plugin-container {
max-width: 900px !important;
width: 900px !important;
margin-left: auto !important;
margin-right: auto !important;
padding: 15px 20px 20px 20px !important;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box !important;
}
/* Set the individual plugin cards to max 660px width */
#recommended .plugin-card {
width: 100% !important;
max-width: 660px !important;
margin: 0 auto 24px auto !important;
padding: 24px !important;
border: 1px solid #ddd !important;
border-radius: 8px !important;
box-shadow: 0 1px 3px rgba(0,0,0,0.1) !important;
background: #fff !important;
transition: all 0.2s ease !important;
display: flex !important;
flex-direction: column !important;
position: relative !important;
box-sizing: border-box !important;
}

View File

@ -1,7 +1,7 @@
/* Plugin Browser Styles */
.wp-allstars-wrap .wp-allstars-plugin-browser {
margin: 0 -8px !important;
padding: 0 8px !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
max-width: 100% !important;
}
@ -9,37 +9,57 @@
/* Plugin List Container */
.wp-allstars-wrap #wpa-plugin-list {
display: flex;
flex-wrap: wrap;
flex-direction: column;
align-items: center;
margin: 0;
width: 100%;
padding: 20px;
max-width: 700px;
margin: 0 auto;
}
/* Filter Bar */
/* Filter Bar - Full Width */
.wp-allstars-wrap #wpa-plugin-filters.wp-filter {
margin-left: 0;
margin-right: 0;
width: 100%;
margin: 0 0 11px 0 !important;
width: 100% !important;
max-width: 100% !important;
box-sizing: border-box;
text-align: center;
}
/* Standard WordPress Plugin Grid Layout - exactly matching core */
.wp-allstars-wrap .wp-list-table.plugin-install {
margin-top: 20px;
clear: both;
padding: 0;
}
.wp-allstars-wrap #the-list {
margin: 0;
/* Center filter links */
.wp-filter .filter-links {
display: flex;
flex-wrap: wrap;
padding: 0;
justify-content: center;
float: none !important;
margin: 0 auto;
width: 100%;
}
/* Plugin Cards - essential layout only */
.wp-filter .filter-links li {
float: none;
display: inline-block;
}
/* Responsive filters */
@media screen and (max-width: 782px) {
.wp-filter .filter-links li > a {
padding: 12px 8px;
font-size: 13px;
}
}
@media screen and (max-width: 600px) {
.wp-filter .filter-links li > a {
padding: 10px 6px;
font-size: 12px;
}
}
/* Plugin Cards - Use consistent layout similar to 768px width for all screens */
.plugin-card {
margin: 0 8px 16px;
width: calc(50% - 16px);
margin: 0 0 24px 0 !important;
width: 100% !important;
background-color: #fff;
border: 1px solid #dcdcde;
border-radius: 8px;
@ -47,6 +67,13 @@
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 {
@ -54,23 +81,123 @@
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
/* Ensure the right edge aligns with the navigation above */
.plugin-card:nth-child(even) {
margin-right: 0;
/* Card Content */
.plugin-card-top {
padding: 24px !important;
position: relative;
flex-grow: 1;
}
.plugin-card:nth-child(odd) {
margin-left: 0;
.plugin-icon {
position: relative !important;
float: left !important;
width: 64px !important;
height: 64px !important;
margin: 0 20px 15px 0 !important;
}
/* Consistent styling for all widths */
/* Force equal spacing between all cards */
.plugin-card:nth-child(odd) {
margin-right: 8px;
/* Name and description positioning - 768px style */
.name.column-name {
margin: 0 0 12px 84px !important;
margin-right: 0 !important; /* Full width content */
}
.plugin-card:nth-child(even) {
margin-left: 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;
}
}
/* Global plugin icon positioning that applies to all viewport sizes */
@ -144,7 +271,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: 20px !important; /* Force top padding to stay at 20px */
padding-top: 22px !important; /* Force top padding to stay at 22px */
overflow: hidden !important;
}
@ -152,7 +279,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: 20px !important;
padding-top: 22px !important;
min-height: 100px !important;
}
}
@ -236,13 +363,6 @@ 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 */
@ -329,6 +449,40 @@ 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 */
@ -370,7 +524,6 @@ body.wp-admin .plugin-card-bottom .compatibility-untested *,
display: block;
}
.plugin-card:hover {
border-color: #999;
}
@ -523,7 +676,7 @@ body.wp-admin .plugin-card-bottom .compatibility-untested *,
.wp-filter {
display: flex;
flex-wrap: wrap;
margin: 12px 0 25px;
margin: 12px 0 0;
padding: 0 10px;
background: #fff;
border: 1px solid #dcdcde;
@ -617,6 +770,12 @@ 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;
@ -750,4 +909,11 @@ 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 */

161
admin/data/free-plugins.php Normal file
View File

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

@ -0,0 +1,167 @@
<?php
/**
* Hosting providers data for WP ALLSTARS plugin
*/
// Define hosting providers
function wp_allstars_get_hosting_providers() {
return array(
'closte' => array(
'name' => 'Closte',
'description' => 'Managed WordPress hosting with advanced performance optimization and auto-scaling.',
'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.',
'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.',
'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'
)
)
),
'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/'
)
)
)
);
}

View File

@ -3,7 +3,7 @@
* Pro Plugins Configuration
*/
function wp_allstars_get_pro_plugins_config() {
function wp_allstars_get_pro_plugins() {
return array(
'magic-login-pro' => array(
'name' => 'Magic Login Pro',

46
admin/data/readme.php Normal file
View File

@ -0,0 +1,46 @@
<?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
];
}

View File

@ -0,0 +1,161 @@
<?php
/**
* Recommended plugins data for WP ALLSTARS plugin
*/
// Define recommended plugins
function wp_allstars_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'
)
);
}

543
admin/data/tools.php Normal file
View File

@ -0,0 +1,543 @@
<?php
/**
* Tools data for WP ALLSTARS plugin
*/
// Define tools
function wp_allstars_get_tools() {
return array(
'advise' => array(
'name' => 'Advise.so',
'description' => 'Website analytics and optimization tool for improving user experience and conversion rates.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://advise.so/',
'primary' => true
)
)
),
'seoutils' => array(
'name' => 'SEO Utils',
'description' => 'Collection of SEO tools to analyze and improve website search engine optimization.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://seoutils.app/',
'primary' => true
)
)
),
'dataforseo' => array(
'name' => 'DataForSEO',
'description' => 'API-based SEO data provider for rank tracking, keyword research and competitive analysis.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://dataforseo.com/',
'primary' => true
)
)
),
'ahrefs' => array(
'name' => 'Ahrefs',
'description' => 'Comprehensive SEO toolset for backlink analysis, keyword research, and competitor research.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://ahrefs.com/',
'primary' => true
)
)
),
'localrank' => array(
'name' => 'LocalRank.so',
'description' => 'Local SEO tool for tracking and improving local search rankings for businesses.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://localrank.so/',
'primary' => true
)
)
),
'turnithuman' => array(
'name' => 'Turn It Human',
'description' => 'AI content humanizer that makes AI-generated content sound more natural and authentic.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://turnithuman.com/',
'primary' => true
)
)
),
'searchconsole' => array(
'name' => 'Google Search Console',
'description' => 'Free tool from Google to monitor and troubleshoot your site\'s presence in Google Search results.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://search.google.com/search-console/about',
'primary' => true
)
)
),
'bingwebmaster' => array(
'name' => 'Bing Webmaster Tools',
'description' => 'Free tool from Microsoft to help optimize your website for Bing search engine.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.bing.com/webmasters/about',
'primary' => true
)
)
),
'fiverr' => array(
'name' => 'Fiverr',
'description' => 'Freelance services marketplace for businesses to find digital services including web development.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.fiverr.com/',
'primary' => true
)
)
),
'legiit' => array(
'name' => 'Legiit',
'description' => 'Marketplace for digital marketing services including SEO, content writing, and web design.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://legiit.com/',
'primary' => true
)
)
),
'openwebui' => array(
'name' => 'Open WebUI',
'description' => 'Open-source web interface for interacting with AI models and chatbots.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://openwebui.com/',
'primary' => true
)
)
),
'nextcloud' => array(
'name' => 'Nextcloud',
'description' => 'Self-hosted productivity platform and file sync solution for secure collaboration.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://nextcloud.com/',
'primary' => true
)
)
),
'enpass' => array(
'name' => 'Enpass',
'description' => 'Password manager that stores sensitive information locally on your device.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.enpass.io/',
'primary' => true
)
)
),
'pdfstudio' => array(
'name' => 'PDF Studio',
'description' => 'Professional PDF editor with advanced features for creating and modifying PDF documents.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.qoppa.com/pdfstudio/',
'primary' => true
)
)
),
'affinity' => array(
'name' => 'Affinity',
'description' => 'Professional creative software suite including Photo, Designer, and Publisher applications.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://affinity.serif.com/',
'primary' => true
)
)
),
'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.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://urlmonitor.com/',
'primary' => true
)
)
),
'speedyindex' => array(
'name' => 'Speedy Index',
'description' => 'Tool for monitoring website indexing speed and performance in search engines.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://en.speedyindex.com/',
'primary' => true
)
)
),
'pagespeed' => array(
'name' => 'PageSpeed Insights',
'description' => 'Google tool that analyzes web page performance on mobile and desktop devices.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://pagespeed.web.dev/',
'primary' => true
)
)
),
'windsurf' => array(
'name' => 'Codeium Windsurf',
'description' => 'AI-powered IDE with advanced code completion and generation capabilities.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://codeium.com/windsurf',
'primary' => true
)
)
),
'lowfruits' => array(
'name' => 'Low Fruits',
'description' => 'SEO tool for finding low-competition keywords to target for faster ranking.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://lowfruits.io/',
'primary' => true
)
)
),
'keysearch' => array(
'name' => 'Keysearch',
'description' => 'Affordable keyword research tool for finding valuable keywords for SEO.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.keysearch.co/',
'primary' => true
)
)
),
'smartlead' => array(
'name' => 'SmartLead',
'description' => 'Email outreach platform for cold email campaigns and lead generation.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.smartlead.ai/',
'primary' => true
)
)
),
'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.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.zerogpt.plus/en',
'primary' => true
)
)
),
'neuronwriter' => array(
'name' => 'NeuronWriter',
'description' => 'AI-powered SEO content optimization tool for creating high-ranking content.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.neuronwriter.com/',
'primary' => true
)
)
),
'serposcope' => array(
'name' => 'Serposcope',
'description' => 'Open-source rank tracker to monitor website positions in search engines.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.serposcope.com/en/',
'primary' => true
)
)
),
'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.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.seoptimer.com/',
'primary' => true
)
)
),
'jitsi' => array(
'name' => 'Jitsi Meet',
'description' => 'Free, open-source video conferencing platform with no account required.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://meet.jit.si/',
'primary' => true
)
)
),
'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.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://www.libreoffice.org/',
'primary' => true
)
)
),
'localwp' => array(
'name' => 'Local',
'description' => 'Local WordPress development tool for creating WordPress sites locally.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://localwp.com/',
'primary' => true
)
)
),
'notability' => array(
'name' => 'Notability',
'description' => 'Note-taking app for iPad and Mac with handwriting and PDF annotation features.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://notability.com/',
'primary' => true
)
)
),
'ulysses' => array(
'name' => 'Ulysses',
'description' => 'Writing app for Mac, iPad, and iPhone with a clean interface and powerful features.',
'button_group' => array(
array(
'text' => 'Home Page',
'url' => 'https://ulysses.app/',
'primary' => true
)
)
),
);
}

View File

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

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

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

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

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

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

@ -0,0 +1,168 @@
<?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">
<!-- Modern Admin Colors Setting -->
<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('Modern Admin Colors', 'wp-allstars'); ?>
</label>
</div>
</div>
<p class="wp-setting-description">
<?php esc_html_e('Switch to the Modern Admin colours, to remind that you\'re using an SEO Pro Stack :)', 'wp-allstars'); ?>
</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

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

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

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

@ -83,7 +83,7 @@ jQuery(document).ready(function($) {
// Handle text input changes
$('.wp-allstars-setting-row input[type="text"], .wp-allstars-setting-row input[type="number"], .wp-allstars-setting-row textarea').on('change', function() {
$('.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();
@ -295,6 +295,9 @@ jQuery(document).ready(function($) {
});
}
// Expose initPluginActions to global scope for use in other scripts
window.initPluginActions = initPluginActions;
// Initialize theme handlers
function initThemeHandlers() {
console.log('Initializing theme handlers');
@ -302,26 +305,83 @@ jQuery(document).ready(function($) {
$('.theme-actions .install-now').off('click');
$('.theme-actions .activate-now').off('click');
// Install theme - use standard WordPress behavior
// Install theme - use wp.updates.installTheme AJAX method
$('.theme-actions .install-now').on('click', function(e) {
// We're not preventing default here - let the standard WordPress installer handle it
// Just add the updating message
e.preventDefault();
var $button = $(this);
var slug = $button.data('slug');
$button.addClass('updating-message').text('Installing...');
console.log('Installing theme using standard WordPress URL:', $button.attr('href'));
// The rest will be handled by WordPress core
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 standard WordPress behavior
// Activate theme - use AJAX
$('.theme-actions .activate-now').on('click', function(e) {
// We're not preventing default here - let the standard WordPress activation handle it
// Just add the updating message
e.preventDefault();
var $button = $(this);
var slug = $button.data('slug');
$button.addClass('updating-message').text('Activating...');
console.log('Activating theme using standard WordPress URL:', $button.attr('href'));
// The rest will be handled by WordPress core
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

@ -73,22 +73,22 @@ if (!defined('ABSPATH')) {
});
</script>
<?php endif; ?>
<a class="button button-secondary preview install-theme-preview" href="<?php echo esc_url($theme_data->preview_url); ?>" target="_blank">
<a class="button button-secondary green-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" href="https://www.kadencewp.com/kadence-theme/starter-templates/" target="_blank">
<a class="button button-secondary green-button-secondary" href="https://www.kadencewp.com/kadence-theme/starter-templates/" target="_blank">
<?php esc_html_e('Templates'); ?>
</a>
<a class="button button-secondary" href="https://www.kadencewp.com/wordpress-solutions/kadence-ai/" target="_blank">
<a class="button button-secondary green-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" href="https://www.kadencewp.com/kadence-theme/marketplace/" target="_blank">
<a class="button button-secondary green-button-secondary" href="https://www.kadencewp.com/kadence-theme/marketplace/" target="_blank">
<?php esc_html_e('Marketplace'); ?>
</a>
<a class="button button-secondary" href="https://www.kadencewp.com/pricing/" target="_blank">
<a class="button button-secondary green-button-secondary" href="https://www.kadencewp.com/pricing/" target="_blank">
<?php esc_html_e('Pricing'); ?>
</a>
<a class="button button-primary" href="https://www.kadencewp.com/kadence-theme/" target="_blank">
<a class="button button-primary go-pro-button" href="https://www.kadencewp.com/kadence-theme/" target="_blank">
<?php esc_html_e('Go Pro'); ?>
</a>
</div>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,315 @@
<?php
/**
* WP ALLSTARS Admin Colors Feature
*
* Handles setting the admin color scheme based on user preferences
*
* @package WP_ALLSTARS
* @since 0.2.3
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
/**
* Admin Colors Handler Class
*/
class WP_Allstars_Admin_Colors {
/**
* Option name for the admin color scheme setting
*
* @var string
*/
private $option_name = 'wp_allstars_simple_setting';
/**
* Modern color scheme key
*
* @var string
*/
private $modern_scheme = 'modern';
/**
* Default color scheme key
*
* @var string
*/
private $default_scheme = 'fresh';
/**
* Initialize the class and set up hooks
*/
public function __construct() {
// Set up hooks
add_action('admin_init', array($this, 'set_admin_color_scheme'));
add_action('wp_ajax_wp_allstars_update_option', array($this, 'handle_color_scheme_update'), 5);
add_action('wp_ajax_wp_allstars_get_admin_colors', array($this, 'get_admin_colors_ajax'));
// Add script to handle dynamic color changes
add_action('admin_enqueue_scripts', array($this, 'enqueue_color_scripts'));
}
/**
* Enqueue JavaScript to handle dynamic color scheme changes
*/
public function enqueue_color_scripts($hook) {
// Only load on the plugin settings page
if (strpos($hook, 'wp-allstars') === false) {
return;
}
// Get the available color schemes
global $_wp_admin_css_colors;
// Get URLs for the fresh and modern schemes
$fresh_url = '';
$modern_url = '';
if (isset($_wp_admin_css_colors['fresh'])) {
$fresh_url = $_wp_admin_css_colors['fresh']->url;
}
if (isset($_wp_admin_css_colors['modern'])) {
$modern_url = $_wp_admin_css_colors['modern']->url;
}
// Add inline JS for handling dynamic color scheme changes
$color_js = '
jQuery(document).ready(function($) {
// Store color scheme URLs for direct access
var colorSchemes = {
"fresh": "' . esc_js($fresh_url) . '",
"modern": "' . esc_js($modern_url) . '"
};
// Special handler for admin color scheme toggle
$("#wp_allstars_simple_setting").on("change", function() {
var isEnabled = $(this).is(":checked");
// Apply the color scheme dynamically
if (isEnabled) {
switchColorScheme("modern");
} else {
switchColorScheme("fresh");
}
});
// Function to switch admin color scheme without page reload
function switchColorScheme(newScheme) {
console.log("Switching to color scheme:", newScheme);
// Exit if we dont have URL for this scheme
if (!colorSchemes[newScheme]) {
console.error("No URL found for color scheme:", newScheme);
return;
}
try {
// 1. Update the body class first
var $body = $("body");
$body.removeClass(function(index, className) {
return (className.match(/(^|\s)admin-color-\S+/g) || []).join(" ");
});
$body.addClass("admin-color-" + newScheme);
// 2. Directly replace color stylesheet URLs
var baseUrl = colorSchemes[newScheme];
if (!baseUrl) return;
// Force cache-busting
var cacheBuster = "?_=" + new Date().getTime();
// Replace all stylesheets with colors in their URL
var $adminColorLinks = $("link[href*=\'colors-\'], link[href*=\'/colors.\'], link#colors, link#colors-css, link#admin-colors-css");
// Log what we found
console.log("Found admin color links:", $adminColorLinks.length);
$adminColorLinks.each(function() {
console.log(" - Link:", $(this).attr("href"));
});
// For each stylesheet, create and inject a new one with the correct scheme
$adminColorLinks.each(function() {
var $oldLink = $(this);
var oldHref = $oldLink.attr("href");
var id = $oldLink.attr("id") || "";
// Skip if not a stylesheet
if (!oldHref || $oldLink.attr("rel") !== "stylesheet") return;
// Determine what file is being loaded
var fileType = "";
if (oldHref.indexOf("colors-rtl") !== -1) {
fileType = "colors-rtl.min.css";
} else if (oldHref.indexOf("colors.min") !== -1) {
fileType = "colors.min.css";
} else {
fileType = "colors.css";
}
// Create the new URL
var newUrl = baseUrl + fileType + cacheBuster;
console.log("Replacing", oldHref, "with", newUrl);
// Create a new stylesheet element
var $newLink = $("<link />", {
rel: "stylesheet",
type: "text/css",
id: id,
href: newUrl
});
// Insert new stylesheet and remove old one
$oldLink.after($newLink);
setTimeout(function() {
$oldLink.remove();
}, 100);
});
// If we found no stylesheets, inject the main one
if ($adminColorLinks.length === 0) {
console.log("No admin color stylesheets found, injecting new one");
$("head").append(
$("<link />", {
rel: "stylesheet",
type: "text/css",
id: "colors-css",
href: baseUrl + "colors.min.css" + cacheBuster
})
);
}
// 3. Save the setting via AJAX
saveColorScheme(newScheme);
} catch (e) {
console.error("Error switching color scheme:", e);
}
}
function saveColorScheme(scheme) {
// AJAX request to save the color scheme setting
$.ajax({
url: ajaxurl,
type: "POST",
data: {
action: "wp_allstars_update_admin_colors",
scheme: scheme,
_wpnonce: wpAllstars.nonce
},
success: function(response) {
if (response.success) {
console.log("Color scheme updated successfully");
} else {
console.error("Error updating color scheme:", response);
}
},
error: function(xhr, status, error) {
console.error("AJAX error:", error);
}
});
}
});
';
wp_add_inline_script('wp-allstars-admin', $color_js);
}
/**
* Set the admin color scheme based on the setting value
*/
public function set_admin_color_scheme() {
// Get current user
$user_id = get_current_user_id();
if (!$user_id) {
return;
}
// Check if our setting is enabled
$modern_colors_enabled = get_option($this->option_name, false);
// Get the scheme to set
$scheme = $modern_colors_enabled ? $this->modern_scheme : $this->default_scheme;
// Update user meta to set the color scheme
update_user_meta($user_id, 'admin_color', $scheme);
}
/**
* Handle color scheme update via AJAX
* Runs early to apply the color scheme change before the general option update handler
*/
public function handle_color_scheme_update() {
// Check for required params
if (!isset($_POST['option']) || !isset($_POST['value'])) {
return;
}
// Only process our specific option
if ($_POST['option'] !== $this->option_name) {
return;
}
// Get the current user ID
$user_id = get_current_user_id();
if (!$user_id) {
return;
}
// Determine which scheme to set based on the value
$value = (bool) $_POST['value'];
$scheme = $value ? $this->modern_scheme : $this->default_scheme;
// Update the user's color scheme
update_user_meta($user_id, 'admin_color', $scheme);
}
/**
* AJAX handler to update and get admin color schemes - similar to WordPress core
*/
public function get_admin_colors_ajax() {
// Register handler for our new AJAX action
add_action('wp_ajax_wp_allstars_update_admin_colors', array($this, 'update_admin_colors_ajax'));
}
/**
* AJAX handler to update admin color scheme and return class names
*/
public function update_admin_colors_ajax() {
check_ajax_referer('wp-allstars-nonce', '_wpnonce');
$user_id = get_current_user_id();
if (!$user_id) {
wp_send_json_error('Not logged in');
}
// Get the old scheme
$old_scheme = get_user_meta($user_id, 'admin_color', true);
if (!$old_scheme) {
$old_scheme = 'fresh'; // Default WordPress admin color scheme
}
// Get the new scheme
$scheme = isset($_POST['scheme']) ? sanitize_text_field($_POST['scheme']) : 'fresh';
// Validate scheme
global $_wp_admin_css_colors;
if (!isset($_wp_admin_css_colors[$scheme])) {
wp_send_json_error('Invalid color scheme');
}
// Update user meta
update_user_meta($user_id, 'admin_color', $scheme);
// Also update our plugin option
update_option($this->option_name, $scheme === $this->modern_scheme ? 1 : 0);
// Return success with old and new scheme names for CSS class updates
wp_send_json_success(array(
'previousScheme' => 'admin-color-' . $old_scheme,
'currentScheme' => 'admin-color-' . $scheme
));
}
}

View File

@ -2,15 +2,20 @@
/**
* Auto Upload Images functionality
*
* @package WP_Allstars
* @package WP_ALLSTARS
* @since 0.2.0
*/
if (!defined('ABSPATH')) {
exit;
}
class WP_Allstars_Auto_Upload {
/**
* Initialize the class
*/
public function __construct() {
add_filter('content_save_pre', array($this, 'process_content'), 10, 1);
add_filter('content_save_pre', array($this, 'process_content'));
add_action('wp_allstars_image_upload_error', array($this, 'log_error'), 10, 2);
}
@ -57,7 +62,8 @@ class WP_Allstars_Auto_Upload {
return str_replace($url, $local_url, $matches[0]);
}
} catch (Exception $e) {
do_action('wp_allstars_image_upload_error', $url, $e->getMessage());
// Trigger error action for logging
do_action('wp_allstars_image_upload_error', esc_url($url), $e->getMessage());
}
return $matches[0];
@ -80,11 +86,12 @@ 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) {
// Get file info
$file_array = array();
$file_array['name'] = basename($url);
$file_array = array(
'name' => sanitize_file_name(basename($url))
);
// Download file to temp location
$file_array['tmp_name'] = download_url($url);
@ -93,17 +100,18 @@ class WP_Allstars_Auto_Upload {
throw new Exception('Failed to download image: ' . $file_array['tmp_name']->get_error_message());
}
// Check file type
// Check file type for security
$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
// Upload the file to media library
$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());
}
@ -117,10 +125,12 @@ class WP_Allstars_Auto_Upload {
* @param string $error Error message
*/
public function log_error($url, $error) {
error_log(sprintf(
'[WP ALLSTARS] Auto Upload Images Error - URL: %s, Error: %s',
$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)
));
}
}
}
}

View File

@ -1,9 +1,17 @@
<?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
*
* Plugin Name: WP ALLSTARS Plugin
* Plugin URI: https://www.wpallstars.com
* Description: WP ALLSTARS Plugin for WordPress. Speed Matters.
* Version: 0.1.0 (Beta)
* Version: v0.2.3 (Beta)
* Author: WP ALLSTARS
* Author URI: https://www.wpallstars.com
* License: GPL-2.0+
@ -14,84 +22,80 @@
* Requires PHP: 7.2
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
if (!defined('WPINC')) {
exit;
}
// Define plugin version - extract from plugin header
// Define plugin version from the file 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('WP_ALLSTARS_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('WP_ALLSTARS_VERSION', isset($matches[1]) ? $matches[1] : '0.1.0 (Beta)');
}
$plugin_data = get_plugin_data(__FILE__, false, false);
define('WP_ALLSTARS_VERSION', $plugin_data['Version']);
// Activation hook
/**
* Plugin activation hook
*/
function wp_allstars_activate() {
// Add activation logic later if needed
// Setup initial configuration when needed
}
register_activation_hook( __FILE__, 'wp_allstars_activate' );
register_activation_hook(__FILE__, 'wp_allstars_activate');
// Load core functionality
/**
* Load core plugin components
*/
require_once plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-auto-upload.php';
require_once plugin_dir_path(__FILE__) . 'includes/class-wp-allstars-admin-colors.php';
// Load admin UI and configurations
if ( is_admin() ) {
require_once plugin_dir_path( __FILE__ ) . 'admin/pro-plugins-config.php';
require_once plugin_dir_path( __FILE__ ) . 'admin/settings.php';
}
// This function is not needed as we're localizing in wp_allstars_admin_assets
// function wp_allstars_localize_script() {
// wp_localize_script( 'wp-allstars-admin', 'wpAllstars', [
// 'ajaxurl' => admin_url( 'admin-ajax.php' ),
// 'nonce' => wp_create_nonce( 'wp-allstars-nonce' )
// ] );
// }
// add_action( 'admin_enqueue_scripts', 'wp_allstars_localize_script' );
// Admin assets
function wp_allstars_admin_assets() {
// Enqueue styles
wp_enqueue_style(
'wp-allstars-admin',
plugins_url( 'admin/css/wp-allstars-admin.css', __FILE__ ),
array(),
WP_ALLSTARS_VERSION
);
// Enqueue script
// Enqueue WordPress updates script for theme installation
wp_enqueue_script('updates');
// Load admin-specific components
if (is_admin()) {
// Include manager classes
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-admin-manager.php';
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-settings-manager.php';
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-theme-manager.php';
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-workflow-manager.php';
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-tools-manager.php';
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-hosting-manager.php';
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-pro-plugins-manager.php';
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-plugin-manager.php';
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-free-plugins-manager.php';
require_once plugin_dir_path(__FILE__) . 'admin/includes/class-readme-manager.php';
wp_enqueue_script(
'wp-allstars-admin',
plugins_url( 'admin/js/wp-allstars-admin.js', __FILE__ ),
array('jquery', 'updates'),
WP_ALLSTARS_VERSION,
true
);
// Localize script for AJAX
$ajax_data = array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'adminUrl' => admin_url(),
'nonce' => wp_create_nonce( 'wp-allstars-nonce' ),
'updateNonce' => wp_create_nonce( 'updates' )
);
wp_localize_script( 'wp-allstars-admin', 'wpAllstars', $ajax_data );
// Initialize the admin manager
add_action('plugins_loaded', array('WP_Allstars_Admin_Manager', 'init'));
// Data files
require_once plugin_dir_path(__FILE__) . 'admin/data/pro-plugins.php';
require_once plugin_dir_path(__FILE__) . 'admin/data/readme.php';
// Legacy files (for backward compatibility)
require_once plugin_dir_path(__FILE__) . 'admin/settings.php';
}
add_action( 'admin_enqueue_scripts', 'wp_allstars_admin_assets' );
// Initialize classes
/**
* 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 features
*/
function wp_allstars_init_features() {
// Initialize the Admin Colors feature
new WP_Allstars_Admin_Colors();
}
add_action('plugins_loaded', 'wp_allstars_init_features');
/**
* Initialize core plugin classes
*/
$wp_allstars_auto_upload = new WP_Allstars_Auto_Upload();