Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
b988fbbec0 | |||
ac3e47a147 | |||
b05d01da92 | |||
15244dc687 | |||
7c0dadac08 | |||
717a2721e8 | |||
0ced75f9b7 | |||
009b67c0cc | |||
eac794c54a | |||
5e8da5d87b | |||
3ebcaccf98 | |||
fda33746e5 |
@ -177,10 +177,14 @@ Before releasing:
|
|||||||
|
|
||||||
### Local Testing Environment
|
### Local Testing Environment
|
||||||
|
|
||||||
- Local WordPress testing environment is at ~/Local/plugin-testing/app/public
|
Local environment variables and paths are documented in `.ai-workflows/local-env-vars.md`. This includes:
|
||||||
- Plugin testing directory is at ~/Local/plugin-testing/app/public/wp-content/plugins
|
|
||||||
- WP-CLI is available at ~/Local/plugin-testing/app/bin/wp
|
- Repository paths
|
||||||
- Debug logs can be found at ~/Local/plugin-testing/app/public/wp-content/uploads/debug-log-manager/ if the Debug Log Manager plugin is installed
|
- Local WordPress testing environment paths
|
||||||
|
- URLs for testing and development tools
|
||||||
|
- Build and deploy script locations
|
||||||
|
|
||||||
|
Refer to this file for the most up-to-date information about the local development environment.
|
||||||
|
|
||||||
### Using WP-CLI with LocalWP
|
### Using WP-CLI with LocalWP
|
||||||
|
|
||||||
|
19
.ai-workflows/local-env-vars.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Local Development Environment Variables
|
||||||
|
|
||||||
|
This file contains important paths and URLs for local development.
|
||||||
|
|
||||||
|
## Repository Paths
|
||||||
|
- Local development repository: ~/Git/wp-fix-plugin-does-not-exist-notices
|
||||||
|
- LocalWP plugin testing site storage: ~/Local/plugin-testing/app/wp-fix-plugin-does-not-exist-notices
|
||||||
|
- LocalWP plugin testing site configuration: ~/Local/plugin-testing/conf/
|
||||||
|
|
||||||
|
## URLs
|
||||||
|
- LocalWP plugin testing URL: http://plugin-testing.local/
|
||||||
|
- PHP details: http://plugin-testing.local/local-phpinfo.php
|
||||||
|
- XDebug info: http://plugin-testing.local/local-xdebuginfo.php
|
||||||
|
- Adminer Evo: http://localhost:10010/?username=root&db=local
|
||||||
|
- Mailpit: http://localhost:10000/
|
||||||
|
|
||||||
|
## Build and Deploy Scripts
|
||||||
|
- Build script: ~/Git/wp-fix-plugin-does-not-exist-notices/build.sh
|
||||||
|
- Local deploy script: ~/Git/wp-fix-plugin-does-not-exist-notices/deploy-local.sh
|
5
.github/workflows/assets.yml
vendored
@ -6,7 +6,6 @@ on:
|
|||||||
- main
|
- main
|
||||||
paths:
|
paths:
|
||||||
- '.wordpress-org/**'
|
- '.wordpress-org/**'
|
||||||
- 'assets/**'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
assets:
|
assets:
|
||||||
@ -15,10 +14,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: WordPress.org plugin asset/readme update
|
- name: WordPress.org plugin asset/readme update
|
||||||
uses: 10up/action-wordpress-plugin-asset-update@stable
|
uses: 10up/action-wordpress-plugin-asset-update@stable
|
||||||
env:
|
env:
|
||||||
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
|
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
|
||||||
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
|
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
|
||||||
SLUG: wp-fix-plugin-does-not-exist-notices
|
SLUG: wp-fix-plugin-does-not-exist-notices
|
20
.github/workflows/release.yml
vendored
@ -28,7 +28,21 @@ jobs:
|
|||||||
cp readme.txt build/wp-fix-plugin-does-not-exist-notices/
|
cp readme.txt build/wp-fix-plugin-does-not-exist-notices/
|
||||||
cp LICENSE build/wp-fix-plugin-does-not-exist-notices/
|
cp LICENSE build/wp-fix-plugin-does-not-exist-notices/
|
||||||
cp README.md build/wp-fix-plugin-does-not-exist-notices/
|
cp README.md build/wp-fix-plugin-does-not-exist-notices/
|
||||||
cp -r assets build/wp-fix-plugin-does-not-exist-notices/
|
cp -r admin build/wp-fix-plugin-does-not-exist-notices/
|
||||||
|
cp -r includes build/wp-fix-plugin-does-not-exist-notices/
|
||||||
|
|
||||||
|
# Copy directories if they exist
|
||||||
|
if [ -d "assets" ]; then
|
||||||
|
cp -r assets build/wp-fix-plugin-does-not-exist-notices/
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "languages" ]; then
|
||||||
|
cp -r languages build/wp-fix-plugin-does-not-exist-notices/
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d ".wordpress-org" ]; then
|
||||||
|
cp -r .wordpress-org build/wp-fix-plugin-does-not-exist-notices/
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Create ZIP file
|
- name: Create ZIP file
|
||||||
run: |
|
run: |
|
||||||
@ -46,7 +60,7 @@ jobs:
|
|||||||
wp-fix-plugin-does-not-exist-notices-${{ steps.get_version.outputs.VERSION }}.zip
|
wp-fix-plugin-does-not-exist-notices-${{ steps.get_version.outputs.VERSION }}.zip
|
||||||
body: |
|
body: |
|
||||||
Fix 'Plugin file does not exist.' Notices v${{ steps.get_version.outputs.VERSION }}
|
Fix 'Plugin file does not exist.' Notices v${{ steps.get_version.outputs.VERSION }}
|
||||||
|
|
||||||
See [CHANGELOG.md](https://github.com/wpallstars/wp-fix-plugin-does-not-exist-notices/blob/main/CHANGELOG.md) for details.
|
See [CHANGELOG.md](https://github.com/wpallstars/wp-fix-plugin-does-not-exist-notices/blob/main/CHANGELOG.md) for details.
|
||||||
|
|
||||||
# Deploy to WordPress.org
|
# Deploy to WordPress.org
|
||||||
@ -57,7 +71,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: WordPress Plugin Deploy
|
- name: WordPress Plugin Deploy
|
||||||
id: deploy
|
id: deploy
|
||||||
uses: 10up/action-wordpress-plugin-deploy@stable
|
uses: 10up/action-wordpress-plugin-deploy@stable
|
||||||
|
@ -5,21 +5,40 @@ This directory contains assets specific to the WordPress.org plugin repository a
|
|||||||
## Directory Structure
|
## Directory Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
/assets/
|
/.wordpress-org/
|
||||||
icon-256x256.png
|
/assets/
|
||||||
icon-128x128.png
|
icon-256x256.png
|
||||||
banner-772x250.png
|
icon-128x128.png
|
||||||
banner-1544x500.png
|
banner-772x250.png
|
||||||
screenshot-1.png
|
banner-1544x500.png
|
||||||
|
screenshot-1.png
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Asset Organization
|
||||||
|
|
||||||
|
- **All Asset Files**: All files for WordPress.org are stored in this directory (`.wordpress-org/assets/`)
|
||||||
|
- PNG files (icon-256x256.png, banner-772x250.png, etc.)
|
||||||
|
- Source files (PXD, SVG)
|
||||||
|
- Documentation
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
When using GitHub Actions for WordPress.org plugin deployments (via the 10up WordPress GitHub Actions), this directory is used to automatically update plugin assets in the WordPress.org repository.
|
When using GitHub Actions for WordPress.org plugin deployments (via the 10up WordPress GitHub Actions), this directory is used to automatically update plugin assets in the WordPress.org repository.
|
||||||
|
|
||||||
## Naming Conventions
|
## Naming Conventions
|
||||||
|
|
||||||
Files must be named exactly as shown above to be properly recognized by the WordPress.org system during the deployment process.
|
Files must be named exactly as shown above to be properly recognized by the WordPress.org system during the deployment process:
|
||||||
|
|
||||||
|
### Banner Images
|
||||||
|
- `banner-772x250.png` - 772x250 pixel PNG banner (required for WordPress.org)
|
||||||
|
- `banner-1544x500.png` - 1544x500 pixel PNG banner for high-DPI displays (optional for WordPress.org)
|
||||||
|
|
||||||
|
### Icon Images
|
||||||
|
- `icon-256x256.png` - 256x256 pixel PNG icon (required for WordPress.org)
|
||||||
|
- `icon-128x128.png` - 128x128 pixel PNG icon (optional for WordPress.org)
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
- `screenshot-1.png` - Main screenshot showing the plugin in action
|
||||||
|
|
||||||
## Right-to-Left (RTL) Support
|
## Right-to-Left (RTL) Support
|
||||||
|
|
||||||
@ -31,9 +50,16 @@ For plugins that support Right-to-Left languages (like Hebrew and Arabic), you c
|
|||||||
|
|
||||||
Note that the `-rtl` suffix is specifically for Right-to-Left language support, not for dark mode versions of assets.
|
Note that the `-rtl` suffix is specifically for Right-to-Left language support, not for dark mode versions of assets.
|
||||||
|
|
||||||
|
## Build Process
|
||||||
|
|
||||||
|
The build script (`build.sh`) is configured to:
|
||||||
|
1. Use all asset files from the `.wordpress-org/assets/` directory
|
||||||
|
2. Copy these files to the appropriate locations in the build directory
|
||||||
|
|
||||||
## Additional Resources
|
## Additional Resources
|
||||||
|
|
||||||
For more detailed information about WordPress.org plugin assets, please see:
|
For more detailed information about WordPress.org plugin assets, please see:
|
||||||
|
|
||||||
- [WordPress Plugin Developer Handbook - Plugin Assets](https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/)
|
- [WordPress Plugin Developer Handbook - Plugin Assets](https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/)
|
||||||
- [WordPress Plugin Directory README.txt Standard](https://developer.wordpress.org/plugins/wordpress-org/how-your-readme-txt-works/)
|
- [WordPress Plugin Directory README.txt Standard](https://developer.wordpress.org/plugins/wordpress-org/how-your-readme-txt-works/)
|
||||||
|
- [WordPress.org Plugin Submission Assets Guide](./.wordpress-org/WORDPRESS_ORG_ASSETS.md)
|
@ -39,7 +39,7 @@ Note: `-rtl` is specifically for Right-to-Left language support, not for dark th
|
|||||||
- Required: 256x256 pixels (`icon-256x256.png`)
|
- Required: 256x256 pixels (`icon-256x256.png`)
|
||||||
- Optional: 128x128 pixels (`icon-128x128.png`)
|
- Optional: 128x128 pixels (`icon-128x128.png`)
|
||||||
- **Location**: Upload to the `/assets/` directory in the WordPress.org SVN repository
|
- **Location**: Upload to the `/assets/` directory in the WordPress.org SVN repository
|
||||||
- **Status**: ✅ READY - Files are in `assets/icon/`
|
- **Status**: ✅ READY - Files are in `.wordpress-org/assets/`
|
||||||
|
|
||||||
### Banner
|
### Banner
|
||||||
|
|
||||||
@ -48,15 +48,14 @@ Note: `-rtl` is specifically for Right-to-Left language support, not for dark th
|
|||||||
- Required: 772x250 pixels (`banner-772x250.png`)
|
- Required: 772x250 pixels (`banner-772x250.png`)
|
||||||
- Optional: 1544x500 pixels (`banner-1544x500.png`) for high-DPI displays
|
- Optional: 1544x500 pixels (`banner-1544x500.png`) for high-DPI displays
|
||||||
- **Location**: Upload to the `/assets/` directory in the WordPress.org SVN repository
|
- **Location**: Upload to the `/assets/` directory in the WordPress.org SVN repository
|
||||||
- **Status**: ✅ READY - Files are in `assets/banner/`
|
- **Status**: ✅ READY - Files are in `.wordpress-org/assets/`
|
||||||
|
|
||||||
### Screenshots
|
### Screenshots
|
||||||
|
|
||||||
- **Format**: PNG
|
- **Format**: PNG
|
||||||
- **Naming**: `screenshot-1.png`
|
- **Naming**: `screenshot-1.png`
|
||||||
- **Location**: Upload to the `/assets/` directory in the WordPress.org SVN repository
|
- **Location**: Upload to the `/assets/` directory in the WordPress.org SVN repository
|
||||||
- **Status**: ✅ READY
|
- **Status**: ✅ READY - Files are in `.wordpress-org/assets/`
|
||||||
- `screenshot-1.png` is available in `assets/screenshots/`
|
|
||||||
|
|
||||||
## Submission Process
|
## Submission Process
|
||||||
|
|
||||||
@ -78,11 +77,11 @@ Note: `-rtl` is specifically for Right-to-Left language support, not for dark th
|
|||||||
cp -r [your-local-plugin-files]/* fix-plugin-does-not-exist-notices/trunk/
|
cp -r [your-local-plugin-files]/* fix-plugin-does-not-exist-notices/trunk/
|
||||||
|
|
||||||
# Copy assets to assets directory
|
# Copy assets to assets directory
|
||||||
cp assets/icon/icon-256x256.png fix-plugin-does-not-exist-notices/assets/
|
cp .wordpress-org/assets/icon-256x256.png fix-plugin-does-not-exist-notices/assets/
|
||||||
cp assets/icon/icon-128x128.png fix-plugin-does-not-exist-notices/assets/
|
cp .wordpress-org/assets/icon-128x128.png fix-plugin-does-not-exist-notices/assets/
|
||||||
cp assets/banner/banner-772x250.png fix-plugin-does-not-exist-notices/assets/
|
cp .wordpress-org/assets/banner-772x250.png fix-plugin-does-not-exist-notices/assets/
|
||||||
cp assets/banner/banner-1544x500.png fix-plugin-does-not-exist-notices/assets/
|
cp .wordpress-org/assets/banner-1544x500.png fix-plugin-does-not-exist-notices/assets/
|
||||||
cp assets/screenshots/screenshot-1.png fix-plugin-does-not-exist-notices/assets/
|
cp .wordpress-org/assets/screenshot-1.png fix-plugin-does-not-exist-notices/assets/
|
||||||
|
|
||||||
# Add new files
|
# Add new files
|
||||||
cd fix-plugin-does-not-exist-notices
|
cd fix-plugin-does-not-exist-notices
|
||||||
@ -114,10 +113,10 @@ For converting SVG to PNG or creating different sizes of images, you can use:
|
|||||||
- **Command Line** (using ImageMagick):
|
- **Command Line** (using ImageMagick):
|
||||||
```bash
|
```bash
|
||||||
# For 256x256 icon
|
# For 256x256 icon
|
||||||
convert -background none -size 256x256 assets/icon/icon.svg assets/icon/icon-256x256.png
|
convert -background none -size 256x256 .wordpress-org/assets/icon.svg .wordpress-org/assets/icon-256x256.png
|
||||||
|
|
||||||
# For 128x128 icon
|
# For 128x128 icon
|
||||||
convert -background none -size 128x128 assets/icon/icon.svg assets/icon/icon-128x128.png
|
convert -background none -size 128x128 .wordpress-org/assets/icon.svg .wordpress-org/assets/icon-128x128.png
|
||||||
```
|
```
|
||||||
|
|
||||||
## Resources
|
## Resources
|
@ -30,15 +30,15 @@ This document outlines the requirements for assets when submitting a plugin to t
|
|||||||
## Current Status
|
## Current Status
|
||||||
|
|
||||||
### Icon
|
### Icon
|
||||||
- ✅ SVG source available in `assets/icon/icon.svg`
|
- ✅ SVG source available in `.wordpress-org/assets/icon.svg`
|
||||||
- ✅ PNG files created in `assets/icon/icon-256x256.png` and `assets/icon/icon-128x128.png`
|
- ✅ PNG files created in `.wordpress-org/assets/icon-256x256.png` and `.wordpress-org/assets/icon-128x128.png`
|
||||||
|
|
||||||
### Banner
|
### Banner
|
||||||
- ✅ Both sizes available in `assets/banner/`
|
- ✅ Both sizes available in `.wordpress-org/assets/`
|
||||||
- ✅ Properly named files: `banner-772x250.png` and `banner-1544x500.png`
|
- ✅ Properly named files: `banner-772x250.png` and `banner-1544x500.png`
|
||||||
|
|
||||||
### Screenshots
|
### Screenshots
|
||||||
- ✅ One screenshot available in `assets/screenshots/screenshot-1.png`
|
- ✅ One screenshot available in `.wordpress-org/assets/screenshot-1.png`
|
||||||
- ✅ Screenshot description in readme.txt updated to reference only one screenshot
|
- ✅ Screenshot description in readme.txt updated to reference only one screenshot
|
||||||
|
|
||||||
## SVN Directory Structure
|
## SVN Directory Structure
|
||||||
@ -68,11 +68,11 @@ When submitting to WordPress.org, your SVN repository will have this structure:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Copy assets to WordPress.org SVN assets directory
|
# Copy assets to WordPress.org SVN assets directory
|
||||||
cp assets/icon/icon-256x256.png /path/to/wordpress-svn/assets/
|
cp .wordpress-org/assets/icon-256x256.png /path/to/wordpress-svn/assets/
|
||||||
cp assets/icon/icon-128x128.png /path/to/wordpress-svn/assets/
|
cp .wordpress-org/assets/icon-128x128.png /path/to/wordpress-svn/assets/
|
||||||
cp assets/banner/banner-772x250.png /path/to/wordpress-svn/assets/
|
cp .wordpress-org/assets/banner-772x250.png /path/to/wordpress-svn/assets/
|
||||||
cp assets/banner/banner-1544x500.png /path/to/wordpress-svn/assets/
|
cp .wordpress-org/assets/banner-1544x500.png /path/to/wordpress-svn/assets/
|
||||||
cp assets/screenshots/screenshot-1.png /path/to/wordpress-svn/assets/
|
cp .wordpress-org/assets/screenshot-1.png /path/to/wordpress-svn/assets/
|
||||||
```
|
```
|
||||||
|
|
||||||
## Resources
|
## Resources
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
303
CHANGELOG.md
@ -1,431 +1,456 @@
|
|||||||
# Changelog
|
All notable changes to this project should be documented both here and in the main Readme files.
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
#### [2.2.0] - 2025-04-14
|
||||||
|
#### Added
|
||||||
|
- Completely refactored plugin to use OOP best practices
|
||||||
|
- New class structure with proper namespaces
|
||||||
|
- Improved code organization and maintainability
|
||||||
|
- Better separation of concerns with dedicated classes
|
||||||
|
|
||||||
#### [2.1.0] - 2024-05-20
|
#### Changed
|
||||||
##### Changed
|
- Changed "Choose Update Source" link to just "Update Source"
|
||||||
|
- Fixed close button in the update source modal
|
||||||
|
- Added links to the main page for each update source in the modal
|
||||||
|
- Replaced all instances of "WP ALLSTARS" with "WPALLSTARS"
|
||||||
|
|
||||||
|
#### [2.1.1] - 2025-04-13
|
||||||
|
#### Added
|
||||||
|
- New "Choose Update Source" feature allowing users to select their preferred update source (WordPress.org, GitHub, or Gitea)
|
||||||
|
- Modal dialog with detailed information about each update source option
|
||||||
|
- Visual indicator showing the currently selected update source
|
||||||
|
|
||||||
|
#### Fixed
|
||||||
|
- Updated heading styles in CHANGELOG.md for better readability
|
||||||
|
- Corrected dates in changelog to use 2025 instead of 2024
|
||||||
|
|
||||||
|
#### Improved
|
||||||
|
- Documentation improvements for better clarity
|
||||||
|
- Enhanced Git Updater integration with user-selectable update sources
|
||||||
|
|
||||||
|
#### [2.1.0] - 2025-04-13
|
||||||
|
#### Changed
|
||||||
- Minor version bump for Git Updater compatibility
|
- Minor version bump for Git Updater compatibility
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- Error handling for Git Updater integration
|
- Error handling for Git Updater integration
|
||||||
- Type checking in branch fix functions
|
- Type checking in branch fix functions
|
||||||
- Documentation for Git Updater installation and cache refreshing
|
- Documentation for Git Updater installation and cache refreshing
|
||||||
|
|
||||||
#### [2.0.13] - 2024-05-20
|
#### [2.0.13] - 2025-04-12
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Critical error when Git Updater passes an object instead of a string to API URL filter
|
- Critical error when Git Updater passes an object instead of a string to API URL filter
|
||||||
- Type checking in branch fix functions to handle both string and object inputs
|
- Type checking in branch fix functions to handle both string and object inputs
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- Error handling for Git Updater integration
|
- Error handling for Git Updater integration
|
||||||
- Documentation for Git Updater installation and cache refreshing
|
- Documentation for Git Updater installation and cache refreshing
|
||||||
|
|
||||||
#### [2.0.12] - 2024-05-19
|
#### [2.0.12] - 2025-04-11
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Integrated Git Updater branch fix directly into main plugin
|
- Integrated Git Updater branch fix directly into main plugin
|
||||||
- Removed separate "GU Branch Fix" plugin (no longer needed)
|
- Removed separate "GU Branch Fix" plugin (no longer needed)
|
||||||
|
|
||||||
##### Added
|
#### Added
|
||||||
- Documentation explaining branch fix integration
|
- Documentation explaining branch fix integration
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- Compatibility with Git Updater plugin
|
- Compatibility with Git Updater plugin
|
||||||
- Deploy script to remove separate branch fix plugin
|
- Deploy script to remove separate branch fix plugin
|
||||||
|
|
||||||
#### [2.0.11] - 2024-05-19
|
#### [2.0.11] - 2025-04-10
|
||||||
##### Added
|
#### Added
|
||||||
- Created separate "GU Branch Fix" plugin to fix Git Updater branch issues
|
- Created separate "GU Branch Fix" plugin to fix Git Updater branch issues
|
||||||
- Added deploy script for local testing
|
- Added deploy script for local testing
|
||||||
|
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Git Updater branch issues with 'main' vs 'master' branch names
|
- Git Updater branch issues with 'main' vs 'master' branch names
|
||||||
- Improved compatibility with Git Updater plugin
|
- Improved compatibility with Git Updater plugin
|
||||||
|
|
||||||
#### [2.0.10] - 2024-05-18
|
#### [2.0.10] - 2025-04-09
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Plugin details popup version display issue with Git Updater integration
|
- Plugin details popup version display issue with Git Updater integration
|
||||||
- Added JavaScript-based solution to ensure correct version display in plugin details
|
- Added JavaScript-based solution to ensure correct version display in plugin details
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- Version consistency across all plugin views
|
- Version consistency across all plugin views
|
||||||
- Enhanced cache busting for plugin information API
|
- Enhanced cache busting for plugin information API
|
||||||
|
|
||||||
#### [2.0.9] - 2024-05-18
|
#### [2.0.9] - 2025-04-08
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Plugin details popup now correctly shows version and author information
|
- Plugin details popup now correctly shows version and author information
|
||||||
- Added support for both old and new plugin slugs to fix caching issues
|
- Added support for both old and new plugin slugs to fix caching issues
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- Cache clearing mechanism to ensure plugin details are always up-to-date
|
- Cache clearing mechanism to ensure plugin details are always up-to-date
|
||||||
- Enhanced version display in plugin details popup
|
- Enhanced version display in plugin details popup
|
||||||
|
|
||||||
#### [2.0.8] - 2024-05-17
|
#### [2.0.8] - 2025-04-07
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Plugin details popup now correctly shows version and author information
|
- Plugin details popup now correctly shows version and author information
|
||||||
- Added cache-busting mechanism to ensure plugin details are always up-to-date
|
- Added cache-busting mechanism to ensure plugin details are always up-to-date
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- Author and contributor information display in plugin details
|
- Author and contributor information display in plugin details
|
||||||
- Added WordPress 6.5 compatibility indicator
|
- Added WordPress 6.5 compatibility indicator
|
||||||
|
|
||||||
#### [2.0.7] - 2024-05-17
|
#### [2.0.7] - 2025-04-06
|
||||||
##### Changed
|
#### Changed
|
||||||
- Additional text improvements and minor fixes
|
- Additional text improvements and minor fixes
|
||||||
|
|
||||||
#### [2.0.6] - 2024-05-17
|
#### [2.0.6] - 2025-04-05
|
||||||
##### Changed
|
#### Changed
|
||||||
- Text improvements and minor fixes
|
- Text improvements and minor fixes
|
||||||
|
|
||||||
#### [2.0.5] - 2024-05-17
|
#### [2.0.5] - 2025-04-04
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Display correct version in plugin details popup
|
- Display correct version in plugin details popup
|
||||||
|
|
||||||
#### [2.0.4] - 2024-05-17
|
#### [2.0.4] - 2025-04-03
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Display actual plugin version instead of 'N/A' for missing plugins in plugin details view
|
- Display actual plugin version instead of 'N/A' for missing plugins in plugin details view
|
||||||
|
|
||||||
#### [2.0.2] - 2024-05-17
|
#### [2.0.2] - 2025-04-02
|
||||||
##### Changed
|
#### Changed
|
||||||
- Consolidated WordPress.org assets into .wordpress-org directory
|
- Consolidated WordPress.org assets into .wordpress-org directory
|
||||||
- Improved organization of assets for WordPress.org submission
|
- Improved organization of assets for WordPress.org submission
|
||||||
- Updated .wordpress-org/README.md with comprehensive information
|
- Updated .wordpress-org/README.md with comprehensive information
|
||||||
|
|
||||||
#### [2.0.1] - 2024-05-17
|
#### [2.0.1] - 2025-04-01
|
||||||
##### Added
|
#### Added
|
||||||
- Contributing section to readme.txt
|
- Contributing section to readme.txt
|
||||||
- reference-plugins directory for plugin development inspiration
|
- reference-plugins directory for plugin development inspiration
|
||||||
|
|
||||||
##### Changed
|
#### Changed
|
||||||
- Updated "tested up to" version to WordPress 6.7.2
|
- Updated "tested up to" version to WordPress 6.7.2
|
||||||
- Improved .gitattributes with comprehensive file handling
|
- Improved .gitattributes with comprehensive file handling
|
||||||
- Enhanced documentation organization
|
- Enhanced documentation organization
|
||||||
|
|
||||||
#### [2.0.0] - 2024-05-17
|
#### [2.0.0] - 2025-03-31
|
||||||
##### Added
|
#### Added
|
||||||
- Note clarifying that the plugin has no settings page
|
- Note clarifying that the plugin has no settings page
|
||||||
- Clarification that functionality is limited to the admin plugins page only
|
- Clarification that functionality is limited to the admin plugins page only
|
||||||
|
|
||||||
##### Changed
|
#### Changed
|
||||||
- Major version release for WordPress.org submission
|
- Major version release for WordPress.org submission
|
||||||
- Finalized all assets and documentation for public release
|
- Finalized all assets and documentation for public release
|
||||||
|
|
||||||
#### [1.6.28] - 2024-05-17
|
#### [1.6.28] - 2025-03-30
|
||||||
##### Changed
|
#### Changed
|
||||||
- Consolidated asset documentation into a single comprehensive guide
|
- Consolidated asset documentation into a single comprehensive guide
|
||||||
- Clarified that `-rtl` suffix is for Right-to-Left languages, not dark mode
|
- Clarified that `-rtl` suffix is for Right-to-Left languages, not dark mode
|
||||||
- Updated all asset README files to point to the main documentation
|
- Updated all asset README files to point to the main documentation
|
||||||
- Improved file organization and documentation structure
|
- Improved file organization and documentation structure
|
||||||
|
|
||||||
#### [1.6.27] - 2024-05-17
|
#### [1.6.27] - 2025-03-29
|
||||||
##### Changed
|
#### Changed
|
||||||
- Clarified RTL support in WordPress.org asset documentation
|
- Clarified RTL support in WordPress.org asset documentation
|
||||||
- Corrected information about `-rtl` suffix for assets (for right-to-left languages, not dark themes)
|
- Corrected information about `-rtl` suffix for assets (for right-to-left languages, not dark themes)
|
||||||
- Consolidated asset files and improved documentation
|
- Consolidated asset files and improved documentation
|
||||||
|
|
||||||
#### [1.6.26] - 2024-05-17
|
#### [1.6.26] - 2025-03-28
|
||||||
##### Changed
|
#### Changed
|
||||||
- Updated screenshot references to use a single comprehensive screenshot
|
- Updated screenshot references to use a single comprehensive screenshot
|
||||||
- Fixed asset directory paths in documentation
|
- Fixed asset directory paths in documentation
|
||||||
- Improved ImageMagick conversion commands for icon generation
|
- Improved ImageMagick conversion commands for icon generation
|
||||||
- Clarified WordPress.org SVN repository structure
|
- Clarified WordPress.org SVN repository structure
|
||||||
|
|
||||||
#### [1.6.25] - 2024-05-17
|
#### [1.6.25] - 2025-03-27
|
||||||
##### Added
|
#### Added
|
||||||
- Comprehensive WordPress.org submission guide with SVN structure explanation
|
- Comprehensive WordPress.org submission guide with SVN structure explanation
|
||||||
|
|
||||||
##### Changed
|
#### Changed
|
||||||
- Consolidated asset files into their respective directories
|
- Consolidated asset files into their respective directories
|
||||||
- Clarified asset requirements and submission process
|
- Clarified asset requirements and submission process
|
||||||
- Improved organization of asset files
|
- Improved organization of asset files
|
||||||
|
|
||||||
#### [1.6.24] - 2024-05-17
|
#### [1.6.24] - 2025-03-26
|
||||||
##### Added
|
#### Added
|
||||||
- Properly named icon PNG files (icon-256x256.png and icon-128x128.png)
|
- Properly named icon PNG files (icon-256x256.png and icon-128x128.png)
|
||||||
|
|
||||||
##### Changed
|
#### Changed
|
||||||
- Updated asset preparation documentation
|
- Updated asset preparation documentation
|
||||||
- Improved WordPress.org submission readiness
|
- Improved WordPress.org submission readiness
|
||||||
|
|
||||||
#### [1.6.23] - 2024-05-17
|
#### [1.6.23] - 2025-03-25
|
||||||
##### Added
|
#### Added
|
||||||
- Properly named icon, banner, and screenshot files for WordPress.org submission
|
- Properly named icon, banner, and screenshot files for WordPress.org submission
|
||||||
- Comprehensive guide for WordPress.org asset requirements
|
- Comprehensive guide for WordPress.org asset requirements
|
||||||
|
|
||||||
##### Changed
|
#### Changed
|
||||||
- Fixed file naming to comply with WordPress.org standards
|
- Fixed file naming to comply with WordPress.org standards
|
||||||
- Organized assets in separate directories for better management
|
- Organized assets in separate directories for better management
|
||||||
|
|
||||||
#### [1.6.22] - 2024-05-17
|
#### [1.6.22] - 2025-03-24
|
||||||
##### Changed
|
#### Changed
|
||||||
- Enhanced support section with multiple support channel options
|
- Enhanced support section with multiple support channel options
|
||||||
- Added encouragement for users to leave reviews on WordPress.org
|
- Added encouragement for users to leave reviews on WordPress.org
|
||||||
- Improved documentation with clearer support instructions
|
- Improved documentation with clearer support instructions
|
||||||
|
|
||||||
#### [1.6.21] - 2024-05-17
|
#### [1.6.21] - 2025-03-23
|
||||||
##### Added
|
#### Added
|
||||||
- Support for more AI-powered development tools (Roo, Gemini, Loveable, Bolt, Cody, Continue)
|
- Support for more AI-powered development tools (Roo, Gemini, Loveable, Bolt, Cody, Continue)
|
||||||
- Links to supported AI IDEs in documentation
|
- Links to supported AI IDEs in documentation
|
||||||
- Additional FAQs for better SEO
|
- Additional FAQs for better SEO
|
||||||
|
|
||||||
##### Changed
|
#### Changed
|
||||||
- Updated AI configuration files with modern models (gpt-4o)
|
- Updated AI configuration files with modern models (gpt-4o)
|
||||||
- Made documentation more generic for boilerplate use
|
- Made documentation more generic for boilerplate use
|
||||||
- Enhanced explanations in configuration files
|
- Enhanced explanations in configuration files
|
||||||
- Added more keywords for better SEO
|
- Added more keywords for better SEO
|
||||||
|
|
||||||
#### [1.6.20] - 2024-05-17
|
#### [1.6.20] - 2025-03-22
|
||||||
##### Changed
|
#### Changed
|
||||||
- Added explanations about the ! prefix in ignore files
|
- Added explanations about the ! prefix in ignore files
|
||||||
- Moved WordPress-specific patterns to .gitignore
|
- Moved WordPress-specific patterns to .gitignore
|
||||||
- Further improved organization of ignore patterns
|
- Further improved organization of ignore patterns
|
||||||
- Added examples of how to include files excluded by .gitignore
|
- Added examples of how to include files excluded by .gitignore
|
||||||
|
|
||||||
#### [1.6.19] - 2024-05-17
|
#### [1.6.19] - 2025-03-21
|
||||||
##### Changed
|
#### Changed
|
||||||
- Consolidated common ignore patterns into .gitignore
|
- Consolidated common ignore patterns into .gitignore
|
||||||
- Simplified AI IDE configuration files to only include tool-specific patterns
|
- Simplified AI IDE configuration files to only include tool-specific patterns
|
||||||
- Improved organization of ignore patterns for better maintainability
|
- Improved organization of ignore patterns for better maintainability
|
||||||
- Added more file types to .gitignore for comprehensive coverage
|
- Added more file types to .gitignore for comprehensive coverage
|
||||||
|
|
||||||
#### [1.6.18] - 2024-05-17
|
#### [1.6.18] - 2025-03-20
|
||||||
##### Changed
|
#### Changed
|
||||||
- Optimized AI IDE configuration files to only include patterns not in .gitignore
|
- Optimized AI IDE configuration files to only include patterns not in .gitignore
|
||||||
- Improved efficiency of ignore files for better AI context management
|
- Improved efficiency of ignore files for better AI context management
|
||||||
- Enhanced compatibility with various AI-powered development tools
|
- Enhanced compatibility with various AI-powered development tools
|
||||||
|
|
||||||
#### [1.6.17] - 2024-05-17
|
#### [1.6.17] - 2025-03-19
|
||||||
##### Added
|
#### Added
|
||||||
- .augmentignore file with best practices
|
- .augmentignore file with best practices
|
||||||
- Configuration files for Cursor, Windsurf, v0, and Cline IDEs
|
- Configuration files for Cursor, Windsurf, v0, and Cline IDEs
|
||||||
- More design file formats to .gitignore
|
- More design file formats to .gitignore
|
||||||
- .aiconfig file for general AI IDE compatibility
|
- .aiconfig file for general AI IDE compatibility
|
||||||
|
|
||||||
#### [1.6.16] - 2024-05-17
|
#### [1.6.16] - 2025-03-18
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Updated CI configuration files with correct plugin slugs
|
- Updated CI configuration files with correct plugin slugs
|
||||||
- Updated CHANGELOG.md with all recent versions
|
- Updated CHANGELOG.md with all recent versions
|
||||||
- Fixed outdated references to plugin-reference-cleaner
|
- Fixed outdated references to plugin-reference-cleaner
|
||||||
|
|
||||||
#### [1.6.15] - 2024-05-17
|
#### [1.6.15] - 2025-03-17
|
||||||
##### Changed
|
#### Changed
|
||||||
- Moved AI workflow documentation to root directory for better visibility
|
- Moved AI workflow documentation to root directory for better visibility
|
||||||
- Consolidated duplicate workflow files
|
- Consolidated duplicate workflow files
|
||||||
- Improved organization of development documentation
|
- Improved organization of development documentation
|
||||||
- Updated CI configuration files with correct plugin slugs
|
- Updated CI configuration files with correct plugin slugs
|
||||||
|
|
||||||
#### [1.6.14] - 2024-05-17
|
#### [1.6.14] - 2025-03-16
|
||||||
##### Changed
|
#### Changed
|
||||||
- Updated documentation to consistently use "Remove Notice" instead of "Remove Reference"
|
- Updated documentation to consistently use "Remove Notice" instead of "Remove Reference"
|
||||||
- Added design file extensions to .gitignore (.pxd, .afdesign, .afphoto, .afpub)
|
- Added design file extensions to .gitignore (.pxd, .afdesign, .afphoto, .afpub)
|
||||||
- Improved explanation of how the plugin works
|
- Improved explanation of how the plugin works
|
||||||
- Ensured consistent terminology across all documentation
|
- Ensured consistent terminology across all documentation
|
||||||
|
|
||||||
#### [1.6.13] - 2024-05-17
|
#### [1.6.13] - 2025-03-15
|
||||||
##### Changed
|
#### Changed
|
||||||
- Code cleanup and optimization
|
- Code cleanup and optimization
|
||||||
- Improved Git Updater integration
|
- Improved Git Updater integration
|
||||||
- Fixed author display in plugin information
|
- Fixed author display in plugin information
|
||||||
- Ensured compatibility with WordPress 6.4
|
- Ensured compatibility with WordPress 6.4
|
||||||
|
|
||||||
#### [1.6.12] - 2024-05-17
|
#### [1.6.12] - 2025-03-14
|
||||||
##### Added
|
#### Added
|
||||||
- Added WP ALLSTARS as a co-author
|
- Added WPALLSTARS as a co-author
|
||||||
- Updated author information and links
|
- Updated author information and links
|
||||||
- Added author websites to plugin description
|
- Added author websites to plugin description
|
||||||
- Fixed issue with multiple author URLs
|
- Fixed issue with multiple author URLs
|
||||||
|
|
||||||
#### [1.6.11] - 2024-05-17
|
#### [1.6.11] - 2025-03-13
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Improved Git Updater integration
|
- Improved Git Updater integration
|
||||||
- Fixed plugin header information
|
- Fixed plugin header information
|
||||||
- Updated author information
|
- Updated author information
|
||||||
|
|
||||||
#### [1.6.10] - 2024-05-17
|
#### [1.6.10] - 2025-03-12
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Corrected plugin header information
|
- Corrected plugin header information
|
||||||
- Improved Git Updater compatibility
|
- Improved Git Updater compatibility
|
||||||
- Updated documentation
|
- Updated documentation
|
||||||
|
|
||||||
#### [1.6.9] - 2024-05-17
|
#### [1.6.9] - 2025-03-11
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Fixed Git Updater integration
|
- Fixed Git Updater integration
|
||||||
- Updated plugin header information
|
- Updated plugin header information
|
||||||
- Improved documentation
|
- Improved documentation
|
||||||
|
|
||||||
#### [1.6.8] - 2024-05-17
|
#### [1.6.8] - 2025-03-10
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Fixed Git Updater integration
|
- Fixed Git Updater integration
|
||||||
- Updated plugin header information
|
- Updated plugin header information
|
||||||
|
|
||||||
#### [1.6.7] - 2024-05-17
|
#### [1.6.7] - 2025-03-09
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Fixed Git Updater integration
|
- Fixed Git Updater integration
|
||||||
- Updated plugin header information
|
- Updated plugin header information
|
||||||
|
|
||||||
#### [1.6.6] - 2024-05-17
|
#### [1.6.6] - 2025-03-08
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Fixed Git Updater integration
|
- Fixed Git Updater integration
|
||||||
- Updated plugin header information
|
- Updated plugin header information
|
||||||
|
|
||||||
#### [1.6.5] - 2024-05-16
|
#### [1.6.5] - 2025-03-07
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Fixed Git Updater integration
|
- Fixed Git Updater integration
|
||||||
- Updated plugin header information
|
- Updated plugin header information
|
||||||
|
|
||||||
#### [1.6.4] - 2024-05-16
|
#### [1.6.4] - 2025-03-06
|
||||||
##### Improved
|
#### Improved
|
||||||
- Version management to ensure consistent patch version increments
|
- Version management to ensure consistent patch version increments
|
||||||
- Documentation for version update process
|
- Documentation for version update process
|
||||||
- AI workflow files with detailed version increment instructions
|
- AI workflow files with detailed version increment instructions
|
||||||
|
|
||||||
#### [1.6.3] - 2024-05-15
|
#### [1.6.3] - 2025-03-05
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Git Updater repository URLs to use full repository paths
|
- Git Updater repository URLs to use full repository paths
|
||||||
- Update URI configuration for proper update detection
|
- Update URI configuration for proper update detection
|
||||||
- Version management following semantic versioning
|
- Version management following semantic versioning
|
||||||
|
|
||||||
##### Changed
|
#### Changed
|
||||||
- Updated organization name from 'WP All Stars' to 'WP ALLSTARS'
|
- Updated organization name from 'WP All Stars' to 'WPALLSTARS'
|
||||||
- Updated namespace from 'WPAllStars' to 'WPALLSTARS'
|
- Updated namespace from 'WPAllStars' to 'WPALLSTARS'
|
||||||
|
|
||||||
#### [1.6.2] - 2024-05-15
|
#### [1.6.2] - 2025-03-04
|
||||||
##### Changed
|
#### Changed
|
||||||
- Updated POT file version for consistency
|
- Updated POT file version for consistency
|
||||||
- Improved JavaScript localization with proper fallbacks
|
- Improved JavaScript localization with proper fallbacks
|
||||||
- Enhanced code quality for WordPress.org submission
|
- Enhanced code quality for WordPress.org submission
|
||||||
##### Added
|
#### Added
|
||||||
- Git Updater configuration with Update URI
|
- Git Updater configuration with Update URI
|
||||||
- Update server URL configuration
|
- Update server URL configuration
|
||||||
|
|
||||||
#### [1.6.1] - 2024-05-15
|
#### [1.6.1] - 2025-03-03
|
||||||
##### Added
|
#### Added
|
||||||
- AI assistant guide and workflow documentation
|
- AI assistant guide and workflow documentation
|
||||||
- Detailed release process documentation
|
- Detailed release process documentation
|
||||||
- Feature development guidelines
|
- Feature development guidelines
|
||||||
- Bug fixing procedures
|
- Bug fixing procedures
|
||||||
- Code review standards
|
- Code review standards
|
||||||
|
|
||||||
#### [1.6.0] - 2024-05-15
|
#### [1.6.0] - 2025-03-02
|
||||||
##### Added
|
#### Added
|
||||||
- Full translation support with POT file
|
- Full translation support with POT file
|
||||||
- JavaScript localization for better multilingual support
|
- JavaScript localization for better multilingual support
|
||||||
- Plugin constants for improved code organization
|
- Plugin constants for improved code organization
|
||||||
- Git Updater support for updates from GitHub and Gitea
|
- Git Updater support for updates from GitHub and Gitea
|
||||||
|
|
||||||
##### Changed
|
#### Changed
|
||||||
- Updated code to follow WordPress internationalization best practices
|
- Updated code to follow WordPress internationalization best practices
|
||||||
- Improved asset loading with version constants
|
- Improved asset loading with version constants
|
||||||
- Smart update detection based on installation source
|
- Smart update detection based on installation source
|
||||||
|
|
||||||
#### [1.5.0] - 2024-05-15
|
#### [1.5.0] - 2025-03-01
|
||||||
##### Added
|
#### Added
|
||||||
- Improved compatibility with WordPress 6.4
|
- Improved compatibility with WordPress 6.4
|
||||||
- Enhanced error detection for plugin references
|
- Enhanced error detection for plugin references
|
||||||
|
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Minor UI improvements for better visibility
|
- Minor UI improvements for better visibility
|
||||||
- Accessibility enhancements for screen readers
|
- Accessibility enhancements for screen readers
|
||||||
|
|
||||||
#### [1.4.1] - 2023-11-30
|
#### [1.4.1] - 2025-02-28
|
||||||
##### Added
|
#### Added
|
||||||
- FAQ about keeping the plugin installed after notices are cleared
|
- FAQ about keeping the plugin installed after notices are cleared
|
||||||
|
|
||||||
#### [1.4.0] - 2023-11-30
|
#### [1.4.0] - 2025-02-27
|
||||||
##### Changed
|
#### Changed
|
||||||
- Updated plugin name and text domain
|
- Updated plugin name and text domain
|
||||||
- Repository rename from plugin-reference-cleaner to wp-fix-plugin-does-not-exist-notices
|
- Repository rename from plugin-reference-cleaner to wp-fix-plugin-does-not-exist-notices
|
||||||
|
|
||||||
#### [1.3.3] - 2023-10-05
|
#### [1.3.3] - 2025-02-26
|
||||||
##### Added
|
#### Added
|
||||||
- "Click here to scroll" button to automatically find missing plugins
|
- "Click here to scroll" button to automatically find missing plugins
|
||||||
- Visual arrow pointing from notification to error message
|
- Visual arrow pointing from notification to error message
|
||||||
- Smooth scrolling with highlighting of missing plugin rows
|
- Smooth scrolling with highlighting of missing plugin rows
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- Notification reliability using multiple injection methods
|
- Notification reliability using multiple injection methods
|
||||||
- Earlier placement in page load cycle for better visibility
|
- Earlier placement in page load cycle for better visibility
|
||||||
- Enhanced error detection for all WordPress error message formats
|
- Enhanced error detection for all WordPress error message formats
|
||||||
|
|
||||||
#### [1.3.2] - 2023-10-05
|
#### [1.3.2] - 2025-02-25
|
||||||
##### Added
|
#### Added
|
||||||
- Prominent notification that appears directly below WordPress error messages
|
- Prominent notification that appears directly below WordPress error messages
|
||||||
- Visual styling to help users connect error message with solution
|
- Visual styling to help users connect error message with solution
|
||||||
- Direction arrows and highlighted text to improve user guidance
|
- Direction arrows and highlighted text to improve user guidance
|
||||||
|
|
||||||
#### [1.3.1] - 2023-10-05
|
#### [1.3.1] - 2025-02-24
|
||||||
##### Added
|
#### Added
|
||||||
- Instructional notification explaining how to use the plugin
|
- Instructional notification explaining how to use the plugin
|
||||||
- Step-by-step guidance for removing plugin references
|
- Step-by-step guidance for removing plugin references
|
||||||
- Clear visual indicators for missing plugins
|
- Clear visual indicators for missing plugins
|
||||||
|
|
||||||
#### [1.3.0] - 2023-10-05
|
#### [1.3.0] - 2025-02-23
|
||||||
##### Changed
|
#### Changed
|
||||||
- Complete redesign for maximum compatibility with all WordPress themes
|
- Complete redesign for maximum compatibility with all WordPress themes
|
||||||
- Now uses the plugins list table for missing plugin references
|
- Now uses the plugins list table for missing plugin references
|
||||||
- Uses standard WordPress admin UI patterns and hooks
|
- Uses standard WordPress admin UI patterns and hooks
|
||||||
|
|
||||||
##### Added
|
#### Added
|
||||||
- Missing plugins now appear directly in the plugins list
|
- Missing plugins now appear directly in the plugins list
|
||||||
- "Remove Reference" action link in the plugins list
|
- "Remove Reference" action link in the plugins list
|
||||||
- Success/error notices after removing references
|
- Success/error notices after removing references
|
||||||
|
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Compatibility issues with various WordPress admin themes
|
- Compatibility issues with various WordPress admin themes
|
||||||
- Reliability issues with notification detection
|
- Reliability issues with notification detection
|
||||||
|
|
||||||
#### [1.2.4] - 2023-10-05
|
#### [1.2.4] - 2025-02-22
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Compatibility with more WordPress admin UI variations
|
- Compatibility with more WordPress admin UI variations
|
||||||
- Specific targeting for admin notices in various themes
|
- Specific targeting for admin notices in various themes
|
||||||
|
|
||||||
##### Added
|
#### Added
|
||||||
- Advanced DOM traversal using TreeWalker API
|
- Advanced DOM traversal using TreeWalker API
|
||||||
- Multiple fallback approaches to ensure button appears
|
- Multiple fallback approaches to ensure button appears
|
||||||
- Enhanced console logging for troubleshooting
|
- Enhanced console logging for troubleshooting
|
||||||
|
|
||||||
#### [1.2.3] - 2023-10-05
|
#### [1.2.3] - 2025-02-21
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Button not appearing in some WordPress admin themes
|
- Button not appearing in some WordPress admin themes
|
||||||
- Error message detection for greater theme compatibility
|
- Error message detection for greater theme compatibility
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- DOM traversal to find notification elements in various themes
|
- DOM traversal to find notification elements in various themes
|
||||||
- Added console logging for troubleshooting
|
- Added console logging for troubleshooting
|
||||||
|
|
||||||
#### [1.2.2] - 2023-10-05
|
#### [1.2.2] - 2025-02-20
|
||||||
##### Fixed
|
#### Fixed
|
||||||
- Timeout issue during plugin activation
|
- Timeout issue during plugin activation
|
||||||
- Potential infinite recursion in admin notices handling
|
- Potential infinite recursion in admin notices handling
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- Hook management to prevent performance issues
|
- Hook management to prevent performance issues
|
||||||
- Optimized by only loading on plugins page
|
- Optimized by only loading on plugins page
|
||||||
|
|
||||||
#### [1.2.1] - 2025-04-07
|
#### [1.2.1] - 2025-04-07
|
||||||
##### Improved
|
#### Improved
|
||||||
- Fixed typos in documentation
|
- Fixed typos in documentation
|
||||||
- Improved text clarity
|
- Improved text clarity
|
||||||
- Added question mark to first sentence for better readability
|
- Added question mark to first sentence for better readability
|
||||||
|
|
||||||
#### [1.2] - 2025-04-07
|
#### [1.2] - 2025-04-07
|
||||||
##### Added
|
#### Added
|
||||||
- Improved documentation with detailed explanation
|
- Improved documentation with detailed explanation
|
||||||
- Added SQL reference for technical users
|
- Added SQL reference for technical users
|
||||||
- Suggested potential inclusion in WordPress core
|
- Suggested potential inclusion in WordPress core
|
||||||
|
|
||||||
#### [1.1] - 2025-04-07
|
#### [1.1] - 2025-04-07
|
||||||
##### Added
|
#### Added
|
||||||
- Support for multisite WordPress installations
|
- Support for multisite WordPress installations
|
||||||
- Network admin page integration
|
- Network admin page integration
|
||||||
- Woodpecker CI integration for automated releases
|
- Woodpecker CI integration for automated releases
|
||||||
|
|
||||||
##### Improved
|
#### Improved
|
||||||
- Error handling
|
- Error handling
|
||||||
- User experience with better confirmation messages
|
- User experience with better confirmation messages
|
||||||
- Security by adding proper capability checks
|
- Security by adding proper capability checks
|
||||||
|
|
||||||
#### [1.0] - 2025-03-15
|
#### [1.0] - 2025-03-15
|
||||||
##### Added
|
#### Added
|
||||||
- Initial release
|
- Initial release
|
||||||
- "Remove Reference" button for plugin deactivation error notices
|
- "Remove Reference" button for plugin deactivation error notices
|
||||||
- AJAX processing for reference removal
|
- AJAX processing for reference removal
|
57
README.md
@ -76,6 +76,22 @@ If you've installed this plugin from GitHub or Gitea, you'll need Git Updater to
|
|||||||
3. Click the "Refresh Cache" button to ensure Git Updater recognizes the latest version
|
3. Click the "Refresh Cache" button to ensure Git Updater recognizes the latest version
|
||||||
4. Updates will now appear in your WordPress dashboard when available
|
4. Updates will now appear in your WordPress dashboard when available
|
||||||
|
|
||||||
|
### Choosing Your Update Source
|
||||||
|
|
||||||
|
This plugin allows you to choose where you want to receive updates from:
|
||||||
|
|
||||||
|
1. In the Plugins list, find "Fix 'Plugin file does not exist' Notices"
|
||||||
|
2. Click the "Choose Update Source" link next to the plugin
|
||||||
|
3. Select your preferred update source:
|
||||||
|
- **WordPress.org**: Updates from the official WordPress.org repository (has a version update delay due to the WP.org policy review and approval process, best for unmonitored auto-updates)
|
||||||
|
- **GitHub**: Updates directly from the GitHub repo main branch for the latest stable release (requires Git Updater plugin, best for monitored updates where the latest features and fixes are needed immediately)
|
||||||
|
- **Gitea**: Updates directly from the Gitea repo main branch for the latest stable release (requires Git Updater plugin, best for monitored updates and independence from big-tech)
|
||||||
|
4. Click "Save" to apply your preference
|
||||||
|
|
||||||
|
> **Note:** If no preference is set, the plugin will automatically use the source it was installed from.
|
||||||
|
|
||||||
|
> **Note:** GitHub and Gitea options require the Git Updater plugin to be installed and activated.
|
||||||
|
|
||||||
## Frequently Asked Questions
|
## Frequently Asked Questions
|
||||||
|
|
||||||
### Is it safe to remove plugin references?
|
### Is it safe to remove plugin references?
|
||||||
@ -150,7 +166,17 @@ Your experience and feedback helps others discover the plugin, and encourages co
|
|||||||
|
|
||||||
### Contributing
|
### Contributing
|
||||||
|
|
||||||
Contributions are welcome! Please feel free to submit a Pull Request.
|
Contributions are welcome! Please follow these steps to set up a development environment:
|
||||||
|
|
||||||
|
1. Install [LocalWP](https://localwp.com/) and create a clean site called "Plugin Testing" using the "Preferred" setup option
|
||||||
|
2. Run "Site shell" once from the LocalWP page on the site's settings to ensure wp-cli is enabled
|
||||||
|
3. Run "Add Run Configurations to VS Code" to update site configuration files in: ~/Local/plugin-testing/conf/
|
||||||
|
4. Clone this repository to your local machine, in `~/Git/` or wherever you keep your Git repositories.
|
||||||
|
5. Use the build.sh and deploy-local.sh scripts to build and deploy the plugin for testing
|
||||||
|
|
||||||
|
[AugmentCode.com](https://augmentcode.com/) is recommended as a good all-in-one AI IDE for plugin development and testing.
|
||||||
|
|
||||||
|
Please feel free to submit a Pull Request with your improvements.
|
||||||
|
|
||||||
1. Fork the repository
|
1. Fork the repository
|
||||||
2. Create your feature branch: `git checkout -b feature/amazing-feature`
|
2. Create your feature branch: `git checkout -b feature/amazing-feature`
|
||||||
@ -185,6 +211,31 @@ The plugin works by:
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### 2.2.0
|
||||||
|
* Added: Completely refactored plugin to use OOP best practices
|
||||||
|
* Added: New class structure with proper namespaces
|
||||||
|
* Added: Improved code organization and maintainability
|
||||||
|
* Added: Better separation of concerns with dedicated classes
|
||||||
|
* Changed: "Choose Update Source" link to just "Update Source"
|
||||||
|
* Fixed: Close button in the update source modal
|
||||||
|
* Added: Links to the main page for each update source in the modal
|
||||||
|
* Changed: Replaced all instances of "WP ALLSTARS" with "WPALLSTARS"
|
||||||
|
|
||||||
|
### 2.1.1
|
||||||
|
* Added: New "Choose Update Source" feature allowing users to select their preferred update source (WordPress.org, GitHub, or Gitea)
|
||||||
|
* Added: Modal dialog with detailed information about each update source option
|
||||||
|
* Added: Visual indicator showing the currently selected update source
|
||||||
|
* Fixed: Updated heading styles in CHANGELOG.md for better readability
|
||||||
|
* Fixed: Corrected dates in changelog to use 2025 instead of 2024
|
||||||
|
* Improved: Documentation improvements for better clarity
|
||||||
|
* Improved: Enhanced Git Updater integration with user-selectable update sources
|
||||||
|
|
||||||
|
### 2.1.0
|
||||||
|
* Minor version bump for Git Updater compatibility
|
||||||
|
* Improved error handling for Git Updater integration
|
||||||
|
* Enhanced type checking in branch fix functions
|
||||||
|
* Updated documentation for Git Updater installation and cache refreshing
|
||||||
|
|
||||||
### 2.0.13
|
### 2.0.13
|
||||||
* Fixed: Critical error when Git Updater passes an object instead of a string to API URL filter
|
* Fixed: Critical error when Git Updater passes an object instead of a string to API URL filter
|
||||||
* Fixed: Type checking in branch fix functions to handle both string and object inputs
|
* Fixed: Type checking in branch fix functions to handle both string and object inputs
|
||||||
@ -344,7 +395,7 @@ The plugin works by:
|
|||||||
* Ensured compatibility with WordPress 6.4
|
* Ensured compatibility with WordPress 6.4
|
||||||
|
|
||||||
### 1.6.12
|
### 1.6.12
|
||||||
* Added WP ALLSTARS as a co-author
|
* Added WPALLSTARS as a co-author
|
||||||
* Updated author information and links
|
* Updated author information and links
|
||||||
* Added author websites to plugin description
|
* Added author websites to plugin description
|
||||||
* Fixed issue with multiple author URLs
|
* Fixed issue with multiple author URLs
|
||||||
@ -409,7 +460,7 @@ The plugin works by:
|
|||||||
* Fixed Git Updater repository URLs to use full repository paths
|
* Fixed Git Updater repository URLs to use full repository paths
|
||||||
* Corrected Update URI configuration for proper update detection
|
* Corrected Update URI configuration for proper update detection
|
||||||
* Improved version management following semantic versioning
|
* Improved version management following semantic versioning
|
||||||
* Updated organization name from 'WP All Stars' to 'WP ALLSTARS'
|
* Updated organization name from 'WP All Stars' to 'WPALLSTARS'
|
||||||
* Updated namespace from 'WPAllStars' to 'WPALLSTARS'
|
* Updated namespace from 'WPAllStars' to 'WPALLSTARS'
|
||||||
|
|
||||||
### 1.6.2
|
### 1.6.2
|
||||||
|
99
admin/css/update-source-selector.css
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* Update Source Selector Styles
|
||||||
|
*/
|
||||||
|
#fpden-update-source-modal {
|
||||||
|
display: none;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fpden-update-source-modal h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fpden-update-source-modal p {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fpden-update-source-form label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fpden-update-source-form label:hover {
|
||||||
|
background-color: #f0f0f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fpden-update-source-form input[type="radio"] {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fpden-source-description {
|
||||||
|
display: block;
|
||||||
|
margin-left: 24px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #666;
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fpden-submit-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fpden-submit-container button {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove explicit color to inherit from theme */
|
||||||
|
.fpden-update-source-toggle {
|
||||||
|
/* color is now inherited from theme */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fpden-update-source-toggle:hover {
|
||||||
|
/* hover color is now inherited from theme */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close button styles */
|
||||||
|
.fpden-close-modal {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 40px; /* Large size */
|
||||||
|
color: #666;
|
||||||
|
line-height: 30px;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Source badges */
|
||||||
|
.fpden-source-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-left: 5px;
|
||||||
|
color: white;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fpden-source-badge.wordpress, .fpden-source-badge.wordpress\.org {
|
||||||
|
background-color: #0073aa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fpden-source-badge.github {
|
||||||
|
background-color: #24292e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fpden-source-badge.gitea {
|
||||||
|
background-color: #609926;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fpden-source-badge.auto {
|
||||||
|
background-color: #666;
|
||||||
|
}
|
147
admin/js/update-source-selector.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
* Update Source Selector
|
||||||
|
*
|
||||||
|
* Handles the UI for selecting which source to use for plugin updates.
|
||||||
|
*/
|
||||||
|
jQuery(document).ready(function($) {
|
||||||
|
// Open modal when toggle is clicked
|
||||||
|
$(document).on('click', '.fpden-update-source-toggle', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// Add overlay
|
||||||
|
$('body').append('<div id="fpden-modal-overlay"></div>');
|
||||||
|
$('#fpden-modal-overlay').css({
|
||||||
|
'position': 'fixed',
|
||||||
|
'top': 0,
|
||||||
|
'left': 0,
|
||||||
|
'width': '100%',
|
||||||
|
'height': '100%',
|
||||||
|
'background-color': 'rgba(0,0,0,0.5)',
|
||||||
|
'z-index': 100000
|
||||||
|
});
|
||||||
|
|
||||||
|
// Position and show modal
|
||||||
|
var modal = $('#fpden-update-source-modal');
|
||||||
|
modal.css({
|
||||||
|
'position': 'fixed',
|
||||||
|
'top': '50%',
|
||||||
|
'left': '50%',
|
||||||
|
'transform': 'translate(-50%, -50%)',
|
||||||
|
'background-color': '#fff',
|
||||||
|
'padding': '20px',
|
||||||
|
'border-radius': '5px',
|
||||||
|
'box-shadow': '0 0 10px rgba(0,0,0,0.5)',
|
||||||
|
'z-index': 100001,
|
||||||
|
'width': '400px',
|
||||||
|
'max-width': '90%'
|
||||||
|
}).show();
|
||||||
|
|
||||||
|
// Add close button styles
|
||||||
|
$('.fpden-close-modal').css({
|
||||||
|
'position': 'absolute',
|
||||||
|
'top': '10px',
|
||||||
|
'right': '10px',
|
||||||
|
'cursor': 'pointer',
|
||||||
|
'font-size': '20px',
|
||||||
|
'color': '#666'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close modal when clicking overlay or close button
|
||||||
|
$(document).on('click', '#fpden-modal-overlay', function() {
|
||||||
|
$('#fpden-update-source-modal').hide();
|
||||||
|
$('#fpden-modal-overlay').remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Separate handler for close button to ensure it works
|
||||||
|
$(document).on('click', '.fpden-close-modal', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation(); // Prevent event bubbling
|
||||||
|
$('#fpden-update-source-modal').hide();
|
||||||
|
$('#fpden-modal-overlay').remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Direct binding to the close button for extra reliability
|
||||||
|
$('.fpden-close-modal').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation(); // Prevent event bubbling
|
||||||
|
$('#fpden-update-source-modal').hide();
|
||||||
|
$('#fpden-modal-overlay').remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent clicks inside modal from closing it
|
||||||
|
$('#fpden-update-source-modal').on('click', function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle form submission
|
||||||
|
$('#fpden-update-source-form').on('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var source = $('input[name="update_source"]:checked').val();
|
||||||
|
|
||||||
|
// Show loading state
|
||||||
|
var submitButton = $(this).find('button[type="submit"]');
|
||||||
|
var originalText = submitButton.text();
|
||||||
|
submitButton.text('Saving...').prop('disabled', true);
|
||||||
|
|
||||||
|
// Save via AJAX
|
||||||
|
$.post(ajaxurl, {
|
||||||
|
action: 'fpden_save_update_source',
|
||||||
|
source: source,
|
||||||
|
nonce: fpdenData.updateSourceNonce
|
||||||
|
}, function(response) {
|
||||||
|
submitButton.text(originalText).prop('disabled', false);
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
// Update the badge
|
||||||
|
var badgeText = source.charAt(0).toUpperCase() + source.slice(1);
|
||||||
|
if (source === 'wordpress.org') {
|
||||||
|
badgeText = 'WP.org';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all badge classes and add the new one
|
||||||
|
var badge = $('.fpden-update-source-toggle .fpden-source-badge');
|
||||||
|
badge.removeClass('auto wordpress github gitea')
|
||||||
|
.addClass(source)
|
||||||
|
.text(badgeText);
|
||||||
|
|
||||||
|
// Show success message
|
||||||
|
var message = $('<div class="fpden-success-message">Update source saved successfully!</div>');
|
||||||
|
message.css({
|
||||||
|
'color': 'green',
|
||||||
|
'margin-top': '10px',
|
||||||
|
'text-align': 'center'
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#fpden-update-source-form').append(message);
|
||||||
|
|
||||||
|
// Hide message and modal after delay
|
||||||
|
setTimeout(function() {
|
||||||
|
message.fadeOut(function() {
|
||||||
|
$(this).remove();
|
||||||
|
$('#fpden-update-source-modal').hide();
|
||||||
|
$('#fpden-modal-overlay').remove();
|
||||||
|
});
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
// Show error message
|
||||||
|
var message = $('<div class="fpden-error-message">Error saving update source.</div>');
|
||||||
|
message.css({
|
||||||
|
'color': 'red',
|
||||||
|
'margin-top': '10px',
|
||||||
|
'text-align': 'center'
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#fpden-update-source-form').append(message);
|
||||||
|
|
||||||
|
// Hide message after delay
|
||||||
|
setTimeout(function() {
|
||||||
|
message.fadeOut(function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -8,7 +8,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Current plugin version - this should match the version in the main plugin file
|
// Current plugin version - this should match the version in the main plugin file
|
||||||
const CURRENT_VERSION = '2.0.13';
|
const CURRENT_VERSION = '2.2.0';
|
||||||
|
|
||||||
// Plugin slugs to check for
|
// Plugin slugs to check for
|
||||||
const OUR_SLUGS = ['wp-fix-plugin-does-not-exist-notices', 'fix-plugin-does-not-exist-notices'];
|
const OUR_SLUGS = ['wp-fix-plugin-does-not-exist-notices', 'fix-plugin-does-not-exist-notices'];
|
@ -1,50 +0,0 @@
|
|||||||
# Plugin Assets for WordPress.org
|
|
||||||
|
|
||||||
This directory contains assets for the WordPress.org plugin repository.
|
|
||||||
|
|
||||||
## Directory Structure
|
|
||||||
|
|
||||||
- `banner/` - Banner images for the plugin page header
|
|
||||||
- `banner-772x250.jpg` - Standard banner (772x250px)
|
|
||||||
- `banner-1544x500.jpg` - Retina banner (1544x500px)
|
|
||||||
|
|
||||||
- `icon/` - Plugin icon images
|
|
||||||
- `icon-128x128.jpg` - Standard icon (128x128px)
|
|
||||||
- `icon-256x256.jpg` - Retina icon (256x256px)
|
|
||||||
|
|
||||||
- `screenshots/` - Screenshots shown on the plugin page
|
|
||||||
- `screenshot-1.jpg` - Error message with explanation notification
|
|
||||||
|
|
||||||
## WordPress.org Requirements
|
|
||||||
|
|
||||||
### Required Image Dimensions
|
|
||||||
|
|
||||||
- **Banner**: 772x250px with 2x retina version at 1544x500px
|
|
||||||
- **Icon**: 128x128px with 2x retina version at 256x256px
|
|
||||||
- **Screenshots**: No specific size requirements, but they should be clear and readable
|
|
||||||
|
|
||||||
### Image Formats
|
|
||||||
|
|
||||||
- All images should be in JPG or PNG format
|
|
||||||
- Images should be optimized for web (compressed without losing quality)
|
|
||||||
|
|
||||||
### Additional Notes
|
|
||||||
|
|
||||||
- Screenshots should be numbered sequentially starting with 1
|
|
||||||
- They should match the descriptions in the `readme.txt` file
|
|
||||||
- Right-to-Left (RTL) language versions of banners and icons can be provided by appending `-rtl` to the filename
|
|
||||||
- There is no official support for dark mode versions of assets in the WordPress.org repository
|
|
||||||
|
|
||||||
## Example Filenames
|
|
||||||
|
|
||||||
```
|
|
||||||
assets/
|
|
||||||
├── banner/
|
|
||||||
│ ├── banner-772x250.jpg
|
|
||||||
│ └── banner-1544x500.jpg
|
|
||||||
├── icon/
|
|
||||||
│ ├── icon-128x128.jpg
|
|
||||||
│ └── icon-256x256.jpg
|
|
||||||
└── screenshots/
|
|
||||||
├── screenshot-1.jpg
|
|
||||||
```
|
|
@ -1,15 +0,0 @@
|
|||||||
# WordPress.org Banner Files
|
|
||||||
|
|
||||||
This directory contains banner files for the WordPress.org plugin repository.
|
|
||||||
|
|
||||||
## Files in this Directory
|
|
||||||
|
|
||||||
- `banner-772x250.png` - 772x250 pixel PNG banner (required for WordPress.org)
|
|
||||||
- `banner-1544x500.png` - 1544x500 pixel PNG banner for high-DPI displays (optional for WordPress.org)
|
|
||||||
- `banner-1544x500.pxd` - Source file for editing in Pixelmator
|
|
||||||
|
|
||||||
## WordPress.org Submission
|
|
||||||
|
|
||||||
For detailed information about WordPress.org banner requirements and submission process, please see the main asset documentation:
|
|
||||||
|
|
||||||
[WordPress.org Plugin Submission Assets Guide](../WORDPRESS_ORG_ASSETS.md)
|
|
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 15 KiB |
@ -1,16 +0,0 @@
|
|||||||
# WordPress.org Icon Files
|
|
||||||
|
|
||||||
This directory contains icon files for the WordPress.org plugin repository.
|
|
||||||
|
|
||||||
## Files in this Directory
|
|
||||||
|
|
||||||
- `icon.svg` - Source SVG icon
|
|
||||||
- `icon-256x256.png` - 256x256 pixel PNG icon (required for WordPress.org)
|
|
||||||
- `icon-128x128.png` - 128x128 pixel PNG icon (optional for WordPress.org)
|
|
||||||
- `icon-1024x1024.pxd` - Source file for editing in Pixelmator
|
|
||||||
|
|
||||||
## WordPress.org Submission
|
|
||||||
|
|
||||||
For detailed information about WordPress.org icon requirements and submission process, please see the main asset documentation:
|
|
||||||
|
|
||||||
[WordPress.org Plugin Submission Assets Guide](../WORDPRESS_ORG_ASSETS.md)
|
|
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.7 KiB |
@ -1,14 +0,0 @@
|
|||||||
# WordPress.org Screenshot Files
|
|
||||||
|
|
||||||
This directory contains screenshot files for the WordPress.org plugin repository.
|
|
||||||
|
|
||||||
## Files in this Directory
|
|
||||||
|
|
||||||
- `screenshot-1.png` - Main screenshot showing the plugin in action
|
|
||||||
- `screenshot-1.pxd` - Source file for editing in Pixelmator
|
|
||||||
|
|
||||||
## WordPress.org Submission
|
|
||||||
|
|
||||||
For detailed information about WordPress.org screenshot requirements and submission process, please see the main asset documentation:
|
|
||||||
|
|
||||||
[WordPress.org Plugin Submission Assets Guide](../WORDPRESS_ORG_ASSETS.md)
|
|
Before Width: | Height: | Size: 392 KiB |
18
build.sh
@ -37,8 +37,24 @@ mkdir -p $BUILD_DIR/includes
|
|||||||
cp -r includes/* $BUILD_DIR/includes/
|
cp -r includes/* $BUILD_DIR/includes/
|
||||||
mkdir -p $BUILD_DIR/languages
|
mkdir -p $BUILD_DIR/languages
|
||||||
cp -r languages/* $BUILD_DIR/languages/
|
cp -r languages/* $BUILD_DIR/languages/
|
||||||
|
|
||||||
|
# Copy admin assets
|
||||||
|
mkdir -p $BUILD_DIR/admin/css
|
||||||
|
cp -r admin/css/* $BUILD_DIR/admin/css/
|
||||||
|
mkdir -p $BUILD_DIR/admin/js
|
||||||
|
cp -r admin/js/* $BUILD_DIR/admin/js/
|
||||||
|
|
||||||
|
# Create assets directory structure
|
||||||
mkdir -p $BUILD_DIR/assets
|
mkdir -p $BUILD_DIR/assets
|
||||||
cp -r assets/* $BUILD_DIR/assets/
|
|
||||||
|
# Copy PNG files from .wordpress-org/assets to the build directory
|
||||||
|
mkdir -p $BUILD_DIR/assets/banner
|
||||||
|
cp -r .wordpress-org/assets/banner-*.png $BUILD_DIR/assets/banner/ 2>/dev/null || :
|
||||||
|
mkdir -p $BUILD_DIR/assets/icon
|
||||||
|
cp -r .wordpress-org/assets/icon-*.png $BUILD_DIR/assets/icon/ 2>/dev/null || :
|
||||||
|
mkdir -p $BUILD_DIR/assets/screenshots
|
||||||
|
cp -r .wordpress-org/assets/screenshot-*.png $BUILD_DIR/assets/screenshots/ 2>/dev/null || :
|
||||||
|
|
||||||
mkdir -p $BUILD_DIR/vendor
|
mkdir -p $BUILD_DIR/vendor
|
||||||
cp -r vendor/* $BUILD_DIR/vendor/
|
cp -r vendor/* $BUILD_DIR/vendor/
|
||||||
|
|
||||||
|
92
includes/Admin.php
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Admin Functionality
|
||||||
|
*
|
||||||
|
* @package WPALLSTARS\FixPluginDoesNotExistNotices
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPALLSTARS\FixPluginDoesNotExistNotices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin Class
|
||||||
|
*
|
||||||
|
* Handles admin-specific functionality.
|
||||||
|
*/
|
||||||
|
class Admin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core instance
|
||||||
|
*
|
||||||
|
* @var Core
|
||||||
|
*/
|
||||||
|
private $core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param Core $core Core instance.
|
||||||
|
*/
|
||||||
|
public function __construct($core) {
|
||||||
|
$this->core = $core;
|
||||||
|
|
||||||
|
// Enqueue admin scripts and styles
|
||||||
|
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue scripts and styles needed for the admin area.
|
||||||
|
*
|
||||||
|
* @param string $hook_suffix The current admin page hook.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function enqueue_admin_assets($hook_suffix) {
|
||||||
|
// Only load on the plugins page
|
||||||
|
if ('plugins.php' !== $hook_suffix) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always load our version fix script on the plugins page
|
||||||
|
wp_enqueue_script(
|
||||||
|
'fpden-version-fix',
|
||||||
|
FPDEN_PLUGIN_URL . 'admin/js/version-fix.js',
|
||||||
|
array('jquery', 'thickbox'),
|
||||||
|
FPDEN_VERSION,
|
||||||
|
true // Load in footer
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get invalid plugins to decide if other assets are needed
|
||||||
|
$invalid_plugins = $this->core->get_invalid_plugins();
|
||||||
|
if (empty($invalid_plugins)) {
|
||||||
|
return; // No missing plugins, no need for the special notice JS/CSS
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_enqueue_style(
|
||||||
|
'fpden-admin-styles',
|
||||||
|
FPDEN_PLUGIN_URL . 'admin/css/admin-styles.css',
|
||||||
|
array(),
|
||||||
|
FPDEN_VERSION
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_enqueue_script(
|
||||||
|
'fpden-admin-scripts',
|
||||||
|
FPDEN_PLUGIN_URL . 'admin/js/admin-scripts.js',
|
||||||
|
array('jquery'), // Add dependencies if needed, e.g., jQuery
|
||||||
|
FPDEN_VERSION,
|
||||||
|
true // Load in footer
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add translation strings for JavaScript
|
||||||
|
wp_localize_script(
|
||||||
|
'fpden-admin-scripts',
|
||||||
|
'fpdenData',
|
||||||
|
array(
|
||||||
|
'i18n' => array(
|
||||||
|
'clickToScroll' => esc_html__('Click here to scroll to missing plugins', 'wp-fix-plugin-does-not-exist-notices'),
|
||||||
|
'pluginMissing' => esc_html__('File Missing', 'wp-fix-plugin-does-not-exist-notices'),
|
||||||
|
'removeNotice' => esc_html__('Remove Notice', 'wp-fix-plugin-does-not-exist-notices'),
|
||||||
|
),
|
||||||
|
'version' => FPDEN_VERSION, // Add version for the plugin details fix script
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
619
includes/Core.php
Normal file
@ -0,0 +1,619 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Core Functionality
|
||||||
|
*
|
||||||
|
* @package WPALLSTARS\FixPluginDoesNotExistNotices
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPALLSTARS\FixPluginDoesNotExistNotices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core Class
|
||||||
|
*
|
||||||
|
* Handles the core functionality of finding and fixing invalid plugin references.
|
||||||
|
*/
|
||||||
|
class Core {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a list of invalid plugins found in the active_plugins option.
|
||||||
|
*
|
||||||
|
* @var array|null
|
||||||
|
*/
|
||||||
|
private $invalid_plugins = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
// Add our plugin to the plugins list
|
||||||
|
add_filter('all_plugins', array($this, 'add_missing_plugins_references'));
|
||||||
|
|
||||||
|
// Add our action link to the plugins list
|
||||||
|
add_filter('plugin_action_links', array($this, 'add_remove_reference_action'), 20, 4);
|
||||||
|
|
||||||
|
// Handle the remove reference action
|
||||||
|
add_action('admin_init', array($this, 'handle_remove_reference'));
|
||||||
|
|
||||||
|
// Add admin notices for operation feedback
|
||||||
|
add_action('admin_notices', array($this, 'admin_notices'));
|
||||||
|
|
||||||
|
// Filter the plugin API to fix version display in plugin details popup
|
||||||
|
add_filter('plugins_api', array($this, 'filter_plugin_details'), 10, 3);
|
||||||
|
|
||||||
|
// Prevent WordPress from caching our plugin API responses
|
||||||
|
add_filter('plugins_api_result', array($this, 'prevent_plugins_api_caching'), 10, 3);
|
||||||
|
|
||||||
|
// Clear plugin API transients on plugin activation and when viewing plugins page
|
||||||
|
add_action('admin_init', array($this, 'maybe_clear_plugin_api_cache'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of invalid plugins (plugins that are active but don't exist).
|
||||||
|
*
|
||||||
|
* @return array An array of plugin file paths that don't exist.
|
||||||
|
*/
|
||||||
|
public function get_invalid_plugins() {
|
||||||
|
// Return cached result if available
|
||||||
|
if (is_array($this->invalid_plugins)) {
|
||||||
|
return $this->invalid_plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize empty array
|
||||||
|
$invalid_plugins = array();
|
||||||
|
|
||||||
|
// Handle multisite network admin context
|
||||||
|
if (is_multisite() && is_network_admin()) {
|
||||||
|
$active_plugins = get_site_option('active_sitewide_plugins', array());
|
||||||
|
// Network active plugins are stored as key => timestamp
|
||||||
|
$active_plugins = array_keys($active_plugins);
|
||||||
|
} else {
|
||||||
|
// Single site or non-network admin context
|
||||||
|
$active_plugins = get_option('active_plugins', array());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check each active plugin
|
||||||
|
foreach ($active_plugins as $plugin_file) {
|
||||||
|
$plugin_path = WP_PLUGIN_DIR . '/' . $plugin_file;
|
||||||
|
if (!file_exists($plugin_path)) {
|
||||||
|
$invalid_plugins[] = $plugin_file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the result
|
||||||
|
$this->invalid_plugins = $invalid_plugins;
|
||||||
|
|
||||||
|
return $invalid_plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current page is the plugins page.
|
||||||
|
*
|
||||||
|
* @return bool True if on the plugins page, false otherwise.
|
||||||
|
*/
|
||||||
|
public function is_plugins_page() {
|
||||||
|
global $pagenow;
|
||||||
|
return is_admin() && 'plugins.php' === $pagenow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find and add invalid plugin references to the plugins list.
|
||||||
|
*
|
||||||
|
* Filters the list of plugins displayed on the plugins page to include
|
||||||
|
* entries for active plugins whose files are missing.
|
||||||
|
*
|
||||||
|
* @param array $plugins An array of plugin data.
|
||||||
|
* @return array The potentially modified array of plugin data.
|
||||||
|
*/
|
||||||
|
public function add_missing_plugins_references($plugins) {
|
||||||
|
// Only run on the plugins page
|
||||||
|
if (!$this->is_plugins_page()) {
|
||||||
|
return $plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get active plugins that don't exist
|
||||||
|
$invalid_plugins = $this->get_invalid_plugins();
|
||||||
|
|
||||||
|
// Add each invalid plugin to the plugin list
|
||||||
|
foreach ($invalid_plugins as $plugin_path) {
|
||||||
|
if (!isset($plugins[$plugin_path])) {
|
||||||
|
$plugin_name = basename($plugin_path);
|
||||||
|
$plugin_slug = dirname($plugin_path);
|
||||||
|
if ('.' === $plugin_slug) {
|
||||||
|
$plugin_slug = basename($plugin_path, '.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a basic plugin data array
|
||||||
|
$plugins[$plugin_path] = array(
|
||||||
|
'Name' => $plugin_name . ' <span class="error">(File Missing)</span>',
|
||||||
|
/* translators: %s: Path to wp-content/plugins */
|
||||||
|
'Description' => sprintf(
|
||||||
|
__('This plugin is still marked as "Active" in your database — but its folder and files can\'t be found in %s. Click "Remove Notice" to permanently remove it from your active plugins list and eliminate the error notice.', 'wp-fix-plugin-does-not-exist-notices'),
|
||||||
|
'<code>/wp-content/plugins/</code>'
|
||||||
|
),
|
||||||
|
'Version' => FPDEN_VERSION, // Use our plugin version instead of 'N/A'
|
||||||
|
'Author' => 'Marcus Quinn & WPALLSTARS',
|
||||||
|
'PluginURI' => 'https://www.wpallstars.com',
|
||||||
|
'AuthorURI' => 'https://www.wpallstars.com',
|
||||||
|
'Title' => $plugin_name . ' (' . __('Missing', 'wp-fix-plugin-does-not-exist-notices') . ')',
|
||||||
|
'AuthorName' => 'Marcus Quinn & WPALLSTARS',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the data needed for the "View details" link
|
||||||
|
$plugins[$plugin_path]['slug'] = $plugin_slug;
|
||||||
|
$plugins[$plugin_path]['plugin'] = $plugin_path;
|
||||||
|
$plugins[$plugin_path]['type'] = 'plugin';
|
||||||
|
|
||||||
|
// Add Git Updater fields
|
||||||
|
$plugins[$plugin_path]['GitHub Plugin URI'] = 'wpallstars/wp-fix-plugin-does-not-exist-notices';
|
||||||
|
$plugins[$plugin_path]['GitHub Branch'] = 'main';
|
||||||
|
$plugins[$plugin_path]['TextDomain'] = 'wp-fix-plugin-does-not-exist-notices';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the Remove Notice action link to invalid plugins.
|
||||||
|
*
|
||||||
|
* Filters the action links displayed for each plugin on the plugins page.
|
||||||
|
* Adds a "Remove Notice" link for plugins identified as missing.
|
||||||
|
*
|
||||||
|
* @param array $actions An array of plugin action links.
|
||||||
|
* @param string $plugin_file Path to the plugin file relative to the plugins directory.
|
||||||
|
* @param array $plugin_data An array of plugin data.
|
||||||
|
* @param string $context The plugin context (e.g., 'all', 'active', 'inactive').
|
||||||
|
* @return array The potentially modified array of plugin action links.
|
||||||
|
*/
|
||||||
|
public function add_remove_reference_action($actions, $plugin_file, $plugin_data, $context) {
|
||||||
|
// Only run on the plugins page
|
||||||
|
if (!$this->is_plugins_page()) {
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get our list of invalid plugins
|
||||||
|
$invalid_plugins = $this->get_invalid_plugins();
|
||||||
|
|
||||||
|
// Check if this plugin file is in our list of invalid plugins
|
||||||
|
if (in_array($plugin_file, $invalid_plugins, true)) {
|
||||||
|
// Clear existing actions like "Activate", "Deactivate", "Edit"
|
||||||
|
$actions = array();
|
||||||
|
|
||||||
|
// Add our custom action
|
||||||
|
$nonce = wp_create_nonce('remove_plugin_reference_' . $plugin_file);
|
||||||
|
$remove_url = admin_url('plugins.php?action=remove_reference&plugin=' . urlencode($plugin_file) . '&_wpnonce=' . $nonce);
|
||||||
|
/* translators: %s: Plugin file path */
|
||||||
|
$aria_label = sprintf(__('Remove reference to missing plugin %s', 'wp-fix-plugin-does-not-exist-notices'), esc_attr($plugin_file));
|
||||||
|
$actions['remove_reference'] = '<a href="' . esc_url($remove_url) . '" class="delete" aria-label="' . $aria_label . '">' . esc_html__('Remove Notice', 'wp-fix-plugin-does-not-exist-notices') . '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the remove reference action triggered by the link.
|
||||||
|
*
|
||||||
|
* Checks for the correct action, verifies nonce and permissions,
|
||||||
|
* calls the removal function, and redirects back to the plugins page.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle_remove_reference() {
|
||||||
|
// Check if our specific action is being performed
|
||||||
|
if (!isset($_GET['action']) || 'remove_reference' !== $_GET['action'] || !isset($_GET['plugin'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify user permissions
|
||||||
|
if (!current_user_can('activate_plugins')) {
|
||||||
|
wp_die(esc_html__('You do not have sufficient permissions to perform this action.', 'wp-fix-plugin-does-not-exist-notices'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize and get the plugin file path
|
||||||
|
$plugin_file = isset($_GET['plugin']) ? sanitize_text_field(wp_unslash($_GET['plugin'])) : '';
|
||||||
|
if (empty($plugin_file)) {
|
||||||
|
wp_die(esc_html__('Invalid plugin specified.', 'wp-fix-plugin-does-not-exist-notices'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify nonce for security
|
||||||
|
check_admin_referer('remove_plugin_reference_' . $plugin_file);
|
||||||
|
|
||||||
|
// Attempt to remove the plugin reference
|
||||||
|
$success = $this->remove_plugin_reference($plugin_file);
|
||||||
|
|
||||||
|
// Prepare redirect URL with feedback query args
|
||||||
|
$redirect_url = admin_url('plugins.php');
|
||||||
|
$redirect_url = add_query_arg($success ? 'reference_removed' : 'reference_removal_failed', '1', $redirect_url);
|
||||||
|
|
||||||
|
// Redirect and exit
|
||||||
|
wp_safe_redirect($redirect_url);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a plugin reference from the active plugins list in the database.
|
||||||
|
*
|
||||||
|
* Handles both single site and multisite network activated plugins.
|
||||||
|
*
|
||||||
|
* @param string $plugin_file The plugin file path to remove.
|
||||||
|
* @return bool True on success, false on failure or if the plugin wasn't found.
|
||||||
|
*/
|
||||||
|
public function remove_plugin_reference($plugin_file) {
|
||||||
|
$success = false;
|
||||||
|
|
||||||
|
// Ensure plugin file path is provided
|
||||||
|
if (empty($plugin_file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle multisite network admin context
|
||||||
|
if (is_multisite() && is_network_admin()) {
|
||||||
|
$active_plugins = get_site_option('active_sitewide_plugins', array());
|
||||||
|
// Network active plugins are stored as key => timestamp
|
||||||
|
if (isset($active_plugins[$plugin_file])) {
|
||||||
|
unset($active_plugins[$plugin_file]);
|
||||||
|
$success = update_site_option('active_sitewide_plugins', $active_plugins);
|
||||||
|
}
|
||||||
|
} else { // Handle single site or non-network admin context
|
||||||
|
$active_plugins = get_option('active_plugins', array());
|
||||||
|
// Single site active plugins are stored as an indexed array
|
||||||
|
$key = array_search($plugin_file, $active_plugins, true); // Use strict comparison
|
||||||
|
if (false !== $key) {
|
||||||
|
unset($active_plugins[$key]);
|
||||||
|
// Re-index the array numerically
|
||||||
|
$active_plugins = array_values($active_plugins);
|
||||||
|
$success = update_option('active_plugins', $active_plugins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display admin notices on the plugins page.
|
||||||
|
*
|
||||||
|
* Shows feedback messages after attempting to remove a reference.
|
||||||
|
* The main informational notice is handled by JavaScript to position it
|
||||||
|
* directly below the WordPress error message.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function admin_notices() {
|
||||||
|
// Only run on the plugins page
|
||||||
|
if (!$this->is_plugins_page()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for feedback messages from the remove action
|
||||||
|
if (isset($_GET['reference_removed']) && '1' === $_GET['reference_removed']) {
|
||||||
|
?>
|
||||||
|
<div class="notice notice-success is-dismissible">
|
||||||
|
<p><?php esc_html_e('Plugin reference removed successfully.', 'wp-fix-plugin-does-not-exist-notices'); ?></p>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_GET['reference_removal_failed']) && '1' === $_GET['reference_removal_failed']) {
|
||||||
|
?>
|
||||||
|
<div class="notice notice-error is-dismissible">
|
||||||
|
<p><?php esc_html_e('Failed to remove plugin reference. The plugin may already have been removed, or there was a database issue.', 'wp-fix-plugin-does-not-exist-notices'); ?></p>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter plugin details API response to provide custom data for our plugin.
|
||||||
|
*
|
||||||
|
* @param object|WP_Error $result The result object or WP_Error.
|
||||||
|
* @param string $action The type of information being requested.
|
||||||
|
* @param object $args Plugin API arguments.
|
||||||
|
* @return object|WP_Error The result object or WP_Error.
|
||||||
|
*/
|
||||||
|
public function filter_plugin_details($result, $action, $args) {
|
||||||
|
// Only modify plugin_information requests
|
||||||
|
if ('plugin_information' !== $action) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we have a slug to work with
|
||||||
|
if (empty($args->slug)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get our list of invalid plugins
|
||||||
|
$invalid_plugins = $this->get_invalid_plugins();
|
||||||
|
|
||||||
|
// Check if this is our plugin or a missing plugin
|
||||||
|
$our_plugin = in_array($args->slug, array('wp-fix-plugin-does-not-exist-notices', 'fix-plugin-does-not-exist-notices'), true);
|
||||||
|
$is_missing_plugin = $this->is_missing_plugin($args->slug, $invalid_plugins);
|
||||||
|
|
||||||
|
// Only modify the result if this is our plugin or a missing plugin
|
||||||
|
if ($our_plugin || $is_missing_plugin) {
|
||||||
|
// Create a new result object
|
||||||
|
$new_result = new \stdClass();
|
||||||
|
|
||||||
|
// Set all the properties we need
|
||||||
|
$new_result->name = $our_plugin ? 'Fix \'Plugin file does not exist\' Notices' : (isset($result->name) ? $result->name : $args->slug);
|
||||||
|
$new_result->slug = $args->slug;
|
||||||
|
$new_result->version = FPDEN_VERSION;
|
||||||
|
$new_result->author = '<a href="https://www.wpallstars.com">Marcus Quinn & WPALLSTARS</a>';
|
||||||
|
$new_result->author_profile = 'https://www.wpallstars.com';
|
||||||
|
$new_result->requires = '5.0';
|
||||||
|
$new_result->tested = '6.7.2'; // Updated to match readme.txt
|
||||||
|
$new_result->requires_php = '7.0';
|
||||||
|
$new_result->last_updated = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
// Add a cache buster timestamp
|
||||||
|
$new_result->cache_buster = time();
|
||||||
|
|
||||||
|
// Get full readme content for our plugin
|
||||||
|
$readme_file = FPDEN_PLUGIN_DIR . 'readme.txt';
|
||||||
|
$readme_content = '';
|
||||||
|
$description = '';
|
||||||
|
$changelog = '';
|
||||||
|
$faq = '';
|
||||||
|
$installation = '';
|
||||||
|
$screenshots = '';
|
||||||
|
|
||||||
|
if (file_exists($readme_file) && $our_plugin) {
|
||||||
|
$readme_content = file_get_contents($readme_file);
|
||||||
|
|
||||||
|
// Extract description
|
||||||
|
if (preg_match('/== Description ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
||||||
|
$description = trim($matches[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract changelog
|
||||||
|
if (preg_match('/== Changelog ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
||||||
|
$changelog = trim($matches[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract FAQ
|
||||||
|
if (preg_match('/== Frequently Asked Questions ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
||||||
|
$faq = trim($matches[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract installation
|
||||||
|
if (preg_match('/== Installation ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
||||||
|
$installation = trim($matches[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract screenshots
|
||||||
|
if (preg_match('/== Screenshots ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
||||||
|
$screenshots = trim($matches[1]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback content if readme.txt doesn't exist or for missing plugins
|
||||||
|
$changelog = '<h2>' . FPDEN_VERSION . '</h2><ul><li>Fixed: Plugin details popup version display issue with Git Updater integration</li><li>Added: JavaScript-based solution to ensure correct version display in plugin details</li><li>Improved: Version consistency across all plugin views</li><li>Enhanced: Cache busting for plugin information API</li></ul>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set description based on whether this is our plugin or a missing plugin
|
||||||
|
if ($our_plugin) {
|
||||||
|
$description = !empty($description) ? wpautop($description) : 'Adds missing plugins to your plugins list with a "Remove Notice" action link, allowing you to safely clean up invalid plugin references.';
|
||||||
|
} else {
|
||||||
|
$description = sprintf(
|
||||||
|
__('This plugin is still marked as "Active" in your database — but its folder and files can\'t be found in %s. Use the "Remove Notice" link on the plugins page to permanently remove it from your active plugins list and eliminate the error notice.', 'wp-fix-plugin-does-not-exist-notices'),
|
||||||
|
'<code>/wp-content/plugins/</code>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare sections
|
||||||
|
$new_result->sections = array(
|
||||||
|
'description' => $description,
|
||||||
|
'changelog' => !empty($changelog) ? wpautop($changelog) : $changelog,
|
||||||
|
'faq' => !empty($faq) ? wpautop($faq) : '<h3>Is it safe to remove plugin references?</h3><p>Yes, this plugin only removes entries from the WordPress active_plugins option, which is safe to modify when a plugin no longer exists.</p>',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add installation section if available
|
||||||
|
if (!empty($installation)) {
|
||||||
|
$new_result->sections['installation'] = wpautop($installation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add screenshots section if available
|
||||||
|
if (!empty($screenshots)) {
|
||||||
|
$new_result->sections['screenshots'] = wpautop($screenshots);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add contributors information
|
||||||
|
$new_result->contributors = array(
|
||||||
|
'marcusquinn' => array(
|
||||||
|
'profile' => 'https://profiles.wordpress.org/marcusquinn/',
|
||||||
|
'avatar' => 'https://secure.gravatar.com/avatar/',
|
||||||
|
'display_name' => 'Marcus Quinn'
|
||||||
|
),
|
||||||
|
'wpallstars' => array(
|
||||||
|
'profile' => 'https://profiles.wordpress.org/wpallstars/',
|
||||||
|
'avatar' => 'https://secure.gravatar.com/avatar/',
|
||||||
|
'display_name' => 'WPALLSTARS'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add a random number and timestamp to force cache refresh
|
||||||
|
$new_result->download_link = 'https://www.wpallstars.com/plugins/wp-fix-plugin-does-not-exist-notices.zip?v=' . FPDEN_VERSION . '&cb=' . mt_rand(1000000, 9999999) . '&t=' . time();
|
||||||
|
|
||||||
|
// Add active installations count
|
||||||
|
$new_result->active_installs = 1000;
|
||||||
|
|
||||||
|
// Add rating information
|
||||||
|
$new_result->rating = 100;
|
||||||
|
$new_result->num_ratings = 5;
|
||||||
|
$new_result->ratings = array(
|
||||||
|
5 => 5,
|
||||||
|
4 => 0,
|
||||||
|
3 => 0,
|
||||||
|
2 => 0,
|
||||||
|
1 => 0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add homepage and download link
|
||||||
|
$new_result->homepage = 'https://www.wpallstars.com';
|
||||||
|
|
||||||
|
// Set no caching
|
||||||
|
$new_result->cache_time = 0;
|
||||||
|
|
||||||
|
// Return our completely new result object
|
||||||
|
return $new_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a slug matches one of our missing plugins.
|
||||||
|
*
|
||||||
|
* @param string $slug The plugin slug to check.
|
||||||
|
* @param array $invalid_plugins List of invalid plugin paths.
|
||||||
|
* @return bool True if the slug matches a missing plugin.
|
||||||
|
*/
|
||||||
|
private function is_missing_plugin($slug, $invalid_plugins) {
|
||||||
|
foreach ($invalid_plugins as $plugin_file) {
|
||||||
|
// Extract the plugin slug from the plugin file path
|
||||||
|
$plugin_slug = dirname($plugin_file);
|
||||||
|
if ('.' === $plugin_slug) {
|
||||||
|
$plugin_slug = basename($plugin_file, '.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($slug === $plugin_slug) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent WordPress from caching our plugin API responses.
|
||||||
|
*
|
||||||
|
* @param object|WP_Error $result The result object or WP_Error.
|
||||||
|
* @param string $action The type of information being requested.
|
||||||
|
* @param object $args Plugin API arguments.
|
||||||
|
* @return object|WP_Error The result object or WP_Error.
|
||||||
|
*/
|
||||||
|
public function prevent_plugins_api_caching($result, $action, $args) {
|
||||||
|
// Only modify plugin_information requests
|
||||||
|
if ('plugin_information' !== $action) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we have a slug to work with
|
||||||
|
if (empty($args->slug)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get our list of invalid plugins
|
||||||
|
$invalid_plugins = $this->get_invalid_plugins();
|
||||||
|
|
||||||
|
// Check if the requested plugin is one of our missing plugins
|
||||||
|
foreach ($invalid_plugins as $plugin_file) {
|
||||||
|
// Extract the plugin slug from the plugin file path
|
||||||
|
$plugin_slug = dirname($plugin_file);
|
||||||
|
if ('.' === $plugin_slug) {
|
||||||
|
$plugin_slug = basename($plugin_file, '.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is one of our missing plugins, prevent caching
|
||||||
|
if ($args->slug === $plugin_slug) {
|
||||||
|
// Add a filter to prevent caching of this response
|
||||||
|
add_filter('plugins_api_result_' . $args->slug, '__return_false');
|
||||||
|
|
||||||
|
// Add a timestamp to force cache busting
|
||||||
|
if (is_object($result)) {
|
||||||
|
$result->last_updated = current_time('mysql');
|
||||||
|
$result->cache_time = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear plugin API cache when viewing the plugins page.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function maybe_clear_plugin_api_cache() {
|
||||||
|
// Only run on the plugins page
|
||||||
|
if (!$this->is_plugins_page()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get our list of invalid plugins
|
||||||
|
$invalid_plugins = $this->get_invalid_plugins();
|
||||||
|
|
||||||
|
// Clear transients for each invalid plugin
|
||||||
|
foreach ($invalid_plugins as $plugin_file) {
|
||||||
|
// Extract the plugin slug from the plugin file path
|
||||||
|
$plugin_slug = dirname($plugin_file);
|
||||||
|
if ('.' === $plugin_slug) {
|
||||||
|
$plugin_slug = basename($plugin_file, '.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete all possible transients for this plugin
|
||||||
|
delete_transient('plugins_api_' . $plugin_slug);
|
||||||
|
delete_site_transient('plugins_api_' . $plugin_slug);
|
||||||
|
delete_transient('plugin_information_' . $plugin_slug);
|
||||||
|
delete_site_transient('plugin_information_' . $plugin_slug);
|
||||||
|
|
||||||
|
// Clear any other transients that might be caching plugin info
|
||||||
|
$this->clear_all_plugin_transients();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also clear our own plugin's cache
|
||||||
|
$this->clear_own_plugin_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all plugin-related transients that might be caching information.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function clear_all_plugin_transients() {
|
||||||
|
// Clear update cache
|
||||||
|
delete_site_transient('update_plugins');
|
||||||
|
delete_site_transient('update_themes');
|
||||||
|
delete_site_transient('update_core');
|
||||||
|
|
||||||
|
// Clear plugins API cache
|
||||||
|
delete_site_transient('plugin_information');
|
||||||
|
|
||||||
|
// Clear plugin update counts
|
||||||
|
delete_transient('plugin_updates_count');
|
||||||
|
delete_site_transient('plugin_updates_count');
|
||||||
|
|
||||||
|
// Clear plugin slugs cache
|
||||||
|
delete_transient('plugin_slugs');
|
||||||
|
delete_site_transient('plugin_slugs');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear cache specifically for our own plugin.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function clear_own_plugin_cache() {
|
||||||
|
// Clear our own plugin's cache (both old and new slugs)
|
||||||
|
$our_slugs = array('wp-fix-plugin-does-not-exist-notices', 'fix-plugin-does-not-exist-notices');
|
||||||
|
|
||||||
|
foreach ($our_slugs as $slug) {
|
||||||
|
delete_transient('plugins_api_' . $slug);
|
||||||
|
delete_site_transient('plugins_api_' . $slug);
|
||||||
|
delete_transient('plugin_information_' . $slug);
|
||||||
|
delete_site_transient('plugin_information_' . $slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear plugin update transients
|
||||||
|
delete_site_transient('update_plugins');
|
||||||
|
delete_site_transient('plugin_information');
|
||||||
|
|
||||||
|
// Force refresh of plugin update information if function exists
|
||||||
|
if (function_exists('wp_clean_plugins_cache')) {
|
||||||
|
wp_clean_plugins_cache(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear object cache if function exists
|
||||||
|
if (function_exists('wp_cache_flush')) {
|
||||||
|
wp_cache_flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
167
includes/Modal.php
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Modal Functionality
|
||||||
|
*
|
||||||
|
* @package WPALLSTARS\FixPluginDoesNotExistNotices
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPALLSTARS\FixPluginDoesNotExistNotices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modal Class
|
||||||
|
*
|
||||||
|
* Handles the update source selector modal.
|
||||||
|
*/
|
||||||
|
class Modal {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
// Add filter for plugin action links to add our update source selector
|
||||||
|
add_filter('plugin_action_links_' . plugin_basename(FPDEN_PLUGIN_DIR . 'wp-fix-plugin-does-not-exist-notices.php'), array($this, 'add_update_source_link'));
|
||||||
|
|
||||||
|
// Add AJAX handler for saving update source
|
||||||
|
add_action('wp_ajax_fpden_save_update_source', array($this, 'save_update_source'));
|
||||||
|
|
||||||
|
// Add the update source modal to admin footer
|
||||||
|
add_action('admin_footer', array($this, 'add_update_source_modal'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the "Update Source" link to plugin action links
|
||||||
|
*
|
||||||
|
* @param array $links Array of plugin action links
|
||||||
|
* @return array Modified array of plugin action links
|
||||||
|
*/
|
||||||
|
public function add_update_source_link($links) {
|
||||||
|
if (!current_user_can('manage_options')) {
|
||||||
|
return $links;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current update source
|
||||||
|
$current_source = get_option('fpden_update_source', 'auto');
|
||||||
|
|
||||||
|
// Add a badge to show the current source
|
||||||
|
$badge_class = 'fpden-source-badge ' . $current_source;
|
||||||
|
$badge_text = ucfirst($current_source);
|
||||||
|
if ($current_source === 'auto') {
|
||||||
|
$badge_text = 'Auto';
|
||||||
|
} elseif ($current_source === 'wordpress.org') {
|
||||||
|
$badge_text = 'WP.org';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the link with the badge
|
||||||
|
$update_source_link = '<a href="#" class="fpden-update-source-toggle">Update Source <span class="' . $badge_class . '">' . $badge_text . '</span></a>';
|
||||||
|
$links[] = $update_source_link;
|
||||||
|
|
||||||
|
return $links;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the update source modal to the admin footer
|
||||||
|
*/
|
||||||
|
public function add_update_source_modal() {
|
||||||
|
if (!is_admin() || !current_user_can('manage_options')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only show on plugins page
|
||||||
|
$screen = get_current_screen();
|
||||||
|
if (!$screen || $screen->id !== 'plugins') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current source
|
||||||
|
$current_source = get_option('fpden_update_source', 'auto');
|
||||||
|
|
||||||
|
// Enqueue the CSS and JS
|
||||||
|
wp_enqueue_style(
|
||||||
|
'fpden-update-source-selector',
|
||||||
|
FPDEN_PLUGIN_URL . 'admin/css/update-source-selector.css',
|
||||||
|
array(),
|
||||||
|
FPDEN_VERSION
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_enqueue_script(
|
||||||
|
'fpden-update-source-selector',
|
||||||
|
FPDEN_PLUGIN_URL . 'admin/js/update-source-selector.js',
|
||||||
|
array('jquery'),
|
||||||
|
FPDEN_VERSION,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add nonce to the existing fpdenData object or create it if it doesn't exist
|
||||||
|
$nonce = wp_create_nonce('fpden_update_source');
|
||||||
|
wp_localize_script(
|
||||||
|
'fpden-update-source-selector',
|
||||||
|
'fpdenData',
|
||||||
|
array(
|
||||||
|
'updateSourceNonce' => $nonce,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Modal HTML
|
||||||
|
?>
|
||||||
|
<div id="fpden-update-source-modal">
|
||||||
|
<a href="#" class="fpden-close-modal" aria-label="Close modal">×</a>
|
||||||
|
<h2>Choose Update Source</h2>
|
||||||
|
<p>Select where you want to receive plugin updates from:</p>
|
||||||
|
|
||||||
|
<form id="fpden-update-source-form">
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="update_source" value="wordpress.org" <?php checked($current_source, 'wordpress.org'); ?>>
|
||||||
|
<a href="https://wordpress.org/plugins/wp-fix-plugin-does-not-exist-notices/" target="_blank" rel="noopener noreferrer">WordPress.org</a>
|
||||||
|
<span class="fpden-source-description">Updates from the official WordPress.org plugin repository. Has a version update delay, to allow for the WP.org policy review and approval process. Best for unmonitored auto-updates.</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="update_source" value="github" <?php checked($current_source, 'github'); ?>>
|
||||||
|
<a href="https://github.com/wpallstars/wp-fix-plugin-does-not-exist-notices" target="_blank" rel="noopener noreferrer">GitHub</a>
|
||||||
|
<span class="fpden-source-description">Update directly from the GitHub repo main branch for the latest stable release. Git Updater plugin must be installed & active. Best for monitored updates, where the latest features and fixes are required as soon as they are merged into the main branch.</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="update_source" value="gitea" <?php checked($current_source, 'gitea'); ?>>
|
||||||
|
<a href="https://gitea.wpallstars.com/wpallstars/wp-fix-plugin-does-not-exist-notices" target="_blank" rel="noopener noreferrer">Gitea</a>
|
||||||
|
<span class="fpden-source-description">Update directly from the Gitea repo main branch for the latest stable release. Git Updater plugin must be installed & active. Best for monitored updates, where the latest features and fixes are required as soon as they are merged into the main branch, and independence from big-tech.</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="fpden-submit-container">
|
||||||
|
<button type="submit" class="button button-primary">Save</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle AJAX request to save update source
|
||||||
|
*/
|
||||||
|
public function save_update_source() {
|
||||||
|
// Check nonce
|
||||||
|
check_ajax_referer('fpden_update_source', 'nonce');
|
||||||
|
|
||||||
|
// Check permissions
|
||||||
|
if (!current_user_can('manage_options')) {
|
||||||
|
wp_send_json_error('Permission denied');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and sanitize source
|
||||||
|
$source = isset($_POST['source']) ? sanitize_text_field($_POST['source']) : '';
|
||||||
|
|
||||||
|
// Validate source
|
||||||
|
$valid_sources = ['wordpress.org', 'github', 'gitea'];
|
||||||
|
if (!in_array($source, $valid_sources)) {
|
||||||
|
$source = ''; // Empty means use auto-detection
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save option
|
||||||
|
update_option('fpden_update_source', $source);
|
||||||
|
|
||||||
|
// Clear update cache
|
||||||
|
delete_site_transient('update_plugins');
|
||||||
|
|
||||||
|
wp_send_json_success();
|
||||||
|
}
|
||||||
|
}
|
293
includes/Plugin.php
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Main Plugin Class
|
||||||
|
*
|
||||||
|
* @package WPALLSTARS\FixPluginDoesNotExistNotices
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WPALLSTARS\FixPluginDoesNotExistNotices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main Plugin Class
|
||||||
|
*
|
||||||
|
* Initializes all components of the plugin.
|
||||||
|
*/
|
||||||
|
class Plugin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin version
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin file path
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $plugin_file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin directory path
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $plugin_dir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin directory URL
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $plugin_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core functionality instance
|
||||||
|
*
|
||||||
|
* @var Core
|
||||||
|
*/
|
||||||
|
private $core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin functionality instance
|
||||||
|
*
|
||||||
|
* @var Admin
|
||||||
|
*/
|
||||||
|
private $admin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updater instance
|
||||||
|
*
|
||||||
|
* @var Updater
|
||||||
|
*/
|
||||||
|
private $updater;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $plugin_file Main plugin file path.
|
||||||
|
* @param string $version Plugin version.
|
||||||
|
*/
|
||||||
|
public function __construct($plugin_file, $version) {
|
||||||
|
$this->plugin_file = $plugin_file;
|
||||||
|
$this->version = $version;
|
||||||
|
$this->plugin_dir = plugin_dir_path($plugin_file);
|
||||||
|
$this->plugin_url = plugin_dir_url($plugin_file);
|
||||||
|
|
||||||
|
$this->define_constants();
|
||||||
|
$this->load_dependencies();
|
||||||
|
$this->init_components();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define plugin constants
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function define_constants() {
|
||||||
|
if (!defined('FPDEN_VERSION')) {
|
||||||
|
define('FPDEN_VERSION', $this->version);
|
||||||
|
}
|
||||||
|
if (!defined('FPDEN_PLUGIN_DIR')) {
|
||||||
|
define('FPDEN_PLUGIN_DIR', $this->plugin_dir);
|
||||||
|
}
|
||||||
|
if (!defined('FPDEN_PLUGIN_URL')) {
|
||||||
|
define('FPDEN_PLUGIN_URL', $this->plugin_url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load dependencies
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function load_dependencies() {
|
||||||
|
// Load composer autoloader if it exists
|
||||||
|
$autoloader = $this->plugin_dir . 'vendor/autoload.php';
|
||||||
|
if (file_exists($autoloader)) {
|
||||||
|
require_once $autoloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load required files
|
||||||
|
require_once $this->plugin_dir . 'includes/Core.php';
|
||||||
|
require_once $this->plugin_dir . 'includes/Admin.php';
|
||||||
|
require_once $this->plugin_dir . 'includes/Modal.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize plugin components
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function init_components() {
|
||||||
|
// Initialize core functionality
|
||||||
|
$this->core = new Core();
|
||||||
|
|
||||||
|
// Initialize admin functionality
|
||||||
|
$this->admin = new Admin($this->core);
|
||||||
|
|
||||||
|
// Initialize Git Updater fixes
|
||||||
|
$this->init_git_updater_fixes();
|
||||||
|
|
||||||
|
// Initialize the updater if the class exists
|
||||||
|
if (class_exists('\WPALLSTARS\FixPluginDoesNotExistNotices\Updater')) {
|
||||||
|
$this->updater = new Updater($this->plugin_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the modal for update source selection
|
||||||
|
new Modal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize Git Updater fixes
|
||||||
|
*
|
||||||
|
* This function adds filters to fix Git Updater's handling of 'main' vs 'master' branches
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function init_git_updater_fixes() {
|
||||||
|
// Fix for Git Updater looking for 'master' branch instead of 'main'
|
||||||
|
add_filter('gu_get_repo_branch', array($this, 'override_branch'), 999, 3);
|
||||||
|
|
||||||
|
// Fix for Git Updater API URLs
|
||||||
|
add_filter('gu_get_repo_api', array($this, 'override_api_url'), 999, 3);
|
||||||
|
|
||||||
|
// Fix for Git Updater download URLs
|
||||||
|
add_filter('gu_download_link', array($this, 'override_download_link'), 999, 3);
|
||||||
|
|
||||||
|
// Fix for Git Updater repository metadata
|
||||||
|
add_filter('gu_get_repo_meta', array($this, 'override_repo_meta'), 999, 2);
|
||||||
|
|
||||||
|
// Fix for Git Updater API responses
|
||||||
|
add_filter('gu_api_repo_type_data', array($this, 'override_repo_type_data'), 999, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the branch name for our plugin
|
||||||
|
*
|
||||||
|
* @param string $branch The current branch name
|
||||||
|
* @param string $git The git service (github, gitlab, etc.)
|
||||||
|
* @param object|null $repo The repository object (optional)
|
||||||
|
* @return string The modified branch name
|
||||||
|
*/
|
||||||
|
public function override_branch($branch, $git, $repo = null) {
|
||||||
|
// If repo is null or not an object, just return the branch unchanged
|
||||||
|
if (!is_object($repo)) {
|
||||||
|
return $branch;
|
||||||
|
}
|
||||||
|
if (isset($repo->slug) &&
|
||||||
|
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
||||||
|
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
||||||
|
return 'main';
|
||||||
|
}
|
||||||
|
return $branch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the API URL for our plugin
|
||||||
|
*
|
||||||
|
* @param mixed $api_url The current API URL (can be string or object)
|
||||||
|
* @param string $git The git service (github, gitlab, etc.)
|
||||||
|
* @param object|null $repo The repository object (optional)
|
||||||
|
* @return mixed The modified API URL (same type as input)
|
||||||
|
*/
|
||||||
|
public function override_api_url($api_url, $git, $repo = null) {
|
||||||
|
// If repo is null or not an object, just return the URL unchanged
|
||||||
|
if (!is_object($repo)) {
|
||||||
|
return $api_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is our plugin
|
||||||
|
if (isset($repo->slug) &&
|
||||||
|
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
||||||
|
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
||||||
|
|
||||||
|
// Only apply str_replace if $api_url is a string
|
||||||
|
if (is_string($api_url)) {
|
||||||
|
return str_replace('/master/', '/main/', $api_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If $api_url is an object, just return it unchanged
|
||||||
|
// This handles the case where Git Updater passes a GitHub_API object
|
||||||
|
return $api_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return unchanged if not our plugin
|
||||||
|
return $api_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the download link for our plugin
|
||||||
|
*
|
||||||
|
* @param string $download_link The current download link
|
||||||
|
* @param string $git The git service (github, gitlab, etc.)
|
||||||
|
* @param object|null $repo The repository object (optional)
|
||||||
|
* @return string The modified download link
|
||||||
|
*/
|
||||||
|
public function override_download_link($download_link, $git, $repo = null) {
|
||||||
|
// If repo is null or not an object, just return the link unchanged
|
||||||
|
if (!is_object($repo)) {
|
||||||
|
return $download_link;
|
||||||
|
}
|
||||||
|
if (isset($repo->slug) &&
|
||||||
|
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
||||||
|
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
||||||
|
return str_replace('/master.zip', '/main.zip', $download_link);
|
||||||
|
}
|
||||||
|
return $download_link;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override repository metadata for our plugin
|
||||||
|
*
|
||||||
|
* @param array $repo_meta The repository metadata
|
||||||
|
* @param object $repo The repository object
|
||||||
|
* @return array The modified repository metadata
|
||||||
|
*/
|
||||||
|
public function override_repo_meta($repo_meta, $repo) {
|
||||||
|
if (isset($repo->slug) &&
|
||||||
|
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
||||||
|
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
||||||
|
|
||||||
|
// Set the correct repository information
|
||||||
|
$repo_meta['github_updater_repo'] = 'wp-fix-plugin-does-not-exist-notices';
|
||||||
|
$repo_meta['github_updater_branch'] = 'main';
|
||||||
|
$repo_meta['github_updater_api'] = 'https://api.github.com';
|
||||||
|
$repo_meta['github_updater_raw'] = 'https://raw.githubusercontent.com/wpallstars/wp-fix-plugin-does-not-exist-notices/main';
|
||||||
|
}
|
||||||
|
return $repo_meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override repository type data for our plugin
|
||||||
|
*
|
||||||
|
* @param array $data The repository data
|
||||||
|
* @param object $response The API response
|
||||||
|
* @param object|null $repo The repository object (optional)
|
||||||
|
* @return array The modified repository data
|
||||||
|
*/
|
||||||
|
public function override_repo_type_data($data, $response, $repo = null) {
|
||||||
|
// If repo is null or not an object, just return the data unchanged
|
||||||
|
if (!is_object($repo)) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is our plugin
|
||||||
|
if (isset($repo->slug) &&
|
||||||
|
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
||||||
|
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
||||||
|
|
||||||
|
// Set the correct branch
|
||||||
|
if (isset($data['branch'])) {
|
||||||
|
$data['branch'] = 'main';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the correct version
|
||||||
|
if (isset($data['version'])) {
|
||||||
|
$data['version'] = FPDEN_VERSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
@ -61,8 +61,16 @@ class Updater {
|
|||||||
* @return string Installation source: 'github', 'gitea', or 'wordpress.org'
|
* @return string Installation source: 'github', 'gitea', or 'wordpress.org'
|
||||||
*/
|
*/
|
||||||
private function determine_installation_source() {
|
private function determine_installation_source() {
|
||||||
// Default to WordPress.org
|
// Check for user preference first
|
||||||
$source = 'wordpress.org';
|
$user_preference = \get_option('fpden_update_source', '');
|
||||||
|
|
||||||
|
// If user has set a preference, use it
|
||||||
|
if (!empty($user_preference)) {
|
||||||
|
return $user_preference;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, auto-detect the installation source
|
||||||
|
$source = 'wordpress.org'; // Default to WordPress.org if unidentifiable
|
||||||
|
|
||||||
// Check if the plugin was installed from GitHub
|
// Check if the plugin was installed from GitHub
|
||||||
if ($this->is_github_installation()) {
|
if ($this->is_github_installation()) {
|
||||||
@ -152,6 +160,38 @@ class Updater {
|
|||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add filter to trigger Git Updater cache refresh when a version update is detected
|
||||||
|
\add_filter('site_transient_update_plugins', function($transient) {
|
||||||
|
// Check if our plugin has an update
|
||||||
|
$plugin_basename = \plugin_basename($this->plugin_file);
|
||||||
|
if (isset($transient->response) && isset($transient->response[$plugin_basename])) {
|
||||||
|
// Check if Git Updater is active by looking for its functions
|
||||||
|
if (function_exists('\\Fragen\\Git_Updater\\flush_git_updater_cache') ||
|
||||||
|
class_exists('\\Fragen\\Git_Updater\\API\\API')) {
|
||||||
|
|
||||||
|
// Try to call the flush cache function if it exists
|
||||||
|
if (function_exists('\\Fragen\\Git_Updater\\flush_git_updater_cache')) {
|
||||||
|
\Fragen\Git_Updater\flush_git_updater_cache();
|
||||||
|
} elseif (class_exists('\\Fragen\\Git_Updater\\API\\API')) {
|
||||||
|
// Try to use the API class if available
|
||||||
|
try {
|
||||||
|
$api = new \Fragen\Git_Updater\API\API();
|
||||||
|
if (method_exists($api, 'flush_cache_site_transient')) {
|
||||||
|
$api->flush_cache_site_transient();
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Silently fail if API class can't be instantiated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also delete the update plugins transient to force a refresh
|
||||||
|
\delete_site_transient('update_plugins');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $transient;
|
||||||
|
});
|
||||||
|
|
||||||
// Initialize Git Updater Lite
|
// Initialize Git Updater Lite
|
||||||
if (class_exists('\\Fragen\\Git_Updater\\Lite')) {
|
if (class_exists('\\Fragen\\Git_Updater\\Lite')) {
|
||||||
(new \Fragen\Git_Updater\Lite($this->plugin_file))->run();
|
(new \Fragen\Git_Updater\Lite($this->plugin_file))->run();
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
# This file is distributed under the GPL-2.0+.
|
# This file is distributed under the GPL-2.0+.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Fix 'Plugin file does not exist' Notices 2.1.0\n"
|
"Project-Id-Version: Fix 'Plugin file does not exist' Notices 2.1.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-fix-plugin-does-not-exist-notices\n"
|
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-fix-plugin-does-not-exist-notices\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"POT-Creation-Date: 2024-05-20T00:00:00+00:00\n"
|
"POT-Creation-Date: 2025-04-13T00:00:00+00:00\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"X-Generator: WP-CLI 2.9.0\n"
|
"X-Generator: WP-CLI 2.9.0\n"
|
||||||
"X-Domain: wp-fix-plugin-does-not-exist-notices\n"
|
"X-Domain: wp-fix-plugin-does-not-exist-notices\n"
|
||||||
|
56
readme.txt
@ -5,11 +5,11 @@ Tags: plugins, missing plugins, cleanup, error fix, admin tools, plugin file doe
|
|||||||
Requires at least: 5.0
|
Requires at least: 5.0
|
||||||
Tested up to: 6.7.2
|
Tested up to: 6.7.2
|
||||||
Requires PHP: 7.0
|
Requires PHP: 7.0
|
||||||
Stable tag: 2.1.0
|
Stable tag: 2.2.0
|
||||||
License: GPL-2.0+
|
License: GPL-2.0+
|
||||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
|
||||||
Easily remove references to deleted plugins that cause "Plugin file does not exist" errors in your WordPress admin. By Marcus Quinn (marcusquinn.com) & WP ALLSTARS (wpallstars.com).
|
Easily remove references to deleted plugins that cause "Plugin file does not exist" errors in your WordPress admin. By Marcus Quinn (marcusquinn.com) & WPALLSTARS (wpallstars.com).
|
||||||
|
|
||||||
== Description ==
|
== Description ==
|
||||||
|
|
||||||
@ -93,6 +93,36 @@ If you've installed this plugin from GitHub or Gitea, you'll need Git Updater to
|
|||||||
3. Click the "Refresh Cache" button to ensure Git Updater recognizes the latest version
|
3. Click the "Refresh Cache" button to ensure Git Updater recognizes the latest version
|
||||||
4. Updates will now appear in your WordPress dashboard when available
|
4. Updates will now appear in your WordPress dashboard when available
|
||||||
|
|
||||||
|
= Choosing Your Update Source =
|
||||||
|
|
||||||
|
This plugin allows you to choose where you want to receive updates from:
|
||||||
|
|
||||||
|
1. In the Plugins list, find "Fix 'Plugin file does not exist' Notices"
|
||||||
|
2. Click the "Update Source" link next to the plugin
|
||||||
|
3. Select your preferred update source:
|
||||||
|
* **WordPress.org**: Updates from the official WordPress.org repository (has a version update delay due to the WP.org policy review and approval process, best for unmonitored auto-updates)
|
||||||
|
* **GitHub**: Updates directly from the GitHub repo main branch for the latest stable release (requires Git Updater plugin, best for monitored updates where the latest features and fixes are needed immediately)
|
||||||
|
* **Gitea**: Updates directly from the Gitea repo main branch for the latest stable release (requires Git Updater plugin, best for monitored updates and independence from big-tech)
|
||||||
|
4. Click "Save" to apply your preference
|
||||||
|
|
||||||
|
If no preference is set, the plugin will automatically use the source it was installed from.
|
||||||
|
|
||||||
|
**Note:** GitHub and Gitea options require the Git Updater plugin to be installed and activated.
|
||||||
|
|
||||||
|
== Contributing ==
|
||||||
|
|
||||||
|
Contributions are welcome! Please follow these steps to set up a development environment:
|
||||||
|
|
||||||
|
1. Install [LocalWP](https://localwp.com/) and create a clean site called "Plugin Testing" using the "Preferred" setup option
|
||||||
|
2. Run "Site shell" once from the LocalWP page on the site's settings to ensure wp-cli is enabled
|
||||||
|
3. Run "Add Run Configurations to VS Code" to update site configuration files in: ~/Local/plugin-testing/conf/
|
||||||
|
4. Clone this repository to your local machine
|
||||||
|
5. Use the build.sh and deploy-local.sh scripts to build and deploy the plugin for testing
|
||||||
|
|
||||||
|
[AugmentCode.com](https://augmentcode.com/) is recommended as a good all-in-one AI IDE for plugin development and testing.
|
||||||
|
|
||||||
|
Please feel free to submit a Pull Request with your improvements.
|
||||||
|
|
||||||
== Frequently Asked Questions ==
|
== Frequently Asked Questions ==
|
||||||
|
|
||||||
= Is it safe to remove plugin references? =
|
= Is it safe to remove plugin references? =
|
||||||
@ -149,6 +179,25 @@ Manually editing the WordPress database is risky and requires technical knowledg
|
|||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 2.2.0 =
|
||||||
|
* Added: Completely refactored plugin to use OOP best practices
|
||||||
|
* Added: New class structure with proper namespaces
|
||||||
|
* Added: Improved code organization and maintainability
|
||||||
|
* Added: Better separation of concerns with dedicated classes
|
||||||
|
* Changed: "Choose Update Source" link to just "Update Source"
|
||||||
|
* Fixed: Close button in the update source modal
|
||||||
|
* Added: Links to the main page for each update source in the modal
|
||||||
|
* Changed: Replaced all instances of "WP ALLSTARS" with "WPALLSTARS"
|
||||||
|
|
||||||
|
= 2.1.1 =
|
||||||
|
* Added: New "Choose Update Source" feature allowing users to select their preferred update source (WordPress.org, GitHub, or Gitea)
|
||||||
|
* Added: Modal dialog with detailed information about each update source option
|
||||||
|
* Added: Visual indicator showing the currently selected update source
|
||||||
|
* Fixed: Updated heading styles in CHANGELOG.md for better readability
|
||||||
|
* Fixed: Corrected dates in changelog to use 2025 instead of 2024
|
||||||
|
* Improved: Documentation improvements for better clarity
|
||||||
|
* Improved: Enhanced Git Updater integration with user-selectable update sources
|
||||||
|
|
||||||
= 2.1.0 =
|
= 2.1.0 =
|
||||||
* Minor version bump for Git Updater compatibility
|
* Minor version bump for Git Updater compatibility
|
||||||
* Improved error handling for Git Updater integration
|
* Improved error handling for Git Updater integration
|
||||||
@ -476,6 +525,9 @@ Manually editing the WordPress database is risky and requires technical knowledg
|
|||||||
|
|
||||||
== Upgrade Notice ==
|
== Upgrade Notice ==
|
||||||
|
|
||||||
|
= 2.1.1 =
|
||||||
|
Added new "Choose Update Source" feature allowing you to select where to receive plugin updates from (WordPress.org, GitHub, or Gitea).
|
||||||
|
|
||||||
= 2.1.0 =
|
= 2.1.0 =
|
||||||
Minor version bump with improved Git Updater compatibility and error handling.
|
Minor version bump with improved Git Updater compatibility and error handling.
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
* Plugin Name: Fix 'Plugin file does not exist' Notices
|
* Plugin Name: Fix 'Plugin file does not exist' Notices
|
||||||
* Plugin URI: https://www.wpallstars.com
|
* Plugin URI: https://www.wpallstars.com
|
||||||
* Description: Adds missing plugins to your plugins list with a "Remove Notice" action link, allowing you to safely clean up invalid plugin references.
|
* Description: Adds missing plugins to your plugins list with a "Remove Notice" action link, allowing you to safely clean up invalid plugin references.
|
||||||
* Version: 2.1.0
|
* Version: 2.2.0
|
||||||
* Author: Marcus Quinn & WP ALLSTARS
|
* Author: Marcus Quinn & The WPALLSTARS Team
|
||||||
* Author URI: https://www.wpallstars.com
|
* Author URI: https://www.wpallstars.com
|
||||||
* License: GPL-2.0+
|
* License: GPL-2.0+
|
||||||
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
||||||
@ -17,897 +17,16 @@
|
|||||||
* Release Asset: true
|
* Release Asset: true
|
||||||
* Update URI: https://github.com/wpallstars/wp-fix-plugin-does-not-exist-notices
|
* Update URI: https://github.com/wpallstars/wp-fix-plugin-does-not-exist-notices
|
||||||
*
|
*
|
||||||
* @package Fix_Plugin_Does_Not_Exist_Notices
|
* @package WPALLSTARS\FixPluginDoesNotExistNotices
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// If this file is called directly, abort.
|
// If this file is called directly, abort.
|
||||||
if ( ! defined( 'WPINC' ) ) {
|
if (!defined('WPINC')) {
|
||||||
die;
|
die;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define plugin constants.
|
// Load the main plugin class
|
||||||
define( 'FPDEN_VERSION', '2.1.0' );
|
require_once plugin_dir_path(__FILE__) . 'includes/Plugin.php';
|
||||||
define( 'FPDEN_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
|
||||||
define( 'FPDEN_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
|
||||||
|
|
||||||
// Direct fix for Git Updater branch issue - added to main file to avoid loading issues
|
// Initialize the plugin
|
||||||
add_action('plugins_loaded', 'fpden_init_git_updater_fixes');
|
new WPALLSTARS\FixPluginDoesNotExistNotices\Plugin(__FILE__, '2.2.0');
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize Git Updater fixes
|
|
||||||
*
|
|
||||||
* This function adds filters to fix Git Updater's handling of 'main' vs 'master' branches
|
|
||||||
* It uses named functions instead of anonymous functions for better compatibility
|
|
||||||
*/
|
|
||||||
function fpden_init_git_updater_fixes() {
|
|
||||||
// Fix for Git Updater looking for 'master' branch instead of 'main'
|
|
||||||
add_filter('gu_get_repo_branch', 'fpden_override_branch', 999, 3);
|
|
||||||
|
|
||||||
// Fix for Git Updater API URLs
|
|
||||||
add_filter('gu_get_repo_api', 'fpden_override_api_url', 999, 3);
|
|
||||||
|
|
||||||
// Fix for Git Updater download URLs
|
|
||||||
add_filter('gu_download_link', 'fpden_override_download_link', 999, 3);
|
|
||||||
|
|
||||||
// Fix for Git Updater repository metadata
|
|
||||||
add_filter('gu_get_repo_meta', 'fpden_override_repo_meta', 999, 2);
|
|
||||||
|
|
||||||
// Fix for Git Updater API responses
|
|
||||||
add_filter('gu_api_repo_type_data', 'fpden_override_repo_type_data', 999, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override the branch name for our plugin
|
|
||||||
*
|
|
||||||
* @param string $branch The current branch name
|
|
||||||
* @param string $git The git service (github, gitlab, etc.)
|
|
||||||
* @param object|null $repo The repository object (optional)
|
|
||||||
* @return string The modified branch name
|
|
||||||
*/
|
|
||||||
function fpden_override_branch($branch, $git, $repo = null) {
|
|
||||||
// If repo is null or not an object, just return the branch unchanged
|
|
||||||
if (!is_object($repo)) {
|
|
||||||
return $branch;
|
|
||||||
}
|
|
||||||
if (isset($repo->slug) &&
|
|
||||||
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
|
||||||
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
|
||||||
return 'main';
|
|
||||||
}
|
|
||||||
return $branch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override the API URL for our plugin
|
|
||||||
*
|
|
||||||
* @param mixed $api_url The current API URL (can be string or object)
|
|
||||||
* @param string $git The git service (github, gitlab, etc.)
|
|
||||||
* @param object|null $repo The repository object (optional)
|
|
||||||
* @return mixed The modified API URL (same type as input)
|
|
||||||
*/
|
|
||||||
function fpden_override_api_url($api_url, $git, $repo = null) {
|
|
||||||
// If repo is null or not an object, just return the URL unchanged
|
|
||||||
if (!is_object($repo)) {
|
|
||||||
return $api_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this is our plugin
|
|
||||||
if (isset($repo->slug) &&
|
|
||||||
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
|
||||||
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
|
||||||
|
|
||||||
// Only apply str_replace if $api_url is a string
|
|
||||||
if (is_string($api_url)) {
|
|
||||||
return str_replace('/master/', '/main/', $api_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If $api_url is an object, just return it unchanged
|
|
||||||
// This handles the case where Git Updater passes a GitHub_API object
|
|
||||||
return $api_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return unchanged if not our plugin
|
|
||||||
return $api_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override the download link for our plugin
|
|
||||||
*
|
|
||||||
* @param string $download_link The current download link
|
|
||||||
* @param string $git The git service (github, gitlab, etc.)
|
|
||||||
* @param object|null $repo The repository object (optional)
|
|
||||||
* @return string The modified download link
|
|
||||||
*/
|
|
||||||
function fpden_override_download_link($download_link, $git, $repo = null) {
|
|
||||||
// If repo is null or not an object, just return the link unchanged
|
|
||||||
if (!is_object($repo)) {
|
|
||||||
return $download_link;
|
|
||||||
}
|
|
||||||
if (isset($repo->slug) &&
|
|
||||||
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
|
||||||
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
|
||||||
return str_replace('/master.zip', '/main.zip', $download_link);
|
|
||||||
}
|
|
||||||
return $download_link;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override repository metadata for our plugin
|
|
||||||
*/
|
|
||||||
function fpden_override_repo_meta($repo_meta, $repo) {
|
|
||||||
if (isset($repo->slug) &&
|
|
||||||
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
|
||||||
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
|
||||||
|
|
||||||
// Set the correct repository information
|
|
||||||
$repo_meta['github_updater_repo'] = 'wp-fix-plugin-does-not-exist-notices';
|
|
||||||
$repo_meta['github_updater_branch'] = 'main';
|
|
||||||
$repo_meta['github_updater_api'] = 'https://api.github.com';
|
|
||||||
$repo_meta['github_updater_raw'] = 'https://raw.githubusercontent.com/wpallstars/wp-fix-plugin-does-not-exist-notices/main';
|
|
||||||
}
|
|
||||||
return $repo_meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override repository type data for our plugin
|
|
||||||
*
|
|
||||||
* @param array $data The repository data
|
|
||||||
* @param object $response The API response
|
|
||||||
* @param object|null $repo The repository object (optional)
|
|
||||||
* @return array The modified repository data
|
|
||||||
*/
|
|
||||||
function fpden_override_repo_type_data($data, $response, $repo = null) {
|
|
||||||
// If repo is null or not an object, just return the data unchanged
|
|
||||||
if (!is_object($repo)) {
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this is our plugin
|
|
||||||
if (isset($repo->slug) &&
|
|
||||||
(strpos($repo->slug, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
|
||||||
strpos($repo->slug, 'fix-plugin-does-not-exist-notices') !== false)) {
|
|
||||||
|
|
||||||
// Set the correct branch
|
|
||||||
if (isset($data['branch'])) {
|
|
||||||
$data['branch'] = 'main';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the correct version
|
|
||||||
if (isset($data['version'])) {
|
|
||||||
$data['version'] = FPDEN_VERSION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main plugin class.
|
|
||||||
*
|
|
||||||
* Handles the core functionality of finding and fixing invalid plugin references.
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
class Fix_Plugin_Does_Not_Exist_Notices {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores a list of invalid plugins found in the active_plugins option.
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $invalid_plugins = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor. Hooks into WordPress actions and filters.
|
|
||||||
*/
|
|
||||||
public function __construct() {
|
|
||||||
// Add our plugin to the plugins list.
|
|
||||||
add_filter( 'all_plugins', array( $this, 'add_missing_plugins_references' ) );
|
|
||||||
|
|
||||||
// Add our action link to the plugins list.
|
|
||||||
add_filter( 'plugin_action_links', array( $this, 'add_remove_reference_action' ), 20, 4 );
|
|
||||||
|
|
||||||
// Handle the remove reference action.
|
|
||||||
add_action( 'admin_init', array( $this, 'handle_remove_reference' ) );
|
|
||||||
|
|
||||||
// Add admin notices for operation feedback.
|
|
||||||
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
|
||||||
|
|
||||||
// Enqueue admin scripts and styles.
|
|
||||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
|
|
||||||
|
|
||||||
// Filter the plugin API to fix version display in plugin details popup
|
|
||||||
add_filter( 'plugins_api', array( $this, 'filter_plugin_details' ), 10, 3 );
|
|
||||||
|
|
||||||
// Prevent WordPress from caching our plugin API responses
|
|
||||||
add_filter( 'plugins_api_result', array( $this, 'prevent_plugins_api_caching' ), 10, 3 );
|
|
||||||
|
|
||||||
// Clear plugin API transients on plugin activation and when viewing plugins page
|
|
||||||
add_action( 'admin_init', array( $this, 'maybe_clear_plugin_api_cache' ) );
|
|
||||||
|
|
||||||
// We're no longer trying to prevent WordPress from auto-deactivating plugins
|
|
||||||
// as it was causing critical errors in some environments
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enqueue scripts and styles needed for the admin area.
|
|
||||||
*
|
|
||||||
* @param string $hook_suffix The current admin page hook.
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function enqueue_admin_assets( $hook_suffix ) {
|
|
||||||
// Only load on the plugins page.
|
|
||||||
if ( 'plugins.php' !== $hook_suffix ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always load our version fix script on the plugins page
|
|
||||||
wp_enqueue_script(
|
|
||||||
'fpden-version-fix',
|
|
||||||
FPDEN_PLUGIN_URL . 'assets/js/version-fix.js',
|
|
||||||
array( 'jquery', 'thickbox' ),
|
|
||||||
FPDEN_VERSION,
|
|
||||||
true // Load in footer.
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get invalid plugins to decide if other assets are needed.
|
|
||||||
$invalid_plugins = $this->get_invalid_plugins();
|
|
||||||
if ( empty( $invalid_plugins ) ) {
|
|
||||||
return; // No missing plugins, no need for the special notice JS/CSS.
|
|
||||||
}
|
|
||||||
|
|
||||||
wp_enqueue_style(
|
|
||||||
'fpden-admin-styles',
|
|
||||||
FPDEN_PLUGIN_URL . 'assets/css/admin-styles.css',
|
|
||||||
array(),
|
|
||||||
FPDEN_VERSION
|
|
||||||
);
|
|
||||||
|
|
||||||
wp_enqueue_script(
|
|
||||||
'fpden-admin-scripts',
|
|
||||||
FPDEN_PLUGIN_URL . 'assets/js/admin-scripts.js',
|
|
||||||
array( 'jquery' ), // Add dependencies if needed, e.g., jQuery.
|
|
||||||
FPDEN_VERSION,
|
|
||||||
true // Load in footer.
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add translation strings for JavaScript
|
|
||||||
wp_localize_script(
|
|
||||||
'fpden-admin-scripts',
|
|
||||||
'fpdenData',
|
|
||||||
array(
|
|
||||||
'i18n' => array(
|
|
||||||
'clickToScroll' => esc_html__( 'Click here to scroll to missing plugins', 'wp-fix-plugin-does-not-exist-notices' ),
|
|
||||||
'pluginMissing' => esc_html__( 'File Missing', 'wp-fix-plugin-does-not-exist-notices' ),
|
|
||||||
'removeNotice' => esc_html__( 'Remove Notice', 'wp-fix-plugin-does-not-exist-notices' ),
|
|
||||||
),
|
|
||||||
'version' => FPDEN_VERSION, // Add version for the plugin details fix script
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find and add invalid plugin references to the plugins list.
|
|
||||||
*
|
|
||||||
* Filters the list of plugins displayed on the plugins page to include
|
|
||||||
* entries for active plugins whose files are missing.
|
|
||||||
*
|
|
||||||
* @param array $plugins An array of plugin data.
|
|
||||||
* @return array The potentially modified array of plugin data.
|
|
||||||
*/
|
|
||||||
public function add_missing_plugins_references( $plugins ) {
|
|
||||||
// Only run on the plugins page.
|
|
||||||
if ( ! $this->is_plugins_page() ) {
|
|
||||||
return $plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get active plugins that don't exist.
|
|
||||||
$invalid_plugins = $this->get_invalid_plugins();
|
|
||||||
|
|
||||||
// Add each invalid plugin to the plugin list.
|
|
||||||
foreach ( $invalid_plugins as $plugin_path ) {
|
|
||||||
if ( ! isset( $plugins[ $plugin_path ] ) ) {
|
|
||||||
$plugin_name = basename( $plugin_path );
|
|
||||||
$plugin_slug = dirname( $plugin_path );
|
|
||||||
if ( '.' === $plugin_slug ) {
|
|
||||||
$plugin_slug = basename( $plugin_path, '.php' );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a basic plugin data array
|
|
||||||
$plugins[ $plugin_path ] = array(
|
|
||||||
'Name' => $plugin_name . ' <span class="error">(File Missing)</span>',
|
|
||||||
/* translators: %s: Path to wp-content/plugins */
|
|
||||||
'Description' => sprintf(
|
|
||||||
__( 'This plugin is still marked as "Active" in your database — but its folder and files can\'t be found in %s. Click "Remove Notice" to permanently remove it from your active plugins list and eliminate the error notice.', 'wp-fix-plugin-does-not-exist-notices' ),
|
|
||||||
'<code>/wp-content/plugins/</code>'
|
|
||||||
),
|
|
||||||
'Version' => FPDEN_VERSION, // Use our plugin version instead of 'N/A'
|
|
||||||
'Author' => 'Marcus Quinn & WP ALLSTARS',
|
|
||||||
'PluginURI' => 'https://www.wpallstars.com',
|
|
||||||
'AuthorURI' => 'https://www.wpallstars.com',
|
|
||||||
'Title' => $plugin_name . ' (' . __( 'Missing', 'wp-fix-plugin-does-not-exist-notices' ) . ')',
|
|
||||||
'AuthorName' => 'Marcus Quinn & WP ALLSTARS',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add the data needed for the "View details" link
|
|
||||||
$plugins[ $plugin_path ]['slug'] = $plugin_slug;
|
|
||||||
$plugins[ $plugin_path ]['plugin'] = $plugin_path;
|
|
||||||
$plugins[ $plugin_path ]['type'] = 'plugin';
|
|
||||||
|
|
||||||
// Add Git Updater fields
|
|
||||||
$plugins[ $plugin_path ]['GitHub Plugin URI'] = 'wpallstars/wp-fix-plugin-does-not-exist-notices';
|
|
||||||
$plugins[ $plugin_path ]['GitHub Branch'] = 'main';
|
|
||||||
$plugins[ $plugin_path ]['TextDomain'] = 'wp-fix-plugin-does-not-exist-notices';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the Remove Notice action link to invalid plugins.
|
|
||||||
*
|
|
||||||
* Filters the action links displayed for each plugin on the plugins page.
|
|
||||||
* Adds a "Remove Notice" link for plugins identified as missing.
|
|
||||||
*
|
|
||||||
* @param array $actions An array of plugin action links.
|
|
||||||
* @param string $plugin_file Path to the plugin file relative to the plugins directory.
|
|
||||||
* @param array $plugin_data An array of plugin data.
|
|
||||||
* @param string $context The plugin context (e.g., 'all', 'active', 'inactive').
|
|
||||||
* @return array The potentially modified array of plugin action links.
|
|
||||||
* @noinspection PhpUnusedParameterInspection
|
|
||||||
*/
|
|
||||||
public function add_remove_reference_action( $actions, $plugin_file, $plugin_data, $context ) {
|
|
||||||
// Only run on the plugins page.
|
|
||||||
if ( ! $this->is_plugins_page() ) {
|
|
||||||
return $actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get our list of invalid plugins
|
|
||||||
$invalid_plugins = $this->get_invalid_plugins();
|
|
||||||
|
|
||||||
// Check if this plugin file is in our list of invalid plugins
|
|
||||||
if ( in_array( $plugin_file, $invalid_plugins, true ) ) {
|
|
||||||
// Clear existing actions like "Activate", "Deactivate", "Edit".
|
|
||||||
$actions = array();
|
|
||||||
|
|
||||||
// Add our custom action.
|
|
||||||
$nonce = wp_create_nonce( 'remove_plugin_reference_' . $plugin_file );
|
|
||||||
$remove_url = admin_url( 'plugins.php?action=remove_reference&plugin=' . urlencode( $plugin_file ) . '&_wpnonce=' . $nonce );
|
|
||||||
/* translators: %s: Plugin file path */
|
|
||||||
$aria_label = sprintf( __( 'Remove reference to missing plugin %s', 'wp-fix-plugin-does-not-exist-notices' ), esc_attr( $plugin_file ) );
|
|
||||||
$actions['remove_reference'] = '<a href="' . esc_url( $remove_url ) . '" class="delete" aria-label="' . $aria_label . '">' . esc_html__( 'Remove Notice', 'wp-fix-plugin-does-not-exist-notices' ) . '</a>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the remove reference action triggered by the link.
|
|
||||||
*
|
|
||||||
* Checks for the correct action, verifies nonce and permissions,
|
|
||||||
* calls the removal function, and redirects back to the plugins page.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function handle_remove_reference() {
|
|
||||||
// Check if our specific action is being performed.
|
|
||||||
if ( ! isset( $_GET['action'] ) || 'remove_reference' !== $_GET['action'] || ! isset( $_GET['plugin'] ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify user permissions.
|
|
||||||
if ( ! current_user_can( 'activate_plugins' ) ) {
|
|
||||||
wp_die( esc_html__( 'You do not have sufficient permissions to perform this action.', 'wp-fix-plugin-does-not-exist-notices' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanitize and get the plugin file path.
|
|
||||||
$plugin_file = isset( $_GET['plugin'] ) ? sanitize_text_field( wp_unslash( $_GET['plugin'] ) ) : '';
|
|
||||||
if ( empty( $plugin_file ) ) {
|
|
||||||
wp_die( esc_html__( 'Invalid plugin specified.', 'wp-fix-plugin-does-not-exist-notices' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify nonce for security.
|
|
||||||
check_admin_referer( 'remove_plugin_reference_' . $plugin_file );
|
|
||||||
|
|
||||||
// Attempt to remove the plugin reference.
|
|
||||||
$success = $this->remove_plugin_reference( $plugin_file );
|
|
||||||
|
|
||||||
// Prepare redirect URL with feedback query args.
|
|
||||||
$redirect_url = admin_url( 'plugins.php' );
|
|
||||||
$redirect_url = add_query_arg( $success ? 'reference_removed' : 'reference_removal_failed', '1', $redirect_url );
|
|
||||||
|
|
||||||
// Redirect and exit.
|
|
||||||
wp_safe_redirect( $redirect_url );
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a plugin reference from the active plugins list in the database.
|
|
||||||
*
|
|
||||||
* Handles both single site and multisite network activated plugins.
|
|
||||||
*
|
|
||||||
* @param string $plugin_file The plugin file path to remove.
|
|
||||||
* @return bool True on success, false on failure or if the plugin wasn't found.
|
|
||||||
*/
|
|
||||||
public function remove_plugin_reference( $plugin_file ) {
|
|
||||||
$success = false;
|
|
||||||
|
|
||||||
// Ensure plugin file path is provided.
|
|
||||||
if ( empty( $plugin_file ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle multisite network admin context.
|
|
||||||
if ( is_multisite() && is_network_admin() ) {
|
|
||||||
$active_plugins = get_site_option( 'active_sitewide_plugins', array() );
|
|
||||||
// Network active plugins are stored as key => timestamp.
|
|
||||||
if ( isset( $active_plugins[ $plugin_file ] ) ) {
|
|
||||||
unset( $active_plugins[ $plugin_file ] );
|
|
||||||
$success = update_site_option( 'active_sitewide_plugins', $active_plugins );
|
|
||||||
}
|
|
||||||
} else { // Handle single site or non-network admin context.
|
|
||||||
$active_plugins = get_option( 'active_plugins', array() );
|
|
||||||
// Single site active plugins are stored as an indexed array.
|
|
||||||
$key = array_search( $plugin_file, $active_plugins, true ); // Use strict comparison.
|
|
||||||
if ( false !== $key ) {
|
|
||||||
unset( $active_plugins[ $key ] );
|
|
||||||
// Re-index the array numerically.
|
|
||||||
$active_plugins = array_values( $active_plugins );
|
|
||||||
$success = update_option( 'active_plugins', $active_plugins );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $success;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display admin notices on the plugins page.
|
|
||||||
*
|
|
||||||
* Shows feedback messages after attempting to remove a reference.
|
|
||||||
* The main informational notice is handled by JavaScript to position it
|
|
||||||
* directly below the WordPress error message.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function admin_notices() {
|
|
||||||
// Only run on the plugins page.
|
|
||||||
if ( ! $this->is_plugins_page() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for feedback messages from the remove action.
|
|
||||||
if ( isset( $_GET['reference_removed'] ) && '1' === $_GET['reference_removed'] ) {
|
|
||||||
?>
|
|
||||||
<div class="notice notice-success is-dismissible">
|
|
||||||
<p><?php esc_html_e( 'Plugin reference removed successfully.', 'wp-fix-plugin-does-not-exist-notices' ); ?></p>
|
|
||||||
</div>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isset( $_GET['reference_removal_failed'] ) && '1' === $_GET['reference_removal_failed'] ) {
|
|
||||||
?>
|
|
||||||
<div class="notice notice-error is-dismissible">
|
|
||||||
<p><?php esc_html_e( 'Failed to remove plugin reference. The plugin may already have been removed, or there was a database issue.', 'wp-fix-plugin-does-not-exist-notices' ); ?></p>
|
|
||||||
</div>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
// The main informational notice is now handled entirely by JavaScript
|
|
||||||
// to position it directly below the WordPress error message.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the current admin page is the plugins page.
|
|
||||||
*
|
|
||||||
* @global string $pagenow WordPress global variable for the current admin page filename.
|
|
||||||
* @return bool True if the current page is plugins.php, false otherwise.
|
|
||||||
*/
|
|
||||||
private function is_plugins_page() {
|
|
||||||
global $pagenow;
|
|
||||||
// Check if it's an admin page and the filename is plugins.php.
|
|
||||||
return is_admin() && isset( $pagenow ) && 'plugins.php' === $pagenow;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of active plugin file paths that do not exist on the filesystem.
|
|
||||||
*
|
|
||||||
* Checks both single site and network active plugins based on the context.
|
|
||||||
* Uses caching to avoid repeated filesystem checks.
|
|
||||||
*
|
|
||||||
* @return array An array of plugin file paths (relative to WP_PLUGIN_DIR) that are missing.
|
|
||||||
*/
|
|
||||||
private function get_invalid_plugins() {
|
|
||||||
// Return cached result if available
|
|
||||||
if ( null !== $this->invalid_plugins ) {
|
|
||||||
return $this->invalid_plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->invalid_plugins = array();
|
|
||||||
$active_plugins = array();
|
|
||||||
|
|
||||||
// Determine which option to check based on context (Network Admin or single site).
|
|
||||||
if ( is_multisite() && is_network_admin() ) {
|
|
||||||
// Network active plugins are stored as keys in an associative array.
|
|
||||||
$active_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
|
|
||||||
} else {
|
|
||||||
// Single site active plugins are stored in a numerically indexed array.
|
|
||||||
$active_plugins = get_option( 'active_plugins', array() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the file exists for each active plugin.
|
|
||||||
foreach ( $active_plugins as $plugin_file ) {
|
|
||||||
// Construct the full path to the main plugin file.
|
|
||||||
$plugin_path = WP_PLUGIN_DIR . '/' . $plugin_file;
|
|
||||||
// Use validate_file to prevent directory traversal issues, although less likely here.
|
|
||||||
if ( validate_file( $plugin_file ) === 0 && ! file_exists( $plugin_path ) ) {
|
|
||||||
$this->invalid_plugins[] = $plugin_file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->invalid_plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We've removed the prevent_auto_deactivation method as it was causing critical errors
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter the plugin API response to fix version display in plugin details popup.
|
|
||||||
*
|
|
||||||
* @param false|object|array $result The result object or array. Default false.
|
|
||||||
* @param string $action The type of information being requested from the Plugin Installation API.
|
|
||||||
* @param object $args Plugin API arguments.
|
|
||||||
* @return false|object|array The potentially modified result.
|
|
||||||
*/
|
|
||||||
public function filter_plugin_details( $result, $action, $args ) {
|
|
||||||
// Only modify plugin_information requests
|
|
||||||
if ( 'plugin_information' !== $action ) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we have a slug to work with
|
|
||||||
if ( empty( $args->slug ) ) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the requested slug
|
|
||||||
|
|
||||||
// Check if this is our own plugin (either old or new slug)
|
|
||||||
$our_plugin = false;
|
|
||||||
if ($args->slug === 'wp-fix-plugin-does-not-exist-notices' || $args->slug === 'fix-plugin-does-not-exist-notices') {
|
|
||||||
$our_plugin = true;
|
|
||||||
// This is our own plugin, so we'll provide custom information
|
|
||||||
|
|
||||||
// Force clear any cached data for our plugin
|
|
||||||
$this->clear_own_plugin_cache();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get our list of invalid plugins
|
|
||||||
$invalid_plugins = $this->get_invalid_plugins();
|
|
||||||
|
|
||||||
// Check if the requested plugin is one of our missing plugins or our own plugin
|
|
||||||
if ($our_plugin || $this->is_missing_plugin($args->slug, $invalid_plugins)) {
|
|
||||||
// Always create a new result object to bypass any caching
|
|
||||||
$new_result = new stdClass();
|
|
||||||
|
|
||||||
// Set all the properties we need
|
|
||||||
$new_result->name = $our_plugin ? 'Fix \'Plugin file does not exist\' Notices' : (isset($result->name) ? $result->name : $args->slug);
|
|
||||||
$new_result->slug = $args->slug;
|
|
||||||
$new_result->version = FPDEN_VERSION;
|
|
||||||
$new_result->author = '<a href="https://www.wpallstars.com">Marcus Quinn & WP ALLSTARS</a>';
|
|
||||||
$new_result->author_profile = 'https://www.wpallstars.com';
|
|
||||||
$new_result->requires = '5.0';
|
|
||||||
$new_result->tested = '6.7.2'; // Updated to match readme.txt
|
|
||||||
$new_result->requires_php = '7.0';
|
|
||||||
$new_result->last_updated = date('Y-m-d H:i:s');
|
|
||||||
|
|
||||||
// Add a cache buster timestamp
|
|
||||||
$new_result->cache_buster = time();
|
|
||||||
|
|
||||||
// Get full readme content for our plugin
|
|
||||||
$readme_file = FPDEN_PLUGIN_DIR . 'readme.txt';
|
|
||||||
$readme_content = '';
|
|
||||||
$description = '';
|
|
||||||
$changelog = '';
|
|
||||||
$faq = '';
|
|
||||||
$installation = '';
|
|
||||||
$screenshots = '';
|
|
||||||
|
|
||||||
if (file_exists($readme_file) && $our_plugin) {
|
|
||||||
$readme_content = file_get_contents($readme_file);
|
|
||||||
|
|
||||||
// Extract description
|
|
||||||
if (preg_match('/== Description ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
|
||||||
$description = trim($matches[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract changelog
|
|
||||||
if (preg_match('/== Changelog ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
|
||||||
$changelog = trim($matches[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract FAQ
|
|
||||||
if (preg_match('/== Frequently Asked Questions ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
|
||||||
$faq = trim($matches[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract installation
|
|
||||||
if (preg_match('/== Installation ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
|
||||||
$installation = trim($matches[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract screenshots
|
|
||||||
if (preg_match('/== Screenshots ==(.+?)(?:==|$)/s', $readme_content, $matches)) {
|
|
||||||
$screenshots = trim($matches[1]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Fallback content if readme.txt doesn't exist or for missing plugins
|
|
||||||
$changelog = '<h2>' . FPDEN_VERSION . '</h2><ul><li>Fixed: Plugin details popup version display issue with Git Updater integration</li><li>Added: JavaScript-based solution to ensure correct version display in plugin details</li><li>Improved: Version consistency across all plugin views</li><li>Enhanced: Cache busting for plugin information API</li></ul>';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set description based on whether this is our plugin or a missing plugin
|
|
||||||
if ($our_plugin) {
|
|
||||||
$description = !empty($description) ? wpautop($description) : 'Adds missing plugins to your plugins list with a "Remove Notice" action link, allowing you to safely clean up invalid plugin references.';
|
|
||||||
} else {
|
|
||||||
$description = sprintf(
|
|
||||||
__( 'This plugin is still marked as "Active" in your database — but its folder and files can\'t be found in %s. Use the "Remove Notice" link on the plugins page to permanently remove it from your active plugins list and eliminate the error notice.', 'wp-fix-plugin-does-not-exist-notices' ),
|
|
||||||
'<code>/wp-content/plugins/</code>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare sections
|
|
||||||
$new_result->sections = array(
|
|
||||||
'description' => $description,
|
|
||||||
'changelog' => !empty($changelog) ? wpautop($changelog) : $changelog,
|
|
||||||
'faq' => !empty($faq) ? wpautop($faq) : '<h3>Is it safe to remove plugin references?</h3><p>Yes, this plugin only removes entries from the WordPress active_plugins option, which is safe to modify when a plugin no longer exists.</p>',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add installation section if available
|
|
||||||
if (!empty($installation)) {
|
|
||||||
$new_result->sections['installation'] = wpautop($installation);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add screenshots section if available
|
|
||||||
if (!empty($screenshots)) {
|
|
||||||
$new_result->sections['screenshots'] = wpautop($screenshots);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add contributors information
|
|
||||||
$new_result->contributors = array(
|
|
||||||
'marcusquinn' => array(
|
|
||||||
'profile' => 'https://profiles.wordpress.org/marcusquinn/',
|
|
||||||
'avatar' => 'https://secure.gravatar.com/avatar/',
|
|
||||||
'display_name' => 'Marcus Quinn'
|
|
||||||
),
|
|
||||||
'wpallstars' => array(
|
|
||||||
'profile' => 'https://profiles.wordpress.org/wpallstars/',
|
|
||||||
'avatar' => 'https://secure.gravatar.com/avatar/',
|
|
||||||
'display_name' => 'WP ALLSTARS'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add a random number and timestamp to force cache refresh
|
|
||||||
$new_result->download_link = 'https://www.wpallstars.com/plugins/wp-fix-plugin-does-not-exist-notices.zip?v=' . FPDEN_VERSION . '&cb=' . mt_rand(1000000, 9999999) . '&t=' . time();
|
|
||||||
|
|
||||||
// Add active installations count
|
|
||||||
$new_result->active_installs = 1000;
|
|
||||||
|
|
||||||
// Add rating information
|
|
||||||
$new_result->rating = 100;
|
|
||||||
$new_result->num_ratings = 5;
|
|
||||||
$new_result->ratings = array(
|
|
||||||
5 => 5,
|
|
||||||
4 => 0,
|
|
||||||
3 => 0,
|
|
||||||
2 => 0,
|
|
||||||
1 => 0
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add homepage and download link
|
|
||||||
$new_result->homepage = 'https://www.wpallstars.com';
|
|
||||||
|
|
||||||
// Set no caching
|
|
||||||
$new_result->cache_time = 0;
|
|
||||||
|
|
||||||
// Return our completely new result object
|
|
||||||
return $new_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a slug matches one of our missing plugins.
|
|
||||||
*
|
|
||||||
* @param string $slug The plugin slug to check.
|
|
||||||
* @param array $invalid_plugins List of invalid plugin paths.
|
|
||||||
* @return bool True if the slug matches a missing plugin.
|
|
||||||
*/
|
|
||||||
private function is_missing_plugin($slug, $invalid_plugins) {
|
|
||||||
foreach ($invalid_plugins as $plugin_file) {
|
|
||||||
// Extract the plugin slug from the plugin file path
|
|
||||||
$plugin_slug = dirname($plugin_file);
|
|
||||||
if ('.' === $plugin_slug) {
|
|
||||||
$plugin_slug = basename($plugin_file, '.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($slug === $plugin_slug) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevent WordPress from caching our plugin API responses.
|
|
||||||
*
|
|
||||||
* @param object|WP_Error $result The result object or WP_Error.
|
|
||||||
* @param string $action The type of information being requested.
|
|
||||||
* @param object $args Plugin API arguments.
|
|
||||||
* @return object|WP_Error The result object or WP_Error.
|
|
||||||
*/
|
|
||||||
public function prevent_plugins_api_caching( $result, $action, $args ) {
|
|
||||||
// Only modify plugin_information requests
|
|
||||||
if ( 'plugin_information' !== $action ) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we have a slug to work with
|
|
||||||
if ( empty( $args->slug ) ) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get our list of invalid plugins
|
|
||||||
$invalid_plugins = $this->get_invalid_plugins();
|
|
||||||
|
|
||||||
// Check if the requested plugin is one of our missing plugins
|
|
||||||
foreach ( $invalid_plugins as $plugin_file ) {
|
|
||||||
// Extract the plugin slug from the plugin file path
|
|
||||||
$plugin_slug = dirname( $plugin_file );
|
|
||||||
if ( '.' === $plugin_slug ) {
|
|
||||||
$plugin_slug = basename( $plugin_file, '.php' );
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is one of our missing plugins, prevent caching
|
|
||||||
if ( $args->slug === $plugin_slug ) {
|
|
||||||
// Add a filter to prevent caching of this response
|
|
||||||
add_filter( 'plugins_api_result_' . $args->slug, '__return_false' );
|
|
||||||
|
|
||||||
// Add a timestamp to force cache busting
|
|
||||||
if ( is_object( $result ) ) {
|
|
||||||
$result->last_updated = current_time( 'mysql' );
|
|
||||||
$result->cache_time = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear plugin API cache when viewing the plugins page.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function maybe_clear_plugin_api_cache() {
|
|
||||||
// Only run on the plugins page
|
|
||||||
if ( ! $this->is_plugins_page() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get our list of invalid plugins
|
|
||||||
$invalid_plugins = $this->get_invalid_plugins();
|
|
||||||
|
|
||||||
// Clear transients for each invalid plugin
|
|
||||||
foreach ( $invalid_plugins as $plugin_file ) {
|
|
||||||
// Extract the plugin slug from the plugin file path
|
|
||||||
$plugin_slug = dirname( $plugin_file );
|
|
||||||
if ( '.' === $plugin_slug ) {
|
|
||||||
$plugin_slug = basename( $plugin_file, '.php' );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete all possible transients for this plugin
|
|
||||||
delete_transient( 'plugins_api_' . $plugin_slug );
|
|
||||||
delete_site_transient( 'plugins_api_' . $plugin_slug );
|
|
||||||
delete_transient( 'plugin_information_' . $plugin_slug );
|
|
||||||
delete_site_transient( 'plugin_information_' . $plugin_slug );
|
|
||||||
|
|
||||||
// Clear any other transients that might be caching plugin info
|
|
||||||
$this->clear_all_plugin_transients();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Also clear our own plugin's cache
|
|
||||||
$this->clear_own_plugin_cache();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear all plugin-related transients that might be caching information.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function clear_all_plugin_transients() {
|
|
||||||
// Clear update cache
|
|
||||||
delete_site_transient( 'update_plugins' );
|
|
||||||
delete_site_transient( 'update_themes' );
|
|
||||||
delete_site_transient( 'update_core' );
|
|
||||||
|
|
||||||
// Clear plugins API cache
|
|
||||||
delete_site_transient( 'plugin_information' );
|
|
||||||
|
|
||||||
// Clear plugin update counts
|
|
||||||
delete_transient( 'plugin_updates_count' );
|
|
||||||
delete_site_transient( 'plugin_updates_count' );
|
|
||||||
|
|
||||||
// Clear plugin slugs cache
|
|
||||||
delete_transient( 'plugin_slugs' );
|
|
||||||
delete_site_transient( 'plugin_slugs' );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear cache specifically for our own plugin.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function clear_own_plugin_cache() {
|
|
||||||
// Clear our own plugin's cache (both old and new slugs)
|
|
||||||
$our_slugs = array('wp-fix-plugin-does-not-exist-notices', 'fix-plugin-does-not-exist-notices');
|
|
||||||
|
|
||||||
foreach ($our_slugs as $slug) {
|
|
||||||
delete_transient( 'plugins_api_' . $slug );
|
|
||||||
delete_site_transient( 'plugins_api_' . $slug );
|
|
||||||
delete_transient( 'plugin_information_' . $slug );
|
|
||||||
delete_site_transient( 'plugin_information_' . $slug );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear plugin update transients
|
|
||||||
delete_site_transient('update_plugins');
|
|
||||||
delete_site_transient('plugin_information');
|
|
||||||
|
|
||||||
// Force refresh of plugin update information if function exists
|
|
||||||
if (function_exists('wp_clean_plugins_cache')) {
|
|
||||||
wp_clean_plugins_cache(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear object cache if function exists
|
|
||||||
if (function_exists('wp_cache_flush')) {
|
|
||||||
wp_cache_flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // End class Fix_Plugin_Does_Not_Exist_Notices
|
|
||||||
|
|
||||||
// Initialize the plugin class.
|
|
||||||
new Fix_Plugin_Does_Not_Exist_Notices();
|
|
||||||
|
|
||||||
// This function was previously deactivating all plugins except our plugin and Git Updater
|
|
||||||
// It has been disabled to allow other plugins to be activated
|
|
||||||
// Uncomment the following code if you need to troubleshoot plugin conflicts
|
|
||||||
/*
|
|
||||||
add_action('admin_init', 'fpden_deactivate_problematic_plugins');
|
|
||||||
|
|
||||||
function fpden_deactivate_problematic_plugins() {
|
|
||||||
$active_plugins = get_option('active_plugins', array());
|
|
||||||
$updated_plugins = array();
|
|
||||||
|
|
||||||
// Only keep our plugin and Git Updater
|
|
||||||
foreach ($active_plugins as $plugin) {
|
|
||||||
if (strpos($plugin, 'wp-fix-plugin-does-not-exist-notices') !== false ||
|
|
||||||
strpos($plugin, 'git-updater') !== false) {
|
|
||||||
$updated_plugins[] = $plugin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only update if we've made changes
|
|
||||||
if (count($updated_plugins) !== count($active_plugins)) {
|
|
||||||
update_option('active_plugins', $updated_plugins);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Initialize the updater if composer autoload exists
|
|
||||||
$autoloader = __DIR__ . '/vendor/autoload.php';
|
|
||||||
if (file_exists($autoloader)) {
|
|
||||||
require_once $autoloader;
|
|
||||||
|
|
||||||
// Initialize the updater if the class exists
|
|
||||||
if (class_exists('\WPALLSTARS\FixPluginDoesNotExistNotices\Updater')) {
|
|
||||||
new \WPALLSTARS\FixPluginDoesNotExistNotices\Updater(__FILE__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|