<?php

	final class SjFileGroupCache extends SjBaseCache
	{
		protected $dir;

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

			if (!$self) {
				$self = new SjFileGroupCache($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)) {
						$fname = $this->groupToPath($group);
						@file_put_contents($fname, serialize($this->cache[$group]), LOCK_EX);
					}
				}
			}

			parent::close();
		}

		public function delete($key, $group)
		{
			parent::delete($key, $group);
			$this->dirty[$group] = true;
			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);
			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 && !in_array($group, $this->np_groups) && !isset($this->cache[$group])) {
				$fname = $this->groupToPath($group);
				if (is_readable($fname)) {
					if (filemtime($fname) > time() - $ttl) {
						settype($fname, 'string');
						$this->cache[$group] = unserialize(@file_get_contents($fname));
						return $this->fast_get($key, $group);
					}
				}

				@unlink($fname);
			}

			return false;
		}

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

			if (!$ttl && $this->maxttl) {
				$ttl = $this->maxttl;
			}

			$this->dirty[$group] = $ttl;
			$this->fast_set($key, $data, $group);
			return true;
		}

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