Simple PHP Cache

When your application requires fetching resources from other Web sites, it's never a good idea to fetch it from the remote site upon every visit to your site. I needed this to incorporate Flickr, Twitter, and Google Buzz into my own site. So I wrote this Cache class. Instead of using file_get_contents($url) to fetch an external resource, simply use $cache->get($url) instead. Everything is transparent, and the cache will refresh itself every hour.

See my Twitter, FriendFeed and Google Buzz scripts for examples of how to use it.

<?php
  class Cache {
    private $dir;

    public function __construct($dir) {
      if (!file_exists($dir)) mkdir($dir, 0777, true);
      if (!is_writable($dir)) {
        throw new Exception('Cache directory is not writable!');
      }
      $this->dir = $dir;
    }

    public function refresh($url) {
      if (preg_match('/^http[s]{0,1}:\/\//i', $url) != 0) {
        $contents = file_get_contents($url);
        if ($contents === '') {
          return;
        }
        $this->writeToFile($this->getCacheFileName($url), $contents);
      }
    }

    public function set($url, $contents) {
      $this->writeToFile($this->getCacheFileName($url), $contents);
    }

    public function get($url) {
      $localFile = $this->getCacheFileName($url);
      $mustRefresh = (isset($_GET['cache']) && $_GET['cache'] === '0');
      if ($mustRefresh || !file_exists($localFile)) {
        $this->refresh($url);
      }

      // Refresh every hour.
      if (time() - filemtime($localFile) > 60 * 60) {
        $this->refresh($url);
      }

      return file_get_contents($localFile);
    }

    public function getWithoutRefreshing($url) {
      return file_get_contents($this->getCacheFileName($url));
    }

    public function exists($url) {
      return file_exists($this->getCacheFileName($url));
    }

    public function getLastRefreshed($url) {
      return filemtime($this->getCacheFileName($url));
    }

    private function getCacheFileName($url) {
      $parsed = parse_url($url);
      $fileName = $this->dir . '/' . $parsed['host'];
      $fileName .= isset($parsed['path'])
          ? str_replace(array('/', ':', '&', '=', '@'), '_', $parsed['path'])
          : '';
      $fileName .= isset($parsed['query']) 
          ? str_replace(array('/', ':', '&', '=', '@'), '_', $parsed['query'])
          : '';
      return $fileName . '.cache';
    }

    private function writeToFile($fileName, $data) {
      $fh = fopen($fileName, 'w') or die('Unable to write to file '.$fileName);
      fwrite($fh, $data);
      fclose($fh);
      chmod($fileName, 0777);
    }

    public function clear() {
      $this->rm_rf($this->dir);
    }

    private function rm_rf($dir) {
      if (is_dir($dir)) {
        foreach (scandir($dir) as $item){
          if (!strcmp( $item, '.' ) || !strcmp( $item, '..' )) {
            continue;        
          }
          $this->rm_rf($dir . "/" . $item);
        }
        rmdir($dir);
      }
      else{
        unlink($dir);
      }
    }
  }
  ?>