Skip to Content

check_warnings()

Check for problems.

PHP April 1, 2021

Usage

PHP
nebula()->check_warnings()

Parameters

This function does not accept any parameters. Is this incorrect?

Additional Notes

This function will return an array of warnings/errors and other logs, but is only available to admins and developers.

Source File

Located in /libs/Utilities/Warnings.php on line 68.

1 Hook

Find these filters and actions in the source code below to hook into them. Use do_action() and add_filter() in your functions file or plugin.

Filters
"nebula_warnings"
Need a new filter hook? Request one here.

Actions
This function has no action hooks available. Request one?

PHP
        public function check_warnings(){
            if ( $this->is_ajax_request() ){
                return false;
            }

            if ( $this->is_auditing() || $this->is_warning_level('on') ){
                //Check object cache first
                $nebula_warnings = wp_cache_get('nebula_warnings');

                if ( is_array($nebula_warnings) || !empty($nebula_warnings) ){ //If it is an array (meaning it has run before but did not find anything) or if it is false
                    return $nebula_warnings;
                }

                $this->timer('Check Warnings');
                $nebula_warnings = array(); //Prep the warnings array to fill

                //Admin warnings only
                if ( $this->is_admin_page() ){
                    //Check page slug against taxonomy terms.
                    global $pagenow;
                    if ( $pagenow === 'post.php' || $pagenow === 'edit.php' ){
                        global $post;

                        if ( !empty($post) ){ //If the listing has results
                            foreach ( get_taxonomies() as $taxonomy ){ //Loop through all taxonomies
                                foreach ( get_terms($taxonomy, array('hide_empty' => false)) as $term ){ //Loop through all terms within each taxonomy
                                    if ( $term->slug === $post->post_name ){ //If this page slug matches a taxonomy term
                                        $nebula_warnings['slug_conflict'] = array(
                                            'level' => 'error',
                                            'description' => '<i class="fas fa-fw fa-link"></i> Slug conflict with ' . ucwords(str_replace('_', ' ', $taxonomy)) . ': <strong>' . $term->slug . '</strong> - Consider changing this page slug.'
                                        );
                                        return false;
                                    }
                                }
                            }
                        }
                    }

                    //Test the WordPress filesystem method
                    $fs_method_transient = get_transient('nebula_fs_method');
                    if ( empty($fs_method_transient) || $this->is_debug() ){
                        if ( file_exists(get_template_directory() . '/style.css') ){
                            WP_Filesystem();
                            global $wp_filesystem;
                            $test_file = $wp_filesystem->get_contents(get_template_directory() . '/style.css');

                            if ( empty($test_file) ){
                                $nebula_warnings['file_permissions'] = array(
                                    'level' => 'error',
                                    'description' => '<i class="fas fa-fw fa-server"></i> File system permissions error. Consider changing the FS_METHOD in wp-config.php.',
                                );
                            } else {
                                set_transient('nebula_fs_method', true); //On success, set a transient. No expiration.
                            }
                        }
                    }
                }

                //If the site is served via HTTPS but the Site URL is still set to HTTP
                if ( (is_ssl() || isset($_SERVER['HTTPS'])) && (strpos(home_url(), 'http://') !== false || strpos(get_option('siteurl'), 'http://') !== false) ){
                    $nebula_warnings['site_url_http'] = array(
                        'level' => 'error',
                        'description' => '<i class="fas fa-fw fa-lock-open"></i> <a href="options-general.php">Website Address</a> settings are http but the site is served from https.',
                        'url' => admin_url('options-general.php')
                    );
                }

                //If search indexing is disabled
                if ( get_option('blog_public') == 0 ){ //Stored as a string
                    $nebula_warnings['search_visibility'] = array(
                        'level' => 'error',
                        'description' => '<i class="fab fa-fw fa-searchengin"></i> <a href="options-reading.php">Search Engine Visibility</a> is currently disabled! Therefore, additional SEO checks were not performed.',
                        'url' => admin_url('options-reading.php')
                    );
                } else {
                    //Check for sitemap
                    $sitemap_transient = get_transient('nebula_check_sitemap');
                    if ( empty($sitemap_transient) || $this->is_debug() ){
                        $sitemap_warning = false;
                        if ( is_plugin_active('wordpress-seo/wp-seo.php') ){ //Yoast
                            if ( !$this->is_available(home_url('/') . 'sitemap_index.xml', false, true) ){
                                $sitemap_warning = true;
                                $nebula_warnings['missing_sitemap'] = array(
                                    'level' => 'warning',
                                    'description' => '<i class="fas fa-fw fa-sitemap"></i> Missing sitemap XML. Yoast is enabled, but <a href="' . home_url('/') . 'sitemap_index.xml' . '" target="_blank">sitemap_index.xml</a> is unavailable.'
                                );
                            }
                        } elseif ( is_plugin_active('autodescription/autodescription.php') ){ //The SEO Framework
                            if ( !$this->is_available(home_url('/') . 'sitemap.xml', false, true) ){
                                $sitemap_warning = true;
                                $nebula_warnings['missing_sitemap'] = array(
                                    'level' => 'warning',
                                    'description' => '<i class="fas fa-fw fa-sitemap"></i> Missing sitemap XML. The SEO Framework is enabled, but <a href="' . home_url('/') . 'sitemap.xml' . '" target="_blank">sitemap.xml</a> is unavailable.'
                                );
                            }
                        } else {
                            if ( !$this->is_available(home_url('/') . 'wp-sitemap.xml', false, true)  ){ //WordPress Core
                                $sitemap_warning = true;
                                $nebula_warnings['missing_sitemap'] = array(
                                    'level' => 'warning',
                                    'description' => '<i class="fas fa-fw fa-sitemap"></i> Missing sitemap XML. WordPress core <a href="' . home_url('/') . 'wp-sitemap.xml' . '" target="_blank">sitemap_index.xml</a> is unavailable.'
                                );

                                //Check if the SimpleXML PHP module is installed on the server (required for WP core sitemap generation)
                                if ( !function_exists('simplexml_load_string') ){
                                    $sitemap_warning = true;
                                    $nebula_warnings['simplexml'] = array(
                                        'level' => 'warning',
                                        'description' => '<i class="fas fa-fw fa-sitemap"></i> SimpleXML PHP module is not available. This is required for WordPress core sitemap generation.'
                                    );
                                }
                            }
                        }

                        //If there is no warning, only check periodically
                        if ( !$sitemap_warning ){
                            set_transient('nebula_check_sitemap', 'Sitemap Found', WEEK_IN_SECONDS);
                        }
                    }

                    //If not pinging additional update services (blog must be public for this to be available)
                    if ( $this->is_warning_level('verbose') ){
                        $ping_sites = get_option('ping_sites');
                        if ( empty($ping_sites) || $ping_sites === 'http://rpc.pingomatic.com/' ){ //If it is empty or only has the default value
                            $nebula_warnings['update_services'] = array(
                                'level' => 'warning',
                                'description' => '<i class="fas fa-fw fa-rss"></i> Additional <a href="options-writing.php">Update Services</a> should be pinged. <a href="https://codex.wordpress.org/Update_Services#XML-RPC_Ping_Services" target="_blank" rel="noopener">Recommended update services &raquo;</a>',
                                'url' => admin_url('options-writing.php')
                            );
                        }
                    }
                }

                //Check PHP version
                $php_version_lifecycle = $this->php_version_support();
                if ( !empty($php_version_lifecycle) ){
                    if ( $php_version_lifecycle['lifecycle'] === 'security' ){
                        if ( $php_version_lifecycle['end']-time() < MONTH_IN_SECONDS ){ //If end of life is within 1 month
                            $nebula_warnings['php_lifecycle_main'] = array(
                                'level' => 'warning',
                                'description' => '<i class="fab fa-fw fa-php"></i> PHP <strong>' . PHP_VERSION . '</strong> <a href="http://php.net/supported-versions.php" target="_blank" rel="noopener">is nearing end of life</a>. Security updates end in ' . human_time_diff($php_version_lifecycle['end']) . ' on ' . date('F j, Y', $php_version_lifecycle['end']) . '.',
                                'url' => 'http://php.net/supported-versions.php',
                                'meta' => array('target' => '_blank', 'rel' => 'noopener')
                            );
                        }
                    } elseif ( $php_version_lifecycle['lifecycle'] === 'end' ){
                        $nebula_warnings['php_lifecycle_end'] = array(
                            'level' => 'error',
                            'description' => '<i class="fab fa-fw fa-php"></i> PHP ' . PHP_VERSION . ' <a href="http://php.net/supported-versions.php" target="_blank" rel="noopener">no longer receives security updates</a>! End of life occurred ' . human_time_diff($php_version_lifecycle['end']) . ' ago on ' . date('F j, Y', $php_version_lifecycle['end']) . '.',
                            'url' => 'http://php.net/supported-versions.php',
                            'meta' => array('target' => '_blank', 'rel' => 'noopener')
                        );
                    }
                }

                //Check specific directories for indexing (Apache directory listings)
                $directory_indexing = get_transient('nebula_directory_indexing');

                if ( empty($directory_indexing) || nebula()->is_debug() || nebula()->is_auditing() ){ //Use the transient unless ?debug or explicitly auditing
                    $directories = array(get_home_url(), includes_url(), content_url()); //Directories to test
                    $found_problem = false;
                    foreach ( $directories as $directory ){
                        //Get the contents of the directory
                        $directory_request = $this->remote_get($directory, array(
                            'timeout' => 3,
                            'limit_response_size' => KB_IN_BYTES*512 //Limit the response to 512kb
                        ));

                        if ( !is_wp_error($directory_request) && !empty($directory_request) ){ //If not an error and response exists
                            if ( $directory_request['response']['code'] <= 400 ){ //Check if the response code is less than 400 (in this case 400+ is good)
                                if ( strpos(strtolower($directory_request['body']), 'index of') ){ //Check if the "Index of" text appears in the body content (bad)
                                    $nebula_warnings['directory_indexing'] = array(
                                        'level' => 'error',
                                        'description' => '<i class="far fa-fw fa-list-alt"></i> Directory indexing is not disabled. Visitors can see file listings of directories!',
                                    );

                                    $found_problem = true;
                                    set_transient('nebula_directory_indexing', 'bad', WEEK_IN_SECONDS);
                                    break; //Exit loop since we found an issue
                                }
                            }
                        }
                    }

                    //If we did not find a problem, set a longer transient
                    if ( empty($found_problem) ){
                        set_transient('nebula_directory_indexing', 'good'); //No expiration so it is not cleared when making new posts
                    }
                } else {
                    if ( $directory_indexing === 'bad' ){
                        $nebula_warnings['directory_indexing'] = array(
                            'level' => 'error',
                            'description' => '<i class="far fa-fw fa-list-alt"></i> At the time last checked, directory indexing was allowed. Visitors may be able to see file listings of directories! <a href="' . home_url('/?audit=true') . '" target="_blank">Run an audit to re-scan &raquo;</a>',
                        );
                    }
                }

                //Check individual files for anything unusual
                if ( nebula()->is_auditing() ){ //Only check all files when auditing
                    $directories_to_scan = array(ABSPATH . '/wp-admin', ABSPATH . '/wp-includes', get_template_directory(), get_stylesheet_directory()); //Change this to simply ABSPATH to scan the entire WordPress directory
                    foreach ( $directories_to_scan as $directory ){
                        foreach ( $this->glob_r($directory . '/*') as $file ){
                            if ( !$this->contains($file, array('/cache', '/uploads')) ){ //Skip certain directories
                                if ( is_file($file) ){
                                    //If file was last modified before the year 2000
                                    if ( filemtime($file) < 946702800 ){ //PHP 7.4 use numeric separators here
                                        $nebula_warnings['unusual_filemtime'] = array(
                                            'level' => 'warning',
                                            'description' => '<i class="fas fa-fw fa-hourglass-start"></i> <strong>' . $file . '</strong> was last modified on ' . date('F j, Y', filemtime($file)) . '. This is somewhat unusual and should be looked into.'
                                        );
                                    }

                                    //If the file size is larger than 10mb
                                    if ( filesize($file) > MB_IN_BYTES*10 ){
                                        $nebula_warnings['large_file'] = array(
                                            'level' => 'warning',
                                            'description' => '<i class="fas fa-fw fa-file"></i> <strong>' . $file . '</strong> has a large filesize of ' . bcdiv(filesize($file), MB_IN_BYTES, 0) . 'mb.'
                                        );
                                    }
                                }
                            }
                        }
                    }
                } else { //Otherwise just check a few files
                    foreach ( $this->get_log_files('all') as $types ){
                        foreach ( $types as $log_file ){
                            if ( $log_file['bytes'] > MB_IN_BYTES*25 ){
                                $nebula_warnings[] = array( //No key on this one so they do not overwrite when multiple are present
                                    'level' => 'warning',
                                    'description' => '<i class="fas fa-fw fa-weight"></i> Large debug file: <strong>' . $log_file['shortpath'] . '</strong> (' . $this->format_bytes($log_file['bytes']) . ') <small><a href="' . esc_url(add_query_arg('debug', 'true')) . '">Re-Scan?</a></small>',
                                );
                            }
                        }
                    }
                }

                //Check for hard Debug Mode
                if ( $this->is_warning_level('verbose') && WP_DEBUG ){
                    $nebula_warnings['wp_debug'] = array(
                        'level' => 'warning',
                        'description' => '<i class="fas fa-fw fa-bug"></i> <strong>WP_DEBUG</strong> is enabled <small>(Generally defined in wp-config.php)</small>'
                    );

                    if ( WP_DEBUG_LOG ){
                        $nebula_warnings['wp_debug_log'] = array(
                            'level' => 'warning',
                            'description' => '<i class="fas fa-fw fa-bug"></i> Debug logging (<strong>WP_DEBUG_LOG</strong>) to /wp-content/debug.log is enabled <small>(Generally defined in wp-config.php)</small>'
                        );
                    }

                    if ( WP_DEBUG_DISPLAY ){
                        $nebula_warnings['wp_debug_display'] = array(
                            'level' => 'error',
                            'description' => '<i class="fas fa-fw fa-bug"></i> Debug errors and warnings are being displayed on the front-end (<Strong>WP_DEBUG_DISPLAY</strong>) <small>(Generally defined in wp-config.php)</small>'
                        );
                    }
                }

                //Check for Google Analytics Tracking ID
                if ( !$this->get_option('ga_tracking_id') && !$this->get_option('gtm_id') ){
                    $nebula_warnings['ga_tracking_id'] = array(
                        'level' => 'error',
                        'description' => '<i class="fas fa-fw fa-chart-area"></i> A <a href="themes.php?page=nebula_options&tab=analytics&option=ga_tracking_id">Google Analytics tracking ID</a> or <a href="themes.php?page=nebula_options&tab=analytics&option=gtm_id">Google Tag Manager ID</a> is strongly recommended!',
                        'url' => admin_url('themes.php?page=nebula_options&tab=analytics')
                    );
                }

                //If Enhanced Ecommerce Plugin is missing Google Analytics Tracking ID
                if ( is_plugin_active('enhanced-e-commerce-for-woocommerce-store/woocommerce-enhanced-ecommerce-google-analytics-integration.php') ){
                    $ee_ga_settings = get_option('woocommerce_enhanced_ecommerce_google_analytics_settings');
                    if ( empty($ee_ga_settings['ga_id']) ){
                        $nebula_warnings['enhanced_ecommerce'] = array(
                            'level' => 'error',
                            'description' => '<i class="fas fa-fw fa-chart-area"></i> <a href="admin.php?page=wc-settings&tab=integration">WooCommerce Enhanced Ecommerce</a> is missing a Google Analytics ID!',
                            'url' => admin_url('admin.php?page=wc-settings&tab=integration')
                        );
                    }
                }

                //Child theme checks
                if ( is_child_theme() ){
                    //Check if the parent theme template is correctly referenced
                    $active_theme = wp_get_theme();
                    if ( !file_exists(dirname(get_stylesheet_directory()) . '/' . $active_theme->get('Template')) ){
                        $nebula_warnings['no_parent_theme'] = array(
                            'level' => 'error',
                            'description' => '<i class="fas fa-fw fa-baby-carriage"></i> A child theme is active, but its parent theme directory <strong>' . $active_theme->get('Template') . '</strong> does not exist!<br/><em>The "Template:" setting in the <a href="' . get_stylesheet_uri() . '" target="_blank" rel="noopener">style.css</a> file of the child theme must match the directory name (above) of the parent theme.</em>'
                        );
                    }

                    //Check if child theme is missing img meta files
                    if ( is_dir(get_stylesheet_directory() . '/assets/img/meta') && file_exists(get_stylesheet_directory() . '/assets/img/meta/favicon.ico') ){
                        //Check to ensure that child theme meta graphics are not identical to Nebula parent theme meta graphics
                        foreach( glob(get_stylesheet_directory() . '/assets/img/meta/*.*') as $child_theme_meta_image ){
                            $parent_theme_meta_image = str_replace(get_stylesheet_directory(), get_template_directory(), $child_theme_meta_image);

                            //Check if the images are the same
                            if ( file_exists($child_theme_meta_image) && file_exists($parent_theme_meta_image) && md5_file($child_theme_meta_image) === md5_file($parent_theme_meta_image) ){ //Compare the two files to see if they are identical
                                $nebula_warnings['child_meta_graphics'] = array(
                                    'level' => 'error',
                                    'description' => '<i class="fas fa-fw fa-images"></i> Child theme meta graphics exist, but are identical to the Nebula meta graphics. Ensure that child theme meta graphics are unique to this website!</em>'
                                );

                                break; //Exit the loop as soon as we find a match
                            }
                        }
                    } else {
                        $nebula_warnings['child_meta_graphics'] = array(
                            'level' => 'error',
                            'description' => '<i class="far fa-fw fa-images"></i> A child theme is active, but missing meta graphics. Create a <code>/assets/img/meta/</code> directory in the child theme (or copy it over from the Nebula parent theme).</em>'
                        );
                    }
                }

                //Check if Relevanssi has built an index for search
                if ( is_plugin_active('relevanssi/relevanssi.php') ){
                    if ( !get_option('relevanssi_indexed') ){
                        $nebula_warnings['relevanssi_index'] = array(
                            'level' => 'error',
                            'description' => '<i class="fas fa-fw fa-search-plus"></i> <a href="options-general.php?page=relevanssi%2Frelevanssi.php&tab=indexing">Relevanssi</a> must build an index to search the site. This must be triggered manually.',
                            'url' => admin_url('options-general.php?page=relevanssi%2Frelevanssi.php&tab=indexing')
                        );
                    }

                    if ( get_option('relevanssi_index_fields') === 'none' ){
                        $nebula_warnings['relevanssi_custom_fields'] = array(
                            'level' => 'warning',
                            'description' => '<i class="fas fa-fw fa-search-plus"></i> <a href="options-general.php?page=relevanssi%2Frelevanssi.php&tab=indexing">Relevanssi</a> is not set to search custom fields.',
                            'url' => admin_url('options-general.php?page=relevanssi%2Frelevanssi.php&tab=indexing')
                        );
                    }
                }

                //Check if Google Optimize is enabled
                if ( $this->get_option('google_optimize_id') ){
                    $nebula_warnings['google_optimize_active'] = array(
                        'level' => 'error',
                        'description' => '<i class="far fa-fw fa-window-restore"></i> <a href="https://optimize.google.com/optimize/home/" target="_blank" rel="noopener">Google Optimize</a> is enabled (via <a href="themes.php?page=nebula_options&tab=analytics&option=google_optimize_id">Nebula Options</a>). Disable when not actively experimenting!',
                        'url' => 'https://optimize.google.com/optimize/home/'
                    );

                    //Google Optimize requires Google Analytics
                    if ( !$this->get_option('ga_tracking_id') && !$this->get_option('gtm_id') ){
                        $nebula_warnings['google_optimize_analytics'] = array(
                            'level' => 'error',
                            'description' => '<i class="far fa-fw fa-window-restore"></i> <a href="themes.php?page=nebula_options&tab=analytics&option=google_optimize_id">Google Optimize ID</a> exists without a <a href="themes.php?page=nebula_options&tab=analytics&option=ga_tracking_id">Google Analytics Tracking ID</a> or <a href="themes.php?page=nebula_options&tab=analytics&option=gtm_id">GTM ID</a>.',
                            'url' => admin_url('themes.php?page=nebula_options&tab=analytics&option=ga_tracking_id')
                        );
                    }
                }

                //Service Worker checks
                if ( $this->get_option('service_worker') ){
                    //Check for Service Worker JavaScript file when using Service Worker
                    if ( !file_exists($this->sw_location(false)) ){
                        $nebula_warnings['sw_missing'] = array(
                            'level' => 'error',
                            'description' => '<i class="far fa-fw fa-file"></i> Service Worker is enabled in <a href="themes.php?page=nebula_options&tab=functions&option=service_worker">Nebula Options</a>, but no Service Worker JavaScript file was found. Either use the <a href="https://github.com/chrisblakley/Nebula/blob/main/Nebula-Child/resources/sw.js" target="_blank">provided sw.js file</a> (by moving it to the root directory), or override the function <a href="https://nebula.gearside.com/functions/sw_location/?utm_campaign=documentation&utm_medium=admin+notice&utm_source=service+worker#override" target="_blank">sw_location()</a> to locate the actual JavaScript file you are using.'
                        );
                    }

                    //Check for /offline page when using Service Worker
                    if ( $this->is_warning_level('verbose') ){
                        $offline_page = get_page_by_path('offline');
                        if ( is_null($offline_page) ){
                            $nebula_warnings['sw_offline'] = array(
                                'level' => 'warning',
                                'description' => '<i class="fas fa-fw fa-ethernet"></i> It is recommended to make an Offline page when using Service Worker. <a href="post-new.php?post_type=page">Manually add one</a>'
                            );
                        }
                    }

                    //Check for SSL when using Service Worker
                    if ( !is_ssl() ){
                        $nebula_warnings['sw_ssl'] = array(
                            'level' => 'warning',
                            'description' => '<i class="fas fa-fw fa-lock-open"></i> Service Worker requires an SSL. Either update the site to https or <a href="themes.php?page=nebula_options&tab=functions&option=service_worker">disable Service Worker</a>.'
                        );
                    }
                }

                //Check for "Just Another WordPress Blog" tagline
                if ( strtolower(get_bloginfo('description')) === 'just another wordpress site' ){
                    $nebula_warnings['default_tagline'] = array(
                        'level' => 'warning',
                        'description' => '<a href="options-general.php">Site Tagline</a> is still "Just Another WordPress Site"!',
                        'url' => admin_url('options-general.php')
                    );
                }

                //Ensure a privacy policy is set with WordPress core
                if ( empty(get_privacy_policy_url()) ){
                    $nebula_warnings['missing_privacy_policy'] = array(
                        'level' => 'warning',
                        'description' => '<i class="fas fa-fw fa-file-alt"></i> <a href="options-privacy.php">Privacy policy</a> is not setup with WordPress.',
                        'url' => admin_url('options-privacy.php')
                    );
                }

                //Check if all Sass files were processed
                if ( !empty($this->sass_process_status) ){
                    $nebula_warnings['sass_status'] = array(
                        'level' => 'log',
                        'description' => '<i class="fab fa-fw fa-sass"></i> ' . $this->sass_process_status
                    );
                }

                $all_nebula_warnings = apply_filters('nebula_warnings', $nebula_warnings); //Allow other functions to hook in to add warnings (like Ecommerce)

                //Check for improper hooks
                if ( is_null($all_nebula_warnings) ){
                    $all_nebula_warnings = array(array(
                        'level' => 'error',
                        'description' => '<i class="fas fa-fw fa-skull"></i> <code>$nebula_warnings</code> array is null. When hooking into the <code>nebula_warnings</code> filter be sure that it is returned too!'
                    ));
                }

                //Sort by warning level
                if ( !empty($all_nebula_warnings) ){
                    usort($all_nebula_warnings, function($itemA, $itemB){
                        $priorities = array('error', 'warning', 'log');
                        $a = array_search($itemA['level'], $priorities);
                        $b = array_search($itemB['level'], $priorities);

                        if ( $a === $b ){
                            return 0;
                        }

                        return ( $a < $b )? -1 : 1;
                    });
                }

                wp_cache_set('nebula_warnings', $all_nebula_warnings); //Store in object cache
                $this->timer('Check Warnings', 'end');
                return $all_nebula_warnings;
            }

            return array(); //Return empty array instead of false
        }

Override

This function can not be short-circuited with an override filter. Request one?