' . \esc_html__( 'Mails', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
if ( ( Settings::get_option( 'snippets_module_enabled' ) ) ) {
$settings_link = '' . \esc_html__( 'Snippets', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
if ( ( Settings::get_option( 'requests_module_enabled' ) ) ) {
$settings_link = '' . \esc_html__( 'Requests', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
if ( ( Settings::get_option( 'tables_module_enabled' ) ) ) {
$settings_link = '' . \esc_html__( 'Tables', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
if ( ( Settings::get_option( 'transients_module_enabled' ) ) ) {
$settings_link = '' . \esc_html__( 'Transients', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
if ( ( Settings::get_option( 'cron_module_enabled' ) ) ) {
$settings_link = '' . \esc_html__( 'Cron Jobs', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
if ( ( Settings::get_option( 'rest_api_module_enabled' ) ) ) {
$settings_link = '' . \esc_html__( 'REST API', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
if ( ( Settings::get_option( 'file_editor_module_enabled' ) ) ) {
$settings_link = '' . \esc_html__( 'File Editor', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
if ( ( Settings::get_option( 'fatals_module_enabled' ) ) ) {
$settings_link = '' . \esc_html__( 'PHP Errors View', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
$settings_link = '' . \esc_html__( 'Error Logs', '0-day-analytics' ) . '';
array_unshift( $links, $settings_link );
}
return $links;
}
/**
* Add meta to plugin details
*
* Add options to plugin meta line
*
* @param string $links - Current links.
* @param string $file - File in use.
*
* @return array Links, now with settings added.
*
* @since 1.8.4
*/
public static function plugin_meta( $links, $file ) {
if ( false !== strpos( $file, 'advanced-analytics.php' ) ) {
$links = array_merge(
$links,
array(
'' . \esc_html__( 'Support', '0-day-analytics' ) . '',
)
);
}
return $links;
}
/**
* Remove all non plugin notices from our plugin pages.
*
* @since 1.8.4
*/
public static function hide_unrelated_notices(): void {
// Bail if we're not on our screen or page.
if ( ! WP_Helper::is_admin_page() ) {
return;
}
self::remove_unrelated_actions( 'user_admin_notices' );
self::remove_unrelated_actions( 'admin_notices' );
self::remove_unrelated_actions( 'all_admin_notices' );
self::remove_unrelated_actions( 'network_admin_notices' );
}
/**
* Remove all notices from our plugin pages based on the provided action hook.
*
* @param string $action The name of the action hook. Expected values: 'user_admin_notices', 'admin_notices', 'all_admin_notices', 'network_admin_notices'.
*
* @since 1.8.4
*/
public static function remove_unrelated_actions( $action ) {
global $wp_filter;
if ( ! isset( $wp_filter[ $action ] ) || empty( $wp_filter[ $action ]->callbacks ) || ! is_array( $wp_filter[ $action ]->callbacks ) ) {
return;
}
foreach ( $wp_filter[ $action ]->callbacks as $priority => $hooks ) {
foreach ( $hooks as $name => $arr ) {
if (
( // Cover object method callback case.
is_array( $arr['function'] ) &&
isset( $arr['function'][0] ) &&
is_object( $arr['function'][0] ) &&
false !== strpos( ( get_class( $arr['function'][0] ) ), 'ADVAN' )
) ||
( // Cover class static method callback case.
! empty( $name ) &&
/*
* Cast to string before comparing.
*
* $name is the key _wp_filter_build_unique_id() produced. Since WP 7.1
* that is (string) spl_object_id() for a closure - "2652" - and PHP
* stores a decimal-integer string as an integer array key, so $name
* arrives here as an int. This file declares strict_types, so strpos()
* raises a TypeError instead of coercing it, and the notice hook fatals.
*
* The comparison itself is unaffected: an object id has never contained
* the prefix, exactly as the spl_object_hash() it replaced never did, so
* closures keep being treated as unrelated and removed.
*/
false !== strpos( (string) $name, 'ADVAN' )
)
) {
continue;
}
unset( $wp_filter[ $action ]->callbacks[ $priority ][ $name ] );
}
}
}
/**
* Adds a powered-by message in the footer of the page.
*
* Only outputs on the frontend.
*
* @return void
*
* @since 2.0.0
*/
public static function powered_by() {
if ( Context_Helper::is_front() ) {
printf(
/* Translators: Plugin link. */
\esc_html__( 'Proudly powered by %s', '0-day-analytics' ),
'' . \esc_attr( ADVAN_NAME ) . ''
);
}
}
/**
* Registers a plugin redirection on activate setting.
*
* @return void
*
* @since 1.0.0
*/
public static function plugin_activate() {
\add_option( self::REDIRECT_OPTION_NAME, true );
}
/**
* Redirects the plugin to its settings page if it was just activated.
*
* @return void
*
* @since 1.0.0
*/
public static function plugin_redirect() {
if ( \get_option( self::REDIRECT_OPTION_NAME, false ) ) {
\delete_option( self::REDIRECT_OPTION_NAME );
if ( ! isset( $_GET['activate-multi'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Redirect only, no action taken.
\wp_safe_redirect( \add_query_arg( 'page', Logs_List::MENU_SLUG, \network_admin_url( 'admin.php' ) ) );
exit;
}
}
}
/**
* Action for _doing_it_wrong() calls.
*
* @param string $function_name The function that was called.
* @param string $message A message explaining what has been done incorrectly.
* @param string $version The version of WordPress where the message was added.
*
* @return void
*
* @since 1.9.2.2
*/
public static function action_doing_it_wrong_run( $function_name, $message, $version ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
global $wp_filter;
$function_name = (string) $function_name;
$message = (string) $message;
if ( ! class_exists( '\QM_Collectors', false ) || ! self::is_just_in_time_for_0_day_domain( $function_name, $message ) ) {
return;
}
$qm_collector_doing_it_wrong = \QM_Collectors::get( 'doing_it_wrong' );
$current_priority = $wp_filter['doing_it_wrong_run']->current_priority();
if ( null === $qm_collector_doing_it_wrong || false === $current_priority ) {
return;
}
switch ( $current_priority ) {
case 0:
\remove_action( 'doing_it_wrong_run', array( $qm_collector_doing_it_wrong, 'action_doing_it_wrong_run' ) );
break;
case 20:
\add_action( 'doing_it_wrong_run', array( $qm_collector_doing_it_wrong, 'action_doing_it_wrong_run' ), 10, 3 );
break;
default:
break;
}
}
/**
* Filter for _doing_it_wrong() calls.
*
* @param bool|mixed $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
* @param string $function_name The function that was called.
* @param string $message A message explaining what has been done incorrectly.
* @param string $version The version of WordPress where the message was added.
*
* @return bool
*
* @since 1.9.2.2
*/
public static function filter_doing_it_wrong_trigger_error( $trigger, $function_name, $message, $version ): bool { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
$trigger = (bool) $trigger;
$function_name = (string) $function_name;
$message = (string) $message;
return self::is_just_in_time_for_0_day_domain( $function_name, $message ) ? false : $trigger;
}
/**
* Whether it is the just_in_time_error for 0-Day-related domains.
*
* @param string $function_name Function name.
* @param string $message Message.
*
* @return bool
*
* @since 1.9.2.2
*/
public static function is_just_in_time_for_0_day_domain( string $function_name, string $message ): bool {
return '_load_textdomain_just_in_time' === $function_name && strpos( $message, '' . ADVAN_TEXTDOMAIN ) !== false;
}
}
}