HEX
Server: Apache/2.4.29 (Ubuntu)
System: Linux bareserver 4.15.0-213-generic #224-Ubuntu SMP Mon Jun 19 13:30:12 UTC 2023 x86_64
User: root (0)
PHP: 7.2.24-0ubuntu0.18.04.17
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
Upload Files
File: /var/www/html/site/newsite/wp-content/themes/ooze/inc/webfont/class-theme-webfont-loader.php
<?php
/**
 * Download webfonts locally.
 *
 * @package wptt/font-loader
 * @license https://opensource.org/licenses/MIT
 */

if ( ! class_exists( 'WPTT_WebFont_Loader' ) ) {
    /**
     * Download webfonts locally.
     */
    class WPTT_WebFont_Loader {

        /**
         * The font-format.
         *
         * Use "woff" or "woff2".
         * This will change the user-agent user to make the request.
         *
         * @access protected
         * @since 1.0.0
         * @var string
         */
        protected $font_format = 'woff2';

        /**
         * The remote URL.
         *
         * @access protected
         * @since 1.1.0
         * @var string
         */
        protected $remote_url;

        /**
         * Base path.
         *
         * @access protected
         * @since 1.1.0
         * @var string
         */
        protected $base_path;

        /**
         * Base URL.
         *
         * @access protected
         * @since 1.1.0
         * @var string
         */
        protected $base_url;

        /**
         * Subfolder name.
         *
         * @access protected
         * @since 1.1.0
         * @var string
         */
        protected $subfolder_name;

        /**
         * The fonts folder.
         *
         * @access protected
         * @since 1.1.0
         * @var string
         */
        protected $fonts_folder;

        /**
         * The local stylesheet's path.
         *
         * @access protected
         * @since 1.1.0
         * @var string
         */
        protected $local_stylesheet_path;

        /**
         * The local stylesheet's URL.
         *
         * @access protected
         * @since 1.1.0
         * @var string
         */
        protected $local_stylesheet_url;

        /**
         * The remote CSS.
         *
         * @access protected
         * @since 1.1.0
         * @var string
         */
        protected $remote_styles;

        /**
         * The final CSS.
         *
         * @access protected
         * @since 1.1.0
         * @var string
         */
        protected $css;

        /**
         * Cleanup routine frequency.
         */
        const CLEANUP_FREQUENCY = 'monthly';

        /**
         * Constructor.
         *
         * Get a new instance of the object for a new URL.
         *
         * @access public
         * @since 1.1.0
         * @param string $url The remote URL.
         */
        public function __construct( $url = '' ) {
            $this->remote_url = $url;

            // Add a cleanup routine.
            $this->schedule_cleanup();
            add_action( 'delete_fonts_folder', array( $this, 'delete_fonts_folder' ) );
        }

        /**
         * Get the local URL which contains the styles.
         *
         * Fallback to the remote URL if we were unable to write the file locally.
         *
         * @access public
         * @since 1.1.0
         * @return string
         */
        public function get_url() {

            // Check if the local stylesheet exists.
            if ( $this->local_file_exists() ) {

                // Attempt to update the stylesheet. Return the local URL on success.
                if ( $this->write_stylesheet() ) {
                    return $this->get_local_stylesheet_url();
                }
            }

            // If the local file exists, return its URL, with a fallback to the remote URL.
            return file_exists( $this->get_local_stylesheet_path() )
                ? $this->get_local_stylesheet_url()
                : $this->remote_url;
        }

        /**
         * Get the local stylesheet URL.
         *
         * @access public
         * @since 1.1.0
         * @return string
         */
        public function get_local_stylesheet_url() {
            if ( ! $this->local_stylesheet_url ) {
                $this->local_stylesheet_url = str_replace(
                    $this->get_base_path(),
                    $this->get_base_url(),
                    $this->get_local_stylesheet_path()
                );
            }
            return $this->local_stylesheet_url;
        }

        /**
         * Get styles with fonts downloaded locally.
         *
         * @access public
         * @since 1.0.0
         * @return string
         */
        public function get_styles() {

            // If we already have the local file, return its contents.
            $local_stylesheet_contents = $this->get_local_stylesheet_contents();
            if ( $local_stylesheet_contents ) {
                return $local_stylesheet_contents;
            }

            // Get the remote URL contents.
            $this->remote_styles = $this->get_remote_url_contents();

            // Get an array of locally-hosted files.
            $files = $this->get_local_files_from_css();

            // Convert paths to URLs.
            foreach ( $files as $remote => $local ) {
                $files[ $remote ] = str_replace(
                    $this->get_base_path(),
                    $this->get_base_url(),
                    $local
                );
            }

            $this->css = str_replace(
                array_keys( $files ),
                array_values( $files ),
                $this->remote_styles
            );

            $this->write_stylesheet();

            return $this->css;
        }

        /**
         * Get local stylesheet contents.
         *
         * @access public
         * @since 1.1.0
         * @return string|false Returns the remote URL contents.
         */
        public function get_local_stylesheet_contents() {
            $local_path = $this->get_local_stylesheet_path();

            // Check if the local stylesheet exists.
            if ( $this->local_file_exists() ) {

                // Attempt to update the stylesheet. Return false on fail.
                if ( ! $this->write_stylesheet() ) {
                    return false;
                }
            }

            ob_start();
            include $local_path;
            return ob_get_clean();
        }

        /**
         * Get remote file contents.
         *
         * @access public
         * @since 1.0.0
         * @return string Returns the remote URL contents.
         */
        public function get_remote_url_contents() {

            /**
             * The user-agent we want to use.
             *
             * The default user-agent is the only one compatible with woff (not woff2)
             * which also supports unicode ranges.
             */
            $user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8';

            // Switch to a user-agent supporting woff2 if we don't need to support IE.
            if ( 'woff2' === $this->font_format ) {
                $user_agent = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0';
            }

            // Get the response.
            $response = wp_remote_get( $this->remote_url, array( 'user-agent' => $user_agent ) );

            // Early exit if there was an error.
            if ( is_wp_error( $response ) ) {
                return '';
            }

            // Get the CSS from our response.
            $contents = wp_remote_retrieve_body( $response );

            return $contents;
        }

        /**
         * Download files mentioned in our CSS locally.
         *
         * @access public
         * @since 1.0.0
         * @return array Returns an array of remote URLs and their local counterparts.
         */
        public function get_local_files_from_css() {
            $font_files = $this->get_remote_files_from_css();
            $stored     = get_site_option( 'downloaded_font_files', array() );
            $change     = false; // If in the end this is true, we need to update the cache option.

            if ( ! defined( 'FS_CHMOD_DIR' ) ) {
                define( 'FS_CHMOD_DIR', ( 0755 & ~ umask() ) );
            }

            // If the fonts folder don't exist, create it.
            if ( ! file_exists( $this->get_fonts_folder() ) ) {
                $this->get_filesystem()->mkdir( $this->get_fonts_folder(), FS_CHMOD_DIR );
            }

            foreach ( $font_files as $font_family => $files ) {

                // The folder path for this font-family.
                $folder_path = $this->get_fonts_folder() . '/' . $font_family;

                // If the folder doesn't exist, create it.
                if ( ! file_exists( $folder_path ) ) {
                    $this->get_filesystem()->mkdir( $folder_path, FS_CHMOD_DIR );
                }

                foreach ( $files as $url ) {

                    // Get the filename.
                    $filename  = basename( wp_parse_url( $url, PHP_URL_PATH ) );
                    $font_path = $folder_path . '/' . $filename;

                    // Check if the file already exists.
                    if ( file_exists( $font_path ) ) {

                        // Skip if already cached.
                        if ( isset( $stored[ $url ] ) ) {
                            continue;
                        }

                        // Add file to the cache and change the $changed var to indicate we need to update the option.
                        $stored[ $url ] = $font_path;
                        $change         = true;

                        // Since the file exists we don't need to proceed with downloading it.
                        continue;
                    }

                    /**
                     * If we got this far, we need to download the file.
                     */

                    // require file.php if the download_url function doesn't exist.
                    if ( ! function_exists( 'download_url' ) ) {
                        require_once wp_normalize_path( ABSPATH . '/wp-admin/includes/file.php' );
                    }

                    // Download file to temporary location.
                    $tmp_path = download_url( $url );

                    // Make sure there were no errors.
                    if ( is_wp_error( $tmp_path ) ) {
                        continue;
                    }

                    // Move temp file to final destination.
                    $success = $this->get_filesystem()->move( $tmp_path, $font_path, true );
                    if ( $success ) {
                        $stored[ $url ] = $font_path;
                        $change         = true;
                    }
                }
            }

            // If there were changes, update the option.
            if ( $change ) {

                // Cleanup the option and then save it.
                foreach ( $stored as $url => $path ) {
                    if ( ! file_exists( $path ) ) {
                        unset( $stored[ $url ] );
                    }
                }
                update_site_option( 'downloaded_font_files', $stored );
            }

            return $stored;
        }

        /**
         * Get font files from the CSS.
         *
         * @access public
         * @since 1.0.0
         * @return array Returns an array of font-families and the font-files used.
         */
        public function get_remote_files_from_css() {

            $font_faces = explode( '@font-face', $this->remote_styles );

            $result = array();

            // Loop all our font-face declarations.
            foreach ( $font_faces as $font_face ) {

                // Make sure we only process styles inside this declaration.
                $style = explode( '}', $font_face )[0];

                // Sanity check.
                if ( false === strpos( $style, 'font-family' ) ) {
                    continue;
                }

                // Get an array of our font-families.
                preg_match_all( '/font-family.*?\;/', $style, $matched_font_families );

                // Get an array of our font-files.
                preg_match_all( '/url\(.*?\)/i', $style, $matched_font_files );

                // Get the font-family name.
                $font_family = 'unknown';
                if ( isset( $matched_font_families[0] ) && isset( $matched_font_families[0][0] ) ) {
                    $font_family = rtrim( ltrim( $matched_font_families[0][0], 'font-family:' ), ';' );
                    $font_family = trim( str_replace( array( "'", ';' ), '', $font_family ) );
                    $font_family = sanitize_key( strtolower( str_replace( ' ', '-', $font_family ) ) );
                }

                // Make sure the font-family is set in our array.
                if ( ! isset( $result[ $font_family ] ) ) {
                    $result[ $font_family ] = array();
                }

                // Get files for this font-family and add them to the array.
                foreach ( $matched_font_files as $match ) {

                    // Sanity check.
                    if ( ! isset( $match[0] ) ) {
                        continue;
                    }

                    // Add the file URL.
                    $font_family_url = rtrim( ltrim( $match[0], 'url(' ), ')' );
                    $font_family_url = str_replace( '"', '', $font_family_url );

                    // Make sure to convert relative URLs to absolute.
                    $font_family_url = $this->get_absolute_path( $font_family_url );

                    $result[ $font_family ][] = $font_family_url;
                }

                // Make sure we have unique items.
                // We're using array_flip here instead of array_unique for improved performance.
                $result[ $font_family ] = array_flip( array_flip( $result[ $font_family ] ) );
            }
            return $result;
        }

        /**
         * Write the CSS to the filesystem.
         *
         * @access protected
         * @since 1.1.0
         * @return string|false Returns the absolute path of the file on success, or false on fail.
         */
        protected function write_stylesheet() {
            $file_path  = $this->get_local_stylesheet_path();
            $filesystem = $this->get_filesystem();

            if ( ! defined( 'FS_CHMOD_DIR' ) ) {
                define( 'FS_CHMOD_DIR', ( 0755 & ~ umask() ) );
            }

            // If the folder doesn't exist, create it.
            if ( ! file_exists( $this->get_fonts_folder() ) ) {
                $this->get_filesystem()->mkdir( $this->get_fonts_folder(), FS_CHMOD_DIR );
            }

            // If the file doesn't exist, create it. Return false if it can not be created.
            if ( ! $filesystem->exists( $file_path ) && ! $filesystem->touch( $file_path ) ) {
                return false;
            }

            // If we got this far, we need to write the file.
            // Get the CSS.
            if ( ! $this->css ) {
                $this->get_styles();
            }

            // Put the contents in the file. Return false if that fails.
            if ( ! $filesystem->put_contents( $file_path, $this->css ) ) {
                return false;
            }

            return $file_path;
        }

        /**
         * Get the stylesheet path.
         *
         * @access public
         * @since 1.1.0
         * @return string
         */
        public function get_local_stylesheet_path() {
            if ( ! $this->local_stylesheet_path ) {
                $this->local_stylesheet_path = $this->get_fonts_folder() . '/' . $this->get_local_stylesheet_filename() . '.css';
            }
            return $this->local_stylesheet_path;
        }

        /**
         * Get the local stylesheet filename.
         *
         * This is a hash, generated from the site-URL, the wp-content path and the URL.
         * This way we can avoid issues with sites changing their URL, or the wp-content path etc.
         *
         * @access public
         * @since 1.1.0
         * @return string
         */
        public function get_local_stylesheet_filename() {
            return md5( $this->get_base_url() . $this->get_base_path() . $this->remote_url . $this->font_format );
        }

        /**
         * Set the font-format to be used.
         *
         * @access public
         * @since 1.0.0
         * @param string $format The format to be used. Use "woff" or "woff2".
         * @return void
         */
        public function set_font_format( $format = 'woff2' ) {
            $this->font_format = $format;
        }

        /**
         * Check if the local stylesheet exists.
         *
         * @access public
         * @since 1.1.0
         * @return bool
         */
        public function local_file_exists() {
            return ( ! file_exists( $this->get_local_stylesheet_path() ) );
        }

        /**
         * Get the base path.
         *
         * @access public
         * @since 1.1.0
         * @return string
         */
        public function get_base_path() {
            if ( ! $this->base_path ) {
                $this->base_path = apply_filters( 'wptt_get_local_fonts_base_path', $this->get_filesystem()->wp_content_dir() );
            }
            return $this->base_path;
        }

        /**
         * Get the base URL.
         *
         * @access public
         * @since 1.1.0
         * @return string
         */
        public function get_base_url() {
            if ( ! $this->base_url ) {
                $this->base_url = apply_filters( 'wptt_get_local_fonts_base_url', content_url() );
            }
            return $this->base_url;
        }

        /**
         * Get the subfolder name.
         *
         * @access public
         * @since 1.1.0
         * @return string
         */
        public function get_subfolder_name() {
            if ( ! $this->subfolder_name ) {
                $this->subfolder_name = apply_filters( 'wptt_get_local_fonts_subfolder_name', 'fonts' );
            }
            return $this->subfolder_name;
        }

        /**
         * Get the folder for fonts.
         *
         * @access public
         * @return string
         */
        public function get_fonts_folder() {
            if ( ! $this->fonts_folder ) {
                $this->fonts_folder = $this->get_base_path();
                if ( $this->get_subfolder_name() ) {
                    $this->fonts_folder .= '/' . $this->get_subfolder_name();
                }
            }
            return $this->fonts_folder;
        }

        /**
         * Schedule a cleanup.
         *
         * Deletes the fonts files on a regular basis.
         * This way font files will get updated regularly,
         * and we avoid edge cases where unused files remain in the server.
         *
         * @access public
         * @since 1.1.0
         * @return void
         */
        public function schedule_cleanup() {
            if ( ! is_multisite() || ( is_multisite() && is_main_site() ) ) {
                if ( ! wp_next_scheduled( 'delete_fonts_folder' ) && ! wp_installing() ) {
                    wp_schedule_event( time(), self::CLEANUP_FREQUENCY, 'delete_fonts_folder' );
                }
            }
        }

        /**
         * Delete the fonts folder.
         *
         * This runs as part of a cleanup routine.
         *
         * @access public
         * @since 1.1.0
         * @return bool
         */
        public function delete_fonts_folder() {
            return $this->get_filesystem()->delete( $this->get_fonts_folder(), true );
        }

        /**
         * Get the filesystem.
         *
         * @access protected
         * @since 1.0.0
         * @return \WP_Filesystem_Base
         */
        protected function get_filesystem() {
            global $wp_filesystem;

            // If the filesystem has not been instantiated yet, do it here.
            if ( ! $wp_filesystem ) {
                if ( ! function_exists( 'WP_Filesystem' ) ) {
                    require_once wp_normalize_path( ABSPATH . '/wp-admin/includes/file.php' );
                }
                WP_Filesystem();
            }
            return $wp_filesystem;
        }

        /**
         * Get an absolute URL from a relative URL.
         *
         * @access protected
         *
         * @param string $url The URL.
         *
         * @return string
         */
        protected function get_absolute_path( $url ) {

            // If dealing with a root-relative URL.
            if ( 0 === stripos( $url, '/' ) ) {
                $parsed_url = parse_url( $this->remote_url );
                return $parsed_url['scheme'] . '://' . $parsed_url['hostname'] . $url;
            }

            return $url;
        }
    }
}

if ( ! function_exists( 'wptt_get_webfont_styles' ) ) {
    /**
     * Get styles for a webfont.
     *
     * This will get the CSS from the remote API,
     * download any fonts it contains,
     * replace references to remote URLs with locally-downloaded assets,
     * and finally return the resulting CSS.
     *
     * @since 1.0.0
     *
     * @param string $url    The URL of the remote webfont.
     * @param string $format The font-format. If you need to support IE, change this to "woff".
     *
     * @return string Returns the CSS.
     */
    function wptt_get_webfont_styles( $url, $format = 'woff2' ) {
        $font = new WPTT_WebFont_Loader( $url );
        $font->set_font_format( $format );
        return $font->get_styles();
    }
}

if ( ! function_exists( 'wptt_get_webfont_url' ) ) {
    /**
     * Get a stylesheet URL for a webfont.
     *
     * @since 1.1.0
     *
     * @param string $url    The URL of the remote webfont.
     * @param string $format The font-format. If you need to support IE, change this to "woff".
     *
     * @return string Returns the CSS.
     */
    function wptt_get_webfont_url( $url, $format = 'woff2' ) {
        $font = new WPTT_WebFont_Loader( $url );
        $font->set_font_format( $format );
        return $font->get_url();
    }
}