Last active
May 12, 2016 10:52
-
-
Save alash3al/c94aad5c1d46f9ac2209767d79f32050 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Horus "Core" - be simple :) | |
* | |
* This version will only work on PHP 7 and higher . | |
* | |
* @package Horus | |
* @copyright 2014 - 2016 (c) Horus | |
* @author Mohammed Al Ashaal <alash3al.xyz> | |
* @license MIT LICENSE | |
* @version v14 | |
*/ | |
Class Horus extends stdClass { | |
/** | |
* An instance of this class | |
* @var Horus | |
*/ | |
private static $instance; | |
/** | |
* Whether to break the routes chain or not | |
* @var bool | |
*/ | |
private $breakRoutes; | |
/** | |
* The parent of the current route | |
* @var string | |
*/ | |
private $parent; | |
/** | |
* Constructor | |
*/ | |
public function __construct() { | |
static::$instance = $this; | |
$_SERVER["PATH_INFO"] = explode("?", $_SERVER["REQUEST_URI"])[0] ?? $_SERVER["REQUEST_URI"]; | |
$strip = "/"; | |
if ( stripos($_SERVER["PATH_INFO"], $_SERVER["SCRIPT_NAME"]) === 0 ) { | |
$strip = $_SERVER["SCRIPT_NAME"]; | |
} else if ( stripos($_SERVER["PATH_INFO"], dirname($_SERVER["SCRIPT_NAME"])) === 0 ) { | |
$strip = dirname($_SERVER["SCRIPT_NAME"]); | |
} | |
$_SERVER["PATH_INFO"] = preg_replace("~/+~", "/", "/" . substr($_SERVER["PATH_INFO"], strlen($strip)) . "/"); | |
$this->parent = "/"; | |
} | |
/** @ignore */ | |
public function __call($name, $args) { | |
if ( isset($this->{$name}) ) { | |
return call_user_func_array($this->{$name}, $args); | |
} | |
throw new Exception("Undefined method {$name}"); | |
} | |
/** @ignore */ | |
public function __set($name, $val) { | |
if ( $val instanceof Closure ) { | |
$this->{$name} = $val->bindTo($val); | |
} else { | |
$this->{$name} = $val; | |
} | |
} | |
/** | |
* Return horus instance | |
* | |
* @return Horus | |
*/ | |
public static function getInstance() { | |
return static::$instance; | |
} | |
/** | |
* Set http header(s) | |
* | |
* @param mixed $field | |
* @param string $value | |
* @return $this | |
*/ | |
public function set($field, $value = null) { | |
if ( is_array($field) ) { | |
foreach ( $field as $f => $v ) | |
$this->set($f, $v); | |
return $this; | |
} | |
$field = str_replace(' ', '-', ucwords(str_replace('-', ' ', strtolower($field)))); | |
header(sprintf("%s: %s", $field, $value), true); | |
return $this; | |
} | |
/** | |
* Append http header(s) | |
* | |
* @param mixed $field | |
* @param string $value | |
* @return $this | |
*/ | |
public function append($field, $value = null) { | |
if ( is_array($field) ) { | |
foreach ( $field as $f => $v ) | |
$this->append($f, $v); | |
return $this; | |
} | |
$field = str_replace(' ', '-', ucwords(str_replace('-', ' ', strtolower($field)))); | |
header(sprintf("%s: %s", $field, $value), false); | |
return $this; | |
} | |
/** | |
* Remove header field(s) | |
* | |
* @param mixed $field | |
* @return $this | |
*/ | |
public function remove($field) { | |
foreach ( (array) $field as $f ) { | |
$f = str_replace(' ', '-', ucwords(str_replace('-', ' ', strtolower($f)))); | |
header_remove($f); | |
} | |
return $this; | |
} | |
/** | |
* Set/Get the http status code | |
* | |
* @param int $code | |
* @return $this | |
*/ | |
public function status($code) { | |
http_response_code((int) $code); | |
return $this; | |
} | |
/** | |
* Make class in the specified dir(s) be autoloaded | |
* | |
* @param string|array $dirs | |
* @return $this | |
*/ | |
public function autoload($dirs) { | |
foreach ( (array) $dirs as $dir ) { | |
spl_autoload_register(function($class) use($dir) { | |
$ds = DIRECTORY_SEPARATOR; | |
$class_orig = $class; | |
$class = str_replace("\\", $ds, $class); | |
$filenames = [ | |
$dir . $ds . $class . ".php", | |
$dir . $ds . $class . $ds . basename($class) . ".php" | |
]; | |
$found = true; | |
foreach ( $filenames as $filename ) { | |
if ( ! is_file($filename) ) { | |
$found = false; | |
} else { | |
$found = true; | |
require_once $filename; | |
return ; | |
} | |
} | |
if ( ! $found ) { | |
throw new Exception("Cannot find the class '{$class_orig}'"); | |
} | |
}); | |
} | |
return $this; | |
} | |
/** | |
* Send a cookie to the borwser | |
* | |
* @param string $name | |
* @param string $value | |
* @param array $options | |
* @return $this | |
*/ | |
public function cookie($name, $value = "", array $options = []) | |
{ | |
$options = array_merge( | |
[ | |
'domain' => null, | |
'path' => '/', | |
'expires' => 0, | |
'secure' => false, | |
'httpOnly' => true | |
], $options); | |
setcookie ( | |
$name, | |
$value, | |
(int) $options['expires'], | |
$options['path'], | |
$options['domain'], | |
$options['secure'], | |
$options['httpOnly'] | |
); | |
return $this; | |
} | |
/** | |
* Return an url for a local path | |
* | |
* @param string $path | |
* @param string $host | |
* @return string | |
*/ | |
public function url($path = "", $hostname = "", $secure = false, $base = "/") { | |
$scheme = $secure ? "https://" : "http://"; | |
$hostname = empty($hostname) ? (explode(":", $_SERVER["SERVER_NAME"])[0] ?? $_SERVER["SERVER_NAME"]) : $hostname; | |
$path = $base . "/" . $path; | |
return $scheme . $hostname . preg_replace("~/+~", "/", $path); | |
} | |
/** | |
* Listen on the requested uri | |
* | |
* @param string $pattern | |
* @param Callback $cb | |
* @return $this | |
*/ | |
public function on(string $pattern, callable $cb) { | |
if ( $this->breakRoutes === true ) { | |
return $this; | |
} | |
$parts = explode(" ", $pattern, 2); | |
if ( sizeof($parts) < 2 ) { | |
$method = $_SERVER["REQUEST_METHOD"]; | |
} else { | |
$method = $parts[0]; | |
$pattern = $parts[1]; | |
} | |
$pattern = preg_replace("~/+~", "/", "/" . $this->parent . "/" . $pattern . "/"); | |
if ( ! preg_match("~^{$method}$~i", $_SERVER["REQUEST_METHOD"]) ) { | |
return $this; | |
} else if ( ! preg_match("~^{$pattern}$~", $_SERVER["PATH_INFO"], $m) ) { | |
return $this; | |
} | |
array_shift($m); | |
if ( call_user_func_array($cb->bindTo($this), $m) !== true ) { | |
// the callback didn't return true "continue" | |
// but returned none-true "stop" . | |
$this->breakRoutes = true; | |
} | |
return $this; | |
} | |
/** | |
* Group some routes under the same pattern without the need to repeate anything | |
* | |
* @param string $pattern | |
* @param Callback $cb | |
* @return $this | |
*/ | |
public function group($pattern, callable $cb) { | |
$old = $this->parent; | |
$this->parent = preg_replace("~/+~", "/", "/" . $this->parent . "/" . $pattern . "/"); | |
if ( preg_match("~^" . $this->parent . "~", $_SERVER["PATH_INFO"], $m) ) { | |
call_user_func_array($cb->bindTo($this), $m); | |
} | |
$this->parent = $old; | |
return $this; | |
} | |
/** | |
* Output the specified filename(s) to the browser and optionally pass vars to it/them | |
* | |
* @param string $___tpl | |
* @param array $___context | |
* @return $this | |
*/ | |
public function render($___tpl, array $___context = []) { | |
extract($___context, EXTR_OVERWRITE); | |
foreach ( (array) $___tpl as $v ) { | |
if ( ! is_file($v) ) { | |
throw new Exception("Template file cannot be found '{$v}'"); | |
} | |
require $v; | |
} | |
return $this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment