<?php

	final class SjFileCache extends SjBaseCache
	{
		protected $dir;
		protected $known_groups = array();

		public static function instance($params, $enabled = true, $persist = true, $maxttl = 3600)
		{
			static $self = false;

			if (!$self) {
				$self = new SjFileCache($params, $enabled, $persist, $maxttl);
			}

			return $self;
		}

		protected function __construct($params = array(), $enabled = true, $persist = true, $maxttl = 3600)
		{
			if (empty($params['path'])) {
				$path = dirname(dirname(__FILE__)) . '/cache';
			}
			else {
				$path = $params['path'];
			}

			$this->dir = $path;
			parent::__construct($params, $enabled, $persist, $maxttl);
		}

		public function close()
		{
			if (!empty($this->dirty) && $this->persist) {
				foreach ($this->dirty as $group => $x) {
					if (false === in_array($group, $this->np_groups)) {
						foreach ($x as $key => $y) {
							$fname = $this->keyToPath($key, $group);

							if (!isset($this->known_groups[$group])) {
								$dir = $this->dir . '/' . urlencode($group);
								if (!file_exists($dir)) {
									@mkdir($dir);
								}

								$this->known_groups[$group] = true;
							}

							@file_put_contents($fname, maybe_serialize($this->cache[$group][$key]), LOCK_EX);
						}
					}
				}
			}

			parent::close();
		}

		public function delete($key, $group)
		{
			parent::delete($key, $group);

			if ($this->persist && false === in_array($group, $this->np_groups)) {
				$fname = $this->keyToPath($key, $group);
				return @unlink($fname);
			}

			return true;
		}

		private function remove_dir($dir, $self)
		{
			$dh = @opendir($dir);
			if (false === $dh) {
				return;
			}

			while (false !== ($obj = readdir($dh))) {
				if ('.' == $obj || '..' == $obj) {
					continue;
				}

				if (false == @unlink($dir . '/' . $obj)) {
					$this->remove_dir($dir . '/' . $obj, true);
				}
			}

			closedir($dh);
			if ($self) {
				@rmdir($dir);
			}
		}

		public function flush()
		{
			$this->remove_dir($this->dir, false);
			$this->known_groups = array();
			parent::flush();
		}

		public function get($key, $group, $ttl = 3600)
		{
			if (!$this->enabled) {
				return false;
			}

			$result = $this->fast_get($key, $group);
			if (false !== $result) {
				return $result;
			}

			if ($this->persist && false === in_array($group, $this->np_groups)) {
				$fname = $this->keyToPath($key, $group);
				if (is_readable($fname)) {
					if (filemtime($fname) > time() - $ttl) {
						settype($fname, 'string');
						$result = maybe_unserialize(@file_get_contents($fname, LOCK_EX));
						$this->fast_set($key, $result, $group);
						$this->known_groups[$group] = true;
						return $result;
					}
				}

				@unlink($fname);
			}

			return false;
		}

		private function keyToPath($key, $group)
		{
			return $this->dir . '/' . urlencode($group) . '/' . urlencode($key) . '.cache';
		}
	}
?>