Location: PHPKode > projects > fluf > fluf-master/lib/fluf.php
<?php
/**
 * (fluf) php
 *
 * A Micro-Routing / Web Application Framework for PHP(5) - Without the excess "fluf"
 *
 * @version 1.0.4
 * @author Nijiko Yonskai <http://nexua.org>
 * @package fluf
 * @license AOL <http://aol.nexua.org/#!/fluf.php/Nijiko+Yonskai/hide@address.com/nijikokun>
 */

namespace {
  class fluf {
    static $server, $env, $files, $request, $get, $post, $session, $cookie, $uri, $method, $script, $autorun = true;
    private static $routes = array();

    static function setup () {
      self::$session = new \fluf\Session('fluf_session');
      foreach (array('request','post','get','server','env','files') as $method)
        self::${$method} = new \fluf\Arrays($GLOBALS['_'.strtoupper($method)]);
      self::$uri = preg_replace('/\?.+/', '', self::$server->REQUEST_URI);
      self::$method = self::$server->REQUEST_METHOD;
      self::$script = self::$server->SCRIPT_NAME;
      self::sanitize();
    }

    private static function sanitize () {
      $uri = explode('/', self::$uri); $name = explode('/', self::$script);
      for ($i = 0; $i < count($name); $i++) if ($uri[$i] == $name[$i]) unset($uri[$i]);
      self::$uri = '/' . implode('/', $uri);
    }

    static function handleResult ($result) {
      if (is_array($result)) { header('Content-type: application/json; charset=utf-8'); echo json_encode($result); }
    }

    static function add ($rule, $method, $middleware = null, $callback = null, $cond = null) {
      if (!empty($middleware)) { if (empty($callback)) { if (is_callable($middleware)) $callback = $middleware; $middleware = null;  } else if (!is_callable($callback)) { $cond = $callback; $callback = $middleware; $middleware = null; } }
      self::$routes[] = new \fluf\Route(self::$uri, $rule, $method, $middleware, $callback, $cond);
      if (self::$autorun) self::run();
    }

    static function ajax ($x = 'HTTP_X_REQUESTED_WITH') {
      return isset($_SERVER[$x]) &&  $_SERVER[$x] === 'XMLHttpRequest';
    }

    static function redirect($path, $exit = true) {
      $uri = "/" . str_replace($_SERVER['DOCUMENT_ROOT'], '', dirname($_SERVER['SCRIPT_FILENAME']));
      header('Location: ' . ((preg_match('%^http\:\/\/|https\:\/\/%', $path) > 0) ? $path : $uri . $path)); if($exit) exit;
    }

    static function run () {
      foreach (self::$routes as $i => $r) {
        if ($r->match && !$r->ran) {
          if (!empty($r->middleware) && count($r->middleware) > 0) {
            $next = function ($error = null) use (&$r, &$next) { $r->mwarecount++;
              if ($error = 'route' || $r->mwarecount >= count($r->middleware)) { $r->mwarecount = 0; fluf::handleResult(call_user_func_array($r->callback, $r->params)); }
              else if (!empty($error) && is_string($error)) throw new Exception($error);
              else call_user_func_array($r->middleware[$r->mwarecount], array(&$r->params, $next));
            };
            call_user_func_array($r->middleware[$r->mwarecount], array($r->params, $next));
          } else fluf::handleResult(call_user_func_array($r->callback, $r->params));
          $r->ran = true;
        } else unset(self::$routes[$i]);
      }
    }
  }

  fluf::setup();
}

namespace fluf {
  class Arrays {
    protected $a;
    public function __construct (&$a) { $this->a = $a; }
    public function __invoke ($k, $v) { if(!isset($v)) return isset($this->a[$k]) ? $this->a[$k] : null; $this->a[$k] = $v; return $v; }
    public function __get ($k) { return isset($this->a[$k]) ? $this->a[$k] : null; }
    public function __set ($k, $v) { $this->a[$k] = $v; return $v; }
  }

  class Session extends Arrays {
    public function __construct ($name) { session_name($name); session_start(); parent::__construct($GLOBALS['_SESSION']); }
    public function __unset ($k) { if (isset($this->a[$k])) unset($this->a[$k]); }
    public function destroy ($unset = false) { if($unset) session_unset(); return session_destroy(); }
  }

  class Cookie extends Arrays {
    public function __construct () { parent::__construct($GLOBALS['_COOKIE']); }
    public function __invoke ($k, $v, $expires = '+30 Days', $path = null, $domain = null, $secure = false, $httponly = false) { if (!isset($v)) (isset($this->a[$k]) ? $this->a[$k] : null); else return $this->set($k, $v, $expires, $path, $domain, $secure, $httponly); }
    public function __set ($k, $v) { return $this->set($k, $v); }
    public function __unset ($k) { if (isset($this->a[$k])) unset($this->a[$k]); return setcookie($k, null, -1); }
    public function set ($k, $v, $expires = '+30 Days', $path = null, $domain = null, $secure = false, $httponly = false) { return setcookie($k, $v, is_string($expires) ? strtotime($expires) : $expires, $path, $domain, $secure, $httponly); }
  }

  class Route {
    public $url, $callback, $middleware = array(), $mwarecount = 0, $match = false, $ran = false, $params = array();
    private $conditions, $uri;

    function __construct ($uri, $url, $method, $middleware = null, $callback = null, $cond = null) {
      if (empty($uri) || empty($url) || empty($method) || empty($callback)) { echo 'empty parameter'; return; }
      if (is_callable($callback)) $this->callback = $callback;
      if (!empty($middleware)) if (is_string($middleware) && is_callable($middleware)) $this->middleware[] = $middleware;
      else if (is_array($middleware)) foreach ($middleware as $key => $value) if (is_callable($value)) $this->middleware[] = $value;
      $this->method = is_array($method) ? $method : array( $method );
      $this->conditions = is_array($cond) ? $cond : array(); $this->url = $url; $this->uri = $uri;
      $this->compile();
    }

    function compile () {
      $names = $values = array(); 
      preg_match_all('@:([\w]+)@', $this->url, $names, PREG_PATTERN_ORDER); $names = $names[0];
      $regex = (preg_replace_callback('@:[\w]+@', array($this, 'regex'), $this->url)) . '/?';
      
      if (preg_match('@^' . $regex . '$@', $this->uri, $values) && in_array(\fluf::$method, $this->method) && array_shift($values)) {
        foreach ($names as $i => $v) $this->params[substr($v,1)] = urldecode($values[$i]);
        $this->match = true;
      }
    }

    function regex ($matches) {
      $key = str_replace(':', '', $matches[0]);
      return array_key_exists($key, $this->conditions) ?  '('.$this->conditions[$key].')' : '([a-zA-Z0-9_\+\-%]+)';
    }
  }

  function map ($rule, $middleware = null, $callback = null, $cond = null) {
    return new \fluf\Map($rule, $middleware, $callback, is_array($cond) ? $cond : array()); 
  }
  
  foreach (array('get','post','put','delete','patch','head','options') as $method) 
    eval('namespace fluf; function '.$method.' ($rule, $middleware = null, $callback = null, $cond = null) { \fluf::add($rule, "'.strtoupper($method).'", $middleware, $callback, $cond); }');

  class Map {
    function __construct ($rule, $middleware, $callback, $cond = array()) { $this->r = $rule; $this->middleware = $middleware; $this->cb = $callback; $this->cd = $cond; return $this; }
    public function via () { if (func_num_args() !== 0) foreach (func_get_args() as $a) \fluf::add($this->r, strtoupper($a), $this->middleware, $this->cb, $this->cd); }
  }
}
Return current item: fluf