Skip to content

Instantly share code, notes, and snippets.

@alash3al
Last active May 12, 2016 10:52
Show Gist options
  • Save alash3al/c94aad5c1d46f9ac2209767d79f32050 to your computer and use it in GitHub Desktop.
Save alash3al/c94aad5c1d46f9ac2209767d79f32050 to your computer and use it in GitHub Desktop.
<?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