Adding modifications from kritbit

master
Nathan Adams 2016-04-14 22:01:11 -05:00
parent 5b104d624b
commit f08b2987e1
34 changed files with 3205 additions and 2404 deletions

View File

@ -1,5 +1,5 @@
<?php
$config["ADMINS"] = array();
<?php
$config["ADMINS"] = array();
return $config;

View File

@ -1,11 +1,11 @@
<?php
foreach (glob("system/vendor/*.php") as $filename)
{
include $filename;
}
require('system/engine/core.php');
$core = new HF_Core();
<?php
foreach (glob("system/vendor/*.php") as $filename)
{
include $filename;
}
require('system/engine/core.php');
$core = new HF_Core();
$core->run();

18
migrations.php 100644
View File

@ -0,0 +1,18 @@
<?php
spl_autoload_extensions(".php"); // comma-separated list
spl_autoload_register();
foreach (glob("system/vendor/*.php") as $filename)
{
include $filename;
}
if (!is_cli()) {
die("This script must be ran from the command line");
}
$core = new \system\engine\HF_Core(true);
$core->runMigrations();

View File

@ -1,15 +1,15 @@
<?php
$config["DEFAULT_ROUTE"] = "main";
$config["USE_H20_TPL"] = true;
$config["SMTP_SERVER"] = "localhost";
$config["SMTP_USER"] = "";
$config["SMTP_PASS"] = "";
$config["SMTP_PORT"] = 25;
$config["SMTP_FROM"] = "HF-noreply@yoursite.com";
$config["DEBUG"] = true;
$config["USE_HF_SMTP"] = true;
$config["SITE_NAME"] = "default";
$config["SITE_URL"] = "";
<?php
$config["DEFAULT_ROUTE"] = "main";
$config["USE_H20_TPL"] = true;
$config["SMTP_SERVER"] = "localhost";
$config["SMTP_USER"] = "";
$config["SMTP_PASS"] = "";
$config["SMTP_PORT"] = 25;
$config["SMTP_FROM"] = "HF-noreply@yoursite.com";
$config["DEBUG"] = true;
$config["USE_HF_SMTP"] = true;
$config["SITE_NAME"] = "default";
$config["SITE_URL"] = "";
return $config;

View File

@ -1,42 +0,0 @@
<?php
class HF_Controller
{
protected $config;
protected $tpl;
/** @var HF_Core */
protected $core;
public function __construct($config, $core, $tpl = null)
{
$this->config = $config;
$this->tpl = $tpl;
$this->core = $core;
$this->initdb();
}
protected function initdb()
{
if (isvarset($this->config["MYSQL_DBNAME"]) && isvarset($this->config["MYSQL_USER"]))
{
$pdo = new PDO(
"mysql:dbname={$this->config['MYSQL_DBNAME']};host={$this->config['MYSQL_HOST']}",
$this->config['MYSQL_USER'],
$this->config['MYSQL_PASS'],
array(
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
)
);
DB::$c = $pdo;
}
}
public function loadRender($template, $parameters=array())
{
$this->tpl->loadTemplate($template);
return $this->tpl->render($parameters);
}
}

View File

@ -1,277 +0,0 @@
<?php
include "system/engine/controller.php";
include "system/engine/SMTP.php";
include "system/engine/exceptions.php";
class HF_Core
{
private $class;
private $method;
private $classname;
private $args = array();
private $config = array();
private $tpl;
private $starttime;
public function __construct()
{
$this->starttime = microtime(true);
$config = include("system/engine/config-default.php");
if (is_file("application/config.php"))
{
$newconfig = include("application/config.php");
}
$this->config = array_merge($config, $newconfig);
if ($this->config["USE_H20_TPL"])
$this->tpl = new H2o(null, array(
"searchpath" => getcwd() . "/application/views/",
"cache_dir" => "application/tmp/",
'cache' => 'file'
));
set_error_handler("HF_Core::error_handler");
$this->findController();
}
public function getRuntime()
{
return $this->starttime - microtime(true);
}
public function siteURL()
{
if (isvarset($this->config["SITE_URL"]))
{
return $this->config["SITE_URL"];
}
$path = explode("/", $_SERVER["REQUEST_URI"]);
$path = array_filter($path, 'strlen');
if (count($path) == 0)
{
return $_SERVER["HTTP_HOST"] . "/";
} else {
if (in_array($this->classname, $path))
{
$newpath = implode("/", array_splice($path, 0, -2));
return $_SERVER["HTTP_HOST"] . "/" . $newpath . "/";
} else {
$newpath = implode("/", $path);
return $_SERVER["HTTP_HOST"] . "/" . $newpath . "/";
}
}
}
private function findController()
{
try
{
if (isvarset($_SERVER["PATH_INFO"]))
{
$request = $_SERVER["PATH_INFO"];
//$request = $_SERVER["PHP_SELF"];
$splitreq = explode("/", $request);
/*$request = "";
for($i = 0; $i < count($splitreq); $i++)
{
if ($splitreq[$i] == "index.php")
{
$request = implode("/", array_splice($splitreq, $i+1));
}
}*/
//print $request;
//$request = substr($request, 1);
//$request = substr($request, 0, -1);
} else {
$request = "";
}
if ($request == "" || $request == "/")
{
require("application/controllers/" . $this->config["DEFAULT_ROUTE"] . ".php");
$this->loadController(new $this->config["DEFAULT_ROUTE"]($this->config, $this, $this->tpl), $this->config["DEFAULT_ROUTE"], "index");
return;
}
if ($request[strlen($request)-1] == "/")
$request = substr($request, 0, -1);
$arr = explode("/", $request);
$path = "application/controllers/";
for($i = 0; $i < count($arr); $i++)
{
if (is_file($path . $arr[$i] . ".php")) // found the controller
{
include($path . $arr[$i] . ".php");
if ($i + 1 < count($arr)) // if there is a define after the controller name - this would be the method name
{
$this->loadController(new $arr[$i]($this->config, $this, $this->tpl), $arr[$i], $arr[$i+1], array_slice ($arr, 2));
} else { // call index
$this->loadController(new $arr[$i]($this->config, $this, $this->tpl), $arr[$i], "index");
}
return;
}
if (is_dir($path . $arr[$i])) // controller is hidden deeper
{
$path = $path . $arr[$i] . "/";
continue;
}
include($path . $this->config["DEFAULT_ROUTE"] . ".php");
$this->loadController(new $this->config["DEFAULT_ROUTE"]($this->config, $this, $this->tpl), $this->config["DEFAULT_ROUTE"], "index");
//$this->load404Controller();
break;
// throw exception controller not found
}
} catch (Exception $e) {
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
}
}
private function load404Controller()
{
if (is_file(getcwd() . "/application/status.php"))
{
include_once (getcwd() . "/application/status.php");
$this->loadController(new status($this->config, $this, $this->tpl), "status", "Status404");
} else {
include_once(getcwd() . "/system/engine/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "HF_Status", "Status404");
}
}
private function load500Controller()
{
if (is_file(getcwd() . "/application/status.php"))
{
include_once (getcwd() . "/application/status.php");
$this->loadController(new status($this->config, $this, $this->tpl), "status", "Status500");
} else {
include_once (getcwd() . "/system/engine/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "HF_Status", "Status500");
}
}
private function loadController($class, $classname, $method, $args = array())
{
$this->class = $class;
$this->classname = $classname;
$this->method = $method;
$this->args = $args;
}
public function run($err=false)
{
try
{
$call = new ReflectionMethod($this->classname, $this->method);
if ($err)
{
$call->invokeArgs($this->class, $this->args);
return;
}
$numOfReqPara = $call->getNumberOfRequiredParameters();
$numOfOptPara = $call->getNumberOfParameters() - $numOfReqPara;
$remainparas = count($this->args) - $numOfReqPara;
if ($numOfReqPara == 0 || ($remainparas >= 0 && $remainparas <= $numOfOptPara))
{
$call->invokeArgs($this->class, $this->args);
}
else
{
$this->load404Controller();
$this->run(true);
}
} catch (ReflectionException $e)
{
if (strstr($e->getMessage(), "does not exist") !== false)
{
$this->load404Controller();
} else {
$this->load500Controller();
}
$this->run(true);
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
} catch (Exception $e) {
$this->load500Controller();
$this->run(true);
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
}
}
public function mail_admins($subject, $msg, $html = false)
{
if (array_key_exists("ADMINS", $this->config))
{
foreach($this->config["ADMINS"] as $email)
{
$this->mail_user($email, $subject, $msg, $html);
}
}
}
public function mail_user($to, $subject, $msg, $html = false)
{
if ($this->config["USE_HF_SMTP"])
{
$smtp = new HF_SMTP($this->config["SMTP_FROM"], $to, $subject, $msg, $this->config["SMTP_SERVER"], $this->config["SMTP_USER"], $this->config["SMTP_PASS"], $this->config["SMTP_PORT"]);
$smtp->send($html);
} else {
require_once "Mail.php";
$smtp = null;
if ($this->$this->config["SMTP_USER"] && $this->config["SMTP_PASS"])
$smtp = Mail::factory('smtp', array(
"host" => $this->config["SMTP_SERVER"],
"port" => $this->config["SMTP_PORT"],
"auth" => true,
'username' => $this->config["SMTP_USER"],
'password' => $this->config["SMTP_PASS"]
));
else
$smtp = Mail::factory('smtp', array(
"host" => $this->config["SMTP_SERVER"],
"port" => $this->config["SMTP_PORT"]
));
$headers = array ('From' => $this->config["SMTP_FROM"],
'To' => $to,
'Subject' => $subject);
$smtp->send($to, $headers, $msg);
}
}
public static function error_handler($err_severity, $err_msg, $err_file, $err_line, array $err_context)
{
if (0 === error_reporting()) { return false;}
switch($err_severity)
{
case E_ERROR: throw new ErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_WARNING: throw new WarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_PARSE: throw new ParseException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_NOTICE: throw new NoticeException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_CORE_ERROR: throw new CoreErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_CORE_WARNING: throw new CoreWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_COMPILE_ERROR: throw new CompileErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_COMPILE_WARNING: throw new CoreWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_ERROR: throw new UserErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_WARNING: throw new UserWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_NOTICE: throw new UserNoticeException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_STRICT: throw new StrictException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_RECOVERABLE_ERROR: throw new RecoverableErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_DEPRECATED: throw new DeprecatedException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_DEPRECATED: throw new UserDeprecatedException ($err_msg, 0, $err_severity, $err_file, $err_line);
}
}
}

View File

@ -1,18 +1,20 @@
<?php
//Original idea by http://www.php.net/manual/en/function.set-error-handler.php#112881
class WarningException extends ErrorException {}
class ParseException extends ErrorException {}
class NoticeException extends ErrorException {}
class CoreErrorException extends ErrorException {}
class CoreWarningException extends ErrorException {}
class CompileErrorException extends ErrorException {}
class CompileWarningException extends ErrorException {}
class UserErrorException extends ErrorException {}
class UserWarningException extends ErrorException {}
class UserNoticeException extends ErrorException {}
class StrictException extends ErrorException {}
class RecoverableErrorException extends ErrorException {}
class DeprecatedException extends ErrorException {}
class UserDeprecatedException extends ErrorException {}
<?php
namespace system\engine;
//Original idea by http://www.php.net/manual/en/function.set-error-handler.php#112881
class WarningException extends \ErrorException {}
class ParseException extends \ErrorException {}
class NoticeException extends \ErrorException {}
class CoreErrorException extends \ErrorException {}
class CoreWarningException extends \ErrorException {}
class CompileErrorException extends \ErrorException {}
class CompileWarningException extends \ErrorException {}
class UserErrorException extends \ErrorException {}
class UserWarningException extends \ErrorException {}
class UserNoticeException extends \ErrorException {}
class StrictException extends \ErrorException {}
class RecoverableErrorException extends \ErrorException {}
class DeprecatedException extends \ErrorException {}
class UserDeprecatedException extends \ErrorException {}

View File

@ -0,0 +1,24 @@
<?php
namespace system\engine;
class HF_Controller
{
protected $config;
protected $tpl;
protected $core;
public function __construct($config, $core, $tpl = null)
{
$this->config = $config;
$this->tpl = $tpl;
$this->core = $core;
}
protected function loadRender($template, $parameters=array())
{
$this->tpl->loadTemplate($template);
return $this->tpl->render($parameters);
}
}

View File

@ -0,0 +1,365 @@
<?php
/*include "system/engine/hf_controller.php";
include "system/engine/smtp.php";
include "system/engine/exceptions.php";
include "system/engine/hf_model.php";*/
namespace system\engine;
use vendor\DB\DB;
include "exceptions.php";
class HF_Core
{
private $class;
private $method;
private $classname;
private $args = array();
private $config = array();
private $tpl;
public function __construct($migrations=false)
{
$config = include("system/engine/config-default.php");
if (is_file("application/config.php"))
{
$newconfig = include("application/config.php");
}
$this->config = array_merge($config, $newconfig);
\vendor\DB\DB::$type = $config["DATABASE_TYPE"];
if ($this->config["USE_H20_TPL"])
$this->tpl = new \H2o(null, array(
"searchpath" => getcwd() . "/application/views/",
"cache_dir" => "application/tmp/",
'cache' => 'file'
));
set_error_handler("\\system\\engine\\HF_Core::error_handler");
//set_exception_handler("\\system\\engine\\HF_Core::exception_handler");
if (!$migrations)
$this->findController();
}
public static function exception_handler($e) {
echo "Hello";
}
public function siteURL()
{
if (isvarset($this->config["SITE_URL"]))
{
return $this->config["SITE_URL"];
}
$path = explode("/", $_SERVER["REQUEST_URI"]);
$path = array_filter($path, 'strlen');
if (count($path) == 0)
{
return $_SERVER["HTTP_HOST"] . "/";
} else {
if (in_array($this->classname, $path))
{
$newpath = implode("/", array_splice($path, 0, -2));
return $_SERVER["HTTP_HOST"] . "/" . $newpath . "/";
} else {
$newpath = implode("/", $path);
return $_SERVER["HTTP_HOST"] . "/" . $newpath . "/";
}
}
}
private function findController()
{
try
{
if (isvarset($_SERVER["PATH_INFO"]))
{
$request = $_SERVER["PATH_INFO"];
//$request = $_SERVER["PHP_SELF"];
$splitreq = explode("/", $request);
/*$request = "";
for($i = 0; $i < count($splitreq); $i++)
{
if ($splitreq[$i] == "index.php")
{
$request = implode("/", array_splice($splitreq, $i+1));
}
}*/
//print $request;
//$request = substr($request, 1);
//$request = substr($request, 0, -1);
} else {
$request = "";
}
if ($request == "" || $request == "/")
{
require_once("application/controllers/" . $this->config["DEFAULT_ROUTE"] . ".php");
$this->loadController(new $this->config["DEFAULT_ROUTE"]($this->config, $this, $this->tpl), $this->config["DEFAULT_ROUTE"], "index");
return;
}
if ($request[strlen($request)-1] == "/")
$request = substr($request, 0, -1);
$arr = explode("/", $request);
$path = "application/controllers/";
for($i = 0; $i < count($arr); $i++)
{
if (is_file($path . $arr[$i] . ".php")) // found the controller
{
include_once($path . $arr[$i] . ".php");
if ($i + 1 < count($arr)) // if there is a define after the controller name - this would be the method name
{
$this->loadController(new $arr[$i]($this->config, $this, $this->tpl), $arr[$i], $arr[$i+1], array_slice ($arr, 3));
} else { // call index
$this->loadController(new $arr[$i]($this->config, $this, $this->tpl), $arr[$i], "index");
}
return;
}
if (is_dir($path . $arr[$i])) // controller is hidden deeper
{
$path = $path . $arr[$i] . "/";
continue;
}
include_once($path . $this->config["DEFAULT_ROUTE"] . ".php");
$this->loadController(new $this->config["DEFAULT_ROUTE"]($this->config, $this, $this->tpl), $this->config["DEFAULT_ROUTE"], "index");
//$this->load404Controller();
break;
// throw exception controller not found
}
} catch (\Exception $e) {
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
}
}
private function load404Controller()
{
if (is_file(getcwd() . "/application/status.php"))
{
include_once (getcwd() . "/application/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "\\system\\engine\\HF_Status", "Status404");
} else {
include_once(getcwd() . "/system/engine/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "\\system\\engine\\HF_Status", "Status404");
}
}
private function load500Controller()
{
if (is_file(getcwd() . "/application/status.php"))
{
include_once (getcwd() . "/application/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "\\system\\engine\\HF_Status", "Status500");
} else {
include_once (getcwd() . "/system/engine/status.php");
$this->loadController(new HF_Status($this->config, $this, $this->tpl), "\\system\\engine\\HF_Status", "Status500");
}
}
private function loadController($class, $classname, $method, $args = array())
{
$this->class = $class;
$this->classname = $classname;
$this->method = $method;
$this->args = $args;
}
public function run($err=false)
{
try
{
$call = new \ReflectionMethod($this->classname, $this->method);
if ($err)
{
$call->invokeArgs($this->class, $this->args);
return;
}
$numOfReqPara = $call->getNumberOfRequiredParameters();
$numOfOptPara = $call->getNumberOfParameters() - $numOfReqPara;
$remainparas = count($this->args) - $numOfReqPara;
if ($numOfReqPara == 0 || ($remainparas >= 0 && $remainparas <= $numOfOptPara))
{
$call->invokeArgs($this->class, $this->args);
}
else
{
$this->load404Controller();
$this->run(true);
}
}
catch (\ReflectionException $e)
{
if (strstr($e->getMessage(), "does not exist") !== false)
{
$this->load404Controller();
} else {
$this->load500Controller();
}
$this->run(true);
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
} catch (\Exception $e) {
$this->load500Controller();
$this->run(true);
if ($this->config["DEBUG"])
echo vdump($e, $this);
else
$this->mail_admins("[Exception - " . $this->config["SITE_NAME"] . "]", vdump($e, $this), true);
}
}
public function mail_admins($subject, $msg, $html = false)
{
if (array_key_exists("ADMINS", $this->config))
{
foreach($this->config["ADMINS"] as $email)
{
$this->mail_user($email, $subject, $msg, $html);
}
}
}
public function mail_user($to, $subject, $msg, $html = false)
{
if ($this->config["USE_HF_SMTP"])
{
$smtp = new HF_SMTP($this->config["SMTP_FROM"], $to, $subject, $msg, $this->config["SMTP_SERVER"], $this->config["SMTP_USER"], $this->config["SMTP_PASS"], $this->config["SMTP_PORT"]);
$smtp->send($html);
} else {
require_once "Mail.php";
$smtp = null;
if ($this->$this->config["SMTP_USER"] && $this->config["SMTP_PASS"])
$smtp = Mail::factory('smtp', array(
"host" => $this->config["SMTP_SERVER"],
"port" => $this->config["SMTP_PORT"],
"auth" => true,
'username' => $this->config["SMTP_USER"],
'password' => $this->config["SMTP_PASS"]
));
else
$smtp = Mail::factory('smtp', array(
"host" => $this->config["SMTP_SERVER"],
"port" => $this->config["SMTP_PORT"]
));
$headers = array ('From' => $this->config["SMTP_FROM"],
'To' => $to,
'Subject' => $subject);
$smtp->send($to, $headers, $msg);
}
}
public static function error_handler($err_severity, $err_msg, $err_file, $err_line, array $err_context)
{
if (0 === error_reporting()) { return false;}
switch($err_severity)
{
case E_ERROR: throw new \ErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_WARNING: throw new WarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_PARSE: throw new ParseException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_NOTICE: throw new NoticeException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_CORE_ERROR: throw new CoreErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_CORE_WARNING: throw new CoreWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_COMPILE_ERROR: throw new CompileErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_COMPILE_WARNING: throw new CoreWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_ERROR: throw new UserErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_WARNING: throw new UserWarningException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_NOTICE: throw new UserNoticeException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_STRICT: throw new StrictException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_RECOVERABLE_ERROR: throw new RecoverableErrorException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_DEPRECATED: throw new DeprecatedException ($err_msg, 0, $err_severity, $err_file, $err_line);
case E_USER_DEPRECATED: throw new UserDeprecatedException ($err_msg, 0, $err_severity, $err_file, $err_line);
}
}
public function setupDatabaseConnection() {
switch($this->config["DATABASE_TYPE"]) {
case "SQLITE":
DB::$c = new \PDO("sqlite:" . $this->config["DATABASE_FILE"]);
break;
case "MySQL":
DB::$c = new \PDO(
"mysql:dbname={$this->config['MYSQL_DBNAME']};host={$this->config['MYSQL_HOST']}",
$this->config['MYSQL_USER'],
$this->config['MYSQL_PASS'],
array(
\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_OBJ,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
)
);
break;
}
DB::$c->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
}
public function runMigrations() {
global $argv;
$this->setupDatabaseConnection();
DB::query("CREATE TABLE IF NOT EXISTS migrations (
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
migration INTEGER,
ran_at DATETIME
)");
switch ($argv[1]) {
case "show":
foreach(DB::fetch("SELECT migration, ran_at FROM migrations") as $migration) {
echo $migration["migration"] . " => " . $migration["ran_at"] . PHP_EOL;
}
break;
case "count":
echo DB::column("SELECT COUNT(id) FROM migrations");
break;
case "run":
$migrations = DB::fetch("SELECT migration FROM migrations");
$migrationArray = [];
foreach($migrations as $migration) {
$migrationArray[] = $migration["migration"];
}
foreach (glob("application/migrations/*.php") as $filename)
{
if (!in_array($filename, $migrationArray)) {
try {
include $filename;
DB::insert("migrations", ["migration" => $filename, "ran_at" => (new \DateTime())->format("Y-m-d")]);
} catch (\Exception $e) {
echo "[HF_Core] - Migration error - $e";
exit(1);
}
}
}
break;
case "clear":
DB::query("DELETE FROM migrations");
break;
case "reset":
switch($this->config["DATABASE_TYPE"]) {
case "SQLITE":
DB::$c = null;
unlink($this->config["DATABASE_FILE"]);
break;
case "MYSQL":
DB::query("DROP DATABASE " . $this->config['MYSQL_DBNAME']);
DB::query("CREATE DATABASE " . $this->config['MYSQL_DBNAME']);
break;
}
break;
}
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace system\engine;
use \vendor\DB\DB;
abstract class HF_Model {
public $id = null;
public static function create($data) {
$obj = new static();
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
foreach(DB::getColumns($table) as $column) {
if (isset($data[$column])) {
$obj->$column = $data[$column];
}
}
return $obj;
}
public function save() {
$fieldMap = [];
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
foreach(DB::getColumns($table) as $column) {
$fieldMap[$column] = $this->$column;
}
if ($fieldMap["id"] == null) {
DB::insert($table, $fieldMap);
} else {
$updateFields = $fieldMap;
unset($updateFields["id"]);
DB::update($table, $updateFields, $fieldMap["id"]);
}
}
public function update($data) {
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
foreach(DB::getColumns($table) as $column) {
if ($column == "id" || strpos($column, "_id") !== false) {
continue; // Don't allow to override id
}
if (isset($data[$column])) {
$this->$column = $data[$column];
}
}
return $this;
}
public function delete() {
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
if ($this->id) {
DB::query("DELETE FROM $table WHERE id = " . $this->id);
}
}
public function deleteRelated($tables = []) {
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
foreach($tables as $relatedTable) {
DB::query("DELETE FROM $relatedTable WHERE $table" . "_id = " . $this->id);
}
}
public static function getByField($field, $value) {
$function = new \ReflectionClass(get_called_class());
$table = strtolower($function->getShortName());
$fields = implode(", ", DB::getColumns($table));
return DB::fetchObject("SELECT $fields FROM $table WHERE $field = ?", get_called_class(), [$value]);
}
}

View File

@ -1,80 +1,82 @@
<?php
// Based on tutorial from here: https://portal.cyberhostpro.com/knowledgebase/170/PHP-Mail-Script-with-SMTP-Authentication.html
class HF_SMTP
{
private $from = "";
private $to = "";
private $subject = "";
private $msg = "";
private $user = null;
private $password = null;
private $port = 25;
private $server = "localhost";
private $smtpserverconn = null;
public function __construct($from, $to, $subject, $msg, $server = "localhost", $user = null, $password = null, $port = 25)
{
$this->from = $from;
$this->to = $to;
$this->subject = $subject;
$this->msg = $msg;
$this->user = $user;
$this->password = $password;
$this->port = $port;
$this->server = $server;
}
public function send($html=false)
{
$err = null;
$errstr = "";
$this->smtpserverconn = fsockopen($this->server, $this->port, $err, $errstr, 100);
$response = fgets($this->smtpserverconn, 515);
if ($response === false)
{
throw new Exception("Could not connect to SMTP server!");
}
if ($this->user != null && $this->password != null)
{
$this->sendCommand("AUTH LOGIN");
$this->sendCommand(base64_encode($this->user));
$this->sendCommand(base64_encode($this->password));
}
$this->sendCommand("HELO " . $_SERVER["SERVER_NAME"]);
$this->sendCommand("MAIL FROM: " . $this->from);
$this->sendCommand("RCPT TO: " . $this->to);
$this->sendCommand("DATA");
if ($html)
{
$this->sendCommand("MIME-Version: 1.0", false);
$this->sendCommand("Content-type: text/html; charset=iso-8859-1", false);
}
$this->sendCommand("From: " . $this->from, false);
$this->sendCommand("To: " . $this->to, false);
$this->sendCommand("Subject: " . $this->subject, false);
$this->sendCommand($this->msg, false);
$this->sendCommand("", false);
$this->sendCommand(".", false);
$this->sendCommand("QUIT");
}
private function sendCommand($command, $return = true)
{
fputs($this->smtpserverconn, $command . "\r\n");
if ($return)
return fgets($this->smtpserverconn, 515);
else
return null;
}
<?php
namespace system\engine;
// Based on tutorial from here: https://portal.cyberhostpro.com/knowledgebase/170/PHP-Mail-Script-with-SMTP-Authentication.html
class HF_SMTP
{
private $from = "";
private $to = "";
private $subject = "";
private $msg = "";
private $user = null;
private $password = null;
private $port = 25;
private $server = "localhost";
private $smtpserverconn = null;
public function __construct($from, $to, $subject, $msg, $server = "localhost", $user = null, $password = null, $port = 25)
{
$this->from = $from;
$this->to = $to;
$this->subject = $subject;
$this->msg = $msg;
$this->user = $user;
$this->password = $password;
$this->port = $port;
$this->server = $server;
}
public function send($html=false)
{
$err = null;
$errstr = "";
$this->smtpserverconn = fsockopen($this->server, $this->port, $err, $errstr, 100);
$response = fgets($this->smtpserverconn, 515);
if ($response === false)
{
throw new Exception("Could not connect to SMTP server!");
}
if ($this->user != null && $this->password != null)
{
$this->sendCommand("AUTH LOGIN");
$this->sendCommand(base64_encode($this->user));
$this->sendCommand(base64_encode($this->password));
}
$this->sendCommand("HELO " . $_SERVER["SERVER_NAME"]);
$this->sendCommand("MAIL FROM: " . $this->from);
$this->sendCommand("RCPT TO: " . $this->to);
$this->sendCommand("DATA");
if ($html)
{
$this->sendCommand("MIME-Version: 1.0", false);
$this->sendCommand("Content-type: text/html; charset=iso-8859-1", false);
}
$this->sendCommand("From: " . $this->from, false);
$this->sendCommand("To: " . $this->to, false);
$this->sendCommand("Subject: " . $this->subject, false);
$this->sendCommand($this->msg, false);
$this->sendCommand("", false);
$this->sendCommand(".", false);
$this->sendCommand("QUIT");
}
private function sendCommand($command, $return = true)
{
fputs($this->smtpserverconn, $command . "\r\n");
if ($return)
return fgets($this->smtpserverconn, 515);
else
return null;
}
}

View File

@ -1,15 +1,17 @@
<?php
class HF_Status extends HF_Controller
{
public function Status404()
{
echo "Page not found!";
}
public function Status500()
{
echo "System error";
}
<?php
namespace system\engine;
class HF_Status extends HF_Controller
{
public function Status404()
{
echo "Page not found!";
}
public function Status500()
{
echo "System error";
}
}

292
system/vendor/DB.php vendored
View File

@ -1,129 +1,165 @@
<?php
/**
* Provides a database wrapper around the PDO service to help reduce the effort
* to interact with a RDBMS such as SQLite, MySQL, or PostgreSQL.
*
* DB::$c = new PDO($dsn);
*
* @author David Pennington
* @copyright (c) 2012 xeoncross.com
* @license MIT License <http://www.opensource.org/licenses/mit-license.php>
********************************** 80 Columns *********************************
*/
class DB
{
static $q,$c,$p,$i = '`';
/**
* Fetch a column offset from the result set (COUNT() queries)
*
* @param string $query query string
* @param array $params query parameters
* @param integer $key index of column offset
* @return array|null
*/
static function column($query, $params = NULL, $key = 0)
{
if($statement = DB::query($query, $params))
return $statement->fetchColumn($key);
}
/**
* Fetch a single query result row
*
* @param string $query query string
* @param array $params query parameters
* @return mixed
*/
static function row($query, $params = NULL)
{
if($statement = DB::query($query, $params))
return $statement->fetch();
}
/**
* Fetches an associative array of all rows as key-value pairs (first
* column is the key, second column is the value).
*
* @param string $query query string
* @param array $params query parameters
* @return array
*/
static function pairs($query, $params = NULL)
{
$data = array();
if($statement = DB::query($query, $params))
while($row = $statement->fetch(\PDO::FETCH_NUM))
$data[$row[0]] = $row[1];
return $data;
}
/**
* Fetch all query result rows
*
* @param string $query query string
* @param array $params query parameters
* @param int $column the optional column to return
* @return array
*/
static function fetch($query, $params = NULL, $column = NULL)
{
if( ! $statement = DB::query($query, $params)) return;
// Return an array of records
if($column === NULL) return $statement->fetchAll();
// Fetch a certain column from all rows
return $statement->fetchAll(\PDO::FETCH_COLUMN, $column);
}
/**
* Prepare and send a query returning the PDOStatement
*
* @param string $query query string
* @param array $params query parameters
* @return object|null
*/
static function query($query, $params = NULL)
{
$statement = static::$c->prepare(DB::$q[] = strtr($query, '`', DB::$i));
$statement->execute($params);
return $statement;
}
/**
* Insert a row into the database
*
* @param string $table name
* @param array $data
* @return integer|null
*/
static function insert($table, array $data)
{
$query = "INSERT INTO`$table`(`" . implode('`,`', array_keys($data))
. '`)VALUES(' . rtrim(str_repeat('?,', count($data = array_values($data))), ',') . ')';
return DB::$p
? DB::column($query . 'RETURNING`id`', $data)
: (DB::query($query, $data) ? static::$c->lastInsertId() : NULL);
}
/**
* Update a database row
*
* @param string $table name
* @param array $data
* @param array $w where conditions
* @return integer|null
*/
static function update($table, $data, $value, $column = 'id')
{
$keys = implode('`=?,`', array_keys($data));
if($statement = DB::query(
"UPDATE`$table`SET`$keys`=? WHERE`$column`=?",
array_values($data + array($value))
))
return $statement->rowCount();
}
<?php
/**
* Provides a database wrapper around the PDO service to help reduce the effort
* to interact with a RDBMS such as SQLite, MySQL, or PostgreSQL.
*
* DB::$c = new PDO($dsn);
*
* @author David Pennington
* @copyright (c) 2012 xeoncross.com
* @license MIT License <http://www.opensource.org/licenses/mit-license.php>
********************************** 80 Columns *********************************
*/
namespace vendor\DB;
class DB
{
static $q,$c,$p,$i = '`';
static $type = "";
/**
* Fetch a column offset from the result set (COUNT() queries)
*
* @param string $query query string
* @param array $params query parameters
* @param integer $key index of column offset
* @return array|null
*/
static function column($query, $params = NULL, $key = 0)
{
if($statement = DB::query($query, $params))
return $statement->fetchColumn($key);
}
/**
* Fetch a single query result row
*
* @param string $query query string
* @param array $params query parameters
* @return mixed
*/
static function row($query, $params = NULL)
{
if($statement = DB::query($query, $params))
return $statement->fetch();
}
/**
* Fetches an associative array of all rows as key-value pairs (first
* column is the key, second column is the value).
*
* @param string $query query string
* @param array $params query parameters
* @return array
*/
static function pairs($query, $params = NULL)
{
$data = array();
if($statement = DB::query($query, $params))
while($row = $statement->fetch(\PDO::FETCH_NUM))
$data[$row[0]] = $row[1];
return $data;
}
/**
* Fetch all query result rows
*
* @param string $query query string
* @param array $params query parameters
* @param int $column the optional column to return
* @return array
*/
static function fetch($query, $params = NULL, $column = NULL)
{
if( ! $statement = DB::query($query, $params)) return;
// Return an array of records
if($column === NULL) return $statement->fetchAll();
// Fetch a certain column from all rows
return $statement->fetchAll(\PDO::FETCH_COLUMN, $column);
}
/**
* Fetch all query result rows as object
*
* @param string $query query string
* @param array $params query parameters
* @return array
*/
static function fetchObject($query, $className, $params = NULL)
{
/** @var \PDOStatement $statement */
if( ! $statement = DB::query($query, $params)) return null;
return $statement->fetchAll(\PDO::FETCH_CLASS, $className);
}
/**
* Prepare and send a query returning the PDOStatement
*
* @param string $query query string
* @param array $params query parameters
* @return object|null
*/
static function query($query, $params = NULL)
{
$statement = static::$c->prepare(DB::$q[] = strtr($query, '`', DB::$i));
$statement->execute($params);
return $statement;
}
/**
* Insert a row into the database
*
* @param string $table name
* @param array $data
* @return integer|null
*/
static function insert($table, array $data)
{
$query = "INSERT INTO`$table`(`" . implode('`,`', array_keys($data))
. '`)VALUES(' . rtrim(str_repeat('?,', count($data = array_values($data))), ',') . ')';
return DB::$p
? DB::column($query . 'RETURNING`id`', $data)
: (DB::query($query, $data) ? static::$c->lastInsertId() : NULL);
}
/**
* Update a database row
*
* @param string $table name
* @param array $data
* @param array $w where conditions
* @return integer|null
*/
static function update($table, $data, $value, $column = 'id')
{
$keys = implode('`=?,`', array_keys($data));
if($statement = DB::query(
"UPDATE`$table`SET`$keys`=? WHERE`$column`=?",
array_values($data + array($value))
))
return $statement->rowCount();
}
/**
* Returns array containing all field names
* @param $table
* @return array
*/
static function getColumns($table) {
switch (self::$type) {
case "SQLITE":
return self::fetch("PRAGMA table_info($table)", null, 1);
break;
case "MySQL":
return self::fetch("DESC $table", null, 0);
break;
}
}
}

View File

@ -1,69 +1,69 @@
<?php
// Original http://stackoverflow.com/a/4282133/195722
function vdump() {
$args = func_get_args();
$backtrace = debug_backtrace();
$code = file($backtrace[0]['file']);
$ret = "<pre style='background: #eee; border: 1px solid #aaa; clear: both; overflow: auto; padding: 10px; text-align: left; margin-bottom: 5px'>";
$ret .- "<b>".htmlspecialchars(trim($code[$backtrace[0]['line']-1]))."</b>\n";
$ret .= "\n";
ob_start();
foreach ($args as $arg)
var_dump($arg);
var_dump($_SERVER);
var_dump($_COOKIE);
$str = ob_get_contents();
ob_end_clean();
$str = preg_replace('/=>(\s+)/', ' => ', $str);
$str = preg_replace('/ => NULL/', ' &rarr; <b style="color: #000">NULL</b>', $str);
$str = preg_replace('/}\n(\s+)\[/', "}\n\n".'$1[', $str);
$str = preg_replace('/ (float|int)\((\-?[\d\.]+)\)/', " <span style='color: #888'>$1</span> <b style='color: brown'>$2</b>", $str);
$str = preg_replace('/array\((\d+)\) {\s+}\n/', "<span style='color: #888'>array&bull;$1</span> <b style='color: brown'>[]</b>", $str);
$str = preg_replace('/ string\((\d+)\) \"(.*)\"/', " <span style='color: #888'>str&bull;$1</span> <b style='color: brown'>'$2'</b>", $str);
$str = preg_replace('/\[\"(.+)\"\] => /', "<span style='color: purple'>'$1'</span> &rarr; ", $str);
$str = preg_replace('/object\((\S+)\)#(\d+) \((\d+)\) {/', "<span style='color: #888'>obj&bull;$2</span> <b style='color: #0C9136'>$1[$3]</b> {", $str);
$str = str_replace("bool(false)", "<span style='color:#888'>bool&bull;</span><span style='color: red'>false</span>", $str);
$str = str_replace("bool(true)", "<span style='color:#888'>bool&bull;</span><span style='color: green'>true</span>", $str);
$ret .= $str;
$ret .= "</pre>";
return $ret;
}
// Original - http://www.php.net/manual/en/function.debug-print-backtrace.php#86932
function debug_string_backtrace() {
ob_start();
debug_print_backtrace();
$trace = ob_get_contents();
ob_end_clean();
// Remove first item from backtrace as it's this function which
// is redundant.
$trace = preg_replace ('/^#0\s+' . __FUNCTION__ . "[^\n]*\n/", '', $trace, 1);
// Renumber backtrace items.
$trace = preg_replace ('/^#(\d+)/me', '\'#\' . ($1 - 1)', $trace);
$trace = wordwrap($trace, 123, "<br>");
return $trace;
<?php
// Original http://stackoverflow.com/a/4282133/195722
function vdump() {
$args = func_get_args();
$backtrace = debug_backtrace();
$code = file($backtrace[0]['file']);
$ret = "<pre style='background: #eee; border: 1px solid #aaa; clear: both; overflow: auto; padding: 10px; text-align: left; margin-bottom: 5px'>";
$ret .= "<b>".htmlspecialchars(trim($code[$backtrace[0]['line']-1]))."</b>\n";
$ret .= "\n";
ob_start();
foreach ($args as $arg)
var_dump($arg);
var_dump($_SERVER);
var_dump($_COOKIE);
$str = ob_get_contents();
ob_end_clean();
$str = preg_replace('/=>(\s+)/', ' => ', $str);
$str = preg_replace('/ => NULL/', ' &rarr; <b style="color: #000">NULL</b>', $str);
$str = preg_replace('/}\n(\s+)\[/', "}\n\n".'$1[', $str);
$str = preg_replace('/ (float|int)\((\-?[\d\.]+)\)/', " <span style='color: #888'>$1</span> <b style='color: brown'>$2</b>", $str);
$str = preg_replace('/array\((\d+)\) {\s+}\n/', "<span style='color: #888'>array&bull;$1</span> <b style='color: brown'>[]</b>", $str);
$str = preg_replace('/ string\((\d+)\) \"(.*)\"/', " <span style='color: #888'>str&bull;$1</span> <b style='color: brown'>'$2'</b>", $str);
$str = preg_replace('/\[\"(.+)\"\] => /', "<span style='color: purple'>'$1'</span> &rarr; ", $str);
$str = preg_replace('/object\((\S+)\)#(\d+) \((\d+)\) {/', "<span style='color: #888'>obj&bull;$2</span> <b style='color: #0C9136'>$1[$3]</b> {", $str);
$str = str_replace("bool(false)", "<span style='color:#888'>bool&bull;</span><span style='color: red'>false</span>", $str);
$str = str_replace("bool(true)", "<span style='color:#888'>bool&bull;</span><span style='color: green'>true</span>", $str);
$ret .= $str;
$ret .= "</pre>";
return $ret;
}
// Original - http://www.php.net/manual/en/function.debug-print-backtrace.php#86932
function debug_string_backtrace() {
ob_start();
debug_print_backtrace();
$trace = ob_get_contents();
ob_end_clean();
// Remove first item from backtrace as it's this function which
// is redundant.
$trace = preg_replace ('/^#0\s+' . __FUNCTION__ . "[^\n]*\n/", '', $trace, 1);
// Renumber backtrace items.
$trace = preg_replace ('/^#(\d+)/me', '\'#\' . ($1 - 1)', $trace);
$trace = wordwrap($trace, 123, "<br>");
return $trace;
}

27
system/vendor/aes.php vendored 100644
View File

@ -0,0 +1,27 @@
<?php
// Source: http://stackoverflow.com/a/8232171/195722
function aes_encrypt($key, $text) {
$realKey = "";
if (count($key) < 32) { //if it's less than 32 bits - pad it
$realKey = str_pad($key, 32 - count($key) + 1);
} else if (count($key) > 32) {
throw new \Exception("Key is too long");
} else {
$realKey = $key;
}
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $realKey, $text, MCRYPT_MODE_ECB));
}
function aes_decrypt($key, $cipherText) {
$realKey = "";
if (count($key) < 32) { //if it's less than 32 bits - pad it
$realKey = str_pad($key, 32 - count($key) + 1);
} else if (count($key) > 32) {
throw new \Exception("Key is too long");
} else {
$realKey = $key;
}
return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $realKey, base64_decode($cipherText), MCRYPT_MODE_ECB);
}

534
system/vendor/h2o.php vendored
View File

@ -1,266 +1,268 @@
<?php
define('H2O_VERSION', '0.3');
defined('DS') or define('DS', DIRECTORY_SEPARATOR);
defined('H2O_ROOT') or define('H2O_ROOT', dirname(__FILE__) . DS);
require H2O_ROOT.'h2o/datatype.php';
require H2O_ROOT.'h2o/loaders.php';
require H2O_ROOT.'h2o/nodes.php';
require H2O_ROOT.'h2o/tags.php';
require H2O_ROOT.'h2o/errors.php';
require H2O_ROOT.'h2o/filters.php';
require H2O_ROOT.'h2o/context.php';
/**
* Example:
* $h2o = new H2O('./template.html', array("loader"=>'file'));
*
*
* $h2o = new H2O('template.html', array("loader"=>'hash'));
*/
class H2o {
var $searchpath;
var $context;
var $loader = false;
static $tags = array();
static $filters = array();
static $extensions = array();
static function getOptions($options = array()) {
return array_merge(array(
'loader' => 'file',
'cache' => 'file', // file | apc | memcache
'cache_prefix' => 'h2o_',
'cache_ttl' => 3600, // file | apc | memcache
'searchpath' => false,
'autoescape' => true,
// Enviroment setting
'BLOCK_START' => '{%',
'BLOCK_END' => '%}',
'VARIABLE_START' => '{{',
'VARIABLE_END' => '}}',
'COMMENT_START' => '{*',
'COMMENT_END' => '*}',
'TRIM_TAGS' => true
), $options);
}
function __construct($file = null, $options = array()) {
# Init a environment
$this->options = $this->getOptions($options);
$loader = $this->options['loader'];
if (!$loader)
return true;
if (is_object($loader)) {
$this->loader = $loader;
$this->loader->setOptions($this->options);
} else {
$loader = "H2o_{$loader}_Loader";
if (!class_exists($loader, false))
throw new Exception('Invalid template loader');
if (isset($options['searchpath'])){
$this->searchpath = $options['searchpath'];
} else if ($file) {
$this->searchpath = dirname(realpath($file)).DS;
} else {
$this->searchpath = getcwd().DS;
}
$loader_searchpath = is_array($this->searchpath) ? $this->searchpath : array($this->searchpath);
$this->loader = new $loader($loader_searchpath, $this->options);
}
$this->loader->runtime = $this;
if (isset($options['i18n'])) {
h2o::load('i18n');
$this->i18n = new H2o_I18n($this->searchpath, $options['i18n']);
}
if ($file) {
$this->nodelist = $this->loadTemplate($file);
}
}
function loadTemplate($file) {
return $this->nodelist = $this->loader->read_cache($file);
}
function loadSubTemplate($file) {
return $this->loader->read($file);
}
# Build a finalized nodelist from template ready to be cached
function parse($source, $filename = '', $env = null) {
if (!$env)
$env = $this->options;
if (!class_exists('H2o_Parser', false))
require H2O_ROOT.'h2o/parser.php';
$parser = new H2o_Parser($source, $filename, $this, $env);
$nodelist = $parser->parse();
return $nodelist;
}
function set($context, $value = null) {
# replace with new context object
if (is_object($context) && $context instanceof H2o_Context) {
return $this->context = $context;
}
# Init context
if (!$this->context) {
$this->context = new H2o_Context($this->defaultContext(), $this->options);
}
# Extend or set value
if (is_array($context)) {
return $this->context->extend($context);
}
elseif (is_string($context)) {
return $this->context[$context] = $value;
}
return false;
}
# Render the nodelist
function render($context = array()) {
$this->set($context);
$this->stream = new StreamWriter;
$this->nodelist->render($this->context, $this->stream);
return $this->stream->close();
}
static function parseString($source, $options = array()) {
$instance = new H2o(null, array_merge($options, array('loader' => false)));
$instance->nodelist = $instance->parse($source);
return $instance;
}
static function &createTag($tag, $args = null, $parser, $position = 0) {
if (!isset(self::$tags[$tag])) {
throw new H2o_Error($tag . " tag doesn't exist");
}
$tagClass = self::$tags[$tag];
$tag = new $tagClass($args, $parser, $position);
return $tag;
}
/**
* Register a new tag
*
*
* h2o::addTag('tag_name', 'ClassName');
*
* h2o::addTag(array(
* 'tag_name' => 'MagClass',
* 'tag_name2' => 'TagClass2'
* ));
*
* h2o::addTag('tag_name'); // Tag_name_Tag
*
* h2o::addTag(array('tag_name',
* @param unknown_type $tag
* @param unknown_type $class
*/
static function addTag($tag, $class = null) {
$tags = array();
if (is_string($tag)) {
if (is_null($class))
$class = ucwords("{$tag}_Tag");
$tags[$tag] = $class;
} elseif (is_array($tag)) {
$tags = $tag;
}
foreach ($tags as $tag => $tagClass) {
if (is_integer($tag)) {
unset($tags[$tag]);
$tag = $tagClass;
$tagClass = ucwords("{$tagClass}_Tag");
}
if (!class_exists($tagClass, false)) {
throw new H2o_Error("{$tagClass} tag is not found");
}
$tags[$tag] = $tagClass;
}
self::$tags = array_merge(self::$tags, $tags);
}
/**
* Register a new filter to h2o runtime
*
* @param unknown_type $filter
* @param unknown_type $callback
* @return unknown
*/
static function addFilter($filter, $callback = null) {
if (is_array($filter)) {
$filters = $filter;
foreach($filters as $key => $filter) {
if (is_numeric($key))
$key = $filter;
self::addFilter($key, $filter);
}
return true;
} elseif (is_string($filter) && class_exists($filter, false) && is_subclass_of($filter, 'FilterCollection')) {
foreach (get_class_methods($filter) as $f) {
if (is_callable(array($filter, $f)))
self::$filters[$f] = array($filter, $f);
}
return true;
}
if (is_null($callback))
$callback = $filter;
if (!is_callable($callback)) {
return false;
}
self::$filters[$filter] = $callback;
}
static function addLookup($callback) {
if (is_callable($callback)) {
H2o_Context::$lookupTable[] = $callback;
} else die('damm it');
}
static function load($extension, $file = null) {
if (!$file) {
$file = H2O_ROOT.'ext'.DS.$extension.'.php';
}
if (is_file($file)) {
include_once ($file);
self::$extensions[$extension] = $file;
}
}
function defaultContext() {
return array('h2o' => new H2o_Info);
}
}
/**
* Convenient wrapper for loading template file or string
* @param $name
* @param $options - H2o options
* @return Instance of H2o Template
*/
function h2o($name, $options = array()) {
$is_file = '/([^\s]*?)(\.[^.\s]*$)/';
if (!preg_match($is_file, $name)) {
return H2o::parseString($name, $options);
}
$instance = new H2o($name, $options);
return $instance;
}
?>
<?php
define('H2O_VERSION', '0.3');
defined('DS') or define('DS', DIRECTORY_SEPARATOR);
defined('H2O_ROOT') or define('H2O_ROOT', dirname(__FILE__) . DS);
require H2O_ROOT.'h2o/datatype.php';
require H2O_ROOT.'h2o/loaders.php';
require H2O_ROOT.'h2o/nodes.php';
require H2O_ROOT.'h2o/tags.php';
require H2O_ROOT.'h2o/errors.php';
require H2O_ROOT.'h2o/filters.php';
require H2O_ROOT.'h2o/context.php';
require H2O_ROOT.'h2o/parser.php';
/**
* Example:
* $h2o = new H2O('./template.html', array("loader"=>'file'));
*
*
* $h2o = new H2O('template.html', array("loader"=>'hash'));
*/
class H2o {
var $searchpath;
var $context;
var $loader = false;
static $tags = array();
static $filters = array();
static $extensions = array();
static function getOptions($options = array()) {
return array_merge(array(
'loader' => 'file',
'cache' => 'file', // file | apc | memcache
'cache_prefix' => 'h2o_',
'cache_ttl' => 3600, // file | apc | memcache
'searchpath' => false,
'autoescape' => true,
// Enviroment setting
'BLOCK_START' => '{%',
'BLOCK_END' => '%}',
'VARIABLE_START' => '{{',
'VARIABLE_END' => '}}',
'COMMENT_START' => '{*',
'COMMENT_END' => '*}',
'TRIM_TAGS' => true
), $options);
}
function __construct($file = null, $options = array()) {
# Init a environment
$this->options = $this->getOptions($options);
$loader = $this->options['loader'];
if (!$loader)
return true;
if (is_object($loader)) {
$this->loader = $loader;
$this->loader->setOptions($this->options);
} else {
$loader = "H2o_{$loader}_Loader";
if (!class_exists($loader, false))
throw new Exception('Invalid template loader');
if (isset($options['searchpath'])){
$this->searchpath = $options['searchpath'];
} else if ($file) {
$this->searchpath = dirname(realpath($file)).DS;
} else {
$this->searchpath = getcwd().DS;
}
$loader_searchpath = is_array($this->searchpath) ? $this->searchpath : array($this->searchpath);
$this->loader = new $loader($loader_searchpath, $this->options);
}
$this->loader->runtime = $this;
if (isset($options['i18n'])) {
h2o::load('i18n');
$this->i18n = new H2o_I18n($this->searchpath, $options['i18n']);
}
if ($file) {
$this->nodelist = $this->loadTemplate($file);
}
}
function loadTemplate($file) {
return $this->nodelist = $this->loader->read_cache($file);
}
function loadSubTemplate($file) {
return $this->loader->read($file);
}
# Build a finalized nodelist from template ready to be cached
function parse($source, $filename = '', $env = null) {
if (!$env)
$env = $this->options;
if (!class_exists('H2o_Parser', false))
require H2O_ROOT.'h2o/parser.php';
$parser = new H2o_Parser($source, $filename, $this, $env);
$nodelist = $parser->parse();
return $nodelist;
}
function set($context, $value = null) {
# replace with new context object
if (is_object($context) && $context instanceof H2o_Context) {
return $this->context = $context;
}
# Init context
if (!$this->context) {
$this->context = new H2o_Context($this->defaultContext(), $this->options);
}
# Extend or set value
if (is_array($context)) {
return $this->context->extend($context);
}
elseif (is_string($context)) {
return $this->context[$context] = $value;
}
return false;
}
# Render the nodelist
function render($context = array()) {
$this->set($context);
$this->stream = new StreamWriter;
$this->nodelist->render($this->context, $this->stream);
return $this->stream->close();
}
static function parseString($source, $options = array()) {
$instance = new H2o(null, array_merge($options, array('loader' => false)));
$instance->nodelist = $instance->parse($source);
return $instance;
}
static function &createTag($tag, $args = null, $parser, $position = 0) {
if (!isset(self::$tags[$tag])) {
throw new H2o_Error($tag . " tag doesn't exist");
}
$tagClass = self::$tags[$tag];
$tag = new $tagClass($args, $parser, $position);
return $tag;
}
/**
* Register a new tag
*
*
* h2o::addTag('tag_name', 'ClassName');
*
* h2o::addTag(array(
* 'tag_name' => 'MagClass',
* 'tag_name2' => 'TagClass2'
* ));
*
* h2o::addTag('tag_name'); // Tag_name_Tag
*
* h2o::addTag(array('tag_name',
* @param unknown_type $tag
* @param unknown_type $class
*/
static function addTag($tag, $class = null) {
$tags = array();
if (is_string($tag)) {
if (is_null($class))
$class = ucwords("{$tag}_Tag");
$tags[$tag] = $class;
} elseif (is_array($tag)) {
$tags = $tag;
}
foreach ($tags as $tag => $tagClass) {
if (is_integer($tag)) {
unset($tags[$tag]);
$tag = $tagClass;
$tagClass = ucwords("{$tagClass}_Tag");
}
if (!class_exists($tagClass, false)) {
throw new H2o_Error("{$tagClass} tag is not found");
}
$tags[$tag] = $tagClass;
}
self::$tags = array_merge(self::$tags, $tags);
}
/**
* Register a new filter to h2o runtime
*
* @param unknown_type $filter
* @param unknown_type $callback
* @return unknown
*/
static function addFilter($filter, $callback = null) {
if (is_array($filter)) {
$filters = $filter;
foreach($filters as $key => $filter) {
if (is_numeric($key))
$key = $filter;
self::addFilter($key, $filter);
}
return true;
} elseif (is_string($filter) && class_exists($filter, false) && is_subclass_of($filter, 'FilterCollection')) {
foreach (get_class_methods($filter) as $f) {
if (is_callable(array($filter, $f)))
self::$filters[$f] = array($filter, $f);
}
return true;
}
if (is_null($callback))
$callback = $filter;
if (!is_callable($callback)) {
return false;
}
self::$filters[$filter] = $callback;
}
static function addLookup($callback) {
if (is_callable($callback)) {
H2o_Context::$lookupTable[] = $callback;
} else die('damm it');
}
static function load($extension, $file = null) {
if (!$file) {
$file = H2O_ROOT.'ext'.DS.$extension.'.php';
}
if (is_file($file)) {
include_once ($file);
self::$extensions[$extension] = $file;
}
}
function defaultContext() {
return array('h2o' => new H2o_Info);
}
}
/**
* Convenient wrapper for loading template file or string
* @param $name
* @param $options - H2o options
* @return Instance of H2o Template
*/
function h2o($name, $options = array()) {
$is_file = '/([^\s]*?)(\.[^.\s]*$)/';
if (!preg_match($is_file, $name)) {
return H2o::parseString($name, $options);
}
$instance = new H2o($name, $options);
return $instance;
}
?>

View File

@ -1,266 +1,266 @@
<?php
/**
* Context object
* encapsulate context, resolve name
*/
class H2o_Context implements ArrayAccess {
public $safeClass = array('stdClass', 'BlockContext');
public $scopes;
public $options;
public $autoescape = true;
private $arrayMethods = array('first'=> 0, 'last'=> 1, 'length'=> 2, 'size'=> 3);
static $lookupTable = array();
function __construct($context = array(), $options = array()){
if (is_object($context))
$context = get_object_vars($context);
$this->scopes = array($context);
if (isset($options['safeClass']))
$this->safeClass = array_merge($this->safeClass, $options['safeClass']);
if (isset($options['autoescape']))
$this->autoescape = $options['autoescape'];
$this->options = $options;
}
function push($layer = array()){
return array_unshift($this->scopes, $layer);
}
/**
* pop the most recent layer
*/
function pop() {
if (!isset($this->scopes[1]))
throw new Exception('cannnot pop from empty stack');
return array_shift($this->scopes);
}
function offsetExists($offset) {
foreach ($this->scopes as $layer) {
if (isset($layer[$offset])) return true;
}
return false;
}
function offsetGet($key) {
foreach ($this->scopes as $layer) {
if (isset($layer[$key]))
return $layer[$key];
}
return;
}
function offsetSet($key, $value) {
if (strpos($key, '.') > -1)
throw new Exception('cannot set non local variable');
return $this->scopes[0][$key] = $value;
}
function offsetUnset($key) {
foreach ($this->scopes as $layer) {
if (isset($layer[$key])) unset($layer[$key]);
}
}
function extend($context) {
$this->scopes[0] = array_merge($this->scopes[0], $context);
}
function set($key, $value) {
return $this->offsetSet($key, $value);
}
function get($key) {
return $this->offsetGet($key);
}
function isDefined($key) {
return $this->offsetExists($key);
}
/**
*
*
*
* Variable name
*
* @param $var variable name or array(0 => variable name, 'filters' => filters array)
* @return unknown_type
*/
function resolve($var) {
# if $var is array - it contains filters to apply
$filters = array();
if ( is_array($var) ) {
$name = array_shift($var);
$filters = isset($var['filters'])? $var['filters'] : array();
}
else $name = $var;
$result = null;
# Lookup basic types, null, boolean, numeric and string
# Variable starts with : (:users.name) to short-circuit lookup
if ($name[0] === ':') {
$object = $this->getVariable(substr($name, 1));
if (!is_null($object)) $result = $object;
} else {
if ($name === 'true') {
$result = true;
}
elseif ($name === 'false') {
$result = false;
}
elseif (preg_match('/^-?\d+(\.\d+)?$/', $name, $matches)) {
$result = isset($matches[1])? floatval($name) : intval($name);
}
elseif (preg_match('/^"([^"\\\\]*(?:\\.[^"\\\\]*)*)"|' .
'\'([^\'\\\\]*(?:\\.[^\'\\\\]*)*)\'$/', $name)) {
$result = stripcslashes(substr($name, 1, -1));
}
}
if (!empty(self::$lookupTable) && $result == Null) {
$result = $this->externalLookup($name);
}
$result = $this->applyFilters($result,$filters);
return $result;
}
function getVariable($name) {
# Local variables. this gives as a bit of performance improvement
if (!strpos($name, '.'))
return $this[$name];
# Prepare for Big lookup
$parts = explode('.', $name);
$object = $this[array_shift($parts)];
# Lookup context
foreach ($parts as $part) {
if (is_array($object) or $object instanceof ArrayAccess) {
if (isset($object[$part])) {
$object = $object[$part];
} elseif ($part === 'first') {
$object = isset($object[0])?$object[0]:null;
} elseif ($part === 'last') {
$last = count($object)-1;
$object = isset($object[$last])?$object[$last]:null;
} elseif ($part === 'size' or $part === 'length') {
return count($object);
} else {
return null;
}
}
elseif (is_object($object)) {
if (isset($object->$part))
$object = $object->$part;
elseif (is_callable(array($object, $part))) {
$methodAllowed = in_array(get_class($object), $this->safeClass) ||
(isset($object->h2o_safe) && (
$object->h2o_safe === true || in_array($part, $object->h2o_safe)
)
);
$object = $methodAllowed ? $object->$part() : null;
}
else return null;
}
else return null;
}
return $object;
}
function applyFilters($object, $filters) {
foreach ($filters as $filter) {
$name = substr(array_shift($filter), 1);
$args = $filter;
if (isset(h2o::$filters[$name])) {
foreach ($args as $i => $argument) {
# name args
if (is_array($argument)) {
foreach ($argument as $n => $arg) {
$args[$i][$n] = $this->resolve($arg);
}
} else {
# resolve argument values
$args[$i] = $this->resolve($argument);
}
}
array_unshift($args, $object);
$object = call_user_func_array(h2o::$filters[$name], $args);
}
}
return $object;
}
function escape($value, $var) {
$safe = false;
$filters = (is_array($var) && isset($var['filters']))? $var['filters'] : array();
foreach ( $filters as $filter ) {
$name = substr(array_shift($filter), 1);
$safe = !$safe && ($name === 'safe');
$escaped = $name === 'escape';
}
$should_escape = $this->autoescape || isset($escaped) && $escaped;
if ( ($should_escape && !$safe)) {
$value = htmlspecialchars($value);
}
return $value;
}
function externalLookup($name) {
if (!empty(self::$lookupTable)) {
foreach (self::$lookupTable as $lookup) {
$tmp = call_user_func_array($lookup, array($name, $this));
if ($tmp !== null)
return $tmp;
}
}
return null;
}
}
class BlockContext {
var $h2o_safe = array('name', 'depth', 'super');
var $block, $index;
private $context;
function __construct($block, $context, $index) {
$this->block =& $block;
$this->context = $context;
$this->index = $index;
}
function name() {
return $this->block->name;
}
function depth() {
return $this->index;
}
function super() {
$stream = new StreamWriter;
$this->block->parent->render($this->context, $stream, $this->index+1);
return $stream->close();
}
function __toString() {
return "[BlockContext : {$this->block->name}, {$this->block->filename}]";
}
}
?>
<?php
/**
* Context object
* encapsulate context, resolve name
*/
class H2o_Context implements ArrayAccess {
public $safeClass = array('stdClass', 'BlockContext');
public $scopes;
public $options;
public $autoescape = true;
private $arrayMethods = array('first'=> 0, 'last'=> 1, 'length'=> 2, 'size'=> 3);
static $lookupTable = array();
function __construct($context = array(), $options = array()){
if (is_object($context))
$context = get_object_vars($context);
$this->scopes = array($context);
if (isset($options['safeClass']))
$this->safeClass = array_merge($this->safeClass, $options['safeClass']);
if (isset($options['autoescape']))
$this->autoescape = $options['autoescape'];
$this->options = $options;
}
function push($layer = array()){
return array_unshift($this->scopes, $layer);
}
/**
* pop the most recent layer
*/
function pop() {
if (!isset($this->scopes[1]))
throw new Exception('cannnot pop from empty stack');
return array_shift($this->scopes);
}
function offsetExists($offset) {
foreach ($this->scopes as $layer) {
if (isset($layer[$offset])) return true;
}
return false;
}
function offsetGet($key) {
foreach ($this->scopes as $layer) {
if (isset($layer[$key]))
return $layer[$key];
}
return;
}
function offsetSet($key, $value) {
if (strpos($key, '.') > -1)
throw new Exception('cannot set non local variable');
return $this->scopes[0][$key] = $value;
}
function offsetUnset($key) {
foreach ($this->scopes as $layer) {
if (isset($layer[$key])) unset($layer[$key]);
}
}
function extend($context) {
$this->scopes[0] = array_merge($this->scopes[0], $context);
}
function set($key, $value) {
return $this->offsetSet($key, $value);
}
function get($key) {
return $this->offsetGet($key);
}
function isDefined($key) {
return $this->offsetExists($key);
}
/**
*
*
*
* Variable name
*
* @param $var variable name or array(0 => variable name, 'filters' => filters array)
* @return unknown_type
*/
function resolve($var) {
# if $var is array - it contains filters to apply
$filters = array();
if ( is_array($var) ) {
$name = array_shift($var);
$filters = isset($var['filters'])? $var['filters'] : array();
}
else $name = $var;
$result = null;
# Lookup basic types, null, boolean, numeric and string
# Variable starts with : (:users.name) to short-circuit lookup
if ($name[0] === ':') {
$object = $this->getVariable(substr($name, 1));
if (!is_null($object)) $result = $object;
} else {
if ($name === 'true') {
$result = true;
}
elseif ($name === 'false') {
$result = false;
}
elseif (preg_match('/^-?\d+(\.\d+)?$/', $name, $matches)) {
$result = isset($matches[1])? floatval($name) : intval($name);
}
elseif (preg_match('/^"([^"\\\\]*(?:\\.[^"\\\\]*)*)"|' .
'\'([^\'\\\\]*(?:\\.[^\'\\\\]*)*)\'$/', $name)) {
$result = stripcslashes(substr($name, 1, -1));
}
}
if (!empty(self::$lookupTable) && $result == Null) {
$result = $this->externalLookup($name);
}
$result = $this->applyFilters($result,$filters);
return $result;
}
function getVariable($name) {
# Local variables. this gives as a bit of performance improvement
if (!strpos($name, '.'))
return $this[$name];
# Prepare for Big lookup
$parts = explode('.', $name);
$object = $this[array_shift($parts)];
# Lookup context
foreach ($parts as $part) {
if (is_array($object) or $object instanceof ArrayAccess) {
if (isset($object[$part])) {
$object = $object[$part];
} elseif ($part === 'first') {
$object = isset($object[0])?$object[0]:null;
} elseif ($part === 'last') {
$last = count($object)-1;
$object = isset($object[$last])?$object[$last]:null;
} elseif ($part === 'size' or $part === 'length') {
return count($object);
} else {
return null;
}
}
elseif (is_object($object)) {
if (isset($object->$part))
$object = $object->$part;
elseif (is_callable(array($object, $part))) {
$methodAllowed = in_array(get_class($object), $this->safeClass) ||
(isset($object->h2o_safe) && (
$object->h2o_safe === true || in_array($part, $object->h2o_safe)
)
);
$object = $methodAllowed ? $object->$part() : null;
}
else return null;
}
else return null;
}
return $object;
}
function applyFilters($object, $filters) {
foreach ($filters as $filter) {
$name = substr(array_shift($filter), 1);
$args = $filter;
if (isset(h2o::$filters[$name])) {
foreach ($args as $i => $argument) {
# name args
if (is_array($argument)) {
foreach ($argument as $n => $arg) {
$args[$i][$n] = $this->resolve($arg);
}
} else {
# resolve argument values
$args[$i] = $this->resolve($argument);
}
}
array_unshift($args, $object);
$object = call_user_func_array(h2o::$filters[$name], $args);
}
}
return $object;
}
function escape($value, $var) {
$safe = false;
$filters = (is_array($var) && isset($var['filters']))? $var['filters'] : array();
foreach ( $filters as $filter ) {
$name = substr(array_shift($filter), 1);
$safe = !$safe && ($name === 'safe');
$escaped = $name === 'escape';
}
$should_escape = $this->autoescape || isset($escaped) && $escaped;
if ( ($should_escape && !$safe)) {
$value = htmlspecialchars($value);
}
return $value;
}
function externalLookup($name) {
if (!empty(self::$lookupTable)) {
foreach (self::$lookupTable as $lookup) {
$tmp = call_user_func_array($lookup, array($name, $this));
if ($tmp !== null)
return $tmp;
}
}
return null;
}
}
class BlockContext {
var $h2o_safe = array('name', 'depth', 'super');
var $block, $index;
private $context;
function __construct($block, $context, $index) {
$this->block =& $block;
$this->context = $context;
$this->index = $index;
}
function name() {
return $this->block->name;
}
function depth() {
return $this->index;
}
function super() {
$stream = new StreamWriter;
$this->block->parent->render($this->context, $stream, $this->index+1);
return $stream->close();
}
function __toString() {
return "[BlockContext : {$this->block->name}, {$this->block->filename}]";
}
}
?>

View File

@ -1,173 +1,173 @@
<?php
class StreamWriter {
var $buffer = array();
var $close;
function __construct() {
$this->close = false;
}
function write($data) {
if ($this->close)
new Exception('tried to write to closed stream');
$this->buffer[] = $data;
}
function close() {
$this->close = true;
return implode('', $this->buffer);
}
}
class Evaluator {
static function gt($l, $r) { return $l > $r; }
static function ge($l, $r) { return $l >= $r; }
static function lt($l, $r) { return $l < $r; }
static function le($l, $r) { return $l <= $r; }
static function eq($l, $r) { return $l == $r; }
static function ne($l, $r) { return $l != $r; }
static function not_($bool) { return !$bool; }
static function and_($l, $r) { return ($l && $r); }
static function or_($l, $r) { return ($l && $r); }
# Currently only support single expression with no preceddence ,no boolean expression
# [expression] = [optional binary] ? operant [ optional compare operant]
# [operant] = variable|string|numeric|boolean
# [compare] = > | < | == | >= | <=
# [binary] = not | !
static function exec($args, $context) {
$argc = count($args);
$first = array_shift($args);
$first = $context->resolve($first);
switch ($argc) {
case 1 :
return $first;
case 2 :
if (is_array($first) && isset($first['operator']) && $first['operator'] == 'not') {
$operant = array_shift($args);
$operant = $context->resolve($operant);
return !($operant);
}
case 3 :
list($op, $right) = $args;
$right = $context->resolve($right);
return call_user_func(array("Evaluator", $op['operator']), $first, $right);
default:
return false;
}
}
}
/**
* $type of token, Block | Variable
*/
class H2o_Token {
function __construct ($type, $content, $position) {
$this->type = $type;
$this->content = $content;
$this->result='';
$this->position = $position;
}
function write($content){
$this->result= $content;
}
}
/**
* a token stream
*/
class TokenStream {
var $pushed;
var $stream;
var $closed;
var $c;
function __construct() {
$this->pushed = array();
$this->stream = array();
$this->closed = false;
}
function pop() {
if (count($this->pushed))
return array_pop($this->pushed);
return array_pop($this->stream);
}
function feed($type, $contents, $position) {
if ($this->closed)
throw new Exception('cannot feed closed stream');
$this->stream[] = new H2o_Token($type, $contents, $position);
}
function push($token) {
if (is_null($token))
throw new Exception('cannot push NULL');
if ($this->closed)
$this->pushed[] = $token;
else
$this->stream[] = $token;
}
function close() {
if ($this->closed)
new Exception('cannot close already closed stream');
$this->closed = true;
$this->stream = array_reverse($this->stream);
}
function isClosed() {
return $this->closed;
}
function current() {
return $this->c ;
}
function next() {
return $this->c = $this->pop();
}
}
class H2o_Info {
var $h2o_safe = array('filters', 'extensions', 'tags');
var $name = 'H2o Template engine';
var $description = "Django inspired template system";
var $version = H2O_VERSION;
function filters() {
return array_keys(h2o::$filters);
}
function tags() {
return array_keys(h2o::$tags);
}
function extensions() {
return array_keys(h2o::$extensions);
}
}
/**
* Functions
*/
function sym_to_str($string) {
return substr($string, 1);
}
function is_sym($string) {
return isset($string[0]) && $string[0] === ':';
}
function symbol($string) {
return ':'.$string;
}
function strip_regex($regex, $delimiter = '/') {
return substr($regex, 1, strrpos($regex, $delimiter)-1);
}
?>
<?php
class StreamWriter {
var $buffer = array();
var $close;
function __construct() {
$this->close = false;
}
function write($data) {
if ($this->close)
new Exception('tried to write to closed stream');
$this->buffer[] = $data;
}
function close() {
$this->close = true;
return implode('', $this->buffer);
}
}
class Evaluator {
static function gt($l, $r) { return $l > $r; }
static function ge($l, $r) { return $l >= $r; }
static function lt($l, $r) { return $l < $r; }
static function le($l, $r) { return $l <= $r; }
static function eq($l, $r) { return $l == $r; }
static function ne($l, $r) { return $l != $r; }
static function not_($bool) { return !$bool; }
static function and_($l, $r) { return ($l && $r); }
static function or_($l, $r) { return ($l && $r); }
# Currently only support single expression with no preceddence ,no boolean expression
# [expression] = [optional binary] ? operant [ optional compare operant]
# [operant] = variable|string|numeric|boolean
# [compare] = > | < | == | >= | <=
# [binary] = not | !
static function exec($args, $context) {
$argc = count($args);
$first = array_shift($args);
$first = $context->resolve($first);
switch ($argc) {
case 1 :
return $first;
case 2 :
if (is_array($first) && isset($first['operator']) && $first['operator'] == 'not') {
$operant = array_shift($args);
$operant = $context->resolve($operant);
return !($operant);
}
case 3 :
list($op, $right) = $args;
$right = $context->resolve($right);
return call_user_func(array("Evaluator", $op['operator']), $first, $right);
default:
return false;
}
}
}
/**
* $type of token, Block | Variable
*/
class H2o_Token {
function __construct ($type, $content, $position) {
$this->type = $type;
$this->content = $content;
$this->result='';
$this->position = $position;
}
function write($content){
$this->result= $content;
}
}
/**
* a token stream
*/
class TokenStream {
var $pushed;
var $stream;
var $closed;
var $c;
function __construct() {
$this->pushed = array();
$this->stream = array();
$this->closed = false;
}
function pop() {
if (count($this->pushed))
return array_pop($this->pushed);
return array_pop($this->stream);
}
function feed($type, $contents, $position) {
if ($this->closed)
throw new Exception('cannot feed closed stream');
$this->stream[] = new H2o_Token($type, $contents, $position);
}
function push($token) {
if (is_null($token))
throw new Exception('cannot push NULL');
if ($this->closed)
$this->pushed[] = $token;
else
$this->stream[] = $token;
}
function close() {
if ($this->closed)
new Exception('cannot close already closed stream');
$this->closed = true;
$this->stream = array_reverse($this->stream);
}
function isClosed() {
return $this->closed;
}
function current() {
return $this->c ;
}
function next() {
return $this->c = $this->pop();
}
}
class H2o_Info {
var $h2o_safe = array('filters', 'extensions', 'tags');
var $name = 'H2o Template engine';
var $description = "Django inspired template system";
var $version = H2O_VERSION;
function filters() {
return array_keys(h2o::$filters);
}
function tags() {
return array_keys(h2o::$tags);
}
function extensions() {
return array_keys(h2o::$extensions);
}
}
/**
* Functions
*/
function sym_to_str($string) {
return substr($string, 1);
}
function is_sym($string) {
return isset($string[0]) && $string[0] === ':';
}
function symbol($string) {
return ':'.$string;
}
function strip_regex($regex, $delimiter = '/') {
return substr($regex, 1, strrpos($regex, $delimiter)-1);
}
?>

View File

@ -1,10 +1,10 @@
<?php
# Errors
class H2o_Error extends Exception {}
class ParseError extends H2o_Error {}
class TemplateNotFound extends H2o_Error {}
class TemplateSyntaxError extends H2o_Error {}
<?php
# Errors
class H2o_Error extends Exception {}
class ParseError extends H2o_Error {}
class TemplateNotFound extends H2o_Error {}
class TemplateSyntaxError extends H2o_Error {}
?>

View File

@ -1,369 +1,369 @@
<?php
class FilterCollection {};
class CoreFilters extends FilterCollection {
static function first($value) {
return $value[0];
}
static function last($value) {
return $value[count($value) - 1];
}
static function join($value, $delimiter = ', ') {
return join($delimiter, $value);
}
static function length($value) {
return count($value);
}
static function urlencode($data) {
if (is_array($data)) {
$result;
foreach ($data as $name => $value) {
$result .= $name.'='.urlencode($value).'&'.$querystring;
}
$querystring = substr($result, 0, strlen($result)-1);
return htmlspecialchars($result);
} else {
return urlencode($data);
}
}
static function hyphenize ($string) {
$rules = array('/[^\w\s-]+/'=>'','/\s+/'=>'-', '/-{2,}/'=>'-');
$string = preg_replace(array_keys($rules), $rules, trim($string));
return $string = trim(strtolower($string));
}
static function urlize( $string, $truncate = false ) {
$reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
preg_match_all($reg_exUrl, $string, $matches);
$usedPatterns = array();
foreach($matches[0] as $pattern){
if(!array_key_exists($pattern, $usedPatterns)){
$usedPatterns[$pattern]=true;
$string = str_replace($pattern, "<a href=\"{$pattern}\" rel=\"nofollow\">{$pattern}</a>", $string);
}
}
$reg_exEmail = "/[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/";
preg_match_all($reg_exEmail, $string, $matches);
$usedPatterns = array();
foreach($matches[0] as $pattern){
if(!array_key_exists($pattern, $usedPatterns)){
$usedPatterns[$pattern]=true;
$string = str_replace($pattern, "<a href=\"mailto:{$pattern}\">{$pattern}</a>", $string);
}
}
return $string;
}
static function set_default($object, $default) {
return !$object ? $default : $object;
}
}
class StringFilters extends FilterCollection {
static function humanize($string) {
$string = preg_replace('/\s+/', ' ', trim(preg_replace('/[^A-Za-z0-9()!,?$]+/', ' ', $string)));
return capfirst($string);
}
static function capitalize($string) {
return ucwords(strtolower($string)) ;
}
static function titlize($string) {
return self::capitalize($string);
}
static function capfirst($string) {
$string = strtolower($string);
return strtoupper($string{0}). substr($string, 1, strlen($string));
}
static function tighten_space($value) {
return preg_replace("/\s{2,}/", ' ', $value);
}
static function escape($value, $attribute = false) {
return htmlspecialchars($value, $attribute ? ENT_QUOTES : ENT_NOQUOTES);
}
static function escapejson($value) {
// The standard django escapejs converts all non-ascii characters into hex codes.
// This function encodes the entire data structure, and strings get quotes around them.
return json_encode($value);
}
static function force_escape($value, $attribute = false) {
return self::escape($value, $attribute);
}
static function e($value, $attribute = false) {
return self::escape($value, $attribute);
}
static function safe($value) {
return $value;
}
static function truncate ($string, $max = 50, $ends = '...') {
return (strlen($string) > $max ? substr($string, 0, $max).$ends : $string);
}
static function limitwords($text, $limit = 50, $ends = '...') {
if (strlen($text) > $limit) {
$words = str_word_count($text, 2);
$pos = array_keys($words);
if (isset($pos[$limit])) {
$text = substr($text, 0, $pos[$limit]) . $ends;
}
}
return $text;
}
}
class NumberFilters extends FilterCollection {
static function filesize ($bytes, $round = 1) {
if ($bytes === 0)
return '0 bytes';
elseif ($bytes === 1)
return '1 byte';
$units = array(
'bytes' => pow(2, 0), 'kB' => pow(2, 10),
'BM' => pow(2, 20), 'GB' => pow(2, 30),
'TB' => pow(2, 40), 'PB' => pow(2, 50),
'EB' => pow(2, 60), 'ZB' => pow(2, 70)
);
$lastUnit = 'bytes';
foreach ($units as $unitName => $unitFactor) {
if ($bytes >= $unitFactor) {
$lastUnit = $unitName;
} else {
$number = round( $bytes / $units[$lastUnit], $round );
return number_format($number) . ' ' . $lastUnit;
}
}
}
static function currency($amount, $currency = 'USD', $precision = 2, $negateWithParentheses = false) {
$definition = array(
'EUR' => array('<27>','.',','), 'GBP' => '<27>', 'JPY' => '<27>',
'USD'=>'$', 'AU' => '$', 'CAN' => '$'
);
$negative = false;
$separator = ',';
$decimals = '.';
$currency = strtoupper($currency);
// Is negative
if (strpos('-', $amount) !== false) {
$negative = true;
$amount = str_replace("-","",$amount);
}
$amount = (float) $amount;
if (!$negative) {
$negative = $amount < 0;
}
if ($negateWithParentheses) {
$amount = abs($amount);
}
// Get rid of negative zero
$zero = round(0, $precision);
if (round($amount, $precision) === $zero) {
$amount = $zero;
}
if (isset($definition[$currency])) {
$symbol = $definition[$currency];
if (is_array($symbol))
@list($symbol, $separator, $decimals) = $symbol;
} else {
$symbol = $currency;
}
$amount = number_format($amount, $precision, $decimals, $separator);
return $negateWithParentheses ? "({$symbol}{$amount})" : "{$symbol}{$amount}";
}
}
class HtmlFilters extends FilterCollection {
static function base_url($url, $options = array()) {
return $url;
}
static function asset_url($url, $options = array()) {
return self::base_url($url, $options);
}
static function image_tag($url, $options = array()) {
$attr = self::htmlAttribute(array('alt','width','height','border'), $options);
return sprintf('<img src="%s" %s/>', $url, $attr);
}
static function css_tag($url, $options = array()) {
$attr = self::htmlAttribute(array('media'), $options);
return sprintf('<link rel="stylesheet" href="%s" type="text/css" %s />', $url, $attr);
}
static function script_tag($url, $options = array()) {
return sprintf('<script src="%s" type="text/javascript"></script>', $url);
}
static function links_to($text, $url, $options = array()) {
$attrs = self::htmlAttribute(array('ref'), $options);
$url = self::base_url($url, $options);
return sprintf('<a href="%s" %s>%s</a>', $url, $attrs, $text);
}
static function links_with ($url, $text, $options = array()) {
return self::links_to($text, $url, $options);
}
static function strip_tags($text) {
$text = preg_replace(array('/</', '/>/'), array(' <', '> '),$text);
return strip_tags($text);
}
static function linebreaks($value, $format = 'p') {
if ($format === 'br')
return HtmlFilters::nl2br($value);
return HtmlFilters::nl2pbr($value);
}
static function nl2br($value) {
return str_replace("\n", "<br />\n", $value);
}
static function nl2pbr($value) {
$result = array();
$parts = preg_split('/(\r?\n){2,}/m', $value);
foreach ($parts as $part) {
array_push($result, '<p>' . HtmlFilters::nl2br($part) . '</p>');
}
return implode("\n", $result);
}
protected static function htmlAttribute($attrs = array(), $data = array()) {
$attrs = self::extract(array_merge(array('id', 'class', 'title', "style"), $attrs), $data);
$result = array();
foreach ($attrs as $name => $value) {
$result[] = "{$name}=\"{$value}\"";
}
return join(' ', $result);
}
protected static function extract($attrs = array(), $data=array()) {
$result = array();
if (empty($data)) return array();
foreach($data as $k => $e) {
if (in_array($k, $attrs)) $result[$k] = $e;
}
return $result;
}
}
class DatetimeFilters extends FilterCollection {
static function date($time, $format = 'jS F Y H:i') {
if ($time instanceof DateTime)
$time = (int) $time->format('U');
if (!is_numeric($time))
$time = strtotime($time);
return date($format, $time);
}
static function relative_time($timestamp, $format = 'g:iA') {
if ($timestamp instanceof DateTime)
$timestamp = (int) $timestamp->format('U');
$timestamp = is_numeric($timestamp) ? $timestamp: strtotime($timestamp);
$time = mktime(0, 0, 0);
$delta = time() - $timestamp;
$string = '';
if ($timestamp < $time - 86400) {
return date("F j, Y, g:i a", $timestamp);
}
if ($delta > 86400 && $timestamp < $time) {
return "Yesterday at " . date("g:i a", $timestamp);
}
if ($delta > 7200)
$string .= floor($delta / 3600) . " hours, ";
else if ($delta > 3660)
$string .= "1 hour, ";
else if ($delta >= 3600)
$string .= "1 hour ";
$delta %= 3600;
if ($delta > 60)
$string .= floor($delta / 60) . " minutes ";
else
$string .= $delta . " seconds ";
return "$string ago";
}
static function relative_date($time) {
if ($time instanceof DateTime)
$time = (int) $time->format('U');
$time = is_numeric($time) ? $time: strtotime($time);
$today = strtotime(date('M j, Y'));
$reldays = ($time - $today)/86400;
if ($reldays >= 0 && $reldays < 1)
return 'today';
else if ($reldays >= 1 && $reldays < 2)
return 'tomorrow';
else if ($reldays >= -1 && $reldays < 0)
return 'yesterday';
if (abs($reldays) < 7) {
if ($reldays > 0) {
$reldays = floor($reldays);
return 'in ' . $reldays . ' day' . ($reldays != 1 ? 's' : '');
} else {
$reldays = abs(floor($reldays));
return $reldays . ' day' . ($reldays != 1 ? 's' : '') . ' ago';
}
}
if (abs($reldays) < 182)
return date('l, F j',$time ? $time : time());
else
return date('l, F j, Y',$time ? $time : time());
}
static function relative_datetime($time) {
$date = self::relative_date($time);
if ($date === 'today')
return self::relative_time($time);
return $date;
}
}
/* Ultizie php funciton as Filters */
h2o::addFilter(array('md5', 'sha1', 'numberformat'=>'number_format', 'wordwrap', 'trim', 'upper' => 'strtoupper', 'lower' => 'strtolower'));
/* Add filter collections */
h2o::addFilter(array('CoreFilters', 'StringFilters', 'NumberFilters', 'DatetimeFilters', 'HtmlFilters'));
/* Alias default to set_default */
h2o::addFilter('default', array('CoreFilters', 'set_default'));
?>
<?php
class FilterCollection {};
class CoreFilters extends FilterCollection {
static function first($value) {
return $value[0];
}
static function last($value) {
return $value[count($value) - 1];
}
static function join($value, $delimiter = ', ') {
return join($delimiter, $value);
}
static function length($value) {
return count($value);
}
static function urlencode($data) {
if (is_array($data)) {
$result;
foreach ($data as $name => $value) {
$result .= $name.'='.urlencode($value).'&'.$querystring;
}
$querystring = substr($result, 0, strlen($result)-1);
return htmlspecialchars($result);
} else {
return urlencode($data);
}
}
static function hyphenize ($string) {
$rules = array('/[^\w\s-]+/'=>'','/\s+/'=>'-', '/-{2,}/'=>'-');
$string = preg_replace(array_keys($rules), $rules, trim($string));
return $string = trim(strtolower($string));
}
static function urlize( $string, $truncate = false ) {
$reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
preg_match_all($reg_exUrl, $string, $matches);
$usedPatterns = array();
foreach($matches[0] as $pattern){
if(!array_key_exists($pattern, $usedPatterns)){
$usedPatterns[$pattern]=true;
$string = str_replace($pattern, "<a href=\"{$pattern}\" rel=\"nofollow\">{$pattern}</a>", $string);
}
}
$reg_exEmail = "/[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/";
preg_match_all($reg_exEmail, $string, $matches);
$usedPatterns = array();
foreach($matches[0] as $pattern){
if(!array_key_exists($pattern, $usedPatterns)){
$usedPatterns[$pattern]=true;
$string = str_replace($pattern, "<a href=\"mailto:{$pattern}\">{$pattern}</a>", $string);
}
}
return $string;
}
static function set_default($object, $default) {
return !$object ? $default : $object;
}
}
class StringFilters extends FilterCollection {
static function humanize($string) {
$string = preg_replace('/\s+/', ' ', trim(preg_replace('/[^A-Za-z0-9()!,?$]+/', ' ', $string)));
return capfirst($string);
}
static function capitalize($string) {
return ucwords(strtolower($string)) ;
}
static function titlize($string) {
return self::capitalize($string);
}
static function capfirst($string) {
$string = strtolower($string);
return strtoupper($string{0}). substr($string, 1, strlen($string));
}
static function tighten_space($value) {
return preg_replace("/\s{2,}/", ' ', $value);
}
static function escape($value, $attribute = false) {
return htmlspecialchars($value, $attribute ? ENT_QUOTES : ENT_NOQUOTES);
}
static function escapejson($value) {
// The standard django escapejs converts all non-ascii characters into hex codes.
// This function encodes the entire data structure, and strings get quotes around them.
return json_encode($value);
}
static function force_escape($value, $attribute = false) {
return self::escape($value, $attribute);
}
static function e($value, $attribute = false) {
return self::escape($value, $attribute);
}
static function safe($value) {
return $value;
}
static function truncate ($string, $max = 50, $ends = '...') {
return (strlen($string) > $max ? substr($string, 0, $max).$ends : $string);
}
static function limitwords($text, $limit = 50, $ends = '...') {
if (strlen($text) > $limit) {
$words = str_word_count($text, 2);
$pos = array_keys($words);
if (isset($pos[$limit])) {
$text = substr($text, 0, $pos[$limit]) . $ends;
}
}
return $text;
}
}
class NumberFilters extends FilterCollection {
static function filesize ($bytes, $round = 1) {
if ($bytes === 0)
return '0 bytes';
elseif ($bytes === 1)
return '1 byte';
$units = array(
'bytes' => pow(2, 0), 'kB' => pow(2, 10),
'BM' => pow(2, 20), 'GB' => pow(2, 30),
'TB' => pow(2, 40), 'PB' => pow(2, 50),
'EB' => pow(2, 60), 'ZB' => pow(2, 70)
);
$lastUnit = 'bytes';
foreach ($units as $unitName => $unitFactor) {
if ($bytes >= $unitFactor) {
$lastUnit = $unitName;
} else {
$number = round( $bytes / $units[$lastUnit], $round );
return number_format($number) . ' ' . $lastUnit;
}
}
}
static function currency($amount, $currency = 'USD', $precision = 2, $negateWithParentheses = false) {
$definition = array(
'EUR' => array('<27>','.',','), 'GBP' => '<27>', 'JPY' => '<27>',
'USD'=>'$', 'AU' => '$', 'CAN' => '$'
);
$negative = false;
$separator = ',';
$decimals = '.';
$currency = strtoupper($currency);
// Is negative
if (strpos('-', $amount) !== false) {
$negative = true;
$amount = str_replace("-","",$amount);
}
$amount = (float) $amount;
if (!$negative) {
$negative = $amount < 0;
}
if ($negateWithParentheses) {
$amount = abs($amount);
}
// Get rid of negative zero
$zero = round(0, $precision);
if (round($amount, $precision) === $zero) {
$amount = $zero;
}
if (isset($definition[$currency])) {
$symbol = $definition[$currency];
if (is_array($symbol))
@list($symbol, $separator, $decimals) = $symbol;
} else {
$symbol = $currency;
}
$amount = number_format($amount, $precision, $decimals, $separator);
return $negateWithParentheses ? "({$symbol}{$amount})" : "{$symbol}{$amount}";
}
}
class HtmlFilters extends FilterCollection {
static function base_url($url, $options = array()) {
return $url;
}
static function asset_url($url, $options = array()) {
return self::base_url($url, $options);
}
static function image_tag($url, $options = array()) {
$attr = self::htmlAttribute(array('alt','width','height','border'), $options);
return sprintf('<img src="%s" %s/>', $url, $attr);
}
static function css_tag($url, $options = array()) {
$attr = self::htmlAttribute(array('media'), $options);
return sprintf('<link rel="stylesheet" href="%s" type="text/css" %s />', $url, $attr);
}
static function script_tag($url, $options = array()) {
return sprintf('<script src="%s" type="text/javascript"></script>', $url);
}
static function links_to($text, $url, $options = array()) {
$attrs = self::htmlAttribute(array('ref'), $options);
$url = self::base_url($url, $options);
return sprintf('<a href="%s" %s>%s</a>', $url, $attrs, $text);
}
static function links_with ($url, $text, $options = array()) {
return self::links_to($text, $url, $options);
}
static function strip_tags($text) {
$text = preg_replace(array('/</', '/>/'), array(' <', '> '),$text);
return strip_tags($text);
}
static function linebreaks($value, $format = 'p') {
if ($format === 'br')
return HtmlFilters::nl2br($value);
return HtmlFilters::nl2pbr($value);
}
static function nl2br($value) {
return str_replace("\n", "<br />\n", $value);
}
static function nl2pbr($value) {
$result = array();
$parts = preg_split('/(\r?\n){2,}/m', $value);
foreach ($parts as $part) {
array_push($result, '<p>' . HtmlFilters::nl2br($part) . '</p>');
}
return implode("\n", $result);
}
protected static function htmlAttribute($attrs = array(), $data = array()) {
$attrs = self::extract(array_merge(array('id', 'class', 'title', "style"), $attrs), $data);
$result = array();
foreach ($attrs as $name => $value) {
$result[] = "{$name}=\"{$value}\"";
}
return join(' ', $result);
}
protected static function extract($attrs = array(), $data=array()) {
$result = array();
if (empty($data)) return array();
foreach($data as $k => $e) {
if (in_array($k, $attrs)) $result[$k] = $e;
}
return $result;
}
}
class DatetimeFilters extends FilterCollection {
static function date($time, $format = 'jS F Y H:i') {
if ($time instanceof DateTime)
$time = (int) $time->format('U');
if (!is_numeric($time))
$time = strtotime($time);
return date($format, $time);
}
static function relative_time($timestamp, $format = 'g:iA') {
if ($timestamp instanceof DateTime)
$timestamp = (int) $timestamp->format('U');
$timestamp = is_numeric($timestamp) ? $timestamp: strtotime($timestamp);
$time = mktime(0, 0, 0);
$delta = time() - $timestamp;
$string = '';
if ($timestamp < $time - 86400) {
return date("F j, Y, g:i a", $timestamp);
}
if ($delta > 86400 && $timestamp < $time) {
return "Yesterday at " . date("g:i a", $timestamp);
}
if ($delta > 7200)
$string .= floor($delta / 3600) . " hours, ";
else if ($delta > 3660)
$string .= "1 hour, ";
else if ($delta >= 3600)
$string .= "1 hour ";
$delta %= 3600;
if ($delta > 60)
$string .= floor($delta / 60) . " minutes ";
else
$string .= $delta . " seconds ";
return "$string ago";
}
static function relative_date($time) {
if ($time instanceof DateTime)
$time = (int) $time->format('U');
$time = is_numeric($time) ? $time: strtotime($time);
$today = strtotime(date('M j, Y'));
$reldays = ($time - $today)/86400;
if ($reldays >= 0 && $reldays < 1)
return 'today';
else if ($reldays >= 1 && $reldays < 2)
return 'tomorrow';
else if ($reldays >= -1 && $reldays < 0)
return 'yesterday';
if (abs($reldays) < 7) {
if ($reldays > 0) {
$reldays = floor($reldays);
return 'in ' . $reldays . ' day' . ($reldays != 1 ? 's' : '');
} else {
$reldays = abs(floor($reldays));
return $reldays . ' day' . ($reldays != 1 ? 's' : '') . ' ago';
}
}
if (abs($reldays) < 182)
return date('l, F j',$time ? $time : time());
else
return date('l, F j, Y',$time ? $time : time());
}
static function relative_datetime($time) {
$date = self::relative_date($time);
if ($date === 'today')
return self::relative_time($time);
return $date;
}
}
/* Ultizie php funciton as Filters */
h2o::addFilter(array('md5', 'sha1', 'numberformat'=>'number_format', 'wordwrap', 'trim', 'upper' => 'strtoupper', 'lower' => 'strtolower'));
/* Add filter collections */
h2o::addFilter(array('CoreFilters', 'StringFilters', 'NumberFilters', 'DatetimeFilters', 'HtmlFilters'));
/* Alias default to set_default */
h2o::addFilter('default', array('CoreFilters', 'set_default'));
?>

View File

@ -1,290 +1,290 @@
<?php
/**
*
* @author taylor.luk
* @todo FileLoader need more test coverage
*/
class H2o_Loader {
public $parser;
public $runtime;
public $cached = false;
protected $cache = false;
public $searchpath = false;
function read($filename) {}
function cache_read($file, $object, $ttl = 3600) {}
}
class H2o_File_Loader extends H2o_Loader {
function __construct($searchpath, $options = array()) {
// if (is_file($searchpath)) {
// $searthpath = dirname($searchpath).DS;
// }
// if (!is_dir($searchpath))
// throw new TemplateNotFound($filename);
//
if (!is_array($searchpath))
throw new Exception("searchpath must be an array");
$this->searchpath = (array) $searchpath;
$this->setOptions($options);
}
function setOptions($options = array()) {
if (isset($options['cache']) && $options['cache']) {
$this->cache = h2o_cache($options);
}
}
function read($filename) {
if (!is_file($filename))
$filename = $this->get_template_path($this->searchpath,$filename);
if (is_file($filename)) {
$source = file_get_contents($filename);
return $this->runtime->parse($source);
} else {
throw new TemplateNotFound($filename);
}
}
function get_template_path($search_path, $filename){
for ($i=0 ; $i < count($search_path) ; $i++)
{
if(file_exists($search_path[$i] . $filename)) {
$filename = $search_path[$i] . $filename;
return $filename;
break;
} else {
continue;
}
}
throw new Exception('TemplateNotFound - Looked for template: ' . $filename);
}
function read_cache($filename) {
if (!$this->cache){
$filename = $this->get_template_path($this->searchpath,$filename);
return $this->read($filename);
}
if (!is_file($filename)){
$filename = $this->get_template_path($this->searchpath,$filename);
}
$filename = realpath($filename);
$cache = md5($filename);
$object = $this->cache->read($cache);
$this->cached = $object && !$this->expired($object);
if (!$this->cached) {
$nodelist = $this->read($filename);
$object = (object) array(
'filename' => $filename,
'content' => serialize($nodelist),
'created' => time(),
'templates' => $nodelist->parser->storage['templates'],
'included' => $nodelist->parser->storage['included'] + array_values(h2o::$extensions)
);
$this->cache->write($cache, $object);
} else {
foreach($object->included as $ext => $file) {
include_once (h2o::$extensions[$ext] = $file);
}
}
return unserialize($object->content);
}
function flush_cache() {
$this->cache->flush();
}
function expired($object) {
if (!$object) return false;
$files = array_merge(array($object->filename), $object->templates);
foreach ($files as $file) {
if (!is_file($file))
$file = $this->get_template_path($this->searchpath, $file);
if ($object->created < filemtime($file))
return true;
}
return false;
}
}
function file_loader($file) {
return new H2o_File_Loader($file);
}
class H2o_Hash_Loader {
function __construct($scope, $options = array()) {
$this->scope = $scope;
}
function setOptions() {}
function read($file) {
if (!isset($this->scope[$file]))
throw new TemplateNotFound;
return $this->runtime->parse($this->scope[$file], $file);
}
function read_cache($file) {
return $this->read($file);
}
}
function hash_loader($hash = array()) {
return new H2o_Hash_Loader($hash);
}
/**
* Cache subsystem
*
*/
function h2o_cache($options = array()) {
$type = $options['cache'];
$className = "H2o_".ucwords($type)."_Cache";
if (class_exists($className, false)) {
return new $className($options);
}
return false;
}
class H2o_File_Cache {
var $ttl = 3600;
var $prefix = 'h2o_';
function __construct($options = array()) {
if (isset($options['cache_dir']) && is_writable($options['cache_dir'])) {
$path = $options['cache_dir'];
} else {
$path = dirname($tmp = tempnam(uniqid(rand(), true), ''));
if (file_exists($tmp)) unlink($tmp);
}
if (isset($options['cache_ttl'])) {
$this->ttl = $options['cache_ttl'];
}
if(isset($options['cache_prefix'])) {
$this->prefix = $options['cache_prefix'];
}
$this->path = realpath($path). DS;
}
function read($filename) {
if (!file_exists($this->path . $this->prefix. $filename))
return false;
$content = file_get_contents($this->path . $this->prefix. $filename);
$expires = (int)substr($content, 0, 10);
if (time() >= $expires)
return false;
return unserialize(trim(substr($content, 10)));
}
function write($filename, &$object) {
$expires = time() + $this->ttl;
$content = $expires . serialize($object);
return file_put_contents($this->path . $this->prefix. $filename, $content);
}
function flush() {
foreach (glob($this->path. $this->prefix. '*') as $file) {
@unlink($file);
}
}
}
class H2o_Apc_Cache {
var $ttl = 3600;
var $prefix = 'h2o_';
function __construct($options = array()) {
if (!function_exists('apc_add'))
throw new Exception('APC extension needs to be loaded to use APC cache');
if (isset($options['cache_ttl'])) {
$this->ttl = $options['cache_ttl'];
}
if(isset($options['cache_prefix'])) {
$this->prefix = $options['cache_prefix'];
}
}
function read($filename) {
return apc_fetch($this->prefix.$filename);
}
function write($filename, $object) {
return apc_store($this->prefix.$filename, $object, $this->ttl);
}
function flush() {
return apc_clear_cache('user');
}
}
class H2o_Memcache_Cache {
var $ttl = 3600;
var $prefix = 'h2o_';
/**
* @var host default is file socket
*/
var $host = 'unix:///tmp/memcached.sock';
var $port = 0;
var $object;
function __construct( $scope, $options = array() ) {
if ( !function_exists( 'memcache_set' ) )
throw new Exception( 'Memcache extension needs to be loaded to use memcache' );
if ( isset( $options['cache_ttl'] ) ) {
$this->ttl = $options['cache_ttl'];
}
if( isset( $options['cache_prefix'] ) ) {
$this->prefix = $options['cache_prefix'];
}
if( isset( $options['host'] ) ) {
$this->host = $options['host'];
}
if( isset( $options['port'] ) ) {
$this->port = $options['port'];
}
$this->object = memcache_connect( $this->host, $this->port );
}
function read( $filename ){
return memcache_get( $this->object, $this->prefix.$filename );
}
function write( $filename, $content ) {
return memcache_set( $this->object,$this->prefix.$filename,$content , MEMCACHE_COMPRESSED,$this->ttl );
}
function flush(){
return memcache_flush( $this->object );
}
<?php
/**
*
* @author taylor.luk
* @todo FileLoader need more test coverage
*/
class H2o_Loader {
public $parser;
public $runtime;
public $cached = false;
protected $cache = false;
public $searchpath = false;
function read($filename) {}
function cache_read($file, $object, $ttl = 3600) {}
}
class H2o_File_Loader extends H2o_Loader {
function __construct($searchpath, $options = array()) {
// if (is_file($searchpath)) {
// $searthpath = dirname($searchpath).DS;
// }
// if (!is_dir($searchpath))
// throw new TemplateNotFound($filename);
//
if (!is_array($searchpath))
throw new Exception("searchpath must be an array");
$this->searchpath = (array) $searchpath;
$this->setOptions($options);
}
function setOptions($options = array()) {
if (isset($options['cache']) && $options['cache']) {
$this->cache = h2o_cache($options);
}
}
function read($filename) {
if (!is_file($filename))
$filename = $this->get_template_path($this->searchpath,$filename);
if (is_file($filename)) {
$source = file_get_contents($filename);
return $this->runtime->parse($source);
} else {
throw new TemplateNotFound($filename);
}
}
function get_template_path($search_path, $filename){
for ($i=0 ; $i < count($search_path) ; $i++)
{
if(file_exists($search_path[$i] . $filename)) {
$filename = $search_path[$i] . $filename;
return $filename;
break;
} else {
continue;
}
}
throw new Exception('TemplateNotFound - Looked for template: ' . $filename);
}
function read_cache($filename) {
if (!$this->cache){
$filename = $this->get_template_path($this->searchpath,$filename);
return $this->read($filename);
}
if (!is_file($filename)){
$filename = $this->get_template_path($this->searchpath,$filename);
}
$filename = realpath($filename);
$cache = md5($filename);
$object = $this->cache->read($cache);
$this->cached = $object && !$this->expired($object);
if (!$this->cached) {
$nodelist = $this->read($filename);
$object = (object) array(
'filename' => $filename,
'content' => serialize($nodelist),
'created' => time(),
'templates' => $nodelist->parser->storage['templates'],
'included' => $nodelist->parser->storage['included'] + array_values(h2o::$extensions)
);
$this->cache->write($cache, $object);
} else {
foreach($object->included as $ext => $file) {
include_once (h2o::$extensions[$ext] = $file);
}
}
return unserialize($object->content);
}
function flush_cache() {
$this->cache->flush();
}
function expired($object) {
if (!$object) return false;
$files = array_merge(array($object->filename), $object->templates);
foreach ($files as $file) {
if (!is_file($file))
$file = $this->get_template_path($this->searchpath, $file);
if ($object->created < filemtime($file))
return true;
}
return false;
}
}
function file_loader($file) {
return new H2o_File_Loader($file);
}
class H2o_Hash_Loader {
function __construct($scope, $options = array()) {
$this->scope = $scope;
}
function setOptions() {}
function read($file) {
if (!isset($this->scope[$file]))
throw new TemplateNotFound;
return $this->runtime->parse($this->scope[$file], $file);
}
function read_cache($file) {
return $this->read($file);
}
}
function hash_loader($hash = array()) {
return new H2o_Hash_Loader($hash);
}
/**
* Cache subsystem
*
*/
function h2o_cache($options = array()) {
$type = $options['cache'];
$className = "H2o_".ucwords($type)."_Cache";
if (class_exists($className, false)) {
return new $className($options);
}
return false;
}
class H2o_File_Cache {
var $ttl = 3600;
var $prefix = 'h2o_';
function __construct($options = array()) {
if (isset($options['cache_dir']) && is_writable($options['cache_dir'])) {
$path = $options['cache_dir'];
} else {
$path = dirname($tmp = tempnam(uniqid(rand(), true), ''));
if (file_exists($tmp)) unlink($tmp);
}
if (isset($options['cache_ttl'])) {
$this->ttl = $options['cache_ttl'];
}
if(isset($options['cache_prefix'])) {
$this->prefix = $options['cache_prefix'];
}
$this->path = realpath($path). DS;
}
function read($filename) {
if (!file_exists($this->path . $this->prefix. $filename))
return false;
$content = file_get_contents($this->path . $this->prefix. $filename);
$expires = (int)substr($content, 0, 10);
if (time() >= $expires)
return false;
return unserialize(trim(substr($content, 10)));
}
function write($filename, &$object) {
$expires = time() + $this->ttl;
$content = $expires . serialize($object);
return file_put_contents($this->path . $this->prefix. $filename, $content);
}
function flush() {
foreach (glob($this->path. $this->prefix. '*') as $file) {
@unlink($file);
}
}
}
class H2o_Apc_Cache {
var $ttl = 3600;
var $prefix = 'h2o_';
function __construct($options = array()) {
if (!function_exists('apc_add'))
throw new Exception('APC extension needs to be loaded to use APC cache');
if (isset($options['cache_ttl'])) {
$this->ttl = $options['cache_ttl'];
}
if(isset($options['cache_prefix'])) {
$this->prefix = $options['cache_prefix'];
}
}
function read($filename) {
return apc_fetch($this->prefix.$filename);
}
function write($filename, $object) {
return apc_store($this->prefix.$filename, $object, $this->ttl);
}
function flush() {
return apc_clear_cache('user');
}
}
class H2o_Memcache_Cache {
var $ttl = 3600;
var $prefix = 'h2o_';
/**
* @var host default is file socket
*/
var $host = 'unix:///tmp/memcached.sock';
var $port = 0;
var $object;
function __construct( $scope, $options = array() ) {
if ( !function_exists( 'memcache_set' ) )
throw new Exception( 'Memcache extension needs to be loaded to use memcache' );
if ( isset( $options['cache_ttl'] ) ) {
$this->ttl = $options['cache_ttl'];
}
if( isset( $options['cache_prefix'] ) ) {
$this->prefix = $options['cache_prefix'];
}
if( isset( $options['host'] ) ) {
$this->host = $options['host'];
}
if( isset( $options['port'] ) ) {
$this->port = $options['port'];
}
$this->object = memcache_connect( $this->host, $this->port );
}
function read( $filename ){
return memcache_get( $this->object, $this->prefix.$filename );
}
function write( $filename, $content ) {
return memcache_set( $this->object,$this->prefix.$filename,$content , MEMCACHE_COMPRESSED,$this->ttl );
}
function flush(){
return memcache_flush( $this->object );
}
}

View File

@ -1,84 +1,84 @@
<?php
/*
Nodes
*/
class H2o_Node {
var $position;
function __construct($argstring) {}
function render($context, $stream) {}
}
class NodeList extends H2o_Node implements IteratorAggregate {
var $parser;
var $list;
function __construct(&$parser, $initial = null, $position = 0) {
$this->parser = $parser;
if (is_null($initial))
$initial = array();
$this->list = $initial;
$this->position = $position;
}
function render($context, $stream) {
foreach($this->list as $node) {
$node->render($context, $stream);
}
}
function append($node) {
array_push($this->list, $node);
}
function extend($nodes) {
array_merge($this->list, $nodes);
}
function getLength() {
return count($this->list);
}
function getIterator() {
return new ArrayIterator( $this->list );
}
}
class VariableNode extends H2o_Node {
private $filters = array();
var $variable;
function __construct($variable, $filters, $position = 0) {
if (!empty($filters))
$this->filters = $filters;
$this->variable = $variable;
}
function render($context, $stream) {
$value = $context->resolve($this->variable);
$value = $context->escape($value, $this->variable);
$stream->write($value);
}
}
class CommentNode extends H2o_Node {}
class TextNode extends H2o_Node {
var $content;
function __construct($content, $position = 0) {
$this->content = $content;
$this->position = $position;
}
function render($context, $stream) {
$stream->write($this->content);
}
function is_blank() {
return strlen(trim($this->content));
}
}
<?php
/*
Nodes
*/
class H2o_Node {
var $position;
function __construct($argstring) {}
function render($context, $stream) {}
}
class NodeList extends H2o_Node implements IteratorAggregate {
var $parser;
var $list;
function __construct(&$parser, $initial = null, $position = 0) {
$this->parser = $parser;
if (is_null($initial))
$initial = array();
$this->list = $initial;
$this->position = $position;
}
function render($context, $stream) {
foreach($this->list as $node) {
$node->render($context, $stream);
}
}
function append($node) {
array_push($this->list, $node);
}
function extend($nodes) {
array_merge($this->list, $nodes);
}
function getLength() {
return count($this->list);
}
function getIterator() {
return new ArrayIterator( $this->list );
}
}
class VariableNode extends H2o_Node {
private $filters = array();
var $variable;
function __construct($variable, $filters, $position = 0) {
if (!empty($filters))
$this->filters = $filters;
$this->variable = $variable;
}
function render($context, $stream) {
$value = $context->resolve($this->variable);
$value = $context->escape($value, $this->variable);
$stream->write($value);
}
}
class CommentNode extends H2o_Node {}
class TextNode extends H2o_Node {
var $content;
function __construct($content, $position = 0) {
$this->content = $content;
$this->position = $position;
}
function render($context, $stream) {
$stream->write($this->content);
}
function is_blank() {
return strlen(trim($this->content));
}
}
?>

View File

@ -1,290 +1,290 @@
<?php
class H2o_Lexer {
function __construct($options = array()) {
$this->options = $options;
$trim = '';
if ($this->options['TRIM_TAGS'])
$trim = '(?:\r?\n)?';
$this->pattern = ('/\G(.*?)(?:' .
preg_quote($this->options['BLOCK_START']). '(.*?)' .preg_quote($this->options['BLOCK_END']) . $trim . '|' .
preg_quote($this->options['VARIABLE_START']). '(.*?)' .preg_quote($this->options['VARIABLE_END']) . '|' .
preg_quote($this->options['COMMENT_START']). '(.*?)' .preg_quote($this->options['COMMENT_END']) . $trim . ')/sm'
);
}
function tokenize($source) {
$result = new TokenStream;
$pos = 0;
$matches = array();
preg_match_all($this->pattern, $source, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
if ($match[1])
$result->feed('text', $match[1], $pos);
$tagpos = $pos + strlen($match[1]);
if ($match[2])
$result->feed('block', trim($match[2]), $tagpos);
elseif ($match[3])
$result->feed('variable', trim($match[3]), $tagpos);
elseif ($match[4])
$result->feed('comment', trim($match[4]), $tagpos);
$pos += strlen($match[0]);
}
if ($pos < strlen($source)){
$result->feed('text', substr($source, $pos), $pos);
}
$result->close();
return $result;
}
}
class H2o_Parser {
var $first;
var $storage = array();
var $filename;
var $runtime;
function __construct($source, $filename, $runtime, $options) {
$this->options = $options;
//$this->source = $source;
$this->runtime = $runtime;
$this->filename = $filename;
$this->first = true;
$this->lexer = new H2o_Lexer($options);
$this->tokenstream = $this->lexer->tokenize($source);
$this->storage = array(
'blocks' => array(),
'templates' => array(),
'included' => array()
);
}
function &parse() {
$until = func_get_args();
$nodelist = new NodeList($this);
while($token = $this->tokenstream->next()) {
//$token = $this->tokenstream->current();
switch($token->type) {
case 'text' :
$node = new TextNode($token->content, $token->position);
break;
case 'variable' :
$args = H2o_Parser::parseArguments($token->content, $token->position);
$variable = array_shift($args);
$filters = $args;
$node = new VariableNode($variable, $filters, $token->position);
break;
case 'comment' :
$node = new CommentNode($token->content);
break;
case 'block' :
if (in_array($token->content, $until)) {
$this->token = $token;
return $nodelist;
}
$temp = preg_split('/\s+/',$token->content, 2);
$name = $temp[0];
$args = (count($temp) > 1 ? $temp[1] : null);
$node = H2o::createTag($name, $args, $this, $token->position);
$this->token = $token;
}
$this->searching = join(',',$until);
$this->first = false;
$nodelist->append($node);
}
if ($until) {
throw new TemplateSyntaxError('Unclose tag, expecting '. $until[0]);
}
return $nodelist;
}
function skipTo($until) {
$this->parse($until);
return null;
}
# Parse arguments
static function parseArguments($source = null, $fpos = 0){
$parser = new ArgumentLexer($source, $fpos);
$result = array();
$current_buffer = &$result;
$filter_buffer = array();
$tokens = $parser->parse();
foreach ($tokens as $token) {
list($token, $data) = $token;
if ($token == 'filter_start') {
$filter_buffer = array();
$current_buffer = &$filter_buffer;
}
elseif ($token == 'filter_end') {
if (count($filter_buffer)) {
$i = count($result)-1;
if ( is_array($result[$i]) ) $result[$i]['filters'][] = $filter_buffer;
else $result[$i] = array(0 => $result[$i], 'filters' => array($filter_buffer));
}
$current_buffer = &$result;
}
elseif ($token == 'boolean') {
$current_buffer[] = ($data === 'true'? true : false);
}
elseif ($token == 'name') {
$current_buffer[] = symbol($data);
}
elseif ($token == 'number' || $token == 'string') {
$current_buffer[] = $data;
}
elseif ($token == 'named_argument') {
$last = $current_buffer[count($current_buffer) - 1];
if (!is_array($last))
$current_buffer[] = array();
$namedArgs =& $current_buffer[count($current_buffer) - 1];
list($name,$value) = array_map('trim', explode(':', $data, 2));
# if argument value is variable mark it
$value = self::parseArguments($value);
$namedArgs[$name] = $value[0];
}
elseif( $token == 'operator') {
$current_buffer[] = array('operator'=>$data);
}
}
return $result;
}
}
class H2O_RE {
static $whitespace, $seperator, $parentheses, $pipe, $filter_end, $operator, $boolean, $number, $string, $i18n_string, $name, $named_args;
static function init() {
$r = 'strip_regex';
self::$whitespace = '/\s+/m';
self::$parentheses = '/\(|\)/m';
self::$filter_end = '/;/';
self::$boolean = '/true|false/';
self::$seperator = '/,/';
self::$pipe = '/\|/';
self::$operator = '/\s?(>|<|>=|<=|!=|==|!|and |not |or )\s?/i';
self::$number = '/\d+(\.\d*)?/';
self::$name = '/[a-zA-Z][a-zA-Z0-9-_]*(?:\.[a-zA-Z_0-9][a-zA-Z0-9_-]*)*/';
self::$string = '/(?:
"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)" | # Double Quote string
\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\' # Single Quote String
)/xsm';
self::$i18n_string = "/_\({$r(self::$string)}\) | {$r(self::$string)}/xsm";
self::$named_args = "{
({$r(self::$name)})(?:{$r(self::$whitespace)})?
:
(?:{$r(self::$whitespace)})?({$r(self::$i18n_string)}|{$r(self::$number)}|{$r(self::$name)})
}x";
}
}
H2O_RE::init();
class ArgumentLexer {
private $source;
private $match;
private $pos = 0, $fpos, $eos;
private $operator_map = array(
'!' => 'not', '!='=> 'ne', '==' => 'eq', '>' => 'gt', '<' => 'lt', '<=' => 'le', '>=' => 'ge'
);
function __construct($source, $fpos = 0){
if (!is_null($source))
$this->source = $source;
$this->fpos=$fpos;
}
function parse(){
$result = array();
$filtering = false;
while (!$this->eos()) {
$this->scan(H2O_RE::$whitespace);
if (!$filtering) {
if ($this->scan(H2O_RE::$operator)){
$operator = trim($this->match);
if(isset($this->operator_map[$operator]))
$operator = $this->operator_map[$operator];
$result[] = array('operator', $operator);
}
elseif ($this->scan(H2O_RE::$boolean))
$result[] = array('boolean', $this->match);
elseif ($this->scan(H2O_RE::$named_args))
$result[] = array('named_argument', $this->match);
elseif ($this->scan(H2O_RE::$name))
$result[] = array('name', $this->match);
elseif ($this->scan(H2O_RE::$pipe)) {
$filtering = true;
$result[] = array('filter_start', $this->match);
}
elseif ($this->scan(H2O_RE::$seperator))
$result[] = array('separator', null);
elseif ($this->scan(H2O_RE::$i18n_string))
$result[] = array('string', $this->match);
elseif ($this->scan(H2O_RE::$number))
$result[] = array('number', $this->match);
else
throw new TemplateSyntaxError('unexpected character in filters : "'. $this->source[$this->pos]. '" at '.$this->getPosition());
}
else {
// parse filters, with chaining and ";" as filter end character
if ($this->scan(H2O_RE::$pipe)) {
$result[] = array('filter_end', null);
$result[] = array('filter_start', null);
}
elseif ($this->scan(H2O_RE::$seperator))
$result[] = array('separator', null);
elseif ($this->scan(H2O_RE::$filter_end)) {
$result[] = array('filter_end', null);
$filtering = false;
}
elseif ($this->scan(H2O_RE::$boolean))
$result[] = array('boolean', $this->match);
elseif ($this->scan(H2O_RE::$named_args))
$result[] = array('named_argument', $this->match);
elseif ($this->scan(H2O_RE::$name))
$result[] = array('name', $this->match);
elseif ($this->scan(H2O_RE::$i18n_string))
$result[] = array('string', $this->match);
elseif ($this->scan(H2O_RE::$number))
$result[] = array('number', $this->match);
else
throw new TemplateSyntaxError('unexpected character in filters : "'. $this->source[$this->pos]. '" at '.$this->getPosition());
}
}
// if we are still in the filter state, we add a filter_end token.
if ($filtering)
$result[] = array('filter_end', null);
return $result;
}
# String scanner
function scan($regexp) {
if (preg_match($regexp . 'A', $this->source, $match, null, $this->pos)) {
$this->match = $match[0];
$this->pos += strlen($this->match);
return true;
}
return false;
}
function eos() {
return $this->pos >= strlen($this->source);
}
/**
* return the position in the template
*/
function getPosition() {
return $this->fpos + $this->pos;
}
}
?>
<?php
class H2o_Lexer {
function __construct($options = array()) {
$this->options = $options;
$trim = '';
if ($this->options['TRIM_TAGS'])
$trim = '(?:\r?\n)?';
$this->pattern = ('/\G(.*?)(?:' .
preg_quote($this->options['BLOCK_START']). '(.*?)' .preg_quote($this->options['BLOCK_END']) . $trim . '|' .
preg_quote($this->options['VARIABLE_START']). '(.*?)' .preg_quote($this->options['VARIABLE_END']) . '|' .
preg_quote($this->options['COMMENT_START']). '(.*?)' .preg_quote($this->options['COMMENT_END']) . $trim . ')/sm'
);
}
function tokenize($source) {
$result = new TokenStream;
$pos = 0;
$matches = array();
preg_match_all($this->pattern, $source, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
if ($match[1])
$result->feed('text', $match[1], $pos);
$tagpos = $pos + strlen($match[1]);
if ($match[2])
$result->feed('block', trim($match[2]), $tagpos);
elseif ($match[3])
$result->feed('variable', trim($match[3]), $tagpos);
elseif ($match[4])
$result->feed('comment', trim($match[4]), $tagpos);
$pos += strlen($match[0]);
}
if ($pos < strlen($source)){
$result->feed('text', substr($source, $pos), $pos);
}
$result->close();
return $result;
}
}
class H2o_Parser {
var $first;
var $storage = array();
var $filename;
var $runtime;
function __construct($source, $filename, $runtime, $options) {
$this->options = $options;
//$this->source = $source;
$this->runtime = $runtime;
$this->filename = $filename;
$this->first = true;
$this->lexer = new H2o_Lexer($options);
$this->tokenstream = $this->lexer->tokenize($source);
$this->storage = array(
'blocks' => array(),
'templates' => array(),
'included' => array()
);
}
function &parse() {
$until = func_get_args();
$nodelist = new NodeList($this);
while($token = $this->tokenstream->next()) {
//$token = $this->tokenstream->current();
switch($token->type) {
case 'text' :
$node = new TextNode($token->content, $token->position);
break;
case 'variable' :
$args = H2o_Parser::parseArguments($token->content, $token->position);
$variable = array_shift($args);
$filters = $args;
$node = new VariableNode($variable, $filters, $token->position);
break;
case 'comment' :
$node = new CommentNode($token->content);
break;
case 'block' :
if (in_array($token->content, $until)) {
$this->token = $token;
return $nodelist;
}
$temp = preg_split('/\s+/',$token->content, 2);
$name = $temp[0];
$args = (count($temp) > 1 ? $temp[1] : null);
$node = H2o::createTag($name, $args, $this, $token->position);
$this->token = $token;
}
$this->searching = join(',',$until);
$this->first = false;
$nodelist->append($node);
}
if ($until) {
throw new TemplateSyntaxError('Unclose tag, expecting '. $until[0]);
}
return $nodelist;
}
function skipTo($until) {
$this->parse($until);
return null;
}
# Parse arguments
static function parseArguments($source = null, $fpos = 0){
$parser = new ArgumentLexer($source, $fpos);
$result = array();
$current_buffer = &$result;
$filter_buffer = array();
$tokens = $parser->parse();
foreach ($tokens as $token) {
list($token, $data) = $token;
if ($token == 'filter_start') {
$filter_buffer = array();
$current_buffer = &$filter_buffer;
}
elseif ($token == 'filter_end') {
if (count($filter_buffer)) {
$i = count($result)-1;
if ( is_array($result[$i]) ) $result[$i]['filters'][] = $filter_buffer;
else $result[$i] = array(0 => $result[$i], 'filters' => array($filter_buffer));
}
$current_buffer = &$result;
}
elseif ($token == 'boolean') {
$current_buffer[] = ($data === 'true'? true : false);
}
elseif ($token == 'name') {
$current_buffer[] = symbol($data);
}
elseif ($token == 'number' || $token == 'string') {
$current_buffer[] = $data;
}
elseif ($token == 'named_argument') {
$last = $current_buffer[count($current_buffer) - 1];
if (!is_array($last))
$current_buffer[] = array();
$namedArgs =& $current_buffer[count($current_buffer) - 1];
list($name,$value) = array_map('trim', explode(':', $data, 2));
# if argument value is variable mark it
$value = self::parseArguments($value);
$namedArgs[$name] = $value[0];
}
elseif( $token == 'operator') {
$current_buffer[] = array('operator'=>$data);
}
}
return $result;
}
}
class H2O_RE {
static $whitespace, $seperator, $parentheses, $pipe, $filter_end, $operator, $boolean, $number, $string, $i18n_string, $name, $named_args;
static function init() {
$r = 'strip_regex';
self::$whitespace = '/\s+/m';
self::$parentheses = '/\(|\)/m';
self::$filter_end = '/;/';
self::$boolean = '/true|false/';
self::$seperator = '/,/';
self::$pipe = '/\|/';
self::$operator = '/\s?(>|<|>=|<=|!=|==|!|and |not |or )\s?/i';
self::$number = '/\d+(\.\d*)?/';
self::$name = '/[a-zA-Z][a-zA-Z0-9-_]*(?:\.[a-zA-Z_0-9][a-zA-Z0-9_-]*)*/';
self::$string = '/(?:
"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)" | # Double Quote string
\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\' # Single Quote String
)/xsm';
self::$i18n_string = "/_\({$r(self::$string)}\) | {$r(self::$string)}/xsm";
self::$named_args = "{
({$r(self::$name)})(?:{$r(self::$whitespace)})?
:
(?:{$r(self::$whitespace)})?({$r(self::$i18n_string)}|{$r(self::$number)}|{$r(self::$name)})
}x";
}
}
H2O_RE::init();
class ArgumentLexer {
private $source;
private $match;
private $pos = 0, $fpos, $eos;
private $operator_map = array(
'!' => 'not', '!='=> 'ne', '==' => 'eq', '>' => 'gt', '<' => 'lt', '<=' => 'le', '>=' => 'ge'
);
function __construct($source, $fpos = 0){
if (!is_null($source))
$this->source = $source;
$this->fpos=$fpos;
}
function parse(){
$result = array();
$filtering = false;
while (!$this->eos()) {
$this->scan(H2O_RE::$whitespace);
if (!$filtering) {
if ($this->scan(H2O_RE::$operator)){
$operator = trim($this->match);
if(isset($this->operator_map[$operator]))
$operator = $this->operator_map[$operator];
$result[] = array('operator', $operator);
}
elseif ($this->scan(H2O_RE::$boolean))
$result[] = array('boolean', $this->match);
elseif ($this->scan(H2O_RE::$named_args))
$result[] = array('named_argument', $this->match);
elseif ($this->scan(H2O_RE::$name))
$result[] = array('name', $this->match);
elseif ($this->scan(H2O_RE::$pipe)) {
$filtering = true;
$result[] = array('filter_start', $this->match);
}
elseif ($this->scan(H2O_RE::$seperator))
$result[] = array('separator', null);
elseif ($this->scan(H2O_RE::$i18n_string))
$result[] = array('string', $this->match);
elseif ($this->scan(H2O_RE::$number))
$result[] = array('number', $this->match);
else
throw new TemplateSyntaxError('unexpected character in filters : "'. $this->source[$this->pos]. '" at '.$this->getPosition());
}
else {
// parse filters, with chaining and ";" as filter end character
if ($this->scan(H2O_RE::$pipe)) {
$result[] = array('filter_end', null);
$result[] = array('filter_start', null);
}
elseif ($this->scan(H2O_RE::$seperator))
$result[] = array('separator', null);
elseif ($this->scan(H2O_RE::$filter_end)) {
$result[] = array('filter_end', null);
$filtering = false;
}
elseif ($this->scan(H2O_RE::$boolean))
$result[] = array('boolean', $this->match);
elseif ($this->scan(H2O_RE::$named_args))
$result[] = array('named_argument', $this->match);
elseif ($this->scan(H2O_RE::$name))
$result[] = array('name', $this->match);
elseif ($this->scan(H2O_RE::$i18n_string))
$result[] = array('string', $this->match);
elseif ($this->scan(H2O_RE::$number))
$result[] = array('number', $this->match);
else
throw new TemplateSyntaxError('unexpected character in filters : "'. $this->source[$this->pos]. '" at '.$this->getPosition());
}
}
// if we are still in the filter state, we add a filter_end token.
if ($filtering)
$result[] = array('filter_end', null);
return $result;
}
# String scanner
function scan($regexp) {
if (preg_match($regexp . 'A', $this->source, $match, null, $this->pos)) {
$this->match = $match[0];
$this->pos += strlen($this->match);
return true;
}
return false;
}
function eos() {
return $this->pos >= strlen($this->source);
}
/**
* return the position in the template
*/
function getPosition() {
return $this->fpos + $this->pos;
}
}
?>

17
system/vendor/is_cli.php vendored 100644
View File

@ -0,0 +1,17 @@
<?php
function is_cli()
{
if( defined('STDIN') )
{
return true;
}
if( empty($_SERVER['REMOTE_ADDR']) and !isset($_SERVER['HTTP_USER_AGENT']) and count($_SERVER['argv']) > 0)
{
return true;
}
return false;
}

View File

@ -1,6 +1,6 @@
<?php
function isvarset(&$var)
{
return (isset($var) && (!empty($var) || is_numeric($var))) ? true : false;
<?php
function isvarset(&$var)
{
return (isset($var) && (!empty($var) || is_numeric($var))) ? true : false;
}

View File

@ -0,0 +1,19 @@
Copyright (c) 2015 Nathan Adams <adamsna@datanethost.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,149 @@
<?php
namespace phpoauthlib2;
// Copied from PHP manual comment section:
// http://php.net/manual/en/book.curl.php#90821
// Modified to fit Inefero's/srchub needs
// Now used for oauth lib
class ccurl {
protected $_useragent = 'phpoauthlib2 (http://www.srchub.org); https://srchub.org/p/phpoauthlib2 PHPOAuthLib';
protected $_url;
protected $_followlocation;
protected $_timeout;
protected $_maxRedirects;
protected $_cookieFileLocation = './cookie.txt';
protected $_post;
protected $_postFields;
protected $_referer ="";
// Get around some broken webservers *cough*IIS*cough*?
// http://stackoverflow.com/questions/14459704/does-empty-expect-header-mean-anything
protected $_header = array('Expect:');
protected $_session;
protected $_webpage;
protected $_includeHeader;
protected $_noBody;
protected $_status;
protected $_binaryTransfer;
public $authentication = 0;
public $auth_name = '';
public $auth_pass = '';
public function useAuth($use){
$this->authentication = 0;
if($use == true) $this->authentication = 1;
}
public function setName($name){
$this->auth_name = $name;
}
public function setPass($pass){
$this->auth_pass = $pass;
}
public function addHeader($head)
{
$this->_header[] = $head;
}
public function __construct($url,$followlocation = true,$timeOut = 30,$maxRedirecs = 4,$binaryTransfer = false,$includeHeader = false,$noBody = false)
{
$this->_url = $url;
$this->_followlocation = $followlocation;
$this->_timeout = $timeOut;
$this->_maxRedirects = $maxRedirecs;
$this->_noBody = $noBody;
$this->_includeHeader = $includeHeader;
$this->_binaryTransfer = $binaryTransfer;
$this->_cookieFileLocation = dirname(__FILE__).'/cookie.txt';
}
public function setReferer($referer){
$this->_referer = $referer;
}
public function setCookiFileLocation($path)
{
$this->_cookieFileLocation = $path;
}
public function setPost ($postFields)
{
$this->_post = true;
$this->_postFields = $postFields;
}
public function setUserAgent($userAgent)
{
$this->_useragent = $userAgent;
}
public function createCurl($url = 'nul')
{
if($url != 'nul'){
$this->_url = $url;
}
$s = curl_init();
curl_setopt($s,CURLOPT_URL,$this->_url);
// I understand the implications here - but this isn't a client application
// if my ISP is performing MITM sniffing I have bigger fish to fry
// also the security of a CA signed certificate is questionable at best
// https://www.schneier.com/blog/archives/2012/02/verisign_hacked.html
// Email me if you want to discus this adamsna@datanethost.net
// NA - 12/10/2014
curl_setopt($s, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($s,CURLOPT_HTTPHEADER,$this->_header);
curl_setopt($s,CURLOPT_TIMEOUT,$this->_timeout);
curl_setopt($s,CURLOPT_MAXREDIRS,$this->_maxRedirects);
curl_setopt($s,CURLOPT_RETURNTRANSFER,true);
curl_setopt($s,CURLOPT_FOLLOWLOCATION,$this->_followlocation);
curl_setopt($s,CURLOPT_COOKIEJAR,$this->_cookieFileLocation);
curl_setopt($s,CURLOPT_COOKIEFILE,$this->_cookieFileLocation);
if($this->authentication == 1){
curl_setopt($s, CURLOPT_USERPWD, $this->auth_name.':'.$this->auth_pass);
}
if($this->_post)
{
//curl_setopt($s,CURLOPT_POST,true);
curl_setopt($s, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($s,CURLOPT_POSTFIELDS,$this->_postFields);
}
if($this->_includeHeader)
{
curl_setopt($s,CURLOPT_HEADER,true);
}
if($this->_noBody)
{
curl_setopt($s,CURLOPT_NOBODY,true);
}
curl_setopt($s,CURLOPT_USERAGENT,$this->_useragent);
curl_setopt($s,CURLOPT_REFERER,$this->_referer);
$this->_webpage = curl_exec($s);
$this->_status = curl_getinfo($s,CURLINFO_HTTP_CODE);
curl_close($s);
}
public function getHttpStatus()
{
return $this->_status;
}
public function __tostring(){
return $this->_webpage;
}
}

View File

@ -0,0 +1,5 @@
# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_.google.com TRUE / FALSE 1463331114 NID 73=wOGSMwy8vYCu7qJjpMYLVMQ_gYCNZXru2x8g0p5InvQIpj8X4P2uiXE8QdX50ZcpHvxCXo35XdDS8P5trQSsI0s3UmQ-tmG_01TTIVil6YeJIzFKqoGmKAdWo_0o8MOQ

View File

@ -0,0 +1,24 @@
<?php
use \phpoauthlib2\providers\GoogleAuthProvider;
use \phpoauthlib2\OAuth;
require 'OAuth.php';
require 'providers/GoogleAuthProvider.php';
$authProvider = new GoogleAuthProvider($_GET, [
"client_id" => "apps.googleusercontent.com",
"client_secret" => "<KEY>",
"redirect_uri" => "http://example.com/phpoauthlib2/example.php"
]);
$oauth = new OAuth($authProvider, $_GET);
$check = $oauth->check();
if ($check === true) {
echo "Hello - " . $authProvider->getFirstName();
echo "<br>Your email is - " . $authProvider->getEmail();
} else {
header("Location: " . $check);
}

View File

@ -0,0 +1,26 @@
<?php
namespace system\vendor\phpoauthlib2;
class OAuth {
protected $oauthProvider = null;
protected $request = null;
public function __construct($provider, $request) {
$this->oauthProvider = $provider;
$this->request = $request;
}
public function check() {
if (isset($this->request["code"]) && !empty($this->request["code"])) {
$this->oauthProvider->getProfile();
return true;
} else {
return $this->oauthProvider->getLoginUrl();
}
}
public function getProfile() {
return $this->oauthProvider->getProfile();
}
}

View File

@ -0,0 +1,113 @@
<?php
namespace system\vendor\phpoauthlib2;
require "ccurl.php";
use phpoauthlib2\ccurl;
class OAUTH_SCOPES {
const EMAIL = "EMAIL";
}
class OAuthDataProvider {
protected $version = "2.0";
protected $name = "undefined";
protected $responseType = "code";
protected $header = "Authorization: Bearer";
protected $profile = "";
protected $dialog = "";
protected $nonce = null;
protected $accessToken = null;
protected $state = "";
protected $redirectURL = "";
protected $scope = "";
protected $clientId = "";
protected $client_secret = "";
protected $request = null;
protected $profileData = [];
public function __construct($profile, $dialog, $accessToken, $request, $header="Authorization: Bearer") {
$this->profile = $profile;
$this->dialog = $dialog;
$this->accessToken = $accessToken;
$this->header = $header;
$this->request = $request;
}
public function getLoginUrl() {
$urlBuilder = [];
$urlBuilder[] = "client_id=" . $this->clientId;
$urlBuilder[] = "response_type=" . $this->responseType;
$urlBuilder[] = "scope=" . $this->scope;
$urlBuilder[] = "state=" . $this->state;
$urlBuilder[] = "redirect_uri=" . urlencode($this->redirectURL);
return $this->dialog . "?" . implode("&", $urlBuilder);
}
protected function getToken() {
$tokenBuilder = [];
$tokenBuilder["client_id"] = $this->clientId;
$tokenBuilder["client_secret"] = $this->client_secret;
$tokenBuilder["grant_type"] = "authorization_code";
$tokenBuilder["redirect_uri"] = htmlspecialchars($this->redirectURL);
$tokenBuilder["code"] = $this->request["code"];
$curl = new ccurl($this->accessToken);
$curl->setPost($tokenBuilder);
$curl->createCurl();
return (string)$curl;
}
protected function parseToken() {
$token = $this->getToken();
$convertedToken = json_decode($token, true);
if (!$convertedToken) {
$realToken = $token;
} else {
$realToken = $convertedToken["access_token"];
}
return $realToken;
}
public function getProfile() {
$token = $this->parseToken();
$profileUrl = $this->profile . "=" . $token;
$curl = new ccurl($profileUrl);
$curl->addHeader($this->header . " " . $token);
$curl->createCurl();
$this->profileData = json_decode((string)$curl, true);
return (string)$curl;
}
public function getEmail() {
return null;
}
public function getFirstName() {
return null;
}
public function getLastName() {
return null;
}
public function getGender() {
return null;
}
public function getId() {
return null;
}
public function getRawProfile() {
return $this->profileData;
}
public function getSource() {
return null;
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace system\vendor\phpoauthlib2\providers;
require "OAuthDataProvider.php";
use phpoauthlib2\ccurl;
use phpoauthlib2\OAUTH_SCOPES;
use phpoauthlib2\OAuthDataProvider;
class FacebookAuthProvider extends OAuthDataProvider {
public function __construct($request, $conf, $scopes=[OAUTH_SCOPES::EMAIL]) {
parent::__construct(
"https://graph.facebook.com/me",
"https://www.facebook.com/dialog/oauth",
"https://graph.facebook.com/oauth/access_token",
$request
);
$this->client_secret = $conf["client_secret"];
$this->redirectURL = $conf["redirect_uri"];
$this->clientId = $conf["client_id"];
$tempScopes = [];
foreach($scopes as $scope) {
switch ($scope) {
case OAUTH_SCOPES::EMAIL:
$tempScopes[] = "email";
}
}
$tempScopes[] = "public_profile";
$this->scope = implode(" ", $tempScopes);
}
public function getEmail() {
return $this->profileData["email"];
}
public function getFirstName() {
return $this->profileData["first_name"];
}
public function getLastName() {
return $this->profileData["last_name"];
}
public function getId() {
return $this->profileData["id"];
}
public function getSource() {
return "FACEBOOK";
}
public function parseToken() {
$token = $this->getToken();
return explode("=", $token)[1];
}
public function getProfile() {
$token = $this->parseToken();
$profileUrl = $this->profile . "?fields=first_name,last_name,name,email,age_range&access_token=" . $token;
$curl = new ccurl($profileUrl);
$curl->createCurl();
$ret = (string)$curl;
$this->profileData = json_decode($ret, true);
return $ret;
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace system\vendor\phpoauthlib2\providers;
use phpoauthlib2\ccurl;
use system\vendor\phpoauthlib2\OAUTH_SCOPES;
use system\vendor\phpoauthlib2\OAuth;
use system\vendor\phpoauthlib2\OAuthDataProvider;
class GoogleAuthProvider extends OAuthDataProvider {
public function __construct($request, $conf, $scopes=[OAUTH_SCOPES::EMAIL]) {
parent::__construct(
"https://www.googleapis.com/oauth2/v1/userinfo?access_token",
"https://accounts.google.com/o/oauth2/auth",
"https://accounts.google.com/o/oauth2/token", $request);
$this->client_secret = $conf["client_secret"];
$this->redirectURL = $conf["redirect_uri"];
$this->clientId = $conf["client_id"];
$tmpScopes = [];
foreach($scopes as $scope) {
switch ($scope) {
case OAUTH_SCOPES::EMAIL:
$tmpScopes[] = "https://www.googleapis.com/auth/userinfo.email";
}
}
$this->scope = implode(" ", $tmpScopes);
}
public function getEmail() {
return $this->profileData["email"];
}
public function getFirstName() {
return $this->profileData["given_name"];
}
public function getLastName() {
return $this->profileData["family_name"];
}
public function getGender() {
return $this->profileData["gender"];
}
public function getId() {
return $this->profileData["id"];
}
public function getSource() {
return "GOOGLE";
}
}

View File

@ -0,0 +1,86 @@
# phpoauthlib2
phpoauthlib2 is another OAuth 2.0 library for PHP. The goal of the project is to make it as easy as possible to integrate OAuth into your web application.
You can think of phpoauthlib2 as a combination of ideas from the following projects:
- PHPoAuthLib
- li3_socialauth
- oauth-4-laravel
- PHPoAuthUserData
All wrapped in one simple library.
# Why phpoauthlib2?
Or more specifically why "2"?
For me this is version 2.0. Originally I developed this in private for PHP and it worked but after a refactoring to Django/Python (Python version coming soon to a pip repository near you) then I ported it back to PHP.
# How to use
It's very easy to use this library. Examine the following line -
$authProvider = new GoogleAuthProvider($_GET, [
"client_id" => "apps.googleusercontent.com",
"client_secret" => "<KEY>",
"redirect_uri" => "http://example.com/phpoauthlib2/example.php"
]);
client_id and client_secret are provided by the OAauth provider (in this case Google) and the redirect_uri is where you want to the user to end up on successful login. It should go without saying that client_id and client_secret should be kept private - you should avoid committing them a public place like github (yes - people have services running and monitoring for people who commit credentials. Don't believe me? Commit your Amazon AWS keys and see how fast people will spin up VMs). The library will handle the verification and present you with some simple base methods to extract data you might be interested in or the ability to work with the entire OAuth data.
$oauth = new OAuth($authProvider, $_GET);
OAuth is really a wrapper to do the verification check. In both this line and the previous one we are passing $_GET but phpoauthlib2 can accept any request array from your framework (provided your framework can emit the GET request as an array - which I know at least Symfony can do this).
$check = $oauth->check();
The check method will return true or a string. Not ideal but I couldn't think of any simpler way to do it (obviously not a problem in a lose typed language - but I don't personally like mixing return types). true indicates that the user successfully logged in and you have access to the user's information. A string indicates that you need to redirect them to the OAuth provider to login (the string itself is the redirect URL).
if ($check === true) {
echo "Hello - " . $authProvider->getFirstName();
echo "<br>Your email is - " . $authProvider->getEmail();
} else {
header("Location: " . $check);
}
This library is designed to be very minimal - so you need to decide how to hook into the login subsystem of your web application. In the example file - it's checking to make sure that the login was successful and then can call $authProvider->getXXX (such as getFirstName and getEmail in this example) and the provider class will return those fields from the raw profile data so you don't have to worry about it.
The work flow to integrate to your system is usually:
if ($check === true) {
$mySystem->login($authProvider->getEmail()); // which sets a cookie or session that they logged in with this specific user
header("Location: http://example.com/yoursystem/user.php"); // The line above logs them in to your system - then immediately bounce back to your system and potentially send them straight to their user dashboard
The reasoning behind the getXXX methods is to provide some commonality between providers. That way you can present a OAuth login prompt for different services to the user and you can just call $provider->getEmail() to get their email without having to worry about the actual field that the OAuth provider decided to put it in.
If after you have verified the login was successful you may call
$provider->getRawProfile();
To return the raw return from the OAuth provider (which will be an associative array).
# Google
To get OAuth credentials for Google just go to this URL: https://console.developers.google.com/
And create a project (which is free) and go to APIs & auth -> Credentials.
If you are creating a new project - it may complain that you need to setup the OAuth consent screen. Do this and return to the credentials section and you should be able to setup the project.
Add credentials -> OAuth 2.0 client ID
Then select Web application
It is very important that you input a correct authorized redirect URI. This will be where the user will be sent back on successful login.
# License
I am licensing this under the MIT license. Which essentially grants you the right TDWTFYWWI (to do whatever the f you want with it) - assuming that you acknowledge that I don't provide a warranty.
# What this library is/is not
- This library is a simple interface to use PHP OAuth 2.0 in your web application.
- This library is designed to be as flexible as possible to use in any framework.
- This library is not designed to hold your hand to secure your client_id, client_secret, or other data.
- This library is not designed to be specific to a certain framework.
- This library is not designed to be abstract. The only class you should ever have to extend is OAuthDataProvider - and that is to create a "provider" for different OAuth providers (which merely contains the URLs to send for login, where to query for user data and normalizing data).