<?php
if (!defined('PLUGIN_CACHE_FILE_EXPIRE_MAX')) {
    define('PLUGIN_CACHE_FILE_EXPIRE_MAX', 2592000);
}

/**
 * File class
 */
/**
 * Class Plugin_Cache_File
 */
class Plugin_Cache_File
{
    /**
     * Path to cache dir
     *
     * @var string
     */
    var $_cache_dir = '';

    /**
     * File locking
     *
     * @var boolean
     */
    var $_locking = false;

    /**
     * PHP5 constructor
     *
     * @param array $config
     */
    /* function __construct($config = array())
    {
        $cache_dir = isset($config['cache_dir']) ? trim($config['cache_dir']) :WP_CONTENT_DIR.'/apptivo-cache';
        if(!@is_dir($cache_dir))
            if(@mkdir ($cache_dir))
                 @chmod($cache_dir, 0755);
        $this->_cache_dir = $cache_dir;
        $this->_locking = isset($config['locking']) ? (boolean) $config['locking'] : false;
    } */
    function __construct($config = array()) {
        $cache_dir = isset($config['cache_dir']) ? trim($config['cache_dir']) : WP_CONTENT_DIR . '/apptivo-cache';

        global $wp_filesystem;

        if ( ! function_exists( 'request_filesystem_credentials' ) ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }

        // Initialize the WP_Filesystem
        if ( false === ( $creds = request_filesystem_credentials( site_url() ) ) || ! WP_Filesystem( $creds ) ) {
            // Handle failure if needed
            return;
        }

        // Check if directory exists
        if ( ! $wp_filesystem->is_dir( $cache_dir ) ) {
            // Create directory
            if ( $wp_filesystem->mkdir( $cache_dir ) ) {
                $wp_filesystem->chmod( $cache_dir, 0755 );
            }
        }

        $this->_cache_dir = $cache_dir;
        $this->_locking = isset($config['locking']) ? (bool) $config['locking'] : false;
    }


    /**
     * PHP4 constructor
     *
     * @paran array $config
     * @return W3_Cache_File
     */
    function Plugin_Cache_File($config = array())
    {
        $this->__construct($config);
    }

    /**
     * Adds data
     *
     * @param string $key
     * @param mixed $var
     * @param integer $expire
     * @return boolean
     */
    function add($key, &$var, $expire = 0)
    {
        if ($this->get($key) === false) {
            return $this->set($key, $var, $expire);
        }

        return false;
    }

    /**
     * Sets data
     *
     * @param string $key
     * @param mixed $var
     * @param integer $expire
     * @return boolean
     */
    /* function set($key, &$var, $expire = 0)
    {
        $sub_path = $this->_get_path($key); 
        $path = $this->_cache_dir . '/' . $sub_path;
        $sub_dir = dirname($sub_path);
        $dir = dirname($path);
        if ((@is_dir($dir) || awp_mkdir($sub_dir, 0755, $this->_cache_dir))) {
            $fp = @fopen($path, 'wb');

            if ($fp) {
                if ($this->_locking) {
                    @flock($fp, LOCK_EX);
                }

                @fputs($fp, pack('L', $expire));
                @fputs($fp, @serialize($var));
                @fclose($fp);

                if ($this->_locking) {
                    @flock($fp, LOCK_UN);
                }
                return true;
            }
        }
        return false;
    } */
    function set($key, &$var, $expire = 0) {
        global $wp_filesystem;

        if ( ! function_exists( 'request_filesystem_credentials' ) ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }

        if ( ! $wp_filesystem || ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
            WP_Filesystem();
        }

        $sub_path = $this->_get_path($key);
        $path = $this->_cache_dir . '/' . $sub_path;
        $sub_dir = dirname($sub_path);
        $dir = dirname($path);

        if ( $wp_filesystem->is_dir($dir) || awp_mkdir($sub_dir, 0755, $this->_cache_dir) ) {
            $content = pack('L', $expire) . serialize($var);
            $result = $wp_filesystem->put_contents($path, $content, FS_CHMOD_FILE); // Default: 0644

            return $result;
        }

        return false;
    }

    /**
     * Returns data
     *
     * @param string $key
     * @return mixed
     */
    /* function get($key)
    {
        $var = false;
        $path = $this->_cache_dir . '/' . $this->_get_path($key);

        if (is_readable($path)) {
            $ftime = @filemtime($path);

            if ($ftime) {
                $fp = @fopen($path, 'rb');

                if ($fp) {
                    if ($this->_locking) {
                        @flock($fp, LOCK_SH);
                    }

                    $expires = @fread($fp, 4);

                    if ($expires !== false) {
                        list(, $expire) = @unpack('L', $expires);
                        $expire = ($expire && $expire <= PLUGIN_CACHE_FILE_EXPIRE_MAX ? $expire : PLUGIN_CACHE_FILE_EXPIRE_MAX);

                        if ($ftime > time() - $expire) {
                            $data = '';

                            while (!@feof($fp)) {
                                $data .= @fread($fp, 4096);
                            }

                            $var = @unserialize($data);
                        }
                    }

                    if ($this->_locking) {
                        @flock($fp, LOCK_UN);
                    }

                    @fclose($fp);
                }
            }
        }

        return $var;
    } */
    function get($key) {
        global $wp_filesystem;

        if ( ! function_exists('request_filesystem_credentials') ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }

        if ( ! $wp_filesystem || ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
            WP_Filesystem();
        }

        $var = false;
        $path = $this->_cache_dir . '/' . $this->_get_path($key);

        if ( $wp_filesystem->exists($path) && $wp_filesystem->is_readable($path) ) {
            $ftime = $wp_filesystem->mtime($path);

            if ($ftime) {
                $contents = $wp_filesystem->get_contents($path);

                if ($contents !== false && strlen($contents) > 4) {
                    $expires_data = substr($contents, 0, 4);
                    $data = substr($contents, 4);

                    $unpacked = @unpack('L', $expires_data);
                    if (is_array($unpacked)) {
                        $expire = $unpacked[1];
                        $expire = ($expire && $expire <= PLUGIN_CACHE_FILE_EXPIRE_MAX) ? $expire : PLUGIN_CACHE_FILE_EXPIRE_MAX;

                        if ($ftime > time() - $expire) {
                            $var = @unserialize($data);
                        }
                    }
                }
            }
        }

        return $var;
    }


    /**
     * Replaces data
     *
     * @param string $key
     * @param mixed $var
     * @param integer $expire
     * @return boolean
     */
    function replace($key, &$var, $expire = 0)
    {
        if ($this->get($key) !== false) {
            return $this->set($key, $var, $expire);
        }

        return false;
    }

    /**
     * Deletes data
     *
     * @param string $key
     * @return boolean
     */
    /*function delete($key)
    {
        $path = $this->_cache_dir . '/' . $this->_get_path($key);

        if (file_exists($path)) {
            return @unlink($path);
        }

        return false;
    } */
    function delete($key) {
        $path = $this->_cache_dir . '/' . $this->_get_path($key);

        if ( file_exists($path) ) {
            return wp_delete_file($path); // Proper WP function for deleting files
        }

        return false;
    }

    /**
     * Flushes all data
     *
     * @return boolean
     */
    /* function flush()
    {
        @set_time_limit(180);

        awp_emptydir($this->_cache_dir);

        return true;
    } */
    function flush() {
        // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged
        if (function_exists('set_time_limit')) {
            @set_time_limit(180);
        }

        awp_emptydir($this->_cache_dir);

        return true;
    }

    /**
     * Returns modification time of cache file
     *
     * @param integer $key
     */
    function mtime($key)
    {
        $path = $this->_cache_dir . '/' . $this->_get_path($key);

        if (file_exists($path)) {
            return @filemtime($path);
        }

        return false;
    }

    /**
     * Returns file path for key
     *
     * @param string $key
     * @return string
     */
    function _get_path($key)
    {
        $hash = md5($key);
        $path = sprintf('%s/%s/%s/%s', substr($hash, 0, 1), substr($hash, 1, 1), substr($hash, 2, 1), $hash);

        return $path;
    }
}