Skip to content
Closed
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions inc/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ function bootstrap() {
Icons\bootstrap();
Importers\bootstrap();
Pings\bootstrap();
Plugins\bootstrap();
Salts\bootstrap();
Settings\bootstrap();
Updater\bootstrap();
Expand Down
99 changes: 99 additions & 0 deletions inc/plugins/namespace.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php
/**
* Sets DID-less plugin slug as active.
*
* @package FAIR
*/

namespace FAIR\Plugins;

use function FAIR\Packages\get_did_hash;
use function FAIR\Updater\get_packages;

/**
* Bootstrap.
*
* @return void
*/
function bootstrap() {
add_action( 'load-plugins.php', __NAMESPACE__ . '\\load_filters' );
}

/**
* Load filters.
*
* @return void
*/
function load_filters() {
add_filter( 'option_active_plugins', __NAMESPACE__ . '\\set_as_active' );
add_filter( 'wp_admin_notice_markup', __NAMESPACE__ . '\\hide_notice', 10, 3 );

// just for testing.
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( is_plugin_active( 'git-updater/git-updater.php' ) ) {
wp_admin_notice( 'Git Updater is active' );
}
Comment on lines +21 to +27
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need to remove this when ready to merge.

}

/**
* Set FAIR plugins as active using DID-less slug.
*
* @param array $active_plugins Array of active plugins.
*
* @return array
*/
function set_as_active( $active_plugins ) {
remove_filter( 'option_active_plugins', __NAMESPACE__ . '\\set_as_active' );
$packages = get_packages();
$plugins = $packages['plugins'] ?? [];
$plugins = array_map( 'plugin_basename', $plugins );
foreach ( $plugins as $did => $plugin ) {
if ( is_plugin_active( $plugin ) ) {
$active_plugins[] = get_file_without_did_hash( $did, $plugin );
}
}

return array_filter( array_unique( $active_plugins ) );
}

/**
* Return plugin file without DID hash.
*
* Assumes pattern of <slug>-<hash>.
*
* @param string $did DID.
* @param string $plugin Plugin basename.
*
* @return string
*/
function get_file_without_did_hash( $did, $plugin ) : string {
list( $slug, $file ) = explode( '/', $plugin, 2 );
$slug = str_replace( '-' . get_did_hash( $did ), '', $slug );

return $slug . '/' . $file;
}

/**
* Hide notice reporting DID-less plugin is inactive because it doesn't exist.
*
* @param string $markup Markup of notice.
* @param string $message Message of notice.
* @param array $args Args of notice.
*
* @return string
*/
function hide_notice( $markup, $message, $args ) {
if ( $args['id'] === 'message' ) {
$active = get_option( 'active_plugins' );
foreach ( $active as $plugin ) {
if ( str_contains( $message, $plugin ) && str_contains( $markup, 'error' ) ) {
Copy link
Member

@costdev costdev Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for the 'error' before the loop, in the initial if - can alternatively use in_array( 'error', $args['additional_classes'], true ) instead of checking for 'error' somewhere in the markup.

Copy link
Contributor Author

@afragen afragen Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then I need to also check that the additional_classes is set correctly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can just use:

in_array( 'error', $args['additional_classes'] ?? [], true )

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm noticing that there's another error that has an ID of message and has the error class.

I think, unfortunately, we'll have to check for __( 'Plugin file does not exist.' ) and add a phpcs:ignore comment for the lack of textdomain since this is a Core string.

remove_filter( 'wp_admin_notice_markup', __NAMESPACE__ . '\\hide_notice' );
return '';
}
}
}

return $markup;
}
4 changes: 2 additions & 2 deletions inc/updater/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function get_packages() {
$plugin_id = get_file_data( $plugin_path . $file, [ 'PluginID' => 'Plugin ID' ] )['PluginID'];

if ( ! empty( $plugin_id ) ) {
$packages['plugins'][] = $plugin_path . $file;
$packages['plugins'][ $plugin_id ] = $plugin_path . $file;
}
}

Expand All @@ -54,7 +54,7 @@ function get_packages() {
$theme_id = get_file_data( $theme_path . $file . '/style.css', [ 'ThemeID' => 'Theme ID' ] )['ThemeID'];

if ( ! empty( $theme_id ) ) {
$packages['themes'][] = $theme_path . $file . '/style.css';
$packages['themes'][ $theme_id ] = $theme_path . $file . '/style.css';
}
}

Expand Down
1 change: 1 addition & 0 deletions plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
require_once __DIR__ . '/inc/icons/namespace.php';
require_once __DIR__ . '/inc/importers/namespace.php';
require_once __DIR__ . '/inc/pings/namespace.php';
require_once __DIR__ . '/inc/plugins/namespace.php';
require_once __DIR__ . '/inc/salts/namespace.php';
require_once __DIR__ . '/inc/settings/namespace.php';
require_once __DIR__ . '/inc/updater/namespace.php';
Expand Down