Added B8Framework to project
This commit is contained in:
parent
166e6d8ac0
commit
550e93747c
6
B8Framework/.gitignore
vendored
Executable file
6
B8Framework/.gitignore
vendored
Executable file
|
@ -0,0 +1,6 @@
|
|||
.DS_Store
|
||||
._.DS_Store
|
||||
Thumbs.db
|
||||
.idea
|
||||
composer.lock
|
||||
vendor
|
11
B8Framework/README.md
Executable file
11
B8Framework/README.md
Executable file
|
@ -0,0 +1,11 @@
|
|||
b8 Framework
|
||||
============
|
||||
[![Build Status](https://travis-ci.org/Block8/b8framework.png?branch=master)](https://travis-ci.org/Block8/b8framework)
|
||||
|
||||
|
||||
*b8 framework* is a lightweight, simple framework for high-throughput PHP applications. It does not enforce a specific type of application, nor particularly an application structure, it simply helps you to build things.
|
||||
|
||||
We've used the framework to build web sites, APIs, and web applications, each handling tens of millions of requests a month.
|
||||
|
||||
|
||||
*b8 framework repository is _not quite_ ready for general consumption yet. We have a tool to help you generate all of your project CRUD for you, which still needs to be included. This will be done over the next few days.*
|
126
B8Framework/b8/Application.php
Executable file
126
B8Framework/b8/Application.php
Executable file
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
|
||||
use b8\Config;
|
||||
use b8\Exception\HttpException\NotFoundException;
|
||||
use b8\Http;
|
||||
use b8\View;
|
||||
|
||||
class Application
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $route;
|
||||
|
||||
/**
|
||||
* @var \b8\Controller
|
||||
*/
|
||||
protected $controller;
|
||||
|
||||
/**
|
||||
* @var b8\Http\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var b8\Http\Response
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* @var b8\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
public function __construct(Config $config, Http\Request $request = null)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->response = new Http\Response();
|
||||
|
||||
if (!is_null($request)) {
|
||||
$this->request = $request;
|
||||
} else {
|
||||
$this->request = new Http\Request();
|
||||
}
|
||||
|
||||
$this->router = new Http\Router($this, $this->request, $this->config);
|
||||
|
||||
if (method_exists($this, 'init')) {
|
||||
$this->init();
|
||||
}
|
||||
}
|
||||
|
||||
public function handleRequest()
|
||||
{
|
||||
$this->route = $this->router->dispatch();
|
||||
|
||||
if (!empty($this->route['callback'])) {
|
||||
$callback = $this->route['callback'];
|
||||
|
||||
if (!$callback($this->route, $this->response)) {
|
||||
return $this->response;
|
||||
}
|
||||
}
|
||||
|
||||
$action = lcfirst($this->toPhpName($this->route['action']));
|
||||
|
||||
if (!$this->getController()->hasAction($action)) {
|
||||
throw new NotFoundException('Controller ' . $this->toPhpName($this->route['controller']) . ' does not have action ' . $action);
|
||||
}
|
||||
|
||||
return $this->getController()->handleAction($action, $this->route['args']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \b8\Controller
|
||||
*/
|
||||
public function getController()
|
||||
{
|
||||
if (empty($this->controller)) {
|
||||
$namespace = $this->toPhpName($this->route['namespace']);
|
||||
$controller = $this->toPhpName($this->route['controller']);
|
||||
$controllerClass = $this->config->get('b8.app.namespace') . '\\' . $namespace . '\\' . $controller . 'Controller';
|
||||
$this->controller = $this->loadController($controllerClass);
|
||||
}
|
||||
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
protected function loadController($class)
|
||||
{
|
||||
$controller = new $class($this->config, $this->request, $this->response);
|
||||
$controller->init();
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
protected function controllerExists($route)
|
||||
{
|
||||
$namespace = $this->toPhpName($route['namespace']);
|
||||
$controller = $this->toPhpName($route['controller']);
|
||||
|
||||
$controllerClass = $this->config->get('b8.app.namespace') . '\\' . $namespace . '\\' . $controller . 'Controller';
|
||||
|
||||
return class_exists($controllerClass);
|
||||
}
|
||||
|
||||
public function isValidRoute($route)
|
||||
{
|
||||
if ($this->controllerExists($route)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function toPhpName($string)
|
||||
{
|
||||
$string = str_replace('-', ' ', $string);
|
||||
$string = ucwords($string);
|
||||
$string = str_replace(' ', '', $string);
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
38
B8Framework/b8/Cache.php
Executable file
38
B8Framework/b8/Cache.php
Executable file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
|
||||
/**
|
||||
* @package b8
|
||||
* @subpackage Cache
|
||||
*/
|
||||
|
||||
class Cache
|
||||
{
|
||||
const TYPE_APC = 'ApcCache';
|
||||
const TYPE_REQUEST = 'RequestCache';
|
||||
|
||||
protected static $instance = array();
|
||||
|
||||
/**
|
||||
* LEGACY: Older apps will expect an APC cache in return.
|
||||
* @deprecated
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
return self::getCache(self::TYPE_APC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cache object of a specified type.
|
||||
*/
|
||||
public static function getCache($type = self::TYPE_REQUEST)
|
||||
{
|
||||
if (!isset(self::$instance[$type])) {
|
||||
$class = '\\b8\\Cache\\' . $type;
|
||||
self::$instance[$type] = new $class();
|
||||
}
|
||||
|
||||
return self::$instance[$type];
|
||||
}
|
||||
}
|
115
B8Framework/b8/Cache/ApcCache.php
Executable file
115
B8Framework/b8/Cache/ApcCache.php
Executable file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Cache;
|
||||
|
||||
use b8\Type;
|
||||
|
||||
class ApcCache implements Type\Cache
|
||||
{
|
||||
/**
|
||||
* Check if caching is enabled.
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
$rtn = false;
|
||||
|
||||
$apcCli = ini_get('apc.enable_cli');
|
||||
|
||||
if( function_exists('apc_fetch') &&
|
||||
(php_sapi_name() != 'cli' || in_array($apcCli, array('1', 1, true, 'On'))))
|
||||
{
|
||||
$rtn = true;
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item from the cache:
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if (!$this->isEnabled()) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$success = false;
|
||||
$rtn = apc_fetch($key, $success);
|
||||
|
||||
if (!$success) {
|
||||
$rtn = $default;
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the cache:
|
||||
*/
|
||||
public function set($key, $value = null, $ttl = 0)
|
||||
{
|
||||
if (!$this->isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return apc_store($key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the cache:
|
||||
*/
|
||||
public function delete($key)
|
||||
{
|
||||
if (!$this->isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return apc_delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an item is in the cache:
|
||||
*/
|
||||
public function contains($key)
|
||||
{
|
||||
if (!$this->isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return apc_exists($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-hand syntax for get()
|
||||
* @see Config::get()
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->get($key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-hand syntax for set()
|
||||
* @see Config::set()
|
||||
*/
|
||||
public function __set($key, $value = null)
|
||||
{
|
||||
return $this->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is set
|
||||
*/
|
||||
public function __isset($key)
|
||||
{
|
||||
return $this->contains($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset
|
||||
*/
|
||||
public function __unset($key)
|
||||
{
|
||||
$this->delete($key);
|
||||
}
|
||||
}
|
90
B8Framework/b8/Cache/RequestCache.php
Executable file
90
B8Framework/b8/Cache/RequestCache.php
Executable file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Cache;
|
||||
|
||||
use b8\Type;
|
||||
|
||||
class RequestCache implements Type\Cache
|
||||
{
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* Check if caching is enabled.
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item from the cache:
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
return $this->contains($key) ? $this->data[$key] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the cache:
|
||||
*/
|
||||
public function set($key, $value = null, $ttl = 0)
|
||||
{
|
||||
$this->data[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the cache:
|
||||
*/
|
||||
public function delete($key)
|
||||
{
|
||||
if ($this->contains($key)) {
|
||||
unset($this->data[$key]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an item is in the cache:
|
||||
*/
|
||||
public function contains($key)
|
||||
{
|
||||
return array_key_exists($key, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-hand syntax for get()
|
||||
* @see Config::get()
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->get($key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-hand syntax for set()
|
||||
* @see Config::set()
|
||||
*/
|
||||
public function __set($key, $value = null)
|
||||
{
|
||||
return $this->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is set
|
||||
*/
|
||||
public function __isset($key)
|
||||
{
|
||||
return $this->contains($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset
|
||||
*/
|
||||
public function __unset($key)
|
||||
{
|
||||
$this->delete($key);
|
||||
}
|
||||
}
|
176
B8Framework/b8/Config.php
Executable file
176
B8Framework/b8/Config.php
Executable file
|
@ -0,0 +1,176 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
|
||||
use Symfony\Component\Yaml\Parser as YamlParser;
|
||||
|
||||
if (!defined('B8_PATH')) {
|
||||
define('B8_PATH', dirname(__FILE__) . '/');
|
||||
}
|
||||
|
||||
class Config
|
||||
{
|
||||
protected static $instance;
|
||||
|
||||
public static function getInstance()
|
||||
{
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config = array();
|
||||
|
||||
public function __construct($settings = null)
|
||||
{
|
||||
self::$instance = $this;
|
||||
|
||||
if (empty($settings)) {
|
||||
return;
|
||||
} elseif (is_array($settings)) {
|
||||
// Array of setting data.
|
||||
$this->setArray($settings);
|
||||
} elseif (is_string($settings) && file_exists($settings)) {
|
||||
$this->loadYaml($settings);
|
||||
}
|
||||
}
|
||||
|
||||
public function loadYaml($yamlFile)
|
||||
{
|
||||
// Path to a YAML file.
|
||||
$parser = new YamlParser();
|
||||
$yaml = file_get_contents($yamlFile);
|
||||
$config = (array)$parser->parse($yaml);
|
||||
|
||||
if (empty($config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->setArray($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a configuration value by key, returning a default value if not set.
|
||||
* @param $key string
|
||||
* @param $default mixed
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
$keyParts = explode('.', $key);
|
||||
$selected = $this->config;
|
||||
|
||||
$i = -1;
|
||||
$last_part = count($keyParts) - 1;
|
||||
while ($part = array_shift($keyParts)) {
|
||||
$i++;
|
||||
|
||||
if (!array_key_exists($part, $selected)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ($i === $last_part) {
|
||||
return $selected[$part];
|
||||
} else {
|
||||
$selected = $selected[$part];
|
||||
}
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value by key.
|
||||
* @param $key string
|
||||
* @param $value mixed
|
||||
*/
|
||||
public function set($key, $value = null)
|
||||
{
|
||||
$this->config[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an array of values.
|
||||
*/
|
||||
public function setArray($array)
|
||||
{
|
||||
self::deepMerge($this->config, $array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-hand syntax for get()
|
||||
* @see Config::get()
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-hand syntax for set()
|
||||
* @see Config::set()
|
||||
*/
|
||||
public function __set($key, $value = null)
|
||||
{
|
||||
return $this->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is set
|
||||
*/
|
||||
public function __isset($key)
|
||||
{
|
||||
return isset($this->config[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset
|
||||
*/
|
||||
public function __unset($key)
|
||||
{
|
||||
unset($this->config[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deeply merge the $target array onto the $source array.
|
||||
* The $source array will be modified!
|
||||
* @param array $source
|
||||
* @param array $target
|
||||
*/
|
||||
public static function deepMerge(&$source, $target)
|
||||
{
|
||||
if (count($source) === 0) {
|
||||
$source = $target;
|
||||
return;
|
||||
}
|
||||
foreach ($target as $target_key => $target_value) {
|
||||
if (isset($source[$target_key])) {
|
||||
if (!is_array($source[$target_key]) && !is_array($target_value)) {
|
||||
// Neither value is an array, overwrite
|
||||
$source[$target_key] = $target_value;
|
||||
|
||||
} elseif (is_array($source[$target_key]) && is_array($target_value)) {
|
||||
// Both are arrays, deep merge them
|
||||
self::deepMerge($source[$target_key], $target_value);
|
||||
|
||||
} elseif (is_array($source[$target_key])) {
|
||||
// Source is the array, push target value
|
||||
$source[$target_key][] = $target_value;
|
||||
} else {
|
||||
// Target is the array, push source value and copy back
|
||||
$target_value[] = $source[$target_key];
|
||||
$source[$target_key] = $target_value;
|
||||
}
|
||||
} else {
|
||||
// No merge required, just set the value
|
||||
$source[$target_key] = $target_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getArray()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
}
|
116
B8Framework/b8/Controller.php
Executable file
116
B8Framework/b8/Controller.php
Executable file
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
|
||||
use b8\Config;
|
||||
use b8\Http\Request;
|
||||
use b8\Http\Response;
|
||||
use b8\View;
|
||||
|
||||
/**
|
||||
* b8 Abstract Controller class
|
||||
* @package b8
|
||||
*/
|
||||
abstract class Controller
|
||||
{
|
||||
/**
|
||||
* @var b8\Http\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var b8\Http\Response
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* @var b8\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var b8\View
|
||||
*/
|
||||
protected $controllerView;
|
||||
|
||||
/**
|
||||
* @var b8\View
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
public function __construct(Config $config, Request $request, Response $response)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
public function hasAction($name)
|
||||
{
|
||||
if (method_exists($this, $name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (method_exists($this, '__call')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an action on this controller and returns a Response object.
|
||||
* @return b8\Http\Response
|
||||
*/
|
||||
public function handleAction($action, $actionParams)
|
||||
{
|
||||
return call_user_func_array(array($this, $action), $actionParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the controller.
|
||||
*/
|
||||
abstract public function init();
|
||||
|
||||
/**
|
||||
* Get a hash of incoming request parameters ($_GET, $_POST)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getParams()
|
||||
{
|
||||
return $this->request->getParams();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific incoming request parameter.
|
||||
*
|
||||
* @param $key
|
||||
* @param mixed $default Default return value (if key does not exist)
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParam($key, $default = null)
|
||||
{
|
||||
return $this->request->getParam($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the value of an incoming request parameter.
|
||||
* @param $key
|
||||
* @param $value
|
||||
*/
|
||||
public function setParam($key, $value)
|
||||
{
|
||||
return $this->request->setParam($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an incoming request parameter.
|
||||
* @param $key
|
||||
*/
|
||||
public function unsetParam($key)
|
||||
{
|
||||
return $this->request->unsetParam($key);
|
||||
}
|
||||
}
|
246
B8Framework/b8/Controller/RestController.php
Executable file
246
B8Framework/b8/Controller/RestController.php
Executable file
|
@ -0,0 +1,246 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Controller;
|
||||
use b8\Controller,
|
||||
b8\Type\RestUser,
|
||||
b8\Store\Factory,
|
||||
b8\Exception\HttpException;
|
||||
|
||||
class RestController extends Controller
|
||||
{
|
||||
const SEARCHTYPE_AND = 'AND';
|
||||
const SEARCHTYPE_OR = 'OR';
|
||||
|
||||
public $requiresAuthentication = true;
|
||||
public $updateLastAction = true;
|
||||
|
||||
/**
|
||||
* @var \b8\Type\RestUser
|
||||
*/
|
||||
protected $activeUser;
|
||||
protected $where = array();
|
||||
protected $limit = null;
|
||||
protected $offset = null;
|
||||
protected $joins = array();
|
||||
protected $arrayDepth = 2;
|
||||
protected $params = null;
|
||||
protected $order = array();
|
||||
protected $group = null;
|
||||
protected $manualJoins = array();
|
||||
protected $manualWheres = array();
|
||||
protected $searchType = self::SEARCHTYPE_AND;
|
||||
protected $_resourceName = null;
|
||||
protected $_modelName = null;
|
||||
protected $_tableName = null;
|
||||
protected $_modelClass = null;
|
||||
|
||||
public function init()
|
||||
{
|
||||
}
|
||||
|
||||
protected function setControllerView()
|
||||
{
|
||||
}
|
||||
|
||||
protected function setView()
|
||||
{
|
||||
}
|
||||
|
||||
public function handleAction($action, $actionParams)
|
||||
{
|
||||
$response = call_user_func_array(array($this, $action), $actionParams);
|
||||
$this->response->setContent($response);
|
||||
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
public function setActiveUser(RestUser $user)
|
||||
{
|
||||
$this->activeUser = $user;
|
||||
}
|
||||
|
||||
public function getActiveUser()
|
||||
{
|
||||
return $this->activeUser;
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
if(!$this->activeUser->checkPermission('canRead', $this->_resourceName))
|
||||
{
|
||||
throw new HttpException\ForbiddenException('You do not have permission do this.');
|
||||
}
|
||||
|
||||
$this->where = $this->_parseWhere();
|
||||
$this->limit = is_null($this->limit) ? $this->getParam('limit', 25) : $this->limit;
|
||||
$this->offset = is_null($this->offset) ? $this->getParam('offset', 0) : $this->offset;
|
||||
$this->order = is_null($this->order) || !count($this->order) ? $this->getParam('order', array()) : $this->order;
|
||||
$this->group = is_null($this->group) || !count($this->group) ? $this->getParam('group', null) : $this->group;
|
||||
$this->searchType = $this->getParam('searchType', self::SEARCHTYPE_AND);
|
||||
|
||||
$store = Factory::getStore($this->_modelName);
|
||||
$data = $store->getWhere($this->where, $this->limit, $this->offset, $this->joins, $this->order, $this->manualJoins, $this->group, $this->manualWheres, $this->searchType);
|
||||
|
||||
$rtn = array(
|
||||
'debug' => array(
|
||||
'where' => $this->where,
|
||||
'searchType' => $this->searchType,
|
||||
),
|
||||
'limit' => $this->limit,
|
||||
'offset' => $this->offset,
|
||||
'total' => $data['count'],
|
||||
'items' => array()
|
||||
);
|
||||
|
||||
foreach($data['items'] as $item)
|
||||
{
|
||||
$rtn['items'][] = $item->toArray($this->arrayDepth);
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected function _parseWhere()
|
||||
{
|
||||
$clauses = array(
|
||||
'fuzzy' => 'like',
|
||||
'gt' => '>',
|
||||
'gte' => '>=',
|
||||
'lt' => '<',
|
||||
'lte' => '<=',
|
||||
'neq' => '!=',
|
||||
'between' => 'between'
|
||||
);
|
||||
|
||||
$where = $this->getParam('where', array());
|
||||
$where = array_merge($where, $this->where);
|
||||
|
||||
if(count($where))
|
||||
{
|
||||
foreach($where as &$value)
|
||||
{
|
||||
if(!is_array($value) || !isset($value['operator']))
|
||||
{
|
||||
if(is_array($value) && count($value) == 1)
|
||||
{
|
||||
$value = array_shift($value);
|
||||
}
|
||||
|
||||
$value = array(
|
||||
'operator' => '=',
|
||||
'value' => $value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($clauses as $clause => $operator)
|
||||
{
|
||||
$fields = $this->getParam($clause, array());
|
||||
|
||||
if(count($clause))
|
||||
{
|
||||
if(!is_array($fields))
|
||||
{
|
||||
$fields = array($fields);
|
||||
}
|
||||
foreach($fields as $field)
|
||||
{
|
||||
if(isset($where[$field]))
|
||||
{
|
||||
$where[$field]['operator'] = $operator;
|
||||
if($operator == 'like')
|
||||
{
|
||||
$where[$field]['value'] = str_replace(' ', '%', $where[$field]['value']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
if(!$this->activeUser->checkPermission('canRead', $this->_resourceName))
|
||||
{
|
||||
throw new HttpException\ForbiddenException('You do not have permission do this.');
|
||||
}
|
||||
|
||||
$rtn = Factory::getStore($this->_modelName)->getByPrimaryKey($key);
|
||||
|
||||
if(is_object($rtn) && method_exists($rtn, 'toArray'))
|
||||
{
|
||||
$rtn = $rtn->toArray($this->arrayDepth);
|
||||
}
|
||||
|
||||
return array(strtolower($this->_modelName) => $rtn);
|
||||
}
|
||||
|
||||
public function put($key)
|
||||
{
|
||||
if(!$this->activeUser->checkPermission('canEdit', $this->_resourceName))
|
||||
{
|
||||
throw new HttpException\ForbiddenException('You do not have permission do this.');
|
||||
}
|
||||
|
||||
$store = Factory::getStore($this->_modelName);
|
||||
|
||||
if($obj = $store->getByPrimaryKey($key))
|
||||
{
|
||||
$obj->setValues($this->getParams());
|
||||
$rtn = $store->save($obj);
|
||||
|
||||
return array(strtolower($this->_modelName) => $rtn->toArray($this->arrayDepth));
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function post()
|
||||
{
|
||||
if(!$this->activeUser->checkPermission('canCreate', $this->_resourceName))
|
||||
{
|
||||
throw new HttpException\ForbiddenException('You do not have permission do this.');
|
||||
}
|
||||
|
||||
$store = Factory::getStore($this->_modelName);
|
||||
|
||||
$modelClass = $this->_modelClass;
|
||||
$obj = new $modelClass();
|
||||
$obj->setValues($this->getParams());
|
||||
$rtn = $store->save($obj);
|
||||
|
||||
return array(strtolower($this->_modelName) => $rtn->toArray($this->arrayDepth));
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
if(!$this->activeUser->checkPermission('canDelete', $this->_resourceName))
|
||||
{
|
||||
throw new HttpException\ForbiddenException('You do not have permission do this.');
|
||||
}
|
||||
|
||||
$store = Factory::getStore($this->_modelName);
|
||||
|
||||
try
|
||||
{
|
||||
if($obj = $store->getByPrimaryKey($key))
|
||||
{
|
||||
$store->delete($obj);
|
||||
return array('deleted' => true);
|
||||
}
|
||||
}
|
||||
catch(\Exception $ex)
|
||||
{
|
||||
}
|
||||
|
||||
return array('deleted' => false);
|
||||
}
|
||||
}
|
149
B8Framework/b8/Database.php
Executable file
149
B8Framework/b8/Database.php
Executable file
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
|
||||
use b8\Config;
|
||||
|
||||
class Database extends \PDO
|
||||
{
|
||||
protected static $initialised = false;
|
||||
protected static $servers = array('read' => array(), 'write' => array());
|
||||
protected static $connections = array('read' => null, 'write' => null);
|
||||
protected static $details = array();
|
||||
protected static $lastUsed = array('read' => null, 'write' => null);
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static function setReadServers($read)
|
||||
{
|
||||
$config = Config::getInstance();
|
||||
|
||||
$settings = $config->get('b8.database', array());
|
||||
$settings['servers']['read'] = $read;
|
||||
$config->set('b8.database', $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static function setWriteServers($write)
|
||||
{
|
||||
$config = Config::getInstance();
|
||||
|
||||
$settings = $config->get('b8.database', array());
|
||||
$settings['servers']['write'] = $write;
|
||||
$config->set('b8.database', $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static function setDetails($database, $username, $password)
|
||||
{
|
||||
$config = Config::getInstance();
|
||||
$settings = $config->get('b8.database', array());
|
||||
$settings['name'] = $database;
|
||||
$settings['username'] = $username;
|
||||
$settings['password'] = $password;
|
||||
$config->set('b8.database', $settings);
|
||||
}
|
||||
|
||||
protected static function init()
|
||||
{
|
||||
$config = Config::getInstance();
|
||||
$settings = $config->get('b8.database', array());
|
||||
self::$servers['read'] = $settings['servers']['read'];
|
||||
self::$servers['write'] = $settings['servers']['write'];
|
||||
self::$details['db'] = $settings['name'];
|
||||
self::$details['user'] = $settings['username'];
|
||||
self::$details['pass'] = $settings['password'];
|
||||
self::$initialised = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return \b8\Database
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getConnection($type = 'read')
|
||||
{
|
||||
if (!self::$initialised) {
|
||||
self::init();
|
||||
}
|
||||
|
||||
// If the connection hasn't been used for 5 minutes, force a reconnection:
|
||||
if (!is_null(self::$lastUsed[$type]) && (time() - self::$lastUsed[$type]) > 300) {
|
||||
self::$connections[$type] = null;
|
||||
}
|
||||
|
||||
if(is_null(self::$connections[$type]))
|
||||
{
|
||||
if (is_array(self::$servers[$type])) {
|
||||
// Shuffle, so we pick a random server:
|
||||
$servers = self::$servers[$type];
|
||||
shuffle($servers);
|
||||
} else {
|
||||
// Only one server was specified
|
||||
$servers = array(self::$servers[$type]);
|
||||
}
|
||||
|
||||
$connection = null;
|
||||
|
||||
// Loop until we get a working connection:
|
||||
while(count($servers))
|
||||
{
|
||||
// Pull the next server:
|
||||
$server = array_shift($servers);
|
||||
|
||||
// Try to connect:
|
||||
try
|
||||
{
|
||||
$connection = new self('mysql:host=' . $server . ';dbname=' . self::$details['db'],
|
||||
self::$details['user'],
|
||||
self::$details['pass'],
|
||||
array(
|
||||
\PDO::ATTR_PERSISTENT => false,
|
||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||||
\PDO::ATTR_TIMEOUT => 2,
|
||||
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
|
||||
));
|
||||
}
|
||||
catch(\PDOException $ex)
|
||||
{
|
||||
$connection = false;
|
||||
}
|
||||
|
||||
// Opened a connection? Break the loop:
|
||||
if($connection)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No connection? Oh dear.
|
||||
if(!$connection && $type == 'read')
|
||||
{
|
||||
throw new \Exception('Could not connect to any ' . $type . ' servers.');
|
||||
}
|
||||
|
||||
self::$connections[$type] = $connection;
|
||||
}
|
||||
|
||||
self::$lastUsed[$type] = time();
|
||||
return self::$connections[$type];
|
||||
}
|
||||
|
||||
public function getDetails()
|
||||
{
|
||||
return self::$details;
|
||||
}
|
||||
|
||||
public static function reset()
|
||||
{
|
||||
self::$connections = array('read' => null, 'write' => null);
|
||||
self::$lastUsed = array('read' => null, 'write' => null);
|
||||
self::$initialised = false;
|
||||
}
|
||||
}
|
153
B8Framework/b8/Database/CodeGenerator.php
Executable file
153
B8Framework/b8/Database/CodeGenerator.php
Executable file
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Database;
|
||||
use b8\Database,
|
||||
b8\Database\Map,
|
||||
b8\View\Template;
|
||||
|
||||
class CodeGenerator
|
||||
{
|
||||
protected $_db = null;
|
||||
protected $_map = null;
|
||||
protected $_tables = null;
|
||||
protected $_ns = null;
|
||||
protected $_path = null;
|
||||
|
||||
/**
|
||||
* @param Database $db
|
||||
* @param array $namespaces
|
||||
* @param string $path
|
||||
* @param bool $includeCountQueries
|
||||
*/
|
||||
public function __construct(Database $db, array $namespaces, $path, $includeCountQueries = true)
|
||||
{
|
||||
$this->_db = $db;
|
||||
$this->_ns = $namespaces;
|
||||
$this->_path = $path;
|
||||
$this->_map = new Map($this->_db);
|
||||
$this->_tables = $this->_map->generate();
|
||||
$this->_counts = $includeCountQueries;
|
||||
}
|
||||
|
||||
protected function getNamespace($modelName)
|
||||
{
|
||||
return array_key_exists($modelName, $this->_ns) ? $this->_ns[$modelName] : $this->_ns['default'];
|
||||
}
|
||||
|
||||
public function getPath($namespace)
|
||||
{
|
||||
return array_key_exists($namespace, $this->_path) ? $this->_path[$namespace] : $this->_path['default'];
|
||||
}
|
||||
|
||||
public function generateModels()
|
||||
{
|
||||
print PHP_EOL . 'GENERATING MODELS' . PHP_EOL . PHP_EOL;
|
||||
|
||||
foreach($this->_tables as $tableName => $table)
|
||||
{
|
||||
$namespace = $this->getNamespace($table['php_name']);
|
||||
$modelPath = $this->getPath($namespace) . str_replace('\\', '/', $namespace) . '/Model/';
|
||||
$basePath = $modelPath . 'Base/';
|
||||
$modelFile = $modelPath . $table['php_name'] . '.php';
|
||||
$baseFile = $basePath . $table['php_name'] . 'Base.php';
|
||||
|
||||
if (!is_dir($basePath)) {
|
||||
@mkdir($basePath, 0777, true);
|
||||
}
|
||||
|
||||
$model = $this->_processTemplate($tableName, $table, 'ModelTemplate');
|
||||
$base = $this->_processTemplate($tableName, $table, 'BaseModelTemplate');
|
||||
|
||||
print '-- ' . $table['php_name'] . PHP_EOL;
|
||||
|
||||
if(!is_file($modelFile))
|
||||
{
|
||||
print '-- -- Writing new Model' . PHP_EOL;
|
||||
file_put_contents($modelFile, $model);
|
||||
}
|
||||
|
||||
print '-- -- Writing base Model' . PHP_EOL;
|
||||
file_put_contents($baseFile, $base);
|
||||
}
|
||||
}
|
||||
|
||||
public function generateStores()
|
||||
{
|
||||
print PHP_EOL . 'GENERATING STORES' . PHP_EOL . PHP_EOL;
|
||||
|
||||
foreach($this->_tables as $tableName => $table)
|
||||
{
|
||||
$namespace = $this->getNamespace($table['php_name']);
|
||||
$storePath = $this->getPath($namespace) . str_replace('\\', '/', $namespace) . '/Store/';
|
||||
$basePath = $storePath . 'Base/';
|
||||
$storeFile = $storePath . $table['php_name'] . 'Store.php';
|
||||
$baseFile = $basePath . $table['php_name'] . 'StoreBase.php';
|
||||
|
||||
if (!is_dir($basePath)) {
|
||||
@mkdir($basePath, 0777, true);
|
||||
}
|
||||
|
||||
$model = $this->_processTemplate($tableName, $table, 'StoreTemplate');
|
||||
$base = $this->_processTemplate($tableName, $table, 'BaseStoreTemplate');
|
||||
|
||||
print '-- ' . $table['php_name'] . PHP_EOL;
|
||||
|
||||
if(!is_file($storeFile))
|
||||
{
|
||||
print '-- -- Writing new Store' . PHP_EOL;
|
||||
file_put_contents($storeFile, $model);
|
||||
}
|
||||
|
||||
print '-- -- Writing base Store' . PHP_EOL;
|
||||
file_put_contents($baseFile, $base);
|
||||
}
|
||||
}
|
||||
|
||||
public function generateControllers()
|
||||
{
|
||||
print PHP_EOL . 'GENERATING CONTROLLERS' . PHP_EOL . PHP_EOL;
|
||||
|
||||
@mkdir($this->_path . 'Controller/Base/', 0777, true);
|
||||
|
||||
foreach($this->_tables as $tableName => $table)
|
||||
{
|
||||
$namespace = $this->getNamespace($table['php_name']);
|
||||
$controllerPath = $this->getPath($namespace) . str_replace('\\', '/', $namespace) . '/Controller/';
|
||||
$basePath = $controllerPath . 'Base/';
|
||||
$controllerFile = $controllerPath . $table['php_name'] . 'Controller.php';
|
||||
$baseFile = $basePath . $table['php_name'] . 'ControllerBase.php';
|
||||
|
||||
if (!is_dir($basePath)) {
|
||||
@mkdir($basePath, 0777, true);
|
||||
}
|
||||
|
||||
$model = $this->_processTemplate($tableName, $table, 'ControllerTemplate');
|
||||
$base = $this->_processTemplate($tableName, $table, 'BaseControllerTemplate');
|
||||
|
||||
print '-- ' . $table['php_name'] . PHP_EOL;
|
||||
|
||||
if(!is_file($controllerFile))
|
||||
{
|
||||
print '-- -- Writing new Controller' . PHP_EOL;
|
||||
file_put_contents($controllerFile, $model);
|
||||
}
|
||||
|
||||
print '-- -- Writing base Controller' . PHP_EOL;
|
||||
file_put_contents($baseFile, $base);
|
||||
}
|
||||
}
|
||||
|
||||
protected function _processTemplate($tableName, $table, $template)
|
||||
{
|
||||
$tpl = Template::createFromFile($template, B8_PATH . 'Database/CodeGenerator/');
|
||||
$tpl->appNamespace = $this->getNamespace($table['php_name']);
|
||||
$tpl->name = $tableName;
|
||||
$tpl->table = $table;
|
||||
$tpl->counts = $this->_counts;
|
||||
$tpl->addFunction('get_namespace', function($args, $view) {
|
||||
return $this->getNamespace($view->getVariable($args['model']));
|
||||
});
|
||||
|
||||
return $tpl->render();
|
||||
}
|
||||
}
|
22
B8Framework/b8/Database/CodeGenerator/BaseControllerTemplate.html
Executable file
22
B8Framework/b8/Database/CodeGenerator/BaseControllerTemplate.html
Executable file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* {@table.php_name} base controller for table: {@name}
|
||||
*/
|
||||
|
||||
namespace {@appNamespace}\Controller\Base;
|
||||
|
||||
use b8\Controller\RestController;
|
||||
|
||||
/**
|
||||
* {@table.php_name} base Controller
|
||||
* @see {@appNamespace}\Controller\{@table.php_name}
|
||||
* @uses {@appNamespace}\Store\{@table.php_name}Store
|
||||
* @uses {@appNamespace}\Model\{@table.php_name}
|
||||
*/
|
||||
class {@table.php_name}ControllerBase extends RestController
|
||||
{
|
||||
protected $_modelName = '{@table.php_name}';
|
||||
protected $_resourceName = '{@table.php_name.toLowerCase}s';
|
||||
protected $_modelClass = '\{@appNamespace}\Model\{@table.php_name}';
|
||||
}
|
268
B8Framework/b8/Database/CodeGenerator/BaseModelTemplate.html
Executable file
268
B8Framework/b8/Database/CodeGenerator/BaseModelTemplate.html
Executable file
|
@ -0,0 +1,268 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* {@table.php_name} base model for table: {@name}
|
||||
*/
|
||||
|
||||
namespace {@appNamespace}\Model\Base;
|
||||
|
||||
use {@appNamespace}\Model;
|
||||
use b8\Store\Factory;
|
||||
|
||||
/**
|
||||
* {@table.php_name} Base Model
|
||||
*/
|
||||
class {@table.php_name}Base extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public static $sleepable = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tableName = '{@name}';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $modelName = '{@table.php_name}';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data = array(
|
||||
{loop table.columns}
|
||||
'{@item.name}' => null,
|
||||
{/loop}
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $getters = array(
|
||||
// Direct property getters:
|
||||
{loop table.columns}
|
||||
'{@item.name}' => 'get{@item.php_name}',
|
||||
{/loop}
|
||||
|
||||
// Foreign key getters:
|
||||
{loop table.relationships.toOne}
|
||||
'{@item.php_name}' => 'get{@item.php_name}',
|
||||
{/loop}
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $setters = array(
|
||||
// Direct property setters:
|
||||
{loop table.columns}
|
||||
'{@item.name}' => 'set{@item.php_name}',
|
||||
{/loop}
|
||||
|
||||
// Foreign key setters:
|
||||
{loop table.relationships.toOne}
|
||||
'{@item.php_name}' => 'set{@item.php_name}',
|
||||
{/loop}
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $columns = array(
|
||||
{loop table.columns}
|
||||
'{@item.name}' => array(
|
||||
'type' => '{@item.type}',
|
||||
{if item.length}
|
||||
'length' => {@item.length},
|
||||
{/if}
|
||||
{if item.null}
|
||||
'nullable' => true,
|
||||
{/if}
|
||||
{if item.is_primary_key}
|
||||
'primary_key' => true,
|
||||
{/if}
|
||||
{if item.auto}
|
||||
'auto_increment' => true,
|
||||
{/if}
|
||||
{if item.default_is_null}
|
||||
'default' => null,
|
||||
{/if}
|
||||
{ifnot item.default_is_null}
|
||||
{if item.default}
|
||||
'default' => {if item.default.isNumeric}{@item.default}{/if}{ifnot item.default.isNumeric}'{@item.default}'{/ifnot},
|
||||
{/if}
|
||||
{/ifnot}
|
||||
),
|
||||
{/loop}
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $indexes = array(
|
||||
{loop table.indexes}
|
||||
'{@item.name}' => array({if item.unique}'unique' => true, {/if}'columns' => '{@item.columns}'),
|
||||
{/loop}
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $foreignKeys = array(
|
||||
{loop table.relationships.toOne}
|
||||
'{@item.fk_name}' => array(
|
||||
'local_col' => '{@item.from_col}',
|
||||
'update' => '{@item.fk_update}',
|
||||
'delete' => '{@item.fk_delete}',
|
||||
'table' => '{@item.table}',
|
||||
'col' => '{@item.col}'
|
||||
),
|
||||
{/loop}
|
||||
);
|
||||
|
||||
{loop table.columns}
|
||||
/**
|
||||
* Get the value of {@item.php_name} / {@item.name}.
|
||||
*
|
||||
{if item.validate_int}
|
||||
* @return int
|
||||
{/if}{if item.validate_string}
|
||||
* @return string
|
||||
{/if}{if item.validate_float}
|
||||
* @return float
|
||||
{/if}{if item.validate_date}
|
||||
* @return \DateTime
|
||||
{/if}
|
||||
*/
|
||||
public function get{@item.php_name}()
|
||||
{
|
||||
$rtn = $this->data['{@item.name}'];
|
||||
|
||||
{if item.validate_date}
|
||||
if (!empty($rtn)) {
|
||||
$rtn = new \DateTime($rtn);
|
||||
}
|
||||
|
||||
{/if}
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
{/loop}
|
||||
{loop table.columns}
|
||||
/**
|
||||
* Set the value of {@item.php_name} / {@item.name}.
|
||||
*
|
||||
{if item.validate_null}
|
||||
* Must not be null.
|
||||
{/if}{if item.validate_int}
|
||||
* @param $value int
|
||||
{/if}{if item.validate_string}
|
||||
* @param $value string
|
||||
{/if}{if item.validate_float}
|
||||
* @param $value float
|
||||
{/if}{if item.validate_date}
|
||||
* @param $value \DateTime
|
||||
{/if}
|
||||
*/
|
||||
public function set{@item.php_name}($value)
|
||||
{
|
||||
{if item.validate_null}
|
||||
$this->_validateNotNull('{@item.php_name}', $value);
|
||||
{/if}
|
||||
{if item.validate_int}
|
||||
$this->_validateInt('{@item.php_name}', $value);
|
||||
{/if}
|
||||
{if item.validate_string}
|
||||
$this->_validateString('{@item.php_name}', $value);
|
||||
{/if}
|
||||
{if item.validate_float}
|
||||
$this->_validateFloat('{@item.php_name}', $value);
|
||||
{/if}
|
||||
{if item.validate_date}
|
||||
$this->_validateDate('{@item.php_name}', $value);
|
||||
{/if}
|
||||
|
||||
if ($this->data['{@item.name}'] === $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->data['{@item.name}'] = $value;
|
||||
|
||||
$this->_setModified('{@item.name}');
|
||||
}
|
||||
|
||||
{/loop}{loop table.relationships.toOne}
|
||||
/**
|
||||
* Get the {@item.table_php_name} model for this {@parent.table.php_name} by {@item.col_php}.
|
||||
*
|
||||
* @uses \{@parent.appNamespace}\Store\{@item.table_php_name}Store::getBy{@item.col_php}()
|
||||
* @uses \{@parent.appNamespace}\Model\{@item.table_php_name}
|
||||
* @return \{@parent.appNamespace}\Model\{@item.table_php_name}
|
||||
*/
|
||||
public function get{@item.php_name}()
|
||||
{
|
||||
$key = $this->get{@item.from_col_php}();
|
||||
|
||||
if (empty($key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cacheKey = 'Cache.{@item.table_php_name}.' . $key;
|
||||
$rtn = $this->cache->get($cacheKey, null);
|
||||
|
||||
if (empty($rtn)) {
|
||||
$rtn = Factory::getStore('{@item.table_php_name}', '{get_namespace model: item.table_php_name}')->getBy{@item.col_php}($key);
|
||||
$this->cache->set($cacheKey, $rtn);
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@item.php_name} - Accepts an ID, an array representing a {@item.table_php_name} or a {@item.table_php_name} model.
|
||||
*
|
||||
* @param $value mixed
|
||||
*/
|
||||
public function set{@item.php_name}($value)
|
||||
{
|
||||
// Is this an instance of {@item.table_php_name}?
|
||||
if ($value instanceof \{@parent.appNamespace}\Model\{@item.table_php_name}) {
|
||||
return $this->set{@item.php_name}Object($value);
|
||||
}
|
||||
|
||||
// Is this an array representing a {@item.table_php_name} item?
|
||||
if (is_array($value) && !empty($value['{@item.col}'])) {
|
||||
return $this->set{@item.from_col_php}($value['{@item.col}']);
|
||||
}
|
||||
|
||||
// Is this a scalar value representing the ID of this foreign key?
|
||||
return $this->set{@item.from_col_php}($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set {@item.php_name} - Accepts a {@item.table_php_name} model.
|
||||
*
|
||||
* @param $value \{@parent.appNamespace}\Model\{@item.table_php_name}
|
||||
*/
|
||||
public function set{@item.php_name}Object(\{@parent.appNamespace}\Model\{@item.table_php_name} $value)
|
||||
{
|
||||
return $this->set{@item.from_col_php}($value->get{@item.col_php}());
|
||||
}
|
||||
|
||||
{/loop}{loop table.relationships.toMany}
|
||||
/**
|
||||
* Get {@item.table_php} models by {@item.from_col_php} for this {@parent.table.php_name}.
|
||||
*
|
||||
* @uses \{@parent.appNamespace}\Store\{@item.table_php}Store::getBy{@item.from_col_php}()
|
||||
* @uses \{@parent.appNamespace}\Model\{@item.table_php}
|
||||
* @return \{@parent.appNamespace}\Model\{@item.table_php}[]
|
||||
*/
|
||||
public function get{@item.php_name}()
|
||||
{
|
||||
return Factory::getStore('{@item.table_php}', '{get_namespace model: item.table_php_name}')->getBy{@item.from_col_php}($this->get{@item.col_php}());
|
||||
}
|
||||
|
||||
{/loop}}
|
101
B8Framework/b8/Database/CodeGenerator/BaseStoreTemplate.html
Executable file
101
B8Framework/b8/Database/CodeGenerator/BaseStoreTemplate.html
Executable file
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* {@table.php_name} base store for table: {@name}
|
||||
*/
|
||||
|
||||
namespace {@appNamespace}\Store\Base;
|
||||
|
||||
use b8\Database;
|
||||
use b8\Exception\HttpException;
|
||||
use {@appNamespace}\Store;
|
||||
use {@appNamespace}\Model\{@table.php_name};
|
||||
|
||||
/**
|
||||
* {@table.php_name} Base Store
|
||||
*/
|
||||
class {@table.php_name}StoreBase extends Store
|
||||
{
|
||||
protected $tableName = '{@name}';
|
||||
protected $modelName = '\{@appNamespace}\Model\{@table.php_name}';
|
||||
{if table.primary_key}
|
||||
protected $primaryKey = '{@table.primary_key.column}';
|
||||
|
||||
public function getByPrimaryKey($value, $useConnection = 'read')
|
||||
{
|
||||
return $this->getBy{@table.primary_key.php_name}($value, $useConnection);
|
||||
}
|
||||
{/if}
|
||||
{ifnot table.primary_key}
|
||||
|
||||
public function getByPrimaryKey($value, $useConnection = 'read')
|
||||
{
|
||||
throw new \Exception('getByPrimaryKey is not implemented for this store, as the table has no primary key.');
|
||||
}
|
||||
{/ifnot}
|
||||
{loop table.columns}
|
||||
{if item.unique_indexed}
|
||||
|
||||
public function getBy{@item.php_name}($value, $useConnection = 'read')
|
||||
{
|
||||
if (is_null($value)) {
|
||||
throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.');
|
||||
}
|
||||
|
||||
$query = 'SELECT * FROM `{@parent.name}` WHERE `{@item.name}` = :{@item.name} LIMIT 1';
|
||||
$stmt = Database::getConnection($useConnection)->prepare($query);
|
||||
$stmt->bindValue(':{@item.name}', $value);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
return new {@parent.table.php_name}($data);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
{/if}
|
||||
{if item.many_indexed}
|
||||
|
||||
public function getBy{@item.php_name}($value, $limit = 1000, $useConnection = 'read')
|
||||
{
|
||||
if (is_null($value)) {
|
||||
throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.');
|
||||
}
|
||||
|
||||
{if counts}
|
||||
$query = 'SELECT COUNT(*) AS cnt FROM `{@parent.name}` WHERE `{@item.name}` = :{@item.name}';
|
||||
$stmt = Database::getConnection($useConnection)->prepare($query);
|
||||
$stmt->bindValue(':{@item.name}', $value);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$res = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
$count = (int)$res['cnt'];
|
||||
} else {
|
||||
$count = 0;
|
||||
}
|
||||
{/if}
|
||||
|
||||
$query = 'SELECT * FROM `{@parent.name}` WHERE `{@item.name}` = :{@item.name} LIMIT :limit';
|
||||
$stmt = Database::getConnection($useConnection)->prepare($query);
|
||||
$stmt->bindValue(':{@item.name}', $value);
|
||||
$stmt->bindValue(':limit', (int)$limit, \PDO::PARAM_INT);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
$res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
$map = function ($item) {
|
||||
return new {@parent.table.php_name}($item);
|
||||
};
|
||||
$rtn = array_map($map, $res);
|
||||
|
||||
{ifnot counts}$count = count($rtn);{/ifnot}
|
||||
|
||||
return array('items' => $rtn, 'count' => $count);
|
||||
} else {
|
||||
return array('items' => array(), 'count' => 0);
|
||||
}
|
||||
}
|
||||
{/if}
|
||||
{/loop}
|
||||
}
|
20
B8Framework/b8/Database/CodeGenerator/ControllerTemplate.html
Executable file
20
B8Framework/b8/Database/CodeGenerator/ControllerTemplate.html
Executable file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* {@table.php_name} controller for table: {@name}
|
||||
*/
|
||||
|
||||
namespace {@appNamespace}\Controller;
|
||||
|
||||
use {@appNamespace}\Controller\Base\{@table.php_name}ControllerBase;
|
||||
|
||||
/**
|
||||
* {@table.php_name} Controller
|
||||
* @uses {@appNamespace}\Controller\Base\{@table.php_name}Base
|
||||
* @uses {@appNamespace}\Store\{@table.php_name}Store
|
||||
* @uses {@appNamespace}\Model\{@table.php_name}
|
||||
*/
|
||||
class {@table.php_name}Controller extends {@table.php_name}ControllerBase
|
||||
{
|
||||
// This class has been left blank so that you can modify it - changes in this file will not be overwritten.
|
||||
}
|
18
B8Framework/b8/Database/CodeGenerator/ModelTemplate.html
Executable file
18
B8Framework/b8/Database/CodeGenerator/ModelTemplate.html
Executable file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* {@table.php_name} model for table: {@name}
|
||||
*/
|
||||
|
||||
namespace {@appNamespace}\Model;
|
||||
|
||||
use {@appNamespace}\Model\Base\{@table.php_name}Base;
|
||||
|
||||
/**
|
||||
* {@table.php_name} Model
|
||||
* @uses {@appNamespace}\Model\Base\{@table.php_name}Base
|
||||
*/
|
||||
class {@table.php_name} extends {@table.php_name}Base
|
||||
{
|
||||
// This class has been left blank so that you can modify it - changes in this file will not be overwritten.
|
||||
}
|
18
B8Framework/b8/Database/CodeGenerator/StoreTemplate.html
Executable file
18
B8Framework/b8/Database/CodeGenerator/StoreTemplate.html
Executable file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* {@table.php_name} store for table: {@name}
|
||||
*/
|
||||
|
||||
namespace {@appNamespace}\Store;
|
||||
|
||||
use {@appNamespace}\Store\Base\{@table.php_name}StoreBase;
|
||||
|
||||
/**
|
||||
* {@table.php_name} Store
|
||||
* @uses {@appNamespace}\Store\Base\{@table.php_name}StoreBase
|
||||
*/
|
||||
class {@table.php_name}Store extends {@table.php_name}StoreBase
|
||||
{
|
||||
// This class has been left blank so that you can modify it - changes in this file will not be overwritten.
|
||||
}
|
428
B8Framework/b8/Database/Generator.php
Executable file
428
B8Framework/b8/Database/Generator.php
Executable file
|
@ -0,0 +1,428 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Database generator updates a database to match a set of Models.
|
||||
*/
|
||||
|
||||
namespace b8\Database;
|
||||
use b8\Database;
|
||||
|
||||
class Generator
|
||||
{
|
||||
protected $_db = null;
|
||||
protected $_map = null;
|
||||
protected $_tables = null;
|
||||
protected $_ns = null;
|
||||
protected $_path = null;
|
||||
|
||||
public function __construct(Database $db, $namespace, $path)
|
||||
{
|
||||
$this->_db = $db;
|
||||
$this->_ns = $namespace;
|
||||
$this->_path = $path;
|
||||
$this->_map = new Map($this->_db);
|
||||
$this->_tables = $this->_map->generate();
|
||||
}
|
||||
|
||||
public function generate()
|
||||
{
|
||||
error_reporting(E_ERROR & E_WARNING);
|
||||
$di = new \DirectoryIterator($this->_path);
|
||||
|
||||
$this->_todo = array(
|
||||
'drop_fk' => array(),
|
||||
'drop_index'=> array(),
|
||||
'create' => array(),
|
||||
'alter' => array(),
|
||||
'add_index' => array(),
|
||||
'add_fk' => array(),
|
||||
);
|
||||
|
||||
foreach($di as $file)
|
||||
{
|
||||
if($file->isDot())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$fileName = explode('.', $file->getBasename());
|
||||
if ($fileName[count($fileName)-1] != 'php')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$modelName = '\\' . $this->_ns . '\\Model\\Base\\' . str_replace('.php', '', $file->getFilename());
|
||||
|
||||
require_once($this->_path . $file->getFilename());
|
||||
$model = new $modelName();
|
||||
$columns = $model->columns;
|
||||
$indexes = $model->indexes;
|
||||
$foreignKeys = $model->foreignKeys;
|
||||
$tableName = $model->getTableName();
|
||||
|
||||
if(!array_key_exists($tableName, $this->_tables))
|
||||
{
|
||||
$this->_createTable($tableName, $columns, $indexes, $foreignKeys);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$table = $this->_tables[$tableName];
|
||||
$this->_updateColumns($tableName, $table, $columns);
|
||||
$this->_updateRelationships($tableName, $table, $foreignKeys);
|
||||
$this->_updateIndexes($tableName, $table, $indexes);
|
||||
}
|
||||
}
|
||||
|
||||
print 'DROP FK: ' . count($this->_todo['drop_fk']) . PHP_EOL;
|
||||
print 'DROP INDEX: ' . count($this->_todo['drop_index']) . PHP_EOL;
|
||||
print 'CREATE TABLE: ' . count($this->_todo['create']) . PHP_EOL;
|
||||
print 'ALTER TABLE: ' . count($this->_todo['alter']) . PHP_EOL;
|
||||
print 'ADD INDEX: ' . count($this->_todo['add_index']) . PHP_EOL;
|
||||
print 'ADD FK: ' . count($this->_todo['add_fk']) . PHP_EOL;
|
||||
|
||||
|
||||
$order = array_keys($this->_todo);
|
||||
|
||||
while($group = array_shift($order))
|
||||
{
|
||||
if(!isset($this->_todo[$group]) || !is_array($this->_todo[$group]) || !count($this->_todo[$group]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach($this->_todo[$group] as $query)
|
||||
{
|
||||
try
|
||||
{
|
||||
//print $query . PHP_EOL;
|
||||
$this->_db->query($query);
|
||||
}
|
||||
catch(\Exception $ex)
|
||||
{
|
||||
print 'FAILED TO EXECUTE: ' . $query . PHP_EOL;
|
||||
print $ex->getMessage().PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function _createTable($tbl, $cols, $idxs, $fks)
|
||||
{
|
||||
$defs = array();
|
||||
$pks = array();
|
||||
foreach($cols as $colName => $def)
|
||||
{
|
||||
$add = '`' . $colName . '` ' . $def['type'];
|
||||
|
||||
switch($def['type'])
|
||||
{
|
||||
case 'text':
|
||||
case 'longtext':
|
||||
case 'mediumtext':
|
||||
case 'date':
|
||||
case 'datetime':
|
||||
case 'float':
|
||||
$add .= '';
|
||||
break;
|
||||
|
||||
default:
|
||||
$add .= !empty($def['length']) ? '(' . $def['length'] . ')' : '';
|
||||
break;
|
||||
}
|
||||
|
||||
if(empty($def['nullable']) || !$def['nullable'])
|
||||
{
|
||||
$add .= ' NOT NULL ';
|
||||
}
|
||||
|
||||
if(!empty($def['default']))
|
||||
{
|
||||
$add .= ' DEFAULT ' . (is_numeric($def['default']) ? $def['default'] : '\'' . $def['default'] . '\'');
|
||||
}
|
||||
|
||||
if(!empty($def['auto_increment']) && $def['auto_increment'])
|
||||
{
|
||||
$add .= ' AUTO_INCREMENT ';
|
||||
}
|
||||
|
||||
if(!empty($def['primary_key']) && $def['primary_key'])
|
||||
{
|
||||
$pks[] = '`' . $colName . '`';
|
||||
}
|
||||
|
||||
$defs[] = $add;
|
||||
}
|
||||
|
||||
if(count($pks))
|
||||
{
|
||||
$defs[] = 'PRIMARY KEY (' . implode(', ', $pks) . ')';
|
||||
}
|
||||
|
||||
$stmt = 'CREATE TABLE `' . $tbl . '` (' . PHP_EOL;
|
||||
$stmt .= implode(", \n", $defs);
|
||||
|
||||
$stmt .= PHP_EOL . ') ENGINE=InnoDB DEFAULT CHARSET=utf8';
|
||||
$stmt .= PHP_EOL;
|
||||
|
||||
$this->_todo['create'][] = $stmt;
|
||||
|
||||
foreach($idxs as $name => $idx)
|
||||
{
|
||||
$this->_addIndex($tbl, $name, $idx);
|
||||
}
|
||||
|
||||
foreach($fks as $name => $fk)
|
||||
{
|
||||
$this->_addFk($tbl, $name, $fk);
|
||||
}
|
||||
}
|
||||
|
||||
protected function _updateColumns($tableName, $table, $columns)
|
||||
{
|
||||
$currentColumns = $table['columns'];
|
||||
|
||||
while($column = array_shift($currentColumns))
|
||||
{
|
||||
if(!array_key_exists($column['name'], $columns))
|
||||
{
|
||||
$this->_todo['alter'][$tableName.'.'.$column['name']] = 'ALTER TABLE `' . $tableName . '` DROP COLUMN `' . $column['name'] . '`';
|
||||
}
|
||||
else
|
||||
{
|
||||
$model = $columns[$column['name']];
|
||||
|
||||
$model['nullable'] = !isset($model['nullable']) ? false : $model['nullable'];
|
||||
$model['default'] = !isset($model['default']) ? false : $model['default'];
|
||||
$model['auto_increment'] = !isset($model['auto_increment']) ? false : $model['auto_increment'];
|
||||
$model['primary_key'] = !isset($model['primary_key']) ? false : $model['primary_key'];
|
||||
$column['is_primary_key'] = !isset($column['is_primary_key']) ? false : $column['is_primary_key'];
|
||||
|
||||
if( $column['type'] != $model['type'] ||
|
||||
($column['length'] != $model['length'] && !in_array($model['type'], array('text', 'longtext', 'mediumtext', 'date', 'datetime', 'float'))) ||
|
||||
$column['null'] != $model['nullable'] ||
|
||||
$column['default'] != $model['default'] ||
|
||||
$column['auto'] != $model['auto_increment'])
|
||||
{
|
||||
$this->_updateColumn($tableName, $column['name'], $column['name'], $model);
|
||||
}
|
||||
}
|
||||
|
||||
unset($columns[$column['name']]);
|
||||
}
|
||||
|
||||
if(count($columns))
|
||||
{
|
||||
foreach($columns as $name => $model)
|
||||
{
|
||||
// Check if we're renaming a column:
|
||||
if(isset($model['rename']))
|
||||
{
|
||||
unset($this->_todo['alter'][$tableName.'.'.$model['rename']]);
|
||||
$this->_updateColumn($tableName, $model['rename'], $name, $model);
|
||||
continue;
|
||||
}
|
||||
|
||||
// New column
|
||||
$add = '`' . $name . '` ' . $model['type'];;
|
||||
switch($model['type'])
|
||||
{
|
||||
case 'text':
|
||||
case 'longtext':
|
||||
case 'mediumtext':
|
||||
case 'date':
|
||||
case 'datetime':
|
||||
case 'float':
|
||||
$add .= '';
|
||||
break;
|
||||
|
||||
default:
|
||||
$add .= !empty($model['length']) ? '(' . $model['length'] . ')' : '';
|
||||
break;
|
||||
}
|
||||
|
||||
if(empty($model['nullable']) || !$model['nullable'])
|
||||
{
|
||||
$add .= ' NOT NULL ';
|
||||
}
|
||||
|
||||
if(!empty($model['default']))
|
||||
{
|
||||
$add .= ' DEFAULT ' . (is_numeric($model['default']) ? $model['default'] : '\'' . $model['default'] . '\'');
|
||||
}
|
||||
|
||||
if(!empty($model['auto_increment']) && $model['auto_increment'])
|
||||
{
|
||||
$add .= ' AUTO_INCREMENT ';
|
||||
}
|
||||
|
||||
if(!empty($model['primary_key']) && $model['primary_key'] && !isset($table['indexes']['PRIMARY']))
|
||||
{
|
||||
$add .= ' PRIMARY KEY ';
|
||||
}
|
||||
|
||||
$this->_todo['alter'][] = 'ALTER TABLE `' . $tableName . '` ADD COLUMN ' . $add;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function _updateColumn($tableName, $prevName, $newName, $model)
|
||||
{
|
||||
$add = '`' . $newName . '` ' . $model['type'];;
|
||||
switch($model['type'])
|
||||
{
|
||||
case 'text':
|
||||
case 'longtext':
|
||||
case 'mediumtext':
|
||||
case 'date':
|
||||
case 'datetime':
|
||||
case 'float':
|
||||
$add .= '';
|
||||
break;
|
||||
|
||||
default:
|
||||
$add .= !empty($model['length']) ? '(' . $model['length'] . ')' : '';
|
||||
break;
|
||||
}
|
||||
|
||||
if(empty($model['nullable']) || !$model['nullable'])
|
||||
{
|
||||
$add .= ' NOT NULL ';
|
||||
}
|
||||
|
||||
if(!empty($model['default']))
|
||||
{
|
||||
$add .= ' DEFAULT ' . (is_numeric($model['default']) ? $model['default'] : '\'' . $model['default'] . '\'');
|
||||
}
|
||||
|
||||
if(!empty($model['auto_increment']) && $model['auto_increment'])
|
||||
{
|
||||
$add .= ' AUTO_INCREMENT ';
|
||||
}
|
||||
|
||||
$this->_todo['alter'][] = 'ALTER TABLE `' . $tableName . '` CHANGE COLUMN `' . $prevName . '` ' . $add;
|
||||
}
|
||||
|
||||
protected function _updateRelationships($tableName, $table, $foreignKeys)
|
||||
{
|
||||
$current = $table['relationships']['toOne'];
|
||||
|
||||
while($foreignKey = array_shift($current))
|
||||
{
|
||||
if(!array_key_exists($foreignKey['fk_name'], $foreignKeys))
|
||||
{
|
||||
$this->_dropFk($tableName, $foreignKey['fk_name']);
|
||||
}
|
||||
elseif( $foreignKey['from_col'] != $foreignKeys[$foreignKey['fk_name']]['local_col'] ||
|
||||
$foreignKey['table'] != $foreignKeys[$foreignKey['fk_name']]['table'] ||
|
||||
$foreignKey['col'] != $foreignKeys[$foreignKey['fk_name']]['col'] ||
|
||||
$foreignKey['fk_update'] != $foreignKeys[$foreignKey['fk_name']]['update'] ||
|
||||
$foreignKey['fk_delete'] != $foreignKeys[$foreignKey['fk_name']]['delete'])
|
||||
{
|
||||
$this->_alterFk($tableName, $foreignKey['fk_name'], $foreignKeys[$foreignKey['fk_name']]);
|
||||
}
|
||||
|
||||
unset($foreignKeys[$foreignKey['fk_name']]);
|
||||
}
|
||||
|
||||
if(count($foreignKeys))
|
||||
{
|
||||
foreach($foreignKeys as $name => $foreignKey)
|
||||
{
|
||||
// New column
|
||||
$this->_addFk($tableName, $name, $foreignKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function _updateIndexes($tableName, $table, $indexes)
|
||||
{
|
||||
$current = $table['indexes'];
|
||||
|
||||
while($index = array_shift($current))
|
||||
{
|
||||
if(!array_key_exists($index['name'], $indexes))
|
||||
{
|
||||
$this->_dropIndex($tableName, $index['name']);
|
||||
}
|
||||
elseif( $index['unique'] != $indexes[$index['name']]['unique'] ||
|
||||
$index['columns'] != $indexes[$index['name']]['columns'])
|
||||
{
|
||||
$this->_alterIndex($tableName, $index['name'], $index);
|
||||
}
|
||||
|
||||
unset($indexes[$index['name']]);
|
||||
}
|
||||
|
||||
if(count($indexes))
|
||||
{
|
||||
foreach($indexes as $name => $index)
|
||||
{
|
||||
if($name == 'PRIMARY')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// New index
|
||||
$this->_addIndex($tableName, $name, $index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function _addIndex($table, $name, $idx, $stage = 'add_index')
|
||||
{
|
||||
if($name == 'PRIMARY')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$q = 'CREATE ' . (isset($idx['unique']) && $idx['unique'] ? 'UNIQUE' : '') . ' INDEX `' . $name . '` ON `' . $table . '` (' . $idx['columns'] . ')';
|
||||
|
||||
$this->_todo[$stage][] = $q;
|
||||
}
|
||||
|
||||
protected function _alterIndex($table, $name, $idx, $stage = 'index')
|
||||
{
|
||||
$this->_dropIndex($table, $name, $stage);
|
||||
$this->_addIndex($table, $name, $idx, $stage);
|
||||
}
|
||||
|
||||
protected function _dropIndex($table, $idxName, $stage = 'drop_index')
|
||||
{
|
||||
if($idxName == 'PRIMARY')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$q = 'DROP INDEX `' . $idxName . '` ON `' . $table . '`';
|
||||
$this->_todo[$stage][] = $q;
|
||||
}
|
||||
|
||||
protected function _addFk($table, $name, $fk)
|
||||
{
|
||||
$q = 'ALTER TABLE `' . $table . '` ADD CONSTRAINT `' . $name . '` FOREIGN KEY (`' . $fk['local_col'] . '`) REFERENCES `'.$fk['table'].'` (`'.$fk['col'].'`)';
|
||||
|
||||
if(!empty($fk['delete']))
|
||||
{
|
||||
$q .= ' ON DELETE ' . $fk['delete'] . ' ';
|
||||
}
|
||||
|
||||
if(!empty($fk['update']))
|
||||
{
|
||||
$q .= ' ON UPDATE ' . $fk['update'] . ' ';
|
||||
}
|
||||
|
||||
$this->_todo['add_fk'][] = $q;
|
||||
}
|
||||
|
||||
protected function _alterFk($table, $name, $fk)
|
||||
{
|
||||
$this->_dropFk($table, $name);
|
||||
$this->_addFk($table, $name, $fk);
|
||||
}
|
||||
|
||||
protected function _dropFk($table, $name)
|
||||
{
|
||||
$q = 'ALTER TABLE `'.$table.'` DROP FOREIGN KEY `' . $name . '`';
|
||||
$this->_todo['drop_fk'][] = $q;
|
||||
}
|
||||
}
|
258
B8Framework/b8/Database/Map.php
Executable file
258
B8Framework/b8/Database/Map.php
Executable file
|
@ -0,0 +1,258 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Database;
|
||||
use b8\Database;
|
||||
|
||||
class Map
|
||||
{
|
||||
protected $_db = null;
|
||||
protected $_tables = array();
|
||||
|
||||
public function __construct(Database $db)
|
||||
{
|
||||
$this->_db = $db;
|
||||
}
|
||||
|
||||
public function generate()
|
||||
{
|
||||
$tables = $this->_getTables();
|
||||
|
||||
|
||||
foreach($tables as $table)
|
||||
{
|
||||
$this->_tables[$table] = array();
|
||||
$this->_tables[$table]['php_name'] = $this->_generatePhpName($table);
|
||||
}
|
||||
|
||||
$this->_getRelationships();
|
||||
$this->_getColumns();
|
||||
$this->_getIndexes();
|
||||
|
||||
return $this->_tables;
|
||||
}
|
||||
|
||||
protected function _getTables()
|
||||
{
|
||||
$details = $this->_db->getDetails();
|
||||
|
||||
$rtn = array();
|
||||
|
||||
foreach($this->_db->query('SHOW TABLES')->fetchAll(\PDO::FETCH_ASSOC) as $tbl)
|
||||
{
|
||||
$rtn[] = $tbl['Tables_in_' . $details['db']];
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
protected function _getRelationships()
|
||||
{
|
||||
foreach($this->_tables as $table => $t)
|
||||
{
|
||||
$res = $this->_db->query('SHOW CREATE TABLE `'.$table.'`')->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
foreach($res as $r)
|
||||
{
|
||||
$str = $r['Create Table'];
|
||||
|
||||
$matches = array();
|
||||
if(preg_match_all('/CONSTRAINT\s+\`([a-zA-Z0-9_]+)\`\s+FOREIGN\s+KEY\s+\(\`([a-zA-Z0-9_]+)\`\)\s+REFERENCES\s+\`([a-zA-Z0-9_]+)\`\s+\(\`([a-zA-Z0-9_]+)\`\)(\s+ON (DELETE|UPDATE) (SET NULL|NO ACTION|CASCADE|RESTRICT))?(\s+ON (DELETE|UPDATE) (SET NULL|NO ACTION|CASCADE|RESTRICT))?/', $str, $matches))
|
||||
{
|
||||
for($i = 0; $i < count($matches[0]); $i++)
|
||||
{
|
||||
$fromTable = $table;
|
||||
$fromCol = $matches[2][$i];
|
||||
$toTable = $matches[3][$i];
|
||||
$toCol = $matches[4][$i];
|
||||
$fkName = $matches[1][$i];
|
||||
$fk = array();
|
||||
|
||||
if(isset($matches[6][$i]))
|
||||
{
|
||||
$fk[$matches[6][$i]] = $matches[7][$i];
|
||||
}
|
||||
|
||||
if(isset($matches[9][$i]))
|
||||
{
|
||||
$fk[$matches[9][$i]] = $matches[10][$i];
|
||||
}
|
||||
|
||||
$fk['UPDATE'] = empty($fk['UPDATE']) ? '' : $fk['UPDATE'];
|
||||
$fk['DELETE'] = empty($fk['DELETE']) ? '' : $fk['DELETE'];
|
||||
|
||||
if(isset($this->_tables[$fromTable]) && isset($this->_tables[$toTable]))
|
||||
{
|
||||
$phpName = $this->_generateFkName($fromCol, $this->_tables[$fromTable]['php_name']);
|
||||
|
||||
$this->_tables[$fromTable]['relationships']['toOne'][$fromCol] = array('fk_name' => $fkName, 'fk_delete' => $fk['DELETE'], 'fk_update' => $fk['UPDATE'], 'table_php_name' => $this->_tables[$toTable]['php_name'], 'from_col_php' => $this->_generatePhpName($fromCol), 'from_col' => $fromCol, 'php_name' => $phpName, 'table' => $toTable, 'col' => $toCol, 'col_php' => $this->_generatePhpName($toCol));
|
||||
|
||||
$phpName = $this->_generateFkName($fromCol, $this->_tables[$fromTable]['php_name']) . $this->_tables[$fromTable]['php_name'].'s';
|
||||
$this->_tables[$toTable]['relationships']['toMany'][] = array('from_col_php' => $this->_generatePhpName($fromCol), 'php_name' => $phpName, 'thisCol' => $toCol, 'table' => $fromTable, 'table_php' => $this->_generatePhpName($fromTable), 'fromCol' => $fromCol, 'col_php' => $this->_generatePhpName($toCol));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function _getColumns()
|
||||
{
|
||||
foreach($this->_tables as $key => &$val)
|
||||
{
|
||||
$cols = array();
|
||||
foreach($this->_db->query('DESCRIBE `' . $key . '`')->fetchAll(\PDO::FETCH_ASSOC) as $column)
|
||||
{
|
||||
$col = $this->_processColumn(array(), $column, $val);
|
||||
$cols[$col['name']] = $col;
|
||||
}
|
||||
|
||||
$val['columns'] = $cols;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function _getIndexes()
|
||||
{
|
||||
foreach($this->_tables as $key => &$val)
|
||||
{
|
||||
$indexes = array();
|
||||
|
||||
foreach($this->_db->query('SHOW INDEXES FROM `' . $key . '`')->fetchAll(\PDO::FETCH_ASSOC) as $idx)
|
||||
{
|
||||
if(!isset($indexes[$idx['Key_name']]))
|
||||
{
|
||||
$indexes[$idx['Key_name']] = array();
|
||||
$indexes[$idx['Key_name']]['name'] = $idx['Key_name'];
|
||||
$indexes[$idx['Key_name']]['unique'] = ($idx['Non_unique'] == '0') ? true : false;
|
||||
$indexes[$idx['Key_name']]['columns'] = array();
|
||||
}
|
||||
|
||||
$indexes[$idx['Key_name']]['columns'][$idx['Seq_in_index']] = $idx['Column_name'];
|
||||
}
|
||||
|
||||
$indexes = array_map(function($idx)
|
||||
{
|
||||
ksort($idx['columns']);
|
||||
$idx['columns'] = implode(', ', $idx['columns']);
|
||||
|
||||
return $idx;
|
||||
}, $indexes);
|
||||
|
||||
$val['indexes'] = $indexes;
|
||||
}
|
||||
}
|
||||
|
||||
protected function _processColumn($col, $column, &$table)
|
||||
{
|
||||
$col['name'] = $column['Field'];
|
||||
$col['php_name']= $this->_generatePhpName($col['name']);
|
||||
$matches = array();
|
||||
|
||||
preg_match('/^([a-zA-Z]+)(\()?([0-9\,]+)?(\))?/', $column['Type'], $matches);
|
||||
|
||||
$col['type'] = strtolower($matches[1]);
|
||||
|
||||
if(isset($matches[3]))
|
||||
{
|
||||
$col['length'] = $matches[3];
|
||||
}
|
||||
|
||||
$col['null'] = strtolower($column['Null']) == 'yes' ? true : false;
|
||||
$col['auto'] = strtolower($column['Extra']) == 'auto_increment' ? true : false;
|
||||
|
||||
if ($column['Default'] == 'NULL' || is_null($column['Default'])) {
|
||||
$col['default_is_null'] = true;
|
||||
} else {
|
||||
$col['default_is_null'] = false;
|
||||
$col['default'] = $column['Default'];
|
||||
}
|
||||
|
||||
if(!empty($column['Key']))
|
||||
{
|
||||
if($column['Key'] == 'PRI')
|
||||
{
|
||||
$col['is_primary_key'] = true;
|
||||
$table['primary_key'] = array('column' => $col['name'], 'php_name' => $col['php_name']);
|
||||
}
|
||||
|
||||
if($column['Key'] == 'PRI' || $column['Key'] == 'UNI')
|
||||
{
|
||||
$col['unique_indexed'] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$col['many_indexed'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$col['validate']= array();
|
||||
|
||||
if(!$col['null'])
|
||||
{
|
||||
$col['validate_null'] = true;
|
||||
}
|
||||
|
||||
switch($col['type'])
|
||||
{
|
||||
case 'tinyint':
|
||||
case 'smallint':
|
||||
case 'int':
|
||||
case 'mediumint':
|
||||
case 'bigint':
|
||||
$col['php_type'] = 'int';
|
||||
$col['to_php'] = '_sqlToInt';
|
||||
$col['validate_int']= true;
|
||||
break;
|
||||
|
||||
case 'float':
|
||||
case 'decimal':
|
||||
$col['php_type'] = 'float';
|
||||
$col['to_php'] = '_sqlToFloat';
|
||||
$col['validate_float'] = true;
|
||||
break;
|
||||
|
||||
case 'datetime':
|
||||
case 'date':
|
||||
$col['php_type'] = 'DateTime';
|
||||
$col['to_php'] = '_sqlToDateTime';
|
||||
$col['to_sql'] = '_dateTimeToSql';
|
||||
$col['validate_date'] = true;
|
||||
break;
|
||||
|
||||
case 'varchar':
|
||||
case 'text':
|
||||
default:
|
||||
$col['php_type'] = 'string';
|
||||
$col['validate_string'] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return $col;
|
||||
}
|
||||
|
||||
protected function _generatePhpName($sqlName)
|
||||
{
|
||||
$rtn = $sqlName;
|
||||
$rtn = str_replace('_', ' ', $rtn);
|
||||
$rtn = ucwords($rtn);
|
||||
$rtn = str_replace(' ', '', $rtn);
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
protected function _generateFkName($sqlName, $tablePhpName)
|
||||
{
|
||||
$fkMethod = substr($sqlName, 0, strripos($sqlName, '_'));
|
||||
|
||||
if(empty($fkMethod))
|
||||
{
|
||||
$fkMethod = (substr(strtolower($sqlName), -2) == 'id') ? substr($sqlName, 0, -2) : $tablePhpName;
|
||||
}
|
||||
|
||||
$fkMethod = str_replace('_', ' ', $fkMethod);
|
||||
$fkMethod = ucwords($fkMethod);
|
||||
$fkMethod = str_replace(' ', '', $fkMethod);
|
||||
|
||||
return $fkMethod;
|
||||
}
|
||||
}
|
24
B8Framework/b8/Exception/HttpException.php
Executable file
24
B8Framework/b8/Exception/HttpException.php
Executable file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Exception;
|
||||
|
||||
class HttpException extends \Exception
|
||||
{
|
||||
protected $errorCode = 500;
|
||||
protected $statusMessage = 'Internal Server Error';
|
||||
|
||||
public function getErrorCode()
|
||||
{
|
||||
return $this->errorCode;
|
||||
}
|
||||
|
||||
public function getStatusMessage()
|
||||
{
|
||||
return $this->statusMessage;
|
||||
}
|
||||
|
||||
public function getHttpHeader()
|
||||
{
|
||||
return 'HTTP/1.1 ' . $this->errorCode . ' ' . $this->statusMessage;
|
||||
}
|
||||
}
|
10
B8Framework/b8/Exception/HttpException/BadRequestException.php
Executable file
10
B8Framework/b8/Exception/HttpException/BadRequestException.php
Executable file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Exception\HttpException;
|
||||
use b8\Exception\HttpException;
|
||||
|
||||
class BadRequestException extends HttpException
|
||||
{
|
||||
protected $errorCode = 400;
|
||||
protected $statusMessage = 'Bad Request';
|
||||
}
|
10
B8Framework/b8/Exception/HttpException/ForbiddenException.php
Executable file
10
B8Framework/b8/Exception/HttpException/ForbiddenException.php
Executable file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Exception\HttpException;
|
||||
use b8\Exception\HttpException;
|
||||
|
||||
class ForbiddenException extends HttpException
|
||||
{
|
||||
protected $errorCode = 403;
|
||||
protected $statusMessage = 'Forbidden';
|
||||
}
|
10
B8Framework/b8/Exception/HttpException/NotAuthorizedException.php
Executable file
10
B8Framework/b8/Exception/HttpException/NotAuthorizedException.php
Executable file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Exception\HttpException;
|
||||
use b8\Exception\HttpException;
|
||||
|
||||
class NotAuthorizedException extends HttpException
|
||||
{
|
||||
protected $errorCode = 401;
|
||||
protected $statusMessage = 'Not Authorized';
|
||||
}
|
10
B8Framework/b8/Exception/HttpException/NotFoundException.php
Executable file
10
B8Framework/b8/Exception/HttpException/NotFoundException.php
Executable file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Exception\HttpException;
|
||||
use b8\Exception\HttpException;
|
||||
|
||||
class NotFoundException extends HttpException
|
||||
{
|
||||
protected $errorCode = 404;
|
||||
protected $statusMessage = 'Not Found';
|
||||
}
|
8
B8Framework/b8/Exception/HttpException/ServerErrorException.php
Executable file
8
B8Framework/b8/Exception/HttpException/ServerErrorException.php
Executable file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Exception\HttpException;
|
||||
use b8\Exception\HttpException;
|
||||
|
||||
class ServerErrorException extends HttpException
|
||||
{
|
||||
}
|
10
B8Framework/b8/Exception/HttpException/ValidationException.php
Executable file
10
B8Framework/b8/Exception/HttpException/ValidationException.php
Executable file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Exception\HttpException;
|
||||
use b8\Exception\HttpException;
|
||||
|
||||
class ValidationException extends HttpException
|
||||
{
|
||||
protected $errorCode = 400;
|
||||
protected $statusMessage = 'Bad Request';
|
||||
}
|
44
B8Framework/b8/Form.php
Executable file
44
B8Framework/b8/Form.php
Executable file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
use b8\Form\FieldSet,
|
||||
b8\View;
|
||||
|
||||
class Form extends FieldSet
|
||||
{
|
||||
protected $_action = '';
|
||||
protected $_method = 'POST';
|
||||
|
||||
public function getAction()
|
||||
{
|
||||
return $this->_action;
|
||||
}
|
||||
|
||||
public function setAction($action)
|
||||
{
|
||||
$this->_action = $action;
|
||||
}
|
||||
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->_method;
|
||||
}
|
||||
|
||||
public function setMethod($method)
|
||||
{
|
||||
$this->_method = $method;
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
$view->action = $this->getAction();
|
||||
$view->method = $this->getMethod();
|
||||
|
||||
parent::_onPreRender($view);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->render();
|
||||
}
|
||||
}
|
7
B8Framework/b8/Form/ControlGroup.php
Executable file
7
B8Framework/b8/Form/ControlGroup.php
Executable file
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form;
|
||||
|
||||
class ControlGroup extends FieldSet
|
||||
{
|
||||
}
|
118
B8Framework/b8/Form/Element.php
Executable file
118
B8Framework/b8/Form/Element.php
Executable file
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form;
|
||||
|
||||
use b8\View;
|
||||
use b8\Config;
|
||||
|
||||
abstract class Element
|
||||
{
|
||||
protected $_name;
|
||||
protected $_id;
|
||||
protected $_label;
|
||||
protected $_css;
|
||||
protected $_ccss;
|
||||
protected $_parent;
|
||||
|
||||
public function __construct($name = null)
|
||||
{
|
||||
if(!is_null($name))
|
||||
{
|
||||
$this->setName($name);
|
||||
}
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->_name = strtolower(preg_replace('/([^a-zA-Z0-9_\-])/', '', $name));
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return !$this->_id ? 'element-'.$this->_name : $this->_id;
|
||||
}
|
||||
|
||||
public function setId($id)
|
||||
{
|
||||
$this->_id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabel()
|
||||
{
|
||||
return $this->_label;
|
||||
}
|
||||
|
||||
public function setLabel($label)
|
||||
{
|
||||
$this->_label = $label;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getClass()
|
||||
{
|
||||
return $this->_css;
|
||||
}
|
||||
|
||||
public function setClass($class)
|
||||
{
|
||||
$this->_css = $class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContainerClass()
|
||||
{
|
||||
return $this->_ccss;
|
||||
}
|
||||
|
||||
public function setContainerClass($class)
|
||||
{
|
||||
$this->_ccss = $class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setParent(Element $parent)
|
||||
{
|
||||
$this->_parent = $parent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render($viewFile = null)
|
||||
{
|
||||
$viewPath = Config::getInstance()->get('b8.view.path');
|
||||
|
||||
if(is_null($viewFile))
|
||||
{
|
||||
$class = explode('\\', get_called_class());
|
||||
$viewFile = end($class);
|
||||
}
|
||||
|
||||
if(file_exists($viewPath . 'Form/' . $viewFile . '.phtml'))
|
||||
{
|
||||
$view = new View('Form/' . $viewFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
$view = new View($viewFile, B8_PATH . 'Form/View/');
|
||||
}
|
||||
|
||||
$view->name = $this->getName();
|
||||
$view->id = $this->getId();
|
||||
$view->label = $this->getLabel();
|
||||
$view->css = $this->getClass();
|
||||
$view->ccss = $this->getContainerClass();
|
||||
$view->parent = $this->_parent;
|
||||
|
||||
$this->_onPreRender($view);
|
||||
|
||||
return $view->render();
|
||||
}
|
||||
|
||||
abstract protected function _onPreRender(View &$view);
|
||||
}
|
19
B8Framework/b8/Form/Element/Button.php
Executable file
19
B8Framework/b8/Form/Element/Button.php
Executable file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\Form\Input,
|
||||
b8\View;
|
||||
|
||||
class Button extends Input
|
||||
{
|
||||
public function validate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$view->type = 'button';
|
||||
}
|
||||
}
|
48
B8Framework/b8/Form/Element/Checkbox.php
Executable file
48
B8Framework/b8/Form/Element/Checkbox.php
Executable file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\View,
|
||||
b8\Form\Input;
|
||||
|
||||
class Checkbox extends Input
|
||||
{
|
||||
protected $_checked;
|
||||
protected $_checkedValue;
|
||||
|
||||
public function getCheckedValue()
|
||||
{
|
||||
return $this->_checkedValue;
|
||||
}
|
||||
|
||||
public function setCheckedValue($value)
|
||||
{
|
||||
$this->_checkedValue = $value;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
if(is_bool($value) && $value == true)
|
||||
{
|
||||
$this->_value = $this->getCheckedValue();
|
||||
$this->_checked = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if($value == $this->getCheckedValue())
|
||||
{
|
||||
$this->_value = $this->getCheckedValue();
|
||||
$this->_checked = true;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_value = $value;
|
||||
$this->_checked = false;
|
||||
}
|
||||
|
||||
public function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$view->checkedValue = $this->getCheckedValue();
|
||||
$view->checked = $this->_checked;
|
||||
}
|
||||
}
|
8
B8Framework/b8/Form/Element/CheckboxGroup.php
Executable file
8
B8Framework/b8/Form/Element/CheckboxGroup.php
Executable file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\Form\FieldSet;
|
||||
|
||||
class CheckboxGroup extends FieldSet
|
||||
{
|
||||
}
|
28
B8Framework/b8/Form/Element/Csrf.php
Executable file
28
B8Framework/b8/Form/Element/Csrf.php
Executable file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\Form\Element\Hidden,
|
||||
b8\View;
|
||||
|
||||
class Csrf extends Hidden
|
||||
{
|
||||
protected $_rows = 4;
|
||||
|
||||
public function validate()
|
||||
{
|
||||
if($this->_value != $_COOKIE[$this->getName()])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$csrf = md5(microtime(true));
|
||||
$view->csrf = $csrf;
|
||||
setcookie($this->getName(), $csrf);
|
||||
}
|
||||
}
|
18
B8Framework/b8/Form/Element/Email.php
Executable file
18
B8Framework/b8/Form/Element/Email.php
Executable file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\View;
|
||||
|
||||
class Email extends Text
|
||||
{
|
||||
public function render($viewFile = null)
|
||||
{
|
||||
return parent::render(($viewFile ? $viewFile : 'Text'));
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$view->type = 'email';
|
||||
}
|
||||
}
|
9
B8Framework/b8/Form/Element/Hidden.php
Executable file
9
B8Framework/b8/Form/Element/Hidden.php
Executable file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\Form\Input,
|
||||
b8\View;
|
||||
|
||||
class Hidden extends Input
|
||||
{
|
||||
}
|
19
B8Framework/b8/Form/Element/Password.php
Executable file
19
B8Framework/b8/Form/Element/Password.php
Executable file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\Form\Element\Text,
|
||||
b8\View;
|
||||
|
||||
class Password extends Text
|
||||
{
|
||||
public function render($viewFile = null)
|
||||
{
|
||||
return parent::render(($viewFile ? $viewFile : 'Text'));
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$view->type = 'password';
|
||||
}
|
||||
}
|
8
B8Framework/b8/Form/Element/Radio.php
Executable file
8
B8Framework/b8/Form/Element/Radio.php
Executable file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\Form\Element\Select;
|
||||
|
||||
class Radio extends Select
|
||||
{
|
||||
}
|
21
B8Framework/b8/Form/Element/Select.php
Executable file
21
B8Framework/b8/Form/Element/Select.php
Executable file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\View,
|
||||
b8\Form\Input;
|
||||
|
||||
class Select extends Input
|
||||
{
|
||||
protected $_options = array();
|
||||
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
$this->_options = $options;
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$view->options = $this->_options;
|
||||
}
|
||||
}
|
21
B8Framework/b8/Form/Element/Submit.php
Executable file
21
B8Framework/b8/Form/Element/Submit.php
Executable file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\Form\Element\Button,
|
||||
b8\View;
|
||||
|
||||
class Submit extends Button
|
||||
{
|
||||
protected $_value = 'Submit';
|
||||
|
||||
public function render($viewFile = null)
|
||||
{
|
||||
return parent::render(($viewFile ? $viewFile : 'Button'));
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$view->type = 'submit';
|
||||
}
|
||||
}
|
14
B8Framework/b8/Form/Element/Text.php
Executable file
14
B8Framework/b8/Form/Element/Text.php
Executable file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\Form\Input,
|
||||
b8\View;
|
||||
|
||||
class Text extends Input
|
||||
{
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$view->type = 'text';
|
||||
}
|
||||
}
|
26
B8Framework/b8/Form/Element/TextArea.php
Executable file
26
B8Framework/b8/Form/Element/TextArea.php
Executable file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\Form\Element\Text,
|
||||
b8\View;
|
||||
|
||||
class TextArea extends Text
|
||||
{
|
||||
protected $_rows = 4;
|
||||
|
||||
public function getRows()
|
||||
{
|
||||
return $this->_rows;
|
||||
}
|
||||
|
||||
public function setRows($rows)
|
||||
{
|
||||
$this->_rows = $rows;
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$view->rows = $this->getRows();
|
||||
}
|
||||
}
|
18
B8Framework/b8/Form/Element/Url.php
Executable file
18
B8Framework/b8/Form/Element/Url.php
Executable file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form\Element;
|
||||
use b8\View;
|
||||
|
||||
class Url extends Text
|
||||
{
|
||||
public function render($viewFile = null)
|
||||
{
|
||||
return parent::render(($viewFile ? $viewFile : 'Text'));
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
parent::_onPreRender($view);
|
||||
$view->type = 'url';
|
||||
}
|
||||
}
|
114
B8Framework/b8/Form/FieldSet.php
Executable file
114
B8Framework/b8/Form/FieldSet.php
Executable file
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form;
|
||||
use b8\Form\Element,
|
||||
b8\Form\Input,
|
||||
b8\View;
|
||||
|
||||
class FieldSet extends Element
|
||||
{
|
||||
protected $_children = array();
|
||||
|
||||
public function getValues()
|
||||
{
|
||||
$rtn = array();
|
||||
|
||||
foreach($this->_children as $field)
|
||||
{
|
||||
if($field instanceof FieldSet)
|
||||
{
|
||||
$fieldName = $field->getName();
|
||||
|
||||
if(empty($fieldName))
|
||||
{
|
||||
$rtn = array_merge($rtn, $field->getValues());
|
||||
}
|
||||
else
|
||||
{
|
||||
$rtn[$fieldName] = $field->getValues();
|
||||
}
|
||||
}
|
||||
elseif($field instanceof Input)
|
||||
{
|
||||
if($field->getName())
|
||||
{
|
||||
$rtn[$field->getName()] = $field->getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
public function setValues(array $values)
|
||||
{
|
||||
foreach($this->_children as $field)
|
||||
{
|
||||
if($field instanceof FieldSet)
|
||||
{
|
||||
$fieldName = $field->getName();
|
||||
|
||||
if(empty($fieldName) || !isset($values[$fieldName]))
|
||||
{
|
||||
$field->setValues($values);
|
||||
}
|
||||
else
|
||||
{
|
||||
$field->setValues($values[$fieldName]);
|
||||
}
|
||||
}
|
||||
elseif($field instanceof Input)
|
||||
{
|
||||
$fieldName = $field->getName();
|
||||
|
||||
if(isset($values[$fieldName]))
|
||||
{
|
||||
$field->setValue($values[$fieldName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addField(Element $field)
|
||||
{
|
||||
$this->_children[$field->getName()] = $field;
|
||||
$field->setParent($this);
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
$rtn = true;
|
||||
|
||||
foreach($this->_children as $child)
|
||||
{
|
||||
if(!$child->validate())
|
||||
{
|
||||
$rtn = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
$rendered = array();
|
||||
|
||||
foreach($this->_children as $child)
|
||||
{
|
||||
$rendered[] = $child->render();
|
||||
}
|
||||
|
||||
$view->children = $rendered;
|
||||
}
|
||||
|
||||
public function getChildren()
|
||||
{
|
||||
return $this->_children;
|
||||
}
|
||||
|
||||
public function getChild($fieldName)
|
||||
{
|
||||
return $this->_children[$fieldName];
|
||||
}
|
||||
}
|
124
B8Framework/b8/Form/Input.php
Executable file
124
B8Framework/b8/Form/Input.php
Executable file
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Form;
|
||||
use b8\Form\Element,
|
||||
b8\View;
|
||||
|
||||
class Input extends Element
|
||||
{
|
||||
protected $_required = false;
|
||||
protected $_pattern;
|
||||
protected $_validator;
|
||||
protected $_value;
|
||||
protected $_error;
|
||||
protected $_customError = false;
|
||||
|
||||
public static function create($name, $label, $required = false)
|
||||
{
|
||||
$el = new static();
|
||||
$el->setName($name);
|
||||
$el->setLabel($label);
|
||||
$el->setRequired($required);
|
||||
|
||||
return $el;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->_value;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->_value = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRequired()
|
||||
{
|
||||
return $this->_required;
|
||||
}
|
||||
|
||||
public function setRequired($required)
|
||||
{
|
||||
$this->_required = (bool)$required;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getValidator()
|
||||
{
|
||||
return $this->_validator;
|
||||
}
|
||||
|
||||
public function setValidator($validator)
|
||||
{
|
||||
if(is_callable($validator) || $validator instanceof \Closure)
|
||||
{
|
||||
$this->_validator = $validator;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPattern()
|
||||
{
|
||||
return $this->_pattern;
|
||||
}
|
||||
|
||||
public function setPattern($pattern)
|
||||
{
|
||||
$this->_pattern = $pattern;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
if($this->getRequired() && empty($this->_value))
|
||||
{
|
||||
$this->_error = $this->getLabel() . ' is required.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->getPattern() && !preg_match('/'.$this->getPattern().'/', $this->_value))
|
||||
{
|
||||
$this->_error = 'Invalid value entered.';
|
||||
return false;
|
||||
}
|
||||
|
||||
$validator = $this->getValidator();
|
||||
|
||||
if(is_callable($validator))
|
||||
{
|
||||
try
|
||||
{
|
||||
call_user_func_array($validator, array($this->_value));
|
||||
}
|
||||
catch(\Exception $ex)
|
||||
{
|
||||
$this->_error = $ex->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->_customError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setError($message)
|
||||
{
|
||||
$this->_customError = true;
|
||||
$this->_error = $message;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function _onPreRender(View &$view)
|
||||
{
|
||||
$view->value = $this->getValue();
|
||||
$view->error = $this->_error;
|
||||
$view->pattern = $this->_pattern;
|
||||
$view->required = $this->_required;
|
||||
}
|
||||
}
|
1
B8Framework/b8/Form/View/Button.phtml
Executable file
1
B8Framework/b8/Form/View/Button.phtml
Executable file
|
@ -0,0 +1 @@
|
|||
<input class="btn <?php print $css; ?>" type="<?php print $type; ?>" value="<?php print $value; ?>">
|
15
B8Framework/b8/Form/View/Checkbox.phtml
Executable file
15
B8Framework/b8/Form/View/Checkbox.phtml
Executable file
|
@ -0,0 +1,15 @@
|
|||
<?php if(!($parent instanceof \b8\Form\Element\CheckboxGroup)): ?>
|
||||
<div class="control-group <?php print $ccss ?> <?php print (isset($error) ? 'error' : ''); ?>">
|
||||
<div class="controls">
|
||||
<?php endif; ?>
|
||||
<label class="checkbox <?php print $css; ?>" for="<?php print $id ?>">
|
||||
<input type="checkbox" id="<?php print $id; ?>" name="<?php print $name; ?>" value="<?php print $checkedValue; ?>" <?php print ($checked ? 'checked' : ''); ?> <?php print $required ? 'required' : '' ?>>
|
||||
<?php print $label; ?>
|
||||
</label>
|
||||
<?php if(isset($error)): ?>
|
||||
<span class="help-block"><?php print $error; ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if(!($parent instanceof \b8\Form\Element\CheckboxGroup)): ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
11
B8Framework/b8/Form/View/CheckboxGroup.phtml
Executable file
11
B8Framework/b8/Form/View/CheckboxGroup.phtml
Executable file
|
@ -0,0 +1,11 @@
|
|||
<div class="control-group <?php print $css; ?>">
|
||||
<?php if($label): ?>
|
||||
<label class="control-label"><?php print $label; ?></label>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="controls">
|
||||
<?php foreach($children as $field): ?>
|
||||
<?php print $field; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
6
B8Framework/b8/Form/View/ControlGroup.phtml
Executable file
6
B8Framework/b8/Form/View/ControlGroup.phtml
Executable file
|
@ -0,0 +1,6 @@
|
|||
<div class="control-group <?php print $css; ?>">
|
||||
|
||||
<?php foreach($children as $field): ?>
|
||||
<?php print $field; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
1
B8Framework/b8/Form/View/Csrf.phtml
Executable file
1
B8Framework/b8/Form/View/Csrf.phtml
Executable file
|
@ -0,0 +1 @@
|
|||
<input type="hidden" id="<?php print $id; ?>" name="<?php print $name; ?>" value="<?php print $csrf; ?>">
|
9
B8Framework/b8/Form/View/FieldSet.phtml
Executable file
9
B8Framework/b8/Form/View/FieldSet.phtml
Executable file
|
@ -0,0 +1,9 @@
|
|||
<fieldset class="row <?php print $css; ?>">
|
||||
<?php if($label): ?>
|
||||
<legend><?php print $label; ?></legend>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach($children as $field): ?>
|
||||
<?php print $field; ?>
|
||||
<?php endforeach; ?>
|
||||
</fieldset>
|
6
B8Framework/b8/Form/View/Form.phtml
Executable file
6
B8Framework/b8/Form/View/Form.phtml
Executable file
|
@ -0,0 +1,6 @@
|
|||
<form id="<?php print $id; ?>" class="<?php print $css; ?>" action="<?php print $action; ?>" method="<?php print $method; ?>">
|
||||
<?php foreach($children as $field): ?>
|
||||
<?php print $field; ?>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</form>
|
1
B8Framework/b8/Form/View/Hidden.phtml
Executable file
1
B8Framework/b8/Form/View/Hidden.phtml
Executable file
|
@ -0,0 +1 @@
|
|||
<input type="hidden" id="<?php print $id; ?>" name="<?php print $name; ?>" value="<?php print $value; ?>">
|
18
B8Framework/b8/Form/View/Radio.phtml
Executable file
18
B8Framework/b8/Form/View/Radio.phtml
Executable file
|
@ -0,0 +1,18 @@
|
|||
<div id="<?php print $id; ?>" class="control-group <?php print $ccss; ?>">
|
||||
<?php if($label): ?>
|
||||
<label class="control-label"><?php print $label; ?></label>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="controls">
|
||||
<?php foreach($options as $val => $lbl): ?>
|
||||
<label class="radio" for="radio-<?php print $id; ?>-<?php print $val; ?>">
|
||||
<input type="radio" id="radio-<?php print $id; ?>-<?php print $val; ?>" class="<?php print $css; ?>" name="<?php print $name; ?>" value="<?php print $val; ?>" <?php print ($value == $val) ? ' checked="checked"' : ''; ?> <?php print $required ? 'required' : '' ?>>
|
||||
<?php print $lbl; ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if(isset($error)): ?>
|
||||
<span class="help-block"><?php print $error; ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
17
B8Framework/b8/Form/View/Select.phtml
Executable file
17
B8Framework/b8/Form/View/Select.phtml
Executable file
|
@ -0,0 +1,17 @@
|
|||
<div class="control-group <?php print $ccss; ?>">
|
||||
<?php if($label): ?>
|
||||
<label class="control-label" for="<?php print $id ?>"><?php print $label; ?></label>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="controls">
|
||||
<select id="<?php print $id; ?>" class="<?php print $css; ?>" name="<?php print $name; ?>">
|
||||
<?php foreach($options as $val => $lbl): ?>
|
||||
<option value="<?php print $val; ?>" <?php print ($value == $val) ? ' selected="selected"' : ''; ?>><?php print $lbl; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
<?php if(isset($error)): ?>
|
||||
<span class="help-block"><?php print $error; ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
13
B8Framework/b8/Form/View/Text.phtml
Executable file
13
B8Framework/b8/Form/View/Text.phtml
Executable file
|
@ -0,0 +1,13 @@
|
|||
<div class="control-group <?php print $ccss; ?> <?php print (isset($error) ? 'error' : ''); ?>">
|
||||
<?php if($label): ?>
|
||||
<label class="control-label" for="<?php print $id ?>"><?php print $label; ?></label>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="controls">
|
||||
<input id="<?php print $id; ?>" type="<?php print $type; ?>" class="<?php print $css; ?>" name="<?php print $name; ?>" <?php print isset($value) ? ' value="' . $value . '"' : '' ?> <?php print isset($pattern) ? ' pattern="' . $pattern . '"' : '' ?> <?php print $required ? ' required' : '' ?>>
|
||||
|
||||
<?php if(isset($error)): ?>
|
||||
<span class="help-block"><?php print $error; ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
13
B8Framework/b8/Form/View/TextArea.phtml
Executable file
13
B8Framework/b8/Form/View/TextArea.phtml
Executable file
|
@ -0,0 +1,13 @@
|
|||
<div class="control-group <?php print $ccss; ?> <?php print (isset($error) ? 'error' : ''); ?>">
|
||||
<?php if($label): ?>
|
||||
<label class="control-label" for="<?php print $id ?>"><?php print $label; ?></label>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="controls">
|
||||
<textarea rows="<?php print $rows; ?>" id="<?php print $id; ?>" class="<?php print $css; ?>" name="<?php print $name; ?>" <?php print $required ? ' required' : '' ?>><?php print isset($value) ? $value : '' ?></textarea>
|
||||
|
||||
<?php if(isset($error)): ?>
|
||||
<span class="help-block"><?php print $error; ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
149
B8Framework/b8/Http/Request.php
Executable file
149
B8Framework/b8/Http/Request.php
Executable file
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Http;
|
||||
|
||||
class Request
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $params = array();
|
||||
|
||||
/**
|
||||
* Request data.
|
||||
*/
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* Set up the request.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->parseInput();
|
||||
|
||||
$this->data['path'] = $this->getRequestPath();
|
||||
$this->data['parts'] = array_values(array_filter(explode('/', $this->data['path'])));
|
||||
}
|
||||
|
||||
protected function getRequestPath()
|
||||
{
|
||||
$path = '';
|
||||
|
||||
// Start out with the REQUEST_URI:
|
||||
if (!empty($_SERVER['REQUEST_URI'])) {
|
||||
$path = $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
|
||||
if ($_SERVER['SCRIPT_NAME'] != $_SERVER['REQUEST_URI']) {
|
||||
$scriptPath = str_replace('/index.php', '', $_SERVER['SCRIPT_NAME']);
|
||||
$path = str_replace($scriptPath, '', $path);
|
||||
}
|
||||
|
||||
// Remove index.php from the URL if it is present:
|
||||
$path = str_replace(array('/index.php', 'index.php'), '', $path);
|
||||
|
||||
// Also cut out the query string:
|
||||
$path = explode('?', $path);
|
||||
$path = array_shift($path);
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse incoming variables, incl. $_GET, $_POST and also reads php://input for PUT/DELETE.
|
||||
*/
|
||||
protected function parseInput()
|
||||
{
|
||||
$params = $_REQUEST;
|
||||
|
||||
if(!isset($_SERVER['REQUEST_METHOD']) || in_array($_SERVER['REQUEST_METHOD'], array('PUT', 'DELETE')))
|
||||
{
|
||||
$vars = file_get_contents('php://input');
|
||||
|
||||
if(!is_string($vars) || strlen(trim($vars)) === 0)
|
||||
{
|
||||
$vars = '';
|
||||
}
|
||||
|
||||
$inputData = array();
|
||||
parse_str($vars, $inputData);
|
||||
|
||||
$params = array_merge($params, $inputData);
|
||||
}
|
||||
|
||||
$this->setParams($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all request parameters.
|
||||
* @return array
|
||||
*/
|
||||
public function getParams()
|
||||
{
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a specific request parameter, or a default value if not set.
|
||||
*/
|
||||
public function getParam($key, $default = null)
|
||||
{
|
||||
if (isset($this->params[$key])) {
|
||||
return $this->params[$key];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or override a request parameter.
|
||||
*/
|
||||
public function setParam($key, $value = null)
|
||||
{
|
||||
$this->params[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an array of request parameters.
|
||||
*/
|
||||
public function setParams(array $params)
|
||||
{
|
||||
$this->params = array_merge($this->params, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-set a specific parameter.
|
||||
*/
|
||||
public function unsetParam($key)
|
||||
{
|
||||
unset($this->params[$key]);
|
||||
}
|
||||
|
||||
public function getMethod()
|
||||
{
|
||||
return strtoupper($_SERVER['REQUEST_METHOD']);
|
||||
}
|
||||
|
||||
public function getPath()
|
||||
{
|
||||
return $this->data['path'];
|
||||
}
|
||||
|
||||
public function getPathParts()
|
||||
{
|
||||
return $this->data['parts'];
|
||||
}
|
||||
|
||||
public function isAjax()
|
||||
{
|
||||
if (!isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
132
B8Framework/b8/Http/Response.php
Executable file
132
B8Framework/b8/Http/Response.php
Executable file
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Http;
|
||||
|
||||
class Response
|
||||
{
|
||||
protected $data = array();
|
||||
|
||||
public function __construct(Response $createFrom = null)
|
||||
{
|
||||
if (!is_null($createFrom)) {
|
||||
$this->data = $createFrom->getData();
|
||||
}
|
||||
}
|
||||
|
||||
public function hasLayout()
|
||||
{
|
||||
return !isset($this->data['layout']) ? true : $this->data['layout'];
|
||||
}
|
||||
|
||||
public function disableLayout()
|
||||
{
|
||||
$this->data['layout'] = false;
|
||||
}
|
||||
|
||||
public function enableLayout()
|
||||
{
|
||||
$this->data['layout'] = true;
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function setResponseCode($code)
|
||||
{
|
||||
$this->data['code'] = (int)$code;
|
||||
}
|
||||
|
||||
public function setHeader($key, $val)
|
||||
{
|
||||
$this->data['headers'][$key] = $val;
|
||||
}
|
||||
|
||||
public function clearHeaders()
|
||||
{
|
||||
$this->data['headers'] = array();
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->data['body'] = $content;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->data['body'];
|
||||
}
|
||||
|
||||
public function flush()
|
||||
{
|
||||
$this->sendResponseCode();
|
||||
|
||||
if (isset($this->data['headers'])) {
|
||||
foreach ($this->data['headers'] as $header => $val) {
|
||||
header($header . ': ' . $val, true);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->flushBody();
|
||||
}
|
||||
|
||||
protected function sendResponseCode()
|
||||
{
|
||||
if (!isset($this->data['code'])) {
|
||||
$this->data['code'] = 200;
|
||||
}
|
||||
|
||||
switch ($this->data['code'])
|
||||
{
|
||||
// 300 class
|
||||
case 301:
|
||||
$text = 'Moved Permanently';
|
||||
break;
|
||||
case 302:
|
||||
$text = 'Moved Temporarily';
|
||||
break;
|
||||
|
||||
// 400 class errors
|
||||
case 400:
|
||||
$text = 'Bad Request';
|
||||
break;
|
||||
case 401:
|
||||
$text = 'Not Authorized';
|
||||
break;
|
||||
case 403:
|
||||
$text = 'Forbidden';
|
||||
break;
|
||||
case 404:
|
||||
$text = 'Not Found';
|
||||
break;
|
||||
|
||||
// 500 class errors
|
||||
case 500:
|
||||
$text = 'Internal Server Error';
|
||||
break;
|
||||
|
||||
// OK
|
||||
case 200:
|
||||
default:
|
||||
$text = 'OK';
|
||||
break;
|
||||
}
|
||||
|
||||
header('HTTP/1.1 ' . $this->data['code'] . ' ' . $text, true, $this->data['code']);
|
||||
}
|
||||
|
||||
protected function flushBody()
|
||||
{
|
||||
if (isset($this->data['body'])) {
|
||||
return $this->data['body'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->flush();
|
||||
}
|
||||
}
|
30
B8Framework/b8/Http/Response/JsonResponse.php
Executable file
30
B8Framework/b8/Http/Response/JsonResponse.php
Executable file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Http\Response;
|
||||
|
||||
use b8\Http\Response;
|
||||
|
||||
class JsonResponse extends Response
|
||||
{
|
||||
public function __construct(Response $createFrom = null)
|
||||
{
|
||||
parent::__construct($createFrom);
|
||||
|
||||
$this->setContent(array());
|
||||
$this->setHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function hasLayout()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function flushBody()
|
||||
{
|
||||
if (isset($this->data['body'])) {
|
||||
return json_encode($this->data['body']);
|
||||
}
|
||||
|
||||
return json_encode(null);
|
||||
}
|
||||
}
|
27
B8Framework/b8/Http/Response/RedirectResponse.php
Executable file
27
B8Framework/b8/Http/Response/RedirectResponse.php
Executable file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Http\Response;
|
||||
|
||||
use b8\Http\Response;
|
||||
|
||||
class RedirectResponse extends Response
|
||||
{
|
||||
public function __construct(Response $createFrom = null)
|
||||
{
|
||||
parent::__construct($createFrom);
|
||||
|
||||
$this->setContent(null);
|
||||
$this->setResponseCode(302);
|
||||
}
|
||||
|
||||
public function hasLayout()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function flush()
|
||||
{
|
||||
parent::flush();
|
||||
die;
|
||||
}
|
||||
}
|
123
B8Framework/b8/Http/Router.php
Executable file
123
B8Framework/b8/Http/Router.php
Executable file
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Http;
|
||||
|
||||
use b8\Application;
|
||||
use b8\Config;
|
||||
use b8\Http\Request;
|
||||
|
||||
class Router
|
||||
{
|
||||
/**
|
||||
* @var \b8\Http\Request;
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var \b8\Http\Config;
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var \b8\Application
|
||||
*/
|
||||
protected $application;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $routes = array(array('route' => '/:controller/:action', 'callback' => null, 'defaults' => array()));
|
||||
|
||||
public function __construct(Application $application, Request $request, Config $config)
|
||||
{
|
||||
$this->application = $application;
|
||||
$this->request = $request;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function clearRoutes()
|
||||
{
|
||||
$this->routes = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $route Route definition
|
||||
* @param array $options
|
||||
* @param callable $callback
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function register($route, $options = array(), $callback = null)
|
||||
{
|
||||
if (!is_callable($callback)) {
|
||||
throw new \InvalidArgumentException('$callback must be callable.');
|
||||
}
|
||||
|
||||
array_unshift($this->routes, array('route' => $route, 'callback' => $callback, 'defaults' => $options));
|
||||
}
|
||||
|
||||
public function dispatch()
|
||||
{
|
||||
foreach ($this->routes as $route) {
|
||||
$pathParts = $this->request->getPathParts();
|
||||
|
||||
//-------
|
||||
// Set up default values for everything:
|
||||
//-------
|
||||
$thisNamespace = 'Controller';
|
||||
$thisController = null;
|
||||
$thisAction = null;
|
||||
|
||||
if (array_key_exists('namespace', $route['defaults'])) {
|
||||
$thisNamespace = $route['defaults']['namespace'];
|
||||
}
|
||||
|
||||
if (array_key_exists('controller', $route['defaults'])) {
|
||||
$thisController = $route['defaults']['controller'];
|
||||
}
|
||||
|
||||
if (array_key_exists('action', $route['defaults'])) {
|
||||
$thisAction = $route['defaults']['action'];
|
||||
}
|
||||
|
||||
$routeParts = array_filter(explode('/', $route['route']));
|
||||
$routeMatches = true;
|
||||
|
||||
while (count($routeParts)) {
|
||||
$routePart = array_shift($routeParts);
|
||||
$pathPart = array_shift($pathParts);
|
||||
|
||||
switch ($routePart) {
|
||||
case ':namespace':
|
||||
$thisNamespace = !is_null($pathPart) ? $pathPart : $thisNamespace;
|
||||
break;
|
||||
case ':controller':
|
||||
$thisController = !is_null($pathPart) ? $pathPart : $thisController;
|
||||
break;
|
||||
case ':action':
|
||||
$thisAction = !is_null($pathPart) ? $pathPart : $thisAction;
|
||||
break;
|
||||
default:
|
||||
if ($routePart != $pathPart) {
|
||||
$routeMatches = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$routeMatches || !count($pathParts)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$thisArgs = $pathParts;
|
||||
|
||||
if ($routeMatches) {
|
||||
$route = array('namespace' => $thisNamespace, 'controller' => $thisController, 'action' => $thisAction, 'args' => $thisArgs, 'callback' => $route['callback']);
|
||||
|
||||
if ($this->application->isValidRoute($route)) {
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
188
B8Framework/b8/HttpClient.php
Executable file
188
B8Framework/b8/HttpClient.php
Executable file
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
|
||||
class HttpClient
|
||||
{
|
||||
protected $_base = '';
|
||||
protected $_params = array();
|
||||
protected $_headers = array();
|
||||
|
||||
public function __construct($base = null)
|
||||
{
|
||||
$settings = Config::getInstance()->get('b8.http.client', array('base_url' => '', 'params' => array()));
|
||||
$this->_base = $settings['base_url'];
|
||||
$this->_params = isset($settings['params']) && is_array($settings['params']) ? $settings['params'] : array();
|
||||
$this->_headers = array('Content-Type: application/x-www-form-urlencoded');
|
||||
|
||||
if(!is_null($base))
|
||||
{
|
||||
$this->_base = $base;
|
||||
}
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
$this->_headers = $headers;
|
||||
}
|
||||
|
||||
public function request($method, $uri, $params = array())
|
||||
{
|
||||
// Clean incoming:
|
||||
$method = strtoupper($method);
|
||||
$getParams = $this->_params;
|
||||
|
||||
if($method == 'GET' || $method == 'DELETE')
|
||||
{
|
||||
$getParams = array_merge($getParams, $params);
|
||||
}
|
||||
else
|
||||
{
|
||||
$bodyParams = is_array($params) ? http_build_query($params) : $params;
|
||||
}
|
||||
|
||||
$getParams = http_build_query($getParams);
|
||||
|
||||
if(substr($uri, 0, 1) != '/' && !empty($this->_base))
|
||||
{
|
||||
$uri = '/' . $uri;
|
||||
}
|
||||
|
||||
// Build HTTP context array:
|
||||
$context = array();
|
||||
$context['http']['user_agent'] = 'b8/1.0';
|
||||
$context['http']['timeout'] = 30;
|
||||
$context['http']['method'] = $method;
|
||||
$context['http']['ignore_errors'] = true;
|
||||
$context['http']['header'] = implode(PHP_EOL, $this->_headers);
|
||||
|
||||
if(in_array($method, array('PUT', 'POST')))
|
||||
{
|
||||
$context['http']['content'] = $bodyParams;
|
||||
}
|
||||
|
||||
$uri .= '?' . $getParams;
|
||||
|
||||
$context = stream_context_create($context);
|
||||
$result = file_get_contents($this->_base . $uri, false, $context);
|
||||
|
||||
$res = array();
|
||||
$res['headers'] = $http_response_header;
|
||||
$res['code'] = (int)preg_replace('/HTTP\/1\.[0-1] ([0-9]+)/', '$1', $res['headers'][0]);
|
||||
$res['success'] = false;
|
||||
$res['body'] = $this->_decodeResponse($result);
|
||||
|
||||
if($res['code'] >= 200 && $res['code'] < 300)
|
||||
{
|
||||
$res['success'] = true;
|
||||
}
|
||||
|
||||
// Handle JSON responses:
|
||||
foreach($res['headers'] as $header)
|
||||
{
|
||||
if(stripos($header, 'Content-Type') !== false || stripos($header, 'b8-Type') !== false)
|
||||
{
|
||||
if(stripos($header, 'application/json') !== false)
|
||||
{
|
||||
$res['text_body'] = $res['body'];
|
||||
$res['body'] = json_decode($res['body'], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function get($uri, $params = array())
|
||||
{
|
||||
return $this->request('GET', $uri, $params);
|
||||
}
|
||||
|
||||
public function put($uri, $params = array())
|
||||
{
|
||||
return $this->request('PUT', $uri, $params);
|
||||
}
|
||||
|
||||
public function post($uri, $params = array())
|
||||
{
|
||||
return $this->request('POST', $uri, $params);
|
||||
}
|
||||
|
||||
public function delete($uri, $params = array())
|
||||
{
|
||||
return $this->request('DELETE', $uri, $params);
|
||||
}
|
||||
|
||||
protected function _decodeResponse($originalResponse)
|
||||
{
|
||||
$response = $originalResponse;
|
||||
$body = '';
|
||||
|
||||
do
|
||||
{
|
||||
$line = $this->_readChunk($response);
|
||||
|
||||
if($line == PHP_EOL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$length = hexdec(trim($line));
|
||||
|
||||
if(!is_int($length) || empty($response) || $line === false || $length < 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
$data = $this->_readChunk($response, $length);
|
||||
|
||||
// remove the amount received from the total length on the next loop
|
||||
// it'll attempt to read that much less data
|
||||
$length -= strlen($data);
|
||||
|
||||
// store in string for later use
|
||||
$body .= $data;
|
||||
|
||||
// zero or less or end of connection break
|
||||
if($length <= 0 || empty($response))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
while(true);
|
||||
|
||||
if(empty($body))
|
||||
{
|
||||
$body = $originalResponse;
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
function _readChunk(&$string, $len = 4096)
|
||||
{
|
||||
$rtn = '';
|
||||
for($i = 0; $i <= $len; $i++)
|
||||
{
|
||||
if(empty($string))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
$char = $string[0];
|
||||
$string = substr($string, 1);
|
||||
$rtn .= $char;
|
||||
|
||||
if($char == PHP_EOL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
}
|
149
B8Framework/b8/Image.php
Executable file
149
B8Framework/b8/Image.php
Executable file
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
|
||||
class Image
|
||||
{
|
||||
public static $cachePath = '/tmp/';
|
||||
public static $sourcePath = './';
|
||||
|
||||
|
||||
/**
|
||||
* @var \Imagick
|
||||
*/
|
||||
protected $source;
|
||||
|
||||
public function __construct($imagePath)
|
||||
{
|
||||
$this->setSource(new \Imagick(self::$sourcePath . $imagePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Imagick
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Imagick $image
|
||||
*/
|
||||
public function setSource(\Imagick $image)
|
||||
{
|
||||
$this->source = $image;
|
||||
}
|
||||
|
||||
public function render($media, $width, $height, $format = 'jpeg')
|
||||
{
|
||||
$cachePath = self::$cachePath . $media['fileId'] . '.' . $width . 'x' . $height . '.' . $format;
|
||||
|
||||
if(file_exists($cachePath) && 0)
|
||||
{
|
||||
$output = file_get_contents($cachePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = $this->doRender($media, $width, $height, $format);
|
||||
file_put_contents($cachePath, $output);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function doRender($media, $width, $height, $format = 'jpeg')
|
||||
{
|
||||
$focal = !empty($media['focal_point']) ? $media['focal_point'] : array(0, 0);
|
||||
$focalX = (int)$focal[0];
|
||||
$focalY = (int)$focal[1];
|
||||
|
||||
$width = (int)$width;
|
||||
$height = (int)$height;
|
||||
|
||||
$source = $this->getSource();
|
||||
$sourceWidth = $source->getImageWidth();
|
||||
$sourceHeight = $source->getImageHeight();
|
||||
$sourceRatio = $sourceWidth / $sourceHeight;
|
||||
$targetRatio = $height != 'auto' ? $width / $height : $sourceRatio;
|
||||
|
||||
$quads = $this->_getQuadrants($sourceWidth, $sourceHeight);
|
||||
|
||||
foreach($quads as $name => $l)
|
||||
{
|
||||
if($focalX >= $l[0] && $focalX <= $l[1] && $focalY >= $l[2] && $focalY <= $l[3])
|
||||
{
|
||||
$useQuad = $name;
|
||||
}
|
||||
}
|
||||
|
||||
if($sourceRatio <= $targetRatio)
|
||||
{
|
||||
$scale = $sourceWidth / $width;
|
||||
}
|
||||
else
|
||||
{
|
||||
$scale = $sourceHeight / $height;
|
||||
}
|
||||
|
||||
$resizeWidth = (int)($sourceWidth / $scale);
|
||||
$resizeHeight = (int)($sourceHeight / $scale);
|
||||
|
||||
if($height == 'auto')
|
||||
{
|
||||
$height = $resizeHeight;
|
||||
}
|
||||
|
||||
$source->scaleImage($resizeWidth, $resizeHeight);
|
||||
|
||||
switch($useQuad)
|
||||
{
|
||||
case 'top_left':
|
||||
$cropX = 0;
|
||||
$cropY = 0;
|
||||
break;
|
||||
|
||||
case 'top_right':
|
||||
$cropX = ($resizeWidth - $width);
|
||||
$cropY = 0;
|
||||
break;
|
||||
|
||||
case 'middle_left':
|
||||
$cropX = 0;
|
||||
$cropY = ($resizeHeight - $height) / 2;
|
||||
break;
|
||||
|
||||
case 'middle-right':
|
||||
$cropX = ($resizeWidth - $width);
|
||||
$cropY = ($resizeHeight - $height) / 2;
|
||||
break;
|
||||
|
||||
case 'bottom_left':
|
||||
$cropX = 0;
|
||||
$cropY = ($resizeHeight - $height);
|
||||
break;
|
||||
|
||||
case 'bottom_right':
|
||||
$cropX = ($resizeWidth - $width);
|
||||
$cropY = ($resizeHeight - $height);
|
||||
break;
|
||||
}
|
||||
|
||||
$source->cropImage($width, $height, $cropX, $cropY);
|
||||
$source->setImageFormat($format);
|
||||
|
||||
return $source;
|
||||
}
|
||||
|
||||
protected function _getQuadrants($x, $y)
|
||||
{
|
||||
$rtn = array();
|
||||
$rtn['top_left'] = array(0, $x / 2, 0, $y / 3);
|
||||
$rtn['top_right'] = array(($x / 2) + 1, $x, 0, $y / 3);
|
||||
$rtn['middle_left'] = array(0, $y / 2, ($y / 3)+1, (($y / 3) * 2));
|
||||
$rtn['middle_right'] = array(($x / 2) + 1, $x, ($y / 3)+1, (($y / 3) * 2));
|
||||
$rtn['bottom_left'] = array(0, $y / 2, (($y / 3) * 2)+1, $y);
|
||||
$rtn['bottom_right'] = array(($x / 2) + 1, $x, (($y / 3) * 2)+1, $y);
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
}
|
224
B8Framework/b8/Model.php
Executable file
224
B8Framework/b8/Model.php
Executable file
|
@ -0,0 +1,224 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
|
||||
use b8\Exception\HttpException;
|
||||
use b8\Cache;
|
||||
|
||||
class Model
|
||||
{
|
||||
public static $sleepable = array();
|
||||
protected $getters = array();
|
||||
protected $setters = array();
|
||||
protected $data = array();
|
||||
protected $modified = array();
|
||||
protected $tableName;
|
||||
protected $cache;
|
||||
|
||||
public function __construct($initialData = array())
|
||||
{
|
||||
if(is_array($initialData))
|
||||
{
|
||||
$this->data = array_merge($this->data, $initialData);
|
||||
}
|
||||
|
||||
$this->cache = Cache::getCache(Cache::TYPE_REQUEST);
|
||||
}
|
||||
|
||||
public function getTableName()
|
||||
{
|
||||
return $this->tableName;
|
||||
}
|
||||
|
||||
public function toArray($depth = 2, $currentDepth = 0)
|
||||
{
|
||||
if(isset(static::$sleepable) && is_array(static::$sleepable) && count(static::$sleepable))
|
||||
{
|
||||
$sleepable = static::$sleepable;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sleepable = array_keys($this->getters);
|
||||
}
|
||||
|
||||
$rtn = array();
|
||||
foreach($sleepable as $property)
|
||||
{
|
||||
$rtn[$property] = $this->_propertyToArray($property, $currentDepth, $depth);
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
protected function _propertyToArray($property, $currentDepth, $depth)
|
||||
{
|
||||
$rtn = null;
|
||||
|
||||
if(array_key_exists($property, $this->getters))
|
||||
{
|
||||
$method = $this->getters[$property];
|
||||
$rtn = $this->{$method}();
|
||||
|
||||
if(is_object($rtn) || is_array($rtn))
|
||||
{
|
||||
$rtn = ($depth > $currentDepth) ? $this->_valueToArray($rtn, $currentDepth, $depth) : null;
|
||||
}
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
protected function _valueToArray($value, $currentDepth, $depth)
|
||||
{
|
||||
$rtn = null;
|
||||
if(!is_null($value))
|
||||
{
|
||||
if(is_object($value) && method_exists($value, 'toArray'))
|
||||
{
|
||||
$rtn = $value->toArray($depth, $currentDepth + 1);
|
||||
}
|
||||
elseif(is_array($value))
|
||||
{
|
||||
$childArray = array();
|
||||
|
||||
foreach($value as $k => $v)
|
||||
{
|
||||
$childArray[$k] = $this->_valueToArray($v, $currentDepth + 1, $depth);
|
||||
}
|
||||
|
||||
$rtn = $childArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
$rtn = (is_string($value) && !mb_check_encoding($value, 'UTF-8')) ? mb_convert_encoding($value, 'UTF-8') : $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
public function getDataArray()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function getModified()
|
||||
{
|
||||
return $this->modified;
|
||||
}
|
||||
|
||||
public function setValues(array $values)
|
||||
{
|
||||
foreach($values as $key => $value)
|
||||
{
|
||||
if(isset($this->setters[$key]))
|
||||
{
|
||||
$func = $this->setters[$key];
|
||||
|
||||
if($value === 'null')
|
||||
{
|
||||
$value = null;
|
||||
}
|
||||
elseif($value === 'true')
|
||||
{
|
||||
$value = true;
|
||||
}
|
||||
elseif($value === 'false')
|
||||
{
|
||||
$value = false;
|
||||
}
|
||||
|
||||
$this->{$func}($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function _setModified($column)
|
||||
{
|
||||
$this->modified[$column] = $column;
|
||||
}
|
||||
|
||||
//----------------
|
||||
// Validation
|
||||
//----------------
|
||||
protected function _validateString($name, $value)
|
||||
{
|
||||
if(!is_string($value) && !is_null($value))
|
||||
{
|
||||
throw new HttpException\ValidationException($name . ' must be a string.');
|
||||
}
|
||||
}
|
||||
|
||||
protected function _validateInt($name, &$value)
|
||||
{
|
||||
if(is_bool($value))
|
||||
{
|
||||
$value = $value ? 1 : 0;
|
||||
}
|
||||
|
||||
if(!is_numeric($value) && !is_null($value))
|
||||
{
|
||||
throw new HttpException\ValidationException($name . ' must be an integer.');
|
||||
}
|
||||
|
||||
if(!is_int($value) && !is_null($value))
|
||||
{
|
||||
$value = (int)$value;
|
||||
}
|
||||
}
|
||||
|
||||
protected function _validateFloat($name, &$value)
|
||||
{
|
||||
if(!is_numeric($value) && !is_null($value))
|
||||
{
|
||||
throw new HttpException\ValidationException($name . ' must be a float.');
|
||||
}
|
||||
|
||||
if(!is_float($value) && !is_null($value))
|
||||
{
|
||||
$value = (float)$value;
|
||||
}
|
||||
}
|
||||
|
||||
protected function _validateDate($name, &$value)
|
||||
{
|
||||
if(is_string($value))
|
||||
{
|
||||
$value = empty($value) ? null : new \DateTime($value);
|
||||
}
|
||||
|
||||
if((!is_object($value) || !($value instanceof \DateTime)) && !is_null($value))
|
||||
{
|
||||
throw new HttpException\ValidationException($name . ' must be a date object.');
|
||||
}
|
||||
|
||||
|
||||
$value = empty($value) ? null : $value->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
protected function _validateNotNull($name, &$value)
|
||||
{
|
||||
if(is_null($value))
|
||||
{
|
||||
throw new HttpException\ValidationException($name . ' must not be null.');
|
||||
}
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
if (array_key_exists($key, $this->getters)) {
|
||||
$getter = $this->getters[$key];
|
||||
return $this->{$getter}();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
if (array_key_exists($key, $this->setters)) {
|
||||
$setter = $this->setters[$key];
|
||||
return $this->{$setter}($value);
|
||||
}
|
||||
}
|
||||
}
|
91
B8Framework/b8/Registry.php
Executable file
91
B8Framework/b8/Registry.php
Executable file
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
|
||||
use b8\Config;
|
||||
use b8\Http\Request;
|
||||
|
||||
if (!defined('B8_PATH')) {
|
||||
define('B8_PATH', dirname(__FILE__) . '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* b8\Registry is now deprecated in favour of using the following classes:
|
||||
* @see b8\Http\Request
|
||||
* @see b8\Http\Response
|
||||
* @see b8\Config
|
||||
*/
|
||||
class Registry
|
||||
{
|
||||
/**
|
||||
* @var \b8\Registry
|
||||
*/
|
||||
protected static $instance;
|
||||
protected $_data = array();
|
||||
protected $_params = null;
|
||||
|
||||
/**
|
||||
* @var b8\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var b8\Http\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @return Registry
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function __construct(Config $config, Request $request)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->request = $request;
|
||||
|
||||
self::$instance = $this;
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
return $this->config->get($key, $default);
|
||||
}
|
||||
|
||||
public function set($key, $value)
|
||||
{
|
||||
return $this->config->set($key, $value);
|
||||
}
|
||||
|
||||
public function setArray($array)
|
||||
{
|
||||
return $this->config->set($array);
|
||||
}
|
||||
|
||||
public function getParams()
|
||||
{
|
||||
return $this->request->getParams();
|
||||
}
|
||||
|
||||
public function getParam($key, $default)
|
||||
{
|
||||
return $this->request->getParam($key, $default);
|
||||
}
|
||||
|
||||
public function setParam($key, $value)
|
||||
{
|
||||
return $this->request->setParam($key, $value);
|
||||
}
|
||||
|
||||
public function unsetParam($key)
|
||||
{
|
||||
return $this->request->unsetParam($key);
|
||||
}
|
||||
|
||||
public function parseInput()
|
||||
{
|
||||
}
|
||||
}
|
379
B8Framework/b8/Store.php
Executable file
379
B8Framework/b8/Store.php
Executable file
|
@ -0,0 +1,379 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
use b8\Exception\HttpException;
|
||||
use b8\Database,
|
||||
b8\Model;
|
||||
|
||||
abstract class Store
|
||||
{
|
||||
protected $modelName = null;
|
||||
protected $tableName = null;
|
||||
protected $primaryKey = null;
|
||||
|
||||
/**
|
||||
* @return \b8\Model
|
||||
*/
|
||||
abstract public function getByPrimaryKey($key, $useConnection = 'read');
|
||||
|
||||
public function getWhere($where = array(), $limit = 25, $offset = 0, $joins = array(), $order = array(), $manualJoins = array(), $group = null, $manualWheres = array(), $whereType = 'AND')
|
||||
{
|
||||
$query = 'SELECT ' . $this->tableName . '.* FROM ' . $this->tableName;
|
||||
$countQuery = 'SELECT COUNT(*) AS cnt FROM ' . $this->tableName;
|
||||
|
||||
$wheres = array();
|
||||
$params = array();
|
||||
foreach($where as $key => $value)
|
||||
{
|
||||
$key = $this->fieldCheck($key);
|
||||
|
||||
if(!is_array($value))
|
||||
{
|
||||
$params[] = $value;
|
||||
$wheres[] = $key . ' = ?';
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isset($value['operator']))
|
||||
{
|
||||
if(is_array($value['value']))
|
||||
{
|
||||
if($value['operator'] == 'between')
|
||||
{
|
||||
$params[] = $value['value'][0];
|
||||
$params[] = $value['value'][1];
|
||||
$wheres[] = $key . ' BETWEEN ? AND ?';
|
||||
}
|
||||
elseif($value['operator'] == 'IN')
|
||||
{
|
||||
$in = array();
|
||||
|
||||
foreach($value['value'] as $item)
|
||||
{
|
||||
$params[] = $item;
|
||||
$in[] = '?';
|
||||
}
|
||||
|
||||
$wheres[] = $key . ' IN (' . implode(', ', $in) . ') ';
|
||||
}
|
||||
else
|
||||
{
|
||||
$ors = array();
|
||||
foreach($value['value'] as $item)
|
||||
{
|
||||
if($item == 'null')
|
||||
{
|
||||
switch($value['operator'])
|
||||
{
|
||||
case '!=':
|
||||
$ors[] = $key . ' IS NOT NULL';
|
||||
break;
|
||||
|
||||
case '==':
|
||||
default:
|
||||
$ors[] = $key . ' IS NULL';
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$params[] = $item;
|
||||
$ors[] = $this->fieldCheck($key) . ' ' . $value['operator'] . ' ?';
|
||||
}
|
||||
}
|
||||
$wheres[] = '(' . implode(' OR ', $ors) . ')';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($value['operator'] == 'like')
|
||||
{
|
||||
$params[] = '%' . $value['value'] . '%';
|
||||
$wheres[] = $key . ' ' . $value['operator'] . ' ?';
|
||||
}
|
||||
else
|
||||
{
|
||||
if($value['value'] === 'null')
|
||||
{
|
||||
switch($value['operator'])
|
||||
{
|
||||
case '!=':
|
||||
$wheres[] = $key . ' IS NOT NULL';
|
||||
break;
|
||||
|
||||
case '==':
|
||||
default:
|
||||
$wheres[] = $key . ' IS NULL';
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$params[] = $value['value'];
|
||||
$wheres[] = $key . ' ' . $value['operator'] . ' ?';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$wheres[] = $key . ' IN (' . implode(', ', array_map(array(Database::getConnection('read'), 'quote'), $value)) . ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(count($joins))
|
||||
{
|
||||
foreach($joins as $table => $join)
|
||||
{
|
||||
$query .= ' LEFT JOIN ' . $table . ' ' . $join['alias'] . ' ON ' . $join['on'] . ' ';
|
||||
$countQuery .= ' LEFT JOIN ' . $table . ' ' . $join['alias'] . ' ON ' . $join['on'] . ' ';
|
||||
}
|
||||
}
|
||||
|
||||
if(count($manualJoins))
|
||||
{
|
||||
foreach($manualJoins as $join)
|
||||
{
|
||||
$query .= ' ' . $join . ' ';
|
||||
$countQuery .= ' ' . $join . ' ';
|
||||
}
|
||||
}
|
||||
|
||||
$hasWhere = false;
|
||||
if(count($wheres))
|
||||
{
|
||||
$hasWhere = true;
|
||||
$query .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
|
||||
$countQuery .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
|
||||
}
|
||||
|
||||
if(count($manualWheres))
|
||||
{
|
||||
foreach($manualWheres as $where)
|
||||
{
|
||||
if(!$hasWhere)
|
||||
{
|
||||
$hasWhere = true;
|
||||
$query .= ' WHERE ';
|
||||
$countQuery .= ' WHERE ';
|
||||
}
|
||||
else
|
||||
{
|
||||
$query .= ' ' . $where['type'] . ' ';
|
||||
$countQuery .= ' ' . $where['type'] . ' ';
|
||||
}
|
||||
|
||||
$query .= ' ' . $where['query'];
|
||||
$countQuery .= ' ' . $where['query'];
|
||||
|
||||
if(isset($where['params']))
|
||||
{
|
||||
foreach($where['params'] as $param)
|
||||
{
|
||||
$params[] = $param;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!is_null($group))
|
||||
{
|
||||
$query .= ' GROUP BY ' . $group . ' ';
|
||||
}
|
||||
|
||||
if(count($order))
|
||||
{
|
||||
$orders = array();
|
||||
if(is_string($order) && $order == 'rand')
|
||||
{
|
||||
$query .= ' ORDER BY RAND() ';
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($order as $key => $value)
|
||||
{
|
||||
$orders[] = $this->fieldCheck($key) . ' ' . $value;
|
||||
}
|
||||
|
||||
$query .= ' ORDER BY ' . implode(', ', $orders);
|
||||
}
|
||||
}
|
||||
|
||||
if($limit)
|
||||
{
|
||||
$query .= ' LIMIT ' . $limit;
|
||||
}
|
||||
|
||||
if($offset)
|
||||
{
|
||||
$query .= ' OFFSET ' . $offset;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$stmt = Database::getConnection('read')->prepare($countQuery);
|
||||
$stmt->execute($params);
|
||||
$res = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
$count = (int)$res['cnt'];
|
||||
}
|
||||
catch(\PDOException $ex)
|
||||
{
|
||||
$count = 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$stmt = Database::getConnection('read')->prepare($query);
|
||||
$stmt->execute($params);
|
||||
$res = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$rtn = array();
|
||||
|
||||
foreach($res as $data)
|
||||
{
|
||||
$rtn[] = new $this->modelName($data);
|
||||
}
|
||||
|
||||
return array('items' => $rtn, 'count' => $count);
|
||||
}
|
||||
catch(\PDOException $ex)
|
||||
{
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
public function save(Model $obj, $saveAllColumns = false)
|
||||
{
|
||||
if(!isset($this->primaryKey))
|
||||
{
|
||||
throw new HttpException\BadRequestException('Save not implemented for this store.');
|
||||
}
|
||||
|
||||
if(!($obj instanceof $this->modelName))
|
||||
{
|
||||
throw new HttpException\BadRequestException(get_class($obj) . ' is an invalid model type for this store.');
|
||||
}
|
||||
|
||||
$data = $obj->getDataArray();
|
||||
|
||||
if(isset($data[$this->primaryKey]))
|
||||
{
|
||||
$rtn = $this->saveByUpdate($obj, $saveAllColumns);
|
||||
}
|
||||
else
|
||||
{
|
||||
$rtn = $this->saveByInsert($obj, $saveAllColumns);
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
public function saveByUpdate(Model $obj, $saveAllColumns = false)
|
||||
{
|
||||
$rtn = null;
|
||||
$data = $obj->getDataArray();
|
||||
$modified = ($saveAllColumns) ? array_keys($data) : $obj->getModified();
|
||||
|
||||
$updates = array();
|
||||
$update_params = array();
|
||||
foreach($modified as $key)
|
||||
{
|
||||
$updates[] = $key . ' = :' . $key;
|
||||
$update_params[] = array($key, $data[$key]);
|
||||
}
|
||||
|
||||
if(count($updates))
|
||||
{
|
||||
$qs = 'UPDATE ' . $this->tableName . '
|
||||
SET ' . implode(', ', $updates) . '
|
||||
WHERE ' . $this->primaryKey . ' = :primaryKey';
|
||||
$q = Database::getConnection('write')->prepare($qs);
|
||||
|
||||
foreach($update_params as $update_param)
|
||||
{
|
||||
$q->bindValue(':' . $update_param[0], $update_param[1]);
|
||||
}
|
||||
|
||||
$q->bindValue(':primaryKey', $data[$this->primaryKey]);
|
||||
$q->execute();
|
||||
|
||||
$rtn = $this->getByPrimaryKey($data[$this->primaryKey], 'write');
|
||||
}
|
||||
else
|
||||
{
|
||||
$rtn = $obj;
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
public function saveByInsert(Model $obj, $saveAllColumns = false)
|
||||
{
|
||||
$rtn = null;
|
||||
$data = $obj->getDataArray();
|
||||
$modified = ($saveAllColumns) ? array_keys($data) : $obj->getModified();
|
||||
|
||||
$cols = array();
|
||||
$values = array();
|
||||
$qParams = array();
|
||||
foreach($modified as $key)
|
||||
{
|
||||
$cols[] = $key;
|
||||
$values[] = ':' . $key;
|
||||
$qParams[':' . $key] = $data[$key];
|
||||
}
|
||||
|
||||
if(count($cols))
|
||||
{
|
||||
$qs = 'INSERT INTO ' . $this->tableName . ' (' . implode(', ', $cols) . ') VALUES (' . implode(', ', $values) . ')';
|
||||
$q = Database::getConnection('write')->prepare($qs);
|
||||
|
||||
if($q->execute($qParams))
|
||||
{
|
||||
$id = !empty($data[$this->primaryKey]) ? $data[$this->primaryKey] : Database::getConnection('write')->lastInsertId();
|
||||
$rtn = $this->getByPrimaryKey($id, 'write');
|
||||
}
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
public function delete(Model $obj)
|
||||
{
|
||||
if(!isset($this->primaryKey))
|
||||
{
|
||||
throw new HttpException\BadRequestException('Delete not implemented for this store.');
|
||||
}
|
||||
|
||||
if(!($obj instanceof $this->modelName))
|
||||
{
|
||||
throw new HttpException\BadRequestException(get_class($obj) . ' is an invalid model type for this store.');
|
||||
}
|
||||
|
||||
$data = $obj->getDataArray();
|
||||
|
||||
$q = Database::getConnection('write')->prepare('DELETE FROM ' . $this->tableName . ' WHERE ' . $this->primaryKey . ' = :primaryKey');
|
||||
$q->bindValue(':primaryKey', $data[$this->primaryKey]);
|
||||
$q->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected function fieldCheck($field)
|
||||
{
|
||||
if(empty($field))
|
||||
{
|
||||
throw new HttpException('You cannot have an empty field name.');
|
||||
}
|
||||
|
||||
if(strpos($field, '.') === false)
|
||||
{
|
||||
return $this->tableName . '.' . $field;
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
||||
}
|
65
B8Framework/b8/Store/Factory.php
Executable file
65
B8Framework/b8/Store/Factory.php
Executable file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Store;
|
||||
use b8\Config;
|
||||
|
||||
class Factory
|
||||
{
|
||||
/**
|
||||
* @var \b8\Store\Factory
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* A collection of the stores currently loaded by the factory.
|
||||
* @var \b8\Store[]
|
||||
*/
|
||||
protected $loadedStores = array();
|
||||
|
||||
/**
|
||||
* @return Factory
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if(!isset(self::$instance))
|
||||
{
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $storeName string Store name (should match a model name).
|
||||
*
|
||||
* @return \b8\Store
|
||||
*/
|
||||
public static function getStore($storeName, $namespace = null)
|
||||
{
|
||||
$factory = self::getInstance();
|
||||
return $factory->loadStore($storeName, $namespace);
|
||||
}
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $store
|
||||
*
|
||||
* @return \b8\Store;
|
||||
*/
|
||||
public function loadStore($store, $namespace = null)
|
||||
{
|
||||
if(!isset($this->loadedStores[$store]))
|
||||
{
|
||||
$namespace = is_null($namespace) ? Config::getInstance()->get('b8.app.namespace') : $namespace;
|
||||
$class = $namespace . '\\Store\\' . $store . 'Store';
|
||||
$obj = new $class();
|
||||
|
||||
$this->loadedStores[$store] = $obj;
|
||||
}
|
||||
|
||||
return $this->loadedStores[$store];
|
||||
}
|
||||
}
|
17
B8Framework/b8/Type/Cache.php
Executable file
17
B8Framework/b8/Type/Cache.php
Executable file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Type;
|
||||
|
||||
interface Cache
|
||||
{
|
||||
public function get($key, $default = null);
|
||||
public function set($key, $value = null, $ttl = 0);
|
||||
public function delete($key);
|
||||
public function contains($key);
|
||||
public function isEnabled();
|
||||
|
||||
public function __get($key);
|
||||
public function __set($key, $value = null);
|
||||
public function __unset($key);
|
||||
public function __isset($key);
|
||||
}
|
8
B8Framework/b8/Type/RestUser.php
Executable file
8
B8Framework/b8/Type/RestUser.php
Executable file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace b8\Type;
|
||||
|
||||
interface RestUser
|
||||
{
|
||||
public function checkPermission($permission, $resource);
|
||||
}
|
86
B8Framework/b8/View.php
Executable file
86
B8Framework/b8/View.php
Executable file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace b8;
|
||||
use b8\Exception\HttpException;
|
||||
|
||||
class View
|
||||
{
|
||||
protected $_vars = array();
|
||||
protected static $_helpers = array();
|
||||
protected static $extension = 'phtml';
|
||||
|
||||
public function __construct($file, $path = null)
|
||||
{
|
||||
if (!self::exists($file, $path)) {
|
||||
throw new \Exception('View file does not exist: ' . $file);
|
||||
}
|
||||
|
||||
$this->viewFile = self::getViewFile($file, $path);
|
||||
}
|
||||
|
||||
protected static function getViewFile($file, $path = null)
|
||||
{
|
||||
$viewPath = is_null($path) ? Config::getInstance()->get('b8.view.path') : $path;
|
||||
$fullPath = $viewPath . $file . '.' . static::$extension;
|
||||
|
||||
return $fullPath;
|
||||
}
|
||||
|
||||
public static function exists($file, $path = null)
|
||||
{
|
||||
if (!file_exists(self::getViewFile($file, $path))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function __isset($var)
|
||||
{
|
||||
return isset($this->_vars[$var]);
|
||||
}
|
||||
|
||||
public function __get($var)
|
||||
{
|
||||
return $this->_vars[$var];
|
||||
}
|
||||
|
||||
public function __set($var, $val)
|
||||
{
|
||||
$this->_vars[$var] = $val;
|
||||
}
|
||||
|
||||
public function __call($method, $params = array())
|
||||
{
|
||||
if(!isset(self::$_helpers[$method]))
|
||||
{
|
||||
$class = '\\' . Config::getInstance()->get('b8.app.namespace') . '\\Helper\\' . $method;
|
||||
|
||||
if(!class_exists($class))
|
||||
{
|
||||
$class = '\\b8\\View\\Helper\\' . $method;
|
||||
}
|
||||
|
||||
if(!class_exists($class))
|
||||
{
|
||||
throw new HttpException('Helper class does not exist: ' . $class);
|
||||
}
|
||||
|
||||
self::$_helpers[$method] = new $class();
|
||||
}
|
||||
|
||||
return self::$_helpers[$method];
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
extract($this->_vars);
|
||||
|
||||
ob_start();
|
||||
require($this->viewFile);
|
||||
$html = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
11
B8Framework/b8/View/Helper/Format.php
Executable file
11
B8Framework/b8/View/Helper/Format.php
Executable file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace b8\View\Helper;
|
||||
|
||||
class Format
|
||||
{
|
||||
public function Currency($number, $symbol = true)
|
||||
{
|
||||
return ($symbol ? '£' : '') . number_format($number, 2, '.', ',');
|
||||
}
|
||||
}
|
544
B8Framework/b8/View/Template.php
Executable file
544
B8Framework/b8/View/Template.php
Executable file
|
@ -0,0 +1,544 @@
|
|||
<?php
|
||||
|
||||
namespace b8\View;
|
||||
use b8\View;
|
||||
|
||||
class Template extends View
|
||||
{
|
||||
public static $templateFunctions = array();
|
||||
protected static $extension = 'html';
|
||||
|
||||
public function __construct($viewCode)
|
||||
{
|
||||
$this->viewCode = $viewCode;
|
||||
|
||||
if (!count(self::$templateFunctions)) {
|
||||
self::$templateFunctions = array('include' => array($this, 'includeTemplate'), 'call' => array($this, 'callHelperFunction'));
|
||||
}
|
||||
}
|
||||
|
||||
public static function createFromFile($file, $path = null)
|
||||
{
|
||||
if (!static::exists($file, $path)) {
|
||||
throw new \Exception('View file does not exist: ' . $file);
|
||||
}
|
||||
|
||||
$viewFile = static::getViewFile($file, $path);
|
||||
return new static(file_get_contents($viewFile));
|
||||
}
|
||||
|
||||
public static function createFromString($string)
|
||||
{
|
||||
return new static($string);
|
||||
}
|
||||
|
||||
public function addFunction($name, $handler)
|
||||
{
|
||||
self::$templateFunctions[$name] = $handler;
|
||||
}
|
||||
|
||||
public function removeFunction($name)
|
||||
{
|
||||
unset(self::$templateFunctions[$name]);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return $this->parse($this->viewCode);
|
||||
}
|
||||
|
||||
protected function parse($string)
|
||||
{
|
||||
$lastCond = null;
|
||||
$keywords = array('ifnot', 'if', 'else', 'for', 'loop', '@', '/ifnot', '/if', '/for', '/loop');
|
||||
|
||||
foreach (self::$templateFunctions as $function => $handler) {
|
||||
$keywords[] = $function;
|
||||
}
|
||||
|
||||
$stack = array('children' => array(array('type' => 'string', 'body' => '')));
|
||||
$stack['children'][0]['parent'] =& $stack;
|
||||
$current =& $stack['children'][0];
|
||||
|
||||
while (!empty($string)) {
|
||||
$current['body'] .= $this->readUntil('{', $string);
|
||||
|
||||
if (!empty($string)) {
|
||||
$gotKeyword = false;
|
||||
|
||||
foreach($keywords as $keyword) {
|
||||
$kwLen = strlen($keyword) + 1;
|
||||
|
||||
if (substr($string, 0, $kwLen) == '{' . $keyword) {
|
||||
$gotKeyword = true;
|
||||
$item = array('type' => $keyword, 'cond' => '', 'children' => '');
|
||||
$string = substr($string, $kwLen);
|
||||
|
||||
$cond = trim($this->readUntil('}', $string));
|
||||
$item['cond'] = $cond;
|
||||
$lastCond = $cond;
|
||||
$string = substr($string, 1);
|
||||
|
||||
if (array_key_exists($keyword, self::$templateFunctions)) {
|
||||
$item['function_name'] = $keyword;
|
||||
$item['type'] = 'function';
|
||||
}
|
||||
|
||||
$str = array('type' => 'string', 'body' => '');
|
||||
$parent =& $current['parent'];
|
||||
|
||||
if (substr($current['body'], (0 - strlen(PHP_EOL))) === PHP_EOL) {
|
||||
$current['body'] = substr($current['body'], 0, strlen($current['body']) - strlen(PHP_EOL));
|
||||
}
|
||||
|
||||
$item['parent'] =& $parent;
|
||||
|
||||
$parent['children'][] = $item;
|
||||
|
||||
if ($keyword == '@' || $item['type'] == 'function') {
|
||||
// If we're processing a variable, add a string to the parent and move up to that as current.
|
||||
$parent['children'][] = $str;
|
||||
$current =& $parent['children'][count($parent['children']) - 1];
|
||||
$current['parent'] =& $parent;
|
||||
} elseif (substr($keyword, 0, 1) == '/') {
|
||||
// If we're processing the end of a block (if/loop), add a string to the parent's parent and move up to that.
|
||||
$parent =& $parent['parent'];
|
||||
$parent['children'][] = $str;
|
||||
$current =& $parent['children'][count($parent['children']) - 1];
|
||||
$current['parent'] =& $parent;
|
||||
} else {
|
||||
$parent['children'][count($parent['children']) - 1]['children'][] = $str;
|
||||
$current =& $parent['children'][count($parent['children']) - 1]['children'][0];
|
||||
$current['parent'] =& $parent['children'][count($parent['children']) - 1];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$gotKeyword) {
|
||||
$current['body'] .= substr($string, 0, 1);
|
||||
$string = substr($string, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->processStack($stack);
|
||||
}
|
||||
|
||||
protected function processStack($stack)
|
||||
{
|
||||
$res = '';
|
||||
|
||||
while (count($stack['children'])) {
|
||||
$current = array_shift($stack['children']);
|
||||
|
||||
switch ($current['type']) {
|
||||
case 'string':
|
||||
$res .= $current['body'];
|
||||
break;
|
||||
|
||||
case '@':
|
||||
$res .= $this->doParseVar($current['cond']);
|
||||
break;
|
||||
|
||||
case 'if':
|
||||
$res .= $this->doParseIf($current['cond'], $current);
|
||||
break;
|
||||
|
||||
case 'ifnot':
|
||||
$res .= $this->doParseIfNot($current['cond'], $current);
|
||||
break;
|
||||
|
||||
case 'loop':
|
||||
$res .= $this->doParseLoop($current['cond'], $current);
|
||||
break;
|
||||
|
||||
case 'for':
|
||||
$res .= $this->doParseFor($current['cond'], $current);
|
||||
break;
|
||||
|
||||
case 'function':
|
||||
$res .= $this->doParseFunction($current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
protected function readUntil($until, &$string)
|
||||
{
|
||||
$read = '';
|
||||
|
||||
while (!empty($string)) {
|
||||
$char = substr($string, 0, 1);
|
||||
|
||||
if ($char == $until) {
|
||||
break;
|
||||
}
|
||||
|
||||
$read .= $char;
|
||||
$string = substr($string, 1);
|
||||
}
|
||||
|
||||
return $read;
|
||||
}
|
||||
|
||||
protected function doParseVar($var)
|
||||
{
|
||||
if($var == 'year')
|
||||
{
|
||||
return date('Y');
|
||||
}
|
||||
|
||||
$val = $this->processVariableName($var);
|
||||
return $val;
|
||||
}
|
||||
|
||||
protected function doParseIf($condition, $stack)
|
||||
{
|
||||
if ($this->ifConditionIsTrue($condition)) {
|
||||
return $this->processStack($stack);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
protected function doParseIfNot($condition, $stack)
|
||||
{
|
||||
if (!$this->ifConditionIsTrue($condition)) {
|
||||
return $this->processStack($stack);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
protected function ifConditionIsTrue($condition)
|
||||
{
|
||||
$matches = array();
|
||||
|
||||
if (preg_match('/([a-zA-Z0-9_\-\(\):\s.\"]+)\s+?([\!\=\<\>]+)?\s+?([a-zA-Z0-9\(\)_\-:\s.\"]+)?/', $condition, $matches)) {
|
||||
$left = is_numeric($matches[1]) ? intval($matches[1]) : $this->processVariableName($matches[1]);
|
||||
$right = is_numeric($matches[3]) ? intval($matches[3]) : $this->processVariableName($matches[3]);
|
||||
$operator = $matches[2];
|
||||
|
||||
switch ($operator) {
|
||||
case '==':
|
||||
case '=':
|
||||
return ($left == $right);
|
||||
|
||||
case '!=':
|
||||
return ($left != $right);
|
||||
|
||||
case '>=':
|
||||
return ($left >= $right);
|
||||
|
||||
case '<=':
|
||||
return ($left <= $right);
|
||||
|
||||
case '>':
|
||||
return ($left > $right);
|
||||
|
||||
case '<':
|
||||
return ($left < $right);
|
||||
}
|
||||
} elseif (preg_match('/([a-zA-Z0-9_\-\(\):\s.]+)/', $condition, $matches)) {
|
||||
return $this->processVariableName($condition) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function doParseLoop($var, $stack)
|
||||
{
|
||||
$working = $this->processVariableName($var);
|
||||
|
||||
if(is_null($working))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
if(!is_array($working))
|
||||
{
|
||||
$working = array($working);
|
||||
}
|
||||
|
||||
$rtn = '';
|
||||
foreach ($working as $key => $val) {
|
||||
// Make sure we support nesting loops:
|
||||
$keyWas = isset($this->key) ? $this->key : null;
|
||||
$valWas = isset($this->value) ? $this->value : null;
|
||||
$itemWas = isset($this->item) ? $this->item : null;
|
||||
|
||||
// Set up the necessary variables within the stack:
|
||||
$this->parent = $this;
|
||||
$this->item = $val;
|
||||
$this->key = $key;
|
||||
$this->value = $val;
|
||||
$rtn .= $this->processStack($stack);
|
||||
|
||||
// Restore state for any parent nested loops:
|
||||
$this->item = $itemWas;
|
||||
$this->key = $keyWas;
|
||||
$this->value = $valWas;
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes loops in templates, of the following styles:
|
||||
*
|
||||
* <code>
|
||||
* {for myarray.items}
|
||||
* {@item.title}
|
||||
* {/for}
|
||||
* </code>
|
||||
*
|
||||
* Or:
|
||||
*
|
||||
* <code>
|
||||
* {for 0:pages.count; i++}
|
||||
* <a href="/item/{@i}">{@i}</a>
|
||||
* {/for}
|
||||
* </code>
|
||||
*
|
||||
* @param $cond string The condition string for the loop, to be parsed (e.g. "myarray.items" or "0:pages.count; i++")
|
||||
* @param $stack string The child stack for this loop, to be processed for each item.
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function doParseFor($cond, $stack)
|
||||
{
|
||||
// If this is a simple foreach loop, jump over to parse loop:
|
||||
if (strpos($cond, ';') === false) {
|
||||
return $this->doParseLoop($cond, $stack);
|
||||
}
|
||||
|
||||
// Otherwise, process as a for loop:
|
||||
$parts = explode(';', $cond);
|
||||
$range = explode(':', trim($parts[0]));
|
||||
|
||||
// Process range:
|
||||
$rangeLeft = $this->getForRangePart($range[0]);
|
||||
$rangeRight = $this->getForRangePart($range[1]);
|
||||
|
||||
// Process variable & incrementor / decrementor:
|
||||
$parts[1] = trim($parts[1]);
|
||||
|
||||
$matches = array();
|
||||
if (preg_match('/([a-zA-Z0-9_]+)(\+\+|\-\-)/', $parts[1], $matches)) {
|
||||
$varName = $matches[1];
|
||||
$direction = $matches[2] == '++' ? 'increment' : 'decrement';
|
||||
} else {
|
||||
throw new \Exception('Syntax error in for loop: ' . $cond);
|
||||
}
|
||||
|
||||
$rtn = '';
|
||||
|
||||
if ($direction == 'increment') {
|
||||
for ($i = $rangeLeft; $i < $rangeRight; $i++) {
|
||||
$this->parent = $this;
|
||||
$this->{$varName} = $i;
|
||||
$rtn .= $this->processStack($stack);
|
||||
}
|
||||
} else {
|
||||
for ($i = $rangeLeft; $i > $rangeRight; $i--) {
|
||||
$this->parent = $this;
|
||||
$this->{$varName} = $i;
|
||||
$rtn .= $this->processStack($stack);
|
||||
}
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
protected function getForRangePart($part)
|
||||
{
|
||||
if (is_numeric($part)) {
|
||||
return intval($part);
|
||||
}
|
||||
|
||||
$varPart = $this->processVariableName($part);
|
||||
|
||||
if (is_numeric($varPart)) {
|
||||
return intval($varPart);
|
||||
}
|
||||
|
||||
throw new \Exception('Invalid range in for loop: ' . $part);
|
||||
}
|
||||
|
||||
public function processVariableName($varName)
|
||||
{
|
||||
// Case one - Test for function calls:
|
||||
if (substr($varName, 0, 1) == '(' && substr($varName, -1) == ')') {
|
||||
|
||||
$functionCall = substr($varName, 1, -1);
|
||||
$parts = explode(' ', $functionCall, 2);
|
||||
$functionName = $parts[0];
|
||||
$arguments = isset($parts[1]) ? $parts[1] : null;
|
||||
|
||||
return $this->executeTemplateFunction($functionName, $arguments);
|
||||
}
|
||||
|
||||
// Case two - Test if it is just a string:
|
||||
if (substr($varName, 0, 1) == '"' && substr($varName, -1) == '"') {
|
||||
return substr($varName, 1, -1);
|
||||
}
|
||||
|
||||
// Case three - Test if it is just a number:
|
||||
if (is_numeric($varName)) {
|
||||
return $varName;
|
||||
}
|
||||
|
||||
// Case four - Test for helper calls:
|
||||
if (strpos($varName, ':') !== false) {
|
||||
list($helper, $property) = explode(':', $varName);
|
||||
|
||||
$helper = $this->{$helper}();
|
||||
|
||||
if (property_exists($helper, $property) || method_exists($helper, '__get')) {
|
||||
return $helper->{$property};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Case five - Process as a variable:
|
||||
$varPart = explode('.', $varName);
|
||||
$thisPart = array_shift($varPart);
|
||||
|
||||
|
||||
if(!array_key_exists($thisPart, $this->_vars))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$working = $this->{$thisPart};
|
||||
|
||||
while(count($varPart))
|
||||
{
|
||||
$thisPart = array_shift($varPart);
|
||||
|
||||
if(is_object($working)) {
|
||||
// Check if we're working with an actual property:
|
||||
if (property_exists($working, $thisPart)) {
|
||||
$working = $working->{$thisPart};
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the object has a magic __get method:
|
||||
if (method_exists($working, '__get')) {
|
||||
$working = $working->{$thisPart};
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(is_array($working) && array_key_exists($thisPart, $working))
|
||||
{
|
||||
$working = $working[$thisPart];
|
||||
continue;
|
||||
}
|
||||
|
||||
if($thisPart == 'toLowerCase')
|
||||
{
|
||||
$working = strtolower($working);
|
||||
continue;
|
||||
}
|
||||
|
||||
if($thisPart == 'toUpperCase')
|
||||
{
|
||||
$working = strtoupper($working);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($thisPart == 'isNumeric')
|
||||
{
|
||||
return is_numeric($working);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $working;
|
||||
}
|
||||
|
||||
protected function doParseFunction($stack)
|
||||
{
|
||||
return $this->executeTemplateFunction($stack['function_name'], $stack['cond']);
|
||||
}
|
||||
|
||||
protected function executeTemplateFunction($function, $args)
|
||||
{
|
||||
if (array_key_exists($function, self::$templateFunctions)) {
|
||||
$handler = self::$templateFunctions[$function];
|
||||
$args = $this->processFunctionArguments($args);
|
||||
return $handler($args, $this);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function processFunctionArguments($args)
|
||||
{
|
||||
$rtn = array();
|
||||
|
||||
$args = explode(';', $args);
|
||||
|
||||
foreach ($args as $arg) {
|
||||
$arg = explode(':', $arg);
|
||||
|
||||
if (count($arg) == 2) {
|
||||
|
||||
$key = trim($arg[0]);
|
||||
$val = trim($arg[1]);
|
||||
|
||||
if (strpos($val, ',') !== false) {
|
||||
$val = explode(',', $val);
|
||||
}
|
||||
|
||||
$rtn[$key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
return $rtn;
|
||||
}
|
||||
|
||||
public function getVariable($variable)
|
||||
{
|
||||
return $this->processVariableName($variable);
|
||||
}
|
||||
|
||||
protected function includeTemplate($args, $view)
|
||||
{
|
||||
$template = static::createFromFile($view->getVariable($args['template']));
|
||||
|
||||
if (isset($args['variables'])) {
|
||||
if (!is_array($args['variables'])) {
|
||||
$args['variables'] = array($args['variables']);
|
||||
}
|
||||
|
||||
foreach ($args['variables'] as $variable) {
|
||||
|
||||
$variable = explode('=>', $variable);
|
||||
$variable = array_map('trim', $variable);
|
||||
|
||||
if (count($variable) == 1) {
|
||||
$template->{$variable[0]} = $view->getVariable($variable[0]);
|
||||
} else {
|
||||
$template->{$variable[1]} = $view->getVariable($variable[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $template->render();
|
||||
}
|
||||
|
||||
protected function callHelperFunction($args)
|
||||
{
|
||||
$helper = $args['helper'];
|
||||
$function = $args['method'];
|
||||
|
||||
return $this->{$helper}()->{$function}();
|
||||
}
|
||||
}
|
14
B8Framework/b8/View/UserView.php
Executable file
14
B8Framework/b8/View/UserView.php
Executable file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace b8\View;
|
||||
|
||||
use b8\View\Template;
|
||||
|
||||
class UserView extends Template
|
||||
{
|
||||
public function __construct($string)
|
||||
{
|
||||
trigger_error('Use of UserView is now deprecated. Please use Template instead.', E_USER_NOTICE);
|
||||
parent::__construct($string);
|
||||
}
|
||||
}
|
22
B8Framework/composer.json
Executable file
22
B8Framework/composer.json
Executable file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "block8/b8framework",
|
||||
"type": "library",
|
||||
"description": "Simple, lightweight framework for high-throughput applications",
|
||||
"keywords": ["php", "framework", "b8", "block8", "lightweight", "mvc"],
|
||||
"homepage": "https://github.com/block8/b8framework",
|
||||
"license": "BSD",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Block 8 Limited",
|
||||
"email": "hello@block8.co.uk",
|
||||
"homepage": "http://www.block8.co.uk"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"symfony/yaml": "2.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "b8": "" }
|
||||
}
|
||||
}
|
12
B8Framework/phpci.yml
Executable file
12
B8Framework/phpci.yml
Executable file
|
@ -0,0 +1,12 @@
|
|||
build_settings:
|
||||
ignore:
|
||||
- "vendor"
|
||||
- "tests"
|
||||
irc:
|
||||
server: "irc.freenode.net"
|
||||
port: 6667
|
||||
room: "#phpci"
|
||||
nick: "phpcidev"
|
||||
|
||||
test:
|
||||
lint:
|
40
B8Framework/tests/CacheTest.php
Executable file
40
B8Framework/tests/CacheTest.php
Executable file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/../b8/Registry.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Cache.php');
|
||||
|
||||
use b8\Registry,
|
||||
b8\Cache;
|
||||
|
||||
class CacheTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreateSingleton()
|
||||
{
|
||||
$cache = b8\Cache::getInstance();
|
||||
$this->assertTrue($cache instanceof Cache);
|
||||
}
|
||||
|
||||
public function testDisableCaching()
|
||||
{
|
||||
b8\Registry::getInstance()->set('DisableCaching', true);
|
||||
|
||||
$cache = b8\Cache::getInstance();
|
||||
$this->assertFalse($cache->isEnabled());
|
||||
$this->assertFalse($cache->set('anything', 10));
|
||||
$this->assertTrue(is_null($cache->get('anything')));
|
||||
|
||||
b8\Registry::getInstance()->set('DisableCaching', false);
|
||||
}
|
||||
|
||||
public function testCaching()
|
||||
{
|
||||
$cache = b8\Cache::getInstance();
|
||||
|
||||
if($cache->isEnabled())
|
||||
{
|
||||
$this->assertTrue($cache->set('anything', 10));
|
||||
$this->assertTrue($cache->get('anything') == 10);
|
||||
$this->assertTrue(is_null($cache->get('invalid')));
|
||||
}
|
||||
}
|
||||
}
|
641
B8Framework/tests/CodeGenerationTest.php
Executable file
641
B8Framework/tests/CodeGenerationTest.php
Executable file
|
@ -0,0 +1,641 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/../b8/Registry.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Model.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Controller.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Controller/RestController.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Store.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Store/Factory.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Database.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/View.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/View/UserView.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Database/Map.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Database/Generator.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Database/CodeGenerator.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException/ValidationException.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException/BadRequestException.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException/ForbiddenException.php');
|
||||
|
||||
use b8\Database\Generator,
|
||||
b8\Database\CodeGenerator,
|
||||
b8\Database,
|
||||
b8\Registry;
|
||||
|
||||
class CodeGenerationTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected static $_db;
|
||||
protected static $_base;
|
||||
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
Database::setDetails('b8_test_' . getenv('PHPCI_BUILD'), 'b8_test', 'b8_test');
|
||||
Database::setWriteServers(array('localhost'));
|
||||
Database::setReadServers(array('localhost'));
|
||||
|
||||
Registry::getInstance()->set('b8.app.namespace', 'Generation');
|
||||
|
||||
self::$_db = Database::getConnection('write');
|
||||
|
||||
self::$_db->query('DROP TABLE IF EXISTS tres');
|
||||
self::$_db->query('DROP TABLE IF EXISTS dos');
|
||||
self::$_db->query('DROP TABLE IF EXISTS uno');
|
||||
|
||||
self::$_base = dirname(__FILE__) . '/data/generation/';
|
||||
$gen = new Generator(self::$_db, 'Test', self::$_base .'models/');
|
||||
$gen->generate();
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass()
|
||||
{
|
||||
self::$_db->query('DROP TABLE IF EXISTS tres');
|
||||
self::$_db->query('DROP TABLE IF EXISTS dos');
|
||||
self::$_db->query('DROP TABLE IF EXISTS uno');
|
||||
|
||||
unlink(self::$_base . 'Generation/Model/Base/UnoBase.php');
|
||||
unlink(self::$_base . 'Generation/Model/Base/DosBase.php');
|
||||
unlink(self::$_base . 'Generation/Model/Base/TresBase.php');
|
||||
unlink(self::$_base . 'Generation/Store/Base/UnoStoreBase.php');
|
||||
unlink(self::$_base . 'Generation/Store/Base/DosStoreBase.php');
|
||||
unlink(self::$_base . 'Generation/Store/Base/TresStoreBase.php');
|
||||
unlink(self::$_base . 'Generation/Controller/Base/UnoControllerBase.php');
|
||||
unlink(self::$_base . 'Generation/Controller/Base/DosControllerBase.php');
|
||||
unlink(self::$_base . 'Generation/Controller/Base/TresControllerBase.php');
|
||||
unlink(self::$_base . 'Generation/Model/Uno.php');
|
||||
unlink(self::$_base . 'Generation/Model/Dos.php');
|
||||
unlink(self::$_base . 'Generation/Model/Tres.php');
|
||||
unlink(self::$_base . 'Generation/Store/UnoStore.php');
|
||||
unlink(self::$_base . 'Generation/Store/DosStore.php');
|
||||
unlink(self::$_base . 'Generation/Store/TresStore.php');
|
||||
unlink(self::$_base . 'Generation/Controller/UnoController.php');
|
||||
unlink(self::$_base . 'Generation/Controller/DosController.php');
|
||||
unlink(self::$_base . 'Generation/Controller/TresController.php');
|
||||
}
|
||||
|
||||
public function testGenerate()
|
||||
{
|
||||
error_reporting(E_ALL);
|
||||
$codeGenerator = new CodeGenerator(self::$_db, 'Generation', self::$_base . 'Generation/');
|
||||
$codeGenerator->generateModels();
|
||||
$codeGenerator->generateStores();
|
||||
$codeGenerator->generateControllers();
|
||||
|
||||
$this->assertFileExists(self::$_base . 'Generation/Model/Base/UnoBase.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Model/Base/DosBase.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Model/Base/TresBase.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Store/Base/UnoStoreBase.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Store/Base/DosStoreBase.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Store/Base/TresStoreBase.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Controller/Base/UnoControllerBase.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Controller/Base/DosControllerBase.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Controller/Base/TresControllerBase.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Model/Uno.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Model/Dos.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Model/Tres.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Store/UnoStore.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Store/DosStore.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Store/TresStore.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Controller/UnoController.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Controller/DosController.php');
|
||||
$this->assertFileExists(self::$_base . 'Generation/Controller/TresController.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGenerate
|
||||
*/
|
||||
public function testGeneratedModels()
|
||||
{
|
||||
if(!defined('APPLICATION_PATH'))
|
||||
{
|
||||
define('APPLICATION_PATH', self::$_base);
|
||||
}
|
||||
|
||||
require_once(self::$_base . 'Generation/Model/Base/UnoBase.php');
|
||||
require_once(self::$_base . 'Generation/Model/Base/DosBase.php');
|
||||
require_once(self::$_base . 'Generation/Model/Base/TresBase.php');
|
||||
require_once(self::$_base . 'Generation/Model/Uno.php');
|
||||
require_once(self::$_base . 'Generation/Model/Dos.php');
|
||||
require_once(self::$_base . 'Generation/Model/Tres.php');
|
||||
require_once(self::$_base . 'ArrayPropertyModel.php');
|
||||
|
||||
$uno = new Generation\Model\Uno();
|
||||
$dos = new Generation\Model\Dos();
|
||||
$tres = new Generation\Model\Tres();
|
||||
|
||||
$this->assertTrue($uno instanceof b8\Model);
|
||||
$this->assertTrue($dos instanceof b8\Model);
|
||||
$this->assertTrue($tres instanceof b8\Model);
|
||||
|
||||
$this->assertTrue($uno instanceof Generation\Model\Base\UnoBase);
|
||||
$this->assertTrue($dos instanceof Generation\Model\Base\DosBase);
|
||||
$this->assertTrue($tres instanceof Generation\Model\Base\TresBase);
|
||||
|
||||
$this->assertTrue($uno->getTableName() == 'uno');
|
||||
$this->assertTrue($dos->getTableName() == 'dos');
|
||||
$this->assertTrue($tres->getTableName() == 'tres');
|
||||
|
||||
$uno->setId(1);
|
||||
$uno->setFieldDatetime(new DateTime());
|
||||
$this->assertTrue($uno->getFieldDatetime() instanceof DateTime);
|
||||
|
||||
$unoArray = $uno->toArray();
|
||||
$this->assertArrayHasKey('field_varchar', $unoArray);
|
||||
$this->assertTrue($unoArray['field_datetime'] instanceof DateTime);
|
||||
|
||||
Generation\Model\Uno::$sleepable = array('id', 'field_varchar');
|
||||
$unoArray = $uno->toArray();
|
||||
$this->assertArrayHasKey('field_varchar', $unoArray);
|
||||
$this->assertFalse(array_key_exists('field_datetime', $unoArray));
|
||||
|
||||
$tres->setField($uno);
|
||||
$this->assertTrue($tres->getFieldInt() == 1);
|
||||
|
||||
$this->assertTrue(in_array('id', $uno->getModified()));
|
||||
$this->assertTrue(is_array($uno->getDataArray()));
|
||||
|
||||
$uno->setValues(array('field_int' => 100, 'field_bob' => 100));
|
||||
$this->assertFalse(in_array('field_bob', $uno->getModified()));
|
||||
$this->assertTrue($uno->getFieldInt() === 100);
|
||||
|
||||
$uno->setFieldInt(true);
|
||||
$this->assertTrue($uno->getFieldInt() === 1);
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->setFieldInt('invalid');
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
$uno->setFieldInt('500');
|
||||
$this->assertTrue($uno->getFieldInt() === 500);
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->setFieldFloat('invalid');
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
$uno->setFieldFloat('4.12');
|
||||
$this->assertTrue($uno->getFieldFloat() === 4.12);
|
||||
|
||||
|
||||
$uno->setFieldDatetime('2014-01-01');
|
||||
$this->assertTrue($uno->getFieldDatetime() instanceof DateTime);
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->setFieldDatetime(2012);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->setFieldInt(null);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->setValues(array('field_int' => 'null'));
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
$uno->setValues(array('field_int' => 'true'));
|
||||
$this->assertTrue($uno->getFieldInt() === 1);
|
||||
|
||||
$uno->setValues(array('field_int' => 'false'));
|
||||
$this->assertTrue($uno->getFieldInt() === 0);
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->setFieldVarchar(false);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->setFieldVarchar('Hi');
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertFalse($caught);
|
||||
|
||||
// Test toArray() with an array property:
|
||||
$aModel = new Generation\ArrayPropertyModel();
|
||||
$array = $aModel->toArray();
|
||||
|
||||
$this->assertArrayHasKey('array_property', $array);
|
||||
$this->assertTrue(is_array($array['array_property']));
|
||||
$this->assertTrue(is_array($array['array_property']['three']));
|
||||
$this->assertTrue($array['array_property']['one'] == 'two');
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGeneratedModels
|
||||
*/
|
||||
public function testGeneratedStores()
|
||||
{
|
||||
require_once(self::$_base . 'Generation/Store/Base/UnoStoreBase.php');
|
||||
require_once(self::$_base . 'Generation/Store/Base/DosStoreBase.php');
|
||||
require_once(self::$_base . 'Generation/Store/Base/TresStoreBase.php');
|
||||
require_once(self::$_base . 'Generation/Store/UnoStore.php');
|
||||
require_once(self::$_base . 'Generation/Store/DosStore.php');
|
||||
require_once(self::$_base . 'Generation/Store/TresStore.php');
|
||||
|
||||
$uno = new Generation\Store\UnoStore();
|
||||
$dos = new Generation\Store\DosStore();
|
||||
$tres = new Generation\Store\TresStore();
|
||||
|
||||
$this->assertTrue($uno instanceof b8\Store);
|
||||
$this->assertTrue($dos instanceof b8\Store);
|
||||
$this->assertTrue($tres instanceof b8\Store);
|
||||
|
||||
$this->assertTrue($uno instanceof Generation\Store\Base\UnoStoreBase);
|
||||
$this->assertTrue($dos instanceof Generation\Store\Base\DosStoreBase);
|
||||
$this->assertTrue($tres instanceof Generation\Store\Base\TresStoreBase);
|
||||
|
||||
$tresModel = new Generation\Model\Tres();
|
||||
$tresModel->setFieldVarchar('Hi');
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$tres->save($tresModel);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->save($tresModel);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
|
||||
$unoModel = new Generation\Model\Uno();
|
||||
$unoModel->setFieldVarchar('Hi');
|
||||
|
||||
$unoModel = $uno->save($unoModel);
|
||||
$id = $unoModel->getId();
|
||||
$this->assertTrue(!empty($id));
|
||||
$this->assertTrue($unoModel->getFieldVarchar() == 'Hi');
|
||||
|
||||
$unoModel->setFieldVarchar('Ha');
|
||||
$unoModel = $uno->save($unoModel);
|
||||
$this->assertTrue($id == $unoModel->getId());
|
||||
$this->assertTrue($unoModel->getFieldVarchar() == 'Ha');
|
||||
|
||||
$unoModel = $uno->save($unoModel);
|
||||
$this->assertTrue($id == $unoModel->getId());
|
||||
$this->assertTrue($unoModel->getFieldVarchar() == 'Ha');
|
||||
|
||||
$unoModel2 = $uno->getByPrimaryKey($id);
|
||||
$this->assertTrue($unoModel2->getId() == $unoModel->getId());
|
||||
|
||||
$res = $uno->getWhere(array('field_varchar' => 'Ha'));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => array('operator' => 'between', 'value' => array(0, 100))));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => array('operator' => 'IN', 'value' => array(1, 2, 3, 4))));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => array('operator' => '!=', 'value' => array('null', 100))));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => array('operator' => '==', 'value' => array('null'))));
|
||||
$this->assertTrue($res['count'] == 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => array('operator' => '==', 'value' => 'null')));
|
||||
$this->assertTrue($res['count'] == 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => array('operator' => '!=', 'value' => 'null')));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('field_varchar' => array('operator' => 'like', 'value' => 'Ha')));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('field_varchar' => array('operator' => '!=', 'value' => 'Hi')));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('field_varchar' => array('Ha', 'Hi')));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => 1), 1, 0, array('dos' => array('alias' => 'd', 'on' => 'd.id = uno.id')), array('id' => 'ASC'));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => 1), 1, 0, array('dos' => array('alias' => 'd', 'on' => 'd.id = uno.id')), 'rand');
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => 1), 1, 10);
|
||||
$this->assertTrue(count($res['items']) == 0 && $res['count'] == 1);
|
||||
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->getWhere(array('invalid_column' => 1));
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
$res = $uno->getWhere(array('id' => 1), 1, 0, array(), 'rand', array('LEFT JOIN dos d ON d.id = uno.id'));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
|
||||
$res = $uno->getWhere(array('id' => 1), 1, 0, array(), 'rand', array(), 'field_varchar');
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array(), 1, 0, array(), 'rand', array(), null, array(array('type' => 'AND', 'query' => 'id = 1', 'params' => array())));
|
||||
$this->assertTrue($res['count'] != 0);
|
||||
|
||||
$res = $uno->getWhere(array('id' => 2), 1, 0, array(), 'rand', array(), null, array(array('type' => 'AND', 'query' => 'id = ?', 'params' => array('id'))));
|
||||
$this->assertTrue($res['count'] == 0);
|
||||
|
||||
$caught = false;
|
||||
|
||||
try
|
||||
{
|
||||
$uno->getWhere(array('' => 1));
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
// ----
|
||||
// Tests for Model::toArray() with relationships:
|
||||
// ----
|
||||
$tresModel->setField($unoModel);
|
||||
$array = $tresModel->toArray();
|
||||
|
||||
$this->assertTrue(array_key_exists('Field', $array));
|
||||
$this->assertTrue(array_key_exists('id', $array['Field']));
|
||||
$this->assertTrue($array['Field']['id'] == $unoModel->getId());
|
||||
|
||||
// ----
|
||||
// Tests for Store::delete()
|
||||
// ----
|
||||
|
||||
$caught = false;
|
||||
try
|
||||
{
|
||||
$tres->delete($tresModel);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
$caught = false;
|
||||
try
|
||||
{
|
||||
$uno->delete($tresModel);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
|
||||
$this->assertTrue($uno->delete($unoModel));
|
||||
$this->assertTrue(is_null($uno->getByPrimaryKey(1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGeneratedStores
|
||||
*/
|
||||
public function testGeneratedControllers()
|
||||
{
|
||||
require_once(self::$_base . 'Generation/Controller/Base/UnoControllerBase.php');
|
||||
require_once(self::$_base . 'Generation/Controller/Base/DosControllerBase.php');
|
||||
require_once(self::$_base . 'Generation/Controller/Base/TresControllerBase.php');
|
||||
require_once(self::$_base . 'Generation/Controller/UnoController.php');
|
||||
require_once(self::$_base . 'Generation/Controller/DosController.php');
|
||||
require_once(self::$_base . 'Generation/Controller/TresController.php');
|
||||
require_once(self::$_base . 'TestUser.php');
|
||||
|
||||
$uno = new Generation\Controller\UnoController();
|
||||
$dos = new Generation\Controller\DosController();
|
||||
$tres = new Generation\Controller\TresController();
|
||||
|
||||
$uno->init();
|
||||
$dos->init();
|
||||
$tres->init();
|
||||
|
||||
$this->assertTrue($uno instanceof b8\Controller);
|
||||
$this->assertTrue($dos instanceof b8\Controller);
|
||||
$this->assertTrue($tres instanceof b8\Controller);
|
||||
|
||||
$this->assertTrue($uno instanceof Generation\Controller\Base\UnoControllerBase);
|
||||
$this->assertTrue($dos instanceof Generation\Controller\Base\DosControllerBase);
|
||||
$this->assertTrue($tres instanceof Generation\Controller\Base\TresControllerBase);
|
||||
|
||||
|
||||
Registry::getInstance()->setParam('hello', 'world');
|
||||
$this->assertTrue($uno->getParam('hello', 'dave') == 'world');
|
||||
|
||||
$uno->setParam('hello', 'dave');
|
||||
$this->assertTrue($uno->getParam('hello', 'world') == 'dave');
|
||||
$this->assertTrue(array_key_exists('hello', $uno->getParams()));
|
||||
|
||||
$uno->unsetParam('hello');
|
||||
$this->assertFalse(array_key_exists('hello', $uno->getParams()));
|
||||
|
||||
$testUser = new \TestUser();
|
||||
$uno->setActiveUser($testUser);
|
||||
$dos->setActiveUser($uno->getActiveUser());
|
||||
$tres->setActiveUser($uno->getActiveUser());
|
||||
|
||||
$unoModel = new Generation\Model\Uno();
|
||||
$unoStore = \b8\Store\Factory::getStore('Uno');
|
||||
$unoModel->setFieldVarchar('Hi');
|
||||
|
||||
$unoStore->save($unoModel);
|
||||
$list = $uno->index();
|
||||
|
||||
$this->assertTrue(is_array($list));
|
||||
$this->assertTrue(is_array($list['items']));
|
||||
$this->assertTrue(count($list['items']) > 0);
|
||||
|
||||
$caught = false;
|
||||
try
|
||||
{
|
||||
$dos->index();
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
|
||||
$first = array_shift($list['items']);
|
||||
|
||||
$uno1 = $uno->get($first['id']);
|
||||
$this->assertTrue(is_array($uno1));
|
||||
$this->assertTrue(isset($uno1['uno']));
|
||||
$this->assertTrue($uno1['uno']['id'] == $first['id']);
|
||||
|
||||
$caught = false;
|
||||
try
|
||||
{
|
||||
$dos->get(1);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
|
||||
$uno->setParam('field_varchar', 'Un');
|
||||
$uno1 = $uno->put($first['id']);
|
||||
$this->assertTrue($uno1['uno']['id'] == $first['id']);
|
||||
|
||||
$caught = false;
|
||||
try
|
||||
{
|
||||
$dos->put(1);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
$this->assertTrue(is_null($uno->put(10000)));
|
||||
|
||||
|
||||
$uno->setParam('field_text', 'Hello');
|
||||
$res = $uno->post();
|
||||
$this->assertTrue($res['uno']['field_varchar'] == 'Un');
|
||||
$this->assertTrue(!empty($res['uno']['id']));
|
||||
|
||||
$caught = false;
|
||||
try
|
||||
{
|
||||
$dos->post();
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
$del = $uno->delete($res['uno']['id']);
|
||||
$this->assertTrue($del['deleted']);
|
||||
|
||||
$del = $uno->delete($res['uno']['id']);
|
||||
$this->assertFalse($del['deleted']);
|
||||
|
||||
$del = $tres->delete(100);
|
||||
$this->assertFalse($del['deleted']);
|
||||
|
||||
$caught = false;
|
||||
try
|
||||
{
|
||||
$dos->delete(1000);
|
||||
}
|
||||
catch(Exception $ex)
|
||||
{
|
||||
$caught = true;
|
||||
}
|
||||
|
||||
$this->assertTrue($caught);
|
||||
|
||||
//----
|
||||
// Tests for _parseWhere()
|
||||
//----
|
||||
$uno->setParam('where', array('id' => array(1000)));
|
||||
$uno->setParam('neq', 'id');
|
||||
$list = $uno->index();
|
||||
|
||||
$this->assertTrue(is_array($list));
|
||||
$this->assertTrue(count($list['items']) != 0);
|
||||
|
||||
Registry::getInstance()->forceReset();
|
||||
$uno->setParam('where', array('id' => 1000));
|
||||
$uno->setParam('fuzzy', 'id');
|
||||
$list = $uno->index();
|
||||
|
||||
$this->assertTrue(is_array($list));
|
||||
$this->assertTrue(count($list['items']) == 0);
|
||||
}
|
||||
}
|
80
B8Framework/tests/DatabaseGenerationTest.php
Executable file
80
B8Framework/tests/DatabaseGenerationTest.php
Executable file
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/../b8/Registry.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Model.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Database.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Database/Map.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Database/Generator.php');
|
||||
|
||||
use b8\Database\Generator,
|
||||
b8\Database\Map;
|
||||
|
||||
class DatabaseGenerationTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $_host = 'localhost';
|
||||
protected $_user = 'b8_test';
|
||||
protected $_pass = 'b8_test';
|
||||
protected $_name = 'b8_test';
|
||||
protected $_db;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
\b8\Database::setDetails($this->_name, $this->_user, $this->_pass);
|
||||
\b8\Database::setWriteServers(array($this->_host));
|
||||
|
||||
$this->_db = \b8\Database::getConnection('write');
|
||||
|
||||
$this->_db->query('DROP TABLE IF EXISTS tres');
|
||||
$this->_db->query('DROP TABLE IF EXISTS dos');
|
||||
$this->_db->query('DROP TABLE IF EXISTS uno');
|
||||
}
|
||||
|
||||
public function testCreateDatabase()
|
||||
{
|
||||
$gen = new Generator($this->_db, 'Test', dirname(__FILE__) . '/data/generation/models/');
|
||||
$gen->generate();
|
||||
|
||||
$map = new Map($this->_db);
|
||||
$t = $map->generate();
|
||||
|
||||
$this->assertTrue(array_key_exists('uno', $t));
|
||||
$this->assertTrue(array_key_exists('dos', $t));
|
||||
$this->assertTrue(array_key_exists('tres', $t));
|
||||
$this->assertFalse(array_key_exists('bad_table', $t));
|
||||
$this->assertTrue(count($t['uno']['indexes']) == 1);
|
||||
$this->assertTrue(count($t['dos']['indexes']) == 3);
|
||||
$this->assertTrue(count($t['tres']['indexes']) == 2);
|
||||
$this->assertTrue(count($t['uno']['columns']) == 11);
|
||||
$this->assertTrue(count($t['dos']['columns']) == 4);
|
||||
$this->assertTrue(count($t['tres']['columns']) == 6);
|
||||
$this->assertTrue(array_key_exists('PRIMARY', $t['uno']['indexes']));
|
||||
$this->assertTrue(array_key_exists('PRIMARY', $t['dos']['indexes']));
|
||||
$this->assertFalse(array_key_exists('PRIMARY', $t['tres']['indexes']));
|
||||
}
|
||||
|
||||
public function testUpdateDatabase()
|
||||
{
|
||||
$gen = new Generator($this->_db, 'Test', dirname(__FILE__) . '/data/generation/models/');
|
||||
$gen->generate();
|
||||
|
||||
$gen = new Generator($this->_db, 'Update', dirname(__FILE__) . '/data/generation/update_models/');
|
||||
$gen->generate();
|
||||
|
||||
$map = new Map($this->_db);
|
||||
$t = $map->generate();
|
||||
|
||||
$this->assertTrue(array_key_exists('uno', $t));
|
||||
$this->assertTrue(array_key_exists('dos', $t));
|
||||
$this->assertTrue(array_key_exists('tres', $t));
|
||||
$this->assertFalse(array_key_exists('bad_table', $t));
|
||||
$this->assertTrue(count($t['uno']['indexes']) == 1);
|
||||
$this->assertTrue(count($t['dos']['indexes']) == 3);
|
||||
$this->assertTrue(count($t['tres']['indexes']) == 3);
|
||||
$this->assertTrue(count($t['uno']['columns']) == 10);
|
||||
$this->assertTrue(count($t['dos']['columns']) == 4);
|
||||
$this->assertTrue(count($t['tres']['columns']) == 10);
|
||||
$this->assertTrue(array_key_exists('PRIMARY', $t['uno']['indexes']));
|
||||
$this->assertTrue(array_key_exists('PRIMARY', $t['dos']['indexes']));
|
||||
$this->assertTrue(array_key_exists('PRIMARY', $t['tres']['indexes']));
|
||||
}
|
||||
}
|
54
B8Framework/tests/DatabaseTest.php
Executable file
54
B8Framework/tests/DatabaseTest.php
Executable file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/../b8/Registry.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Database.php');
|
||||
|
||||
class DatabaseTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $_host = 'localhost';
|
||||
protected $_user = 'b8_test';
|
||||
protected $_pass = 'b8_test';
|
||||
protected $_name = 'b8_test';
|
||||
|
||||
public function testGetReadConnection()
|
||||
{
|
||||
\b8\Database::setDetails($this->_name, $this->_user, $this->_pass);
|
||||
\b8\Database::setReadServers(array($this->_host));
|
||||
|
||||
$connection = \b8\Database::getConnection('read');
|
||||
|
||||
$this->assertInstanceOf('\b8\Database', $connection);
|
||||
}
|
||||
|
||||
public function testGetWriteConnection()
|
||||
{
|
||||
\b8\Database::setDetails($this->_name, $this->_user, $this->_pass);
|
||||
\b8\Database::setWriteServers(array($this->_host));
|
||||
|
||||
$connection = \b8\Database::getConnection('write');
|
||||
|
||||
$this->assertInstanceOf('\b8\Database', $connection);
|
||||
}
|
||||
|
||||
public function testGetDetails()
|
||||
{
|
||||
\b8\Database::setDetails($this->_name, $this->_user, $this->_pass);
|
||||
\b8\Database::setReadServers(array('localhost'));
|
||||
|
||||
$details = \b8\Database::getConnection('read')->getDetails();
|
||||
$this->assertTrue(is_array($details));
|
||||
$this->assertTrue(($details['db'] == $this->_name));
|
||||
$this->assertTrue(($details['user'] == $this->_user));
|
||||
$this->assertTrue(($details['pass'] == $this->_pass));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
*/
|
||||
public function testConnectionFailure()
|
||||
{
|
||||
\b8\Database::setDetails('non_existant', 'invalid_user', 'incorrect_password');
|
||||
\b8\Database::setReadServers(array('localhost'));
|
||||
\b8\Database::getConnection('read');
|
||||
}
|
||||
}
|
196
B8Framework/tests/FormTest.php
Executable file
196
B8Framework/tests/FormTest.php
Executable file
|
@ -0,0 +1,196 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/../b8/Registry.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/View.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/View/UserView.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Input.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/FieldSet.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/ControlGroup.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/Text.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/Button.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/Checkbox.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/CheckboxGroup.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/Email.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/Hidden.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/Select.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/Radio.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/Submit.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/TextArea.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Form/Element/Url.php');
|
||||
|
||||
use b8\Form,
|
||||
b8\Registry;
|
||||
|
||||
class FormTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testFormBasics()
|
||||
{
|
||||
$f = new Form();
|
||||
$f->setAction('/');
|
||||
$f->setMethod('POST');
|
||||
|
||||
$this->assertTrue($f->getAction() == '/');
|
||||
$this->assertTrue($f->getMethod() == 'POST');
|
||||
|
||||
Registry::getInstance()->set('ViewPath', dirname(__FILE__) . '/data/view/');
|
||||
|
||||
$this->assertTrue($f->render('form') == '/POST');
|
||||
|
||||
Registry::getInstance()->set('ViewPath', '');
|
||||
$this->assertTrue(strpos((string)$f, '<form') !== false);
|
||||
}
|
||||
|
||||
public function testElementBasics()
|
||||
{
|
||||
$f = new Form\Element\Text('element-name');
|
||||
$f->setId('element-id');
|
||||
$f->setLabel('element-label');
|
||||
$f->setClass('element-class');
|
||||
$f->setContainerClass('container-class');
|
||||
|
||||
$this->assertTrue($f->getName() == 'elementname');
|
||||
$this->assertTrue($f->getId() == 'element-id');
|
||||
$this->assertTrue($f->getLabel() == 'element-label');
|
||||
$this->assertTrue($f->getClass() == 'element-class');
|
||||
$this->assertTrue($f->getContainerClass() == 'container-class');
|
||||
|
||||
$output = $f->render();
|
||||
$this->assertTrue(is_string($output));
|
||||
$this->assertTrue(!empty($output));
|
||||
$this->assertTrue(strpos($output, 'container-class') !== false);
|
||||
}
|
||||
|
||||
public function testInputBasics()
|
||||
{
|
||||
$f = new Form\Element\Text();
|
||||
$f->setValue('input-value');
|
||||
$f->setRequired(true);
|
||||
$f->setValidator(function($value) { return ($value == 'input-value'); });
|
||||
|
||||
$this->assertTrue($f->getValue() == 'input-value');
|
||||
$this->assertTrue($f->getRequired() == true);
|
||||
$this->assertTrue(is_callable($f->getValidator()));
|
||||
}
|
||||
|
||||
public function testInputValidation()
|
||||
{
|
||||
$f = new Form\Element\Text();
|
||||
$f->setRequired(true);
|
||||
$this->assertFalse($f->validate());
|
||||
|
||||
$f->setRequired(false);
|
||||
$f->setPattern('input\-value');
|
||||
$this->assertFalse($f->validate());
|
||||
|
||||
$f->setValue('input-value');
|
||||
$this->assertTrue($f->validate());
|
||||
|
||||
$f->setValidator(function($item)
|
||||
{
|
||||
if($item != 'input-value')
|
||||
{
|
||||
throw new \Exception('Invalid input value.');
|
||||
}
|
||||
});
|
||||
|
||||
$this->assertTrue($f->validate());
|
||||
|
||||
$f->setValue('fail');
|
||||
$f->setPattern(null);
|
||||
$this->assertFalse($f->validate());
|
||||
}
|
||||
|
||||
public function testFieldSetBasics()
|
||||
{
|
||||
$f = new Form\FieldSet();
|
||||
$f2 = new Form\FieldSet('group');
|
||||
$f3 = new Form\FieldSet();
|
||||
|
||||
$t = new Form\Element\Text('one');
|
||||
$t->setRequired(true);
|
||||
$f2->addField($t);
|
||||
|
||||
$t = new Form\Element\Text('two');
|
||||
$f2->addField($t);
|
||||
|
||||
$t = new Form\Element\Text('three');
|
||||
$f3->addField($t);
|
||||
|
||||
$f->addField($f2);
|
||||
$f->addField($f3);
|
||||
|
||||
$this->assertFalse($f->validate());
|
||||
|
||||
$f->setValues(array('group' => array('one' => 'ONE', 'two' => 'TWO'), 'three' => 'THREE'));
|
||||
|
||||
$values = $f->getValues();
|
||||
$this->assertTrue(is_array($values));
|
||||
$this->assertTrue(array_key_exists('group', $values));
|
||||
$this->assertTrue(array_key_exists('one', $values['group']));
|
||||
$this->assertTrue(array_key_exists('three', $values));
|
||||
$this->assertTrue($values['group']['one'] == 'ONE');
|
||||
$this->assertTrue($values['group']['two'] == 'TWO');
|
||||
$this->assertTrue($values['three'] == 'THREE');
|
||||
$this->assertTrue($f->validate());
|
||||
|
||||
$html = $f->render();
|
||||
$this->assertTrue(strpos($html, 'one') !== false);
|
||||
$this->assertTrue(strpos($html, 'two') !== false);
|
||||
}
|
||||
|
||||
public function testElements()
|
||||
{
|
||||
$e = new Form\Element\Button();
|
||||
$this->assertTrue($e->validate());
|
||||
$this->assertTrue(strpos($e->render(), 'button') !== false);
|
||||
|
||||
$e = new Form\Element\Checkbox();
|
||||
$e->setCheckedValue('ten');
|
||||
$this->assertTrue($e->getCheckedValue() == 'ten');
|
||||
$this->assertTrue(strpos($e->render(), 'checkbox') !== false);
|
||||
$this->assertTrue(strpos($e->render(), 'checked') === false);
|
||||
|
||||
$e->setValue(true);
|
||||
$this->assertTrue(strpos($e->render(), 'checked') !== false);
|
||||
|
||||
$e->setValue('ten');
|
||||
$this->assertTrue(strpos($e->render(), 'checked') !== false);
|
||||
|
||||
$e->setValue('fail');
|
||||
$this->assertTrue(strpos($e->render(), 'checked') === false);
|
||||
|
||||
$e = new Form\Element\CheckboxGroup();
|
||||
$this->assertTrue(strpos($e->render(), 'group') !== false);
|
||||
|
||||
$e = new Form\ControlGroup();
|
||||
$this->assertTrue(strpos($e->render(), 'group') !== false);
|
||||
|
||||
$e = new Form\Element\Email();
|
||||
$this->assertTrue(strpos($e->render(), 'email') !== false);
|
||||
|
||||
$e = new Form\Element\Select();
|
||||
$e->setOptions(array('key' => 'Val'));
|
||||
$html = $e->render();
|
||||
$this->assertTrue(strpos($html, 'select') !== false);
|
||||
$this->assertTrue(strpos($html, 'option') !== false);
|
||||
$this->assertTrue(strpos($html, 'key') !== false);
|
||||
$this->assertTrue(strpos($html, 'Val') !== false);
|
||||
|
||||
$e = new Form\Element\Submit();
|
||||
$this->assertTrue($e->validate());
|
||||
$this->assertTrue(strpos($e->render(), 'submit') !== false);
|
||||
|
||||
$e = new Form\Element\Text();
|
||||
$e->setValue('test');
|
||||
$this->assertTrue(strpos($e->render(), 'test') !== false);
|
||||
|
||||
$e = new Form\Element\TextArea();
|
||||
$e->setRows(10);
|
||||
$this->assertTrue(strpos($e->render(), '10') !== false);
|
||||
|
||||
$e = new Form\Element\Url();
|
||||
$this->assertTrue(strpos($e->render(), 'url') !== false);
|
||||
}
|
||||
}
|
66
B8Framework/tests/HttpClientTest.php
Executable file
66
B8Framework/tests/HttpClientTest.php
Executable file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/../b8/Registry.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/HttpClient.php');
|
||||
|
||||
use b8\Registry,
|
||||
b8\HttpClient;
|
||||
|
||||
class HttpClientTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSimpleRequest()
|
||||
{
|
||||
$http = new HttpClient();
|
||||
$html = $http->request('GET', 'https://www.cloudflare.com/');
|
||||
|
||||
$this->assertContains('CloudFlare', $html['body']);
|
||||
}
|
||||
|
||||
public function testBaseUrl()
|
||||
{
|
||||
$http = new HttpClient('https://www.cloudflare.com');
|
||||
$html = $http->request('GET', '/');
|
||||
|
||||
$this->assertContains('CloudFlare', $html['body']);
|
||||
}
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
$http = new HttpClient('https://www.cloudflare.com');
|
||||
$html = $http->get('overview', array('x' => 1));
|
||||
|
||||
$this->assertContains('CloudFlare', $html['body']);
|
||||
}
|
||||
|
||||
public function testGetJson()
|
||||
{
|
||||
$http = new HttpClient('http://echo.jsontest.com');
|
||||
$data = $http->get('/key/value');
|
||||
|
||||
$this->assertArrayHasKey('key', $data['body']);
|
||||
}
|
||||
|
||||
public function testPost()
|
||||
{
|
||||
$http = new HttpClient('http://echo.jsontest.com');
|
||||
$data = $http->post('/key/value', array('test' => 'x'));
|
||||
|
||||
$this->assertTrue(is_array($data));
|
||||
}
|
||||
|
||||
public function testPut()
|
||||
{
|
||||
$http = new HttpClient('http://echo.jsontest.com');
|
||||
$data = $http->put('/key/value', array('test' => 'x'));
|
||||
|
||||
$this->assertTrue(is_array($data));
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
$http = new HttpClient('http://echo.jsontest.com');
|
||||
$data = $http->delete('/key/value', array('test' => 'x'));
|
||||
|
||||
$this->assertTrue(is_array($data));
|
||||
}
|
||||
}
|
115
B8Framework/tests/HttpExceptionTest.php
Executable file
115
B8Framework/tests/HttpExceptionTest.php
Executable file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/../b8/Registry.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException/BadRequestException.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException/ForbiddenException.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException/NotAuthorizedException.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException/NotFoundException.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException/ServerErrorException.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException/ValidationException.php');
|
||||
|
||||
use b8\Exception\HttpException,
|
||||
b8\Exception\HttpException\BadRequestException;
|
||||
|
||||
class HttpExceptionTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testHttpExceptionIsException()
|
||||
{
|
||||
$ex = new HttpException();
|
||||
$this->assertTrue($ex instanceof \Exception);
|
||||
}
|
||||
|
||||
public function testHttpException()
|
||||
{
|
||||
try
|
||||
{
|
||||
throw new HttpException('Test');
|
||||
}
|
||||
catch(HttpException $ex)
|
||||
{
|
||||
$this->assertTrue($ex->getMessage() == 'Test');
|
||||
$this->assertTrue($ex->getErrorCode() == 500);
|
||||
$this->assertTrue($ex->getStatusMessage() == 'Internal Server Error');
|
||||
$this->assertTrue($ex->getHttpHeader() == 'HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
}
|
||||
|
||||
public function testBadRequestException()
|
||||
{
|
||||
try
|
||||
{
|
||||
throw new HttpException\BadRequestException('Test');
|
||||
}
|
||||
catch(HttpException $ex)
|
||||
{
|
||||
$this->assertTrue($ex->getErrorCode() == 400);
|
||||
$this->assertTrue($ex->getStatusMessage() == 'Bad Request');
|
||||
}
|
||||
}
|
||||
|
||||
public function testForbiddenException()
|
||||
{
|
||||
try
|
||||
{
|
||||
throw new HttpException\ForbiddenException('Test');
|
||||
}
|
||||
catch(HttpException $ex)
|
||||
{
|
||||
$this->assertTrue($ex->getErrorCode() == 403);
|
||||
$this->assertTrue($ex->getStatusMessage() == 'Forbidden');
|
||||
}
|
||||
}
|
||||
|
||||
public function testNotAuthorizedException()
|
||||
{
|
||||
try
|
||||
{
|
||||
throw new HttpException\NotAuthorizedException('Test');
|
||||
}
|
||||
catch(HttpException $ex)
|
||||
{
|
||||
$this->assertTrue($ex->getErrorCode() == 401);
|
||||
$this->assertTrue($ex->getStatusMessage() == 'Not Authorized');
|
||||
}
|
||||
}
|
||||
|
||||
public function testNotFoundException()
|
||||
{
|
||||
try
|
||||
{
|
||||
throw new HttpException\NotFoundException('Test');
|
||||
}
|
||||
catch(HttpException $ex)
|
||||
{
|
||||
$this->assertTrue($ex->getErrorCode() == 404);
|
||||
$this->assertTrue($ex->getStatusMessage() == 'Not Found');
|
||||
}
|
||||
}
|
||||
|
||||
public function testServerErrorException()
|
||||
{
|
||||
try
|
||||
{
|
||||
throw new HttpException\ServerErrorException('Test');
|
||||
}
|
||||
catch(HttpException $ex)
|
||||
{
|
||||
$this->assertTrue($ex->getErrorCode() == 500);
|
||||
$this->assertTrue($ex->getStatusMessage() == 'Internal Server Error');
|
||||
}
|
||||
}
|
||||
|
||||
public function testValidationException()
|
||||
{
|
||||
try
|
||||
{
|
||||
throw new HttpException\ValidationException('Test');
|
||||
}
|
||||
catch(HttpException $ex)
|
||||
{
|
||||
$this->assertTrue($ex->getErrorCode() == 400);
|
||||
$this->assertTrue($ex->getStatusMessage() == 'Bad Request');
|
||||
}
|
||||
}
|
||||
}
|
82
B8Framework/tests/RegistryTest.php
Executable file
82
B8Framework/tests/RegistryTest.php
Executable file
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/../b8/Registry.php');
|
||||
use b8\Registry;
|
||||
|
||||
class RegistryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSingleton()
|
||||
{
|
||||
Registry::forceReset();
|
||||
$instance = Registry::getInstance();
|
||||
$instance->set('test', true);
|
||||
|
||||
$instance2 = Registry::getInstance();
|
||||
$this->assertTrue($instance2->get('test', false));
|
||||
}
|
||||
|
||||
public function testStoreAndRetrieve()
|
||||
{
|
||||
Registry::forceReset();
|
||||
$r = Registry::getInstance();
|
||||
$r->set('test', 'cat');
|
||||
|
||||
$this->assertTrue($r->get('test', 'dog') == 'cat');
|
||||
}
|
||||
|
||||
public function testSetArray()
|
||||
{
|
||||
Registry::forceReset();
|
||||
$r = Registry::getInstance();
|
||||
$r->set('one', 'two');
|
||||
$r->setArray(array('test' => 'cat'));
|
||||
|
||||
$this->assertTrue($r->get('test', 'dog') == 'cat');
|
||||
$this->assertTrue($r->get('one', 'three') == 'two');
|
||||
}
|
||||
|
||||
public function testGetNonExistent()
|
||||
{
|
||||
Registry::forceReset();
|
||||
$r = Registry::getInstance();
|
||||
$this->assertTrue(!$r->get('cat', false));
|
||||
}
|
||||
|
||||
public function testGetParams()
|
||||
{
|
||||
Registry::forceReset();
|
||||
|
||||
$_REQUEST = array();
|
||||
$_REQUEST['cat'] = 'dog';
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
|
||||
$r = Registry::getInstance();
|
||||
$params = $r->getParams();
|
||||
$this->assertTrue(is_array($params));
|
||||
$this->assertArrayHasKey('cat', $params);
|
||||
$this->assertArrayNotHasKey('dog', $params);
|
||||
}
|
||||
|
||||
public function testEmptyInput()
|
||||
{
|
||||
Registry::forceReset();
|
||||
$r = Registry::getInstance();
|
||||
$params = $r->getParams();
|
||||
|
||||
$this->assertTrue(is_array($params));
|
||||
$this->assertTrue(!count($params));
|
||||
}
|
||||
|
||||
public function testGetSetUnsetParam()
|
||||
{
|
||||
Registry::forceReset();
|
||||
$r = Registry::getInstance();
|
||||
$this->assertTrue($r->getParam('cat', false) == false);
|
||||
$r->setParam('cat', 'dog');
|
||||
|
||||
$this->assertTrue($r->getParam('cat', false) == 'dog');
|
||||
|
||||
$r->unsetParam('cat');
|
||||
$this->assertTrue($r->getParam('cat', false) == false);
|
||||
}
|
||||
}
|
141
B8Framework/tests/ViewTest.php
Executable file
141
B8Framework/tests/ViewTest.php
Executable file
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/../b8/Registry.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/View.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/View/UserView.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/View/Helper/Format.php');
|
||||
require_once(dirname(__FILE__) . '/../b8/Exception/HttpException.php');
|
||||
|
||||
use b8\View,
|
||||
b8\View\UserView;
|
||||
|
||||
class ViewTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSimpleView()
|
||||
{
|
||||
$view = new b8\View('simple', dirname(__FILE__) . '/data/view/');
|
||||
$this->assertTrue($view->render() == 'Hello');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
*/
|
||||
public function testInvalidView()
|
||||
{
|
||||
new b8\View('dogs', dirname(__FILE__) . '/data/view/');
|
||||
}
|
||||
|
||||
public function testViewVars()
|
||||
{
|
||||
$view = new b8\View('vars', dirname(__FILE__) . '/data/view/');
|
||||
$view->who = 'World';
|
||||
|
||||
$this->assertTrue(isset($view->who));
|
||||
$this->assertFalse(isset($view->what));
|
||||
$this->assertTrue($view->render() == 'Hello World');
|
||||
}
|
||||
|
||||
public function testFormatViewHelper()
|
||||
{
|
||||
$view = new b8\View('format', dirname(__FILE__) . '/data/view/');
|
||||
$view->number = 1000000.25;
|
||||
$view->symbol = true;
|
||||
|
||||
$this->assertTrue($view->render() == '£1,000,000.25');
|
||||
|
||||
$view->number = 1024;
|
||||
$view->symbol = false;
|
||||
$this->assertTrue($view->render() == '1,024.00');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \b8\Exception\HttpException
|
||||
*/
|
||||
public function testInvalidHelper()
|
||||
{
|
||||
$view = new UserView('{@Invalid:test}');
|
||||
$view->render();
|
||||
}
|
||||
|
||||
public function testSimpleUserView()
|
||||
{
|
||||
$view = new UserView('Hello');
|
||||
$this->assertTrue($view->render() == 'Hello');
|
||||
}
|
||||
|
||||
public function testUserViewYear()
|
||||
{
|
||||
$view = new UserView('{@year}');
|
||||
$this->assertTrue($view->render() == date('Y'));
|
||||
}
|
||||
|
||||
public function testUserViewVars()
|
||||
{
|
||||
$view = new UserView('Hello {@who}');
|
||||
$view->who = 'World';
|
||||
$this->assertTrue($view->render() == 'Hello World');
|
||||
|
||||
$view = new UserView('Hello {@who}');
|
||||
$this->assertTrue($view->render() == 'Hello ');
|
||||
|
||||
$view = new UserView('Hello {@who.name}');
|
||||
$view->who = array('name' => 'Dan');
|
||||
$this->assertTrue($view->render() == 'Hello Dan');
|
||||
|
||||
$tmp = new UserView('Hello');
|
||||
$tmp->who = 'World';
|
||||
$view = new UserView('Hello {@tmp.who}');
|
||||
$view->tmp = $tmp;
|
||||
|
||||
$this->assertTrue($view->render() == 'Hello World');
|
||||
|
||||
$tmp = new UserView('Hello');
|
||||
$view = new UserView('Hello {@tmp.who}');
|
||||
$view->tmp = $tmp;
|
||||
|
||||
$this->assertTrue($view->render() == 'Hello ');
|
||||
|
||||
$view = new UserView('Hello {@who.toUpperCase}');
|
||||
$view->who = 'World';
|
||||
$this->assertTrue($view->render() == 'Hello WORLD');
|
||||
|
||||
$view = new UserView('Hello {@who.toLowerCase}');
|
||||
$view->who = 'World';
|
||||
$this->assertTrue($view->render() == 'Hello world');
|
||||
}
|
||||
|
||||
public function testUserViewIf()
|
||||
{
|
||||
$view = new UserView('Hello{if who} World{/if}');
|
||||
$view->who = true;
|
||||
$this->assertTrue($view->render() == 'Hello World');
|
||||
|
||||
$view = new UserView('Hello{if who} World{/if}');
|
||||
$view->who = false;
|
||||
$this->assertTrue($view->render() == 'Hello');
|
||||
|
||||
$view = new UserView('Hello{ifnot who} World{/ifnot}');
|
||||
$view->who = true;
|
||||
$this->assertTrue($view->render() == 'Hello');
|
||||
|
||||
$view = new UserView('Hello {if Format:not_present}World{/if}');
|
||||
$this->assertTrue($view->render() == 'Hello ');
|
||||
|
||||
$view = new UserView('Hello {ifnot Format:not_present}World{/ifnot}');
|
||||
$this->assertTrue($view->render() == 'Hello World');
|
||||
}
|
||||
|
||||
public function testUserViewLoop()
|
||||
{
|
||||
$view = new UserView('Hello {loop who}{@item}{/loop}');
|
||||
$view->who = array('W', 'o', 'r', 'l', 'd');
|
||||
$this->assertTrue($view->render() == 'Hello World');
|
||||
|
||||
$view = new UserView('Hello {loop who}{@item}{/loop}');
|
||||
$this->assertTrue($view->render() == 'Hello ');
|
||||
|
||||
$view = new UserView('Hello {loop who}{@item}{/loop}');
|
||||
$view->who = 'World';
|
||||
$this->assertTrue($view->render() == 'Hello World');
|
||||
}
|
||||
}
|
18
B8Framework/tests/data/generation/ArrayPropertyModel.php
Executable file
18
B8Framework/tests/data/generation/ArrayPropertyModel.php
Executable file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Generation;
|
||||
use Generation\Model\Uno;
|
||||
|
||||
class ArrayPropertyModel extends Uno
|
||||
{
|
||||
public function __construct($initialData = array())
|
||||
{
|
||||
$this->_getters['array_property'] = 'getArrayProperty';
|
||||
self::$sleepable[] = 'array_property';
|
||||
}
|
||||
|
||||
public function getArrayProperty()
|
||||
{
|
||||
return array('one' => 'two', 'three' => array('four' => 'five'));
|
||||
}
|
||||
}
|
13
B8Framework/tests/data/generation/TestUser.php
Executable file
13
B8Framework/tests/data/generation/TestUser.php
Executable file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
require_once(B8_PATH . 'Type/RestUser.php');
|
||||
|
||||
use b8\Type\RestUser;
|
||||
|
||||
class TestUser implements RestUser
|
||||
{
|
||||
public function checkPermission($permission, $resource)
|
||||
{
|
||||
return $resource == 'unos' || $resource == 'tress' ? true : false;
|
||||
}
|
||||
}
|
18
B8Framework/tests/data/generation/models/BadModel.php
Executable file
18
B8Framework/tests/data/generation/models/BadModel.php
Executable file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Test\Model\Base;
|
||||
use b8\Model;
|
||||
|
||||
class BadModel extends Model
|
||||
{
|
||||
protected $_tableName = 'bad_table';
|
||||
|
||||
public $columns = array(
|
||||
'id' => array('type' => 'catfish'),
|
||||
);
|
||||
|
||||
public $indexes = array(
|
||||
);
|
||||
public $foreignKeys = array(
|
||||
);
|
||||
}
|
24
B8Framework/tests/data/generation/models/Dos.php
Executable file
24
B8Framework/tests/data/generation/models/Dos.php
Executable file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Test\Model\Base;
|
||||
use b8\Model;
|
||||
|
||||
class Dos extends Model
|
||||
{
|
||||
protected $_tableName = 'dos';
|
||||
|
||||
public $columns = array(
|
||||
'id' => array('type' => 'int', 'primary_key' => true, 'auto_increment' => false),
|
||||
'field_varchar' => array('type' => 'varchar', 'length' => '250', 'default' => 'Hello World'),
|
||||
'field_datetime'=> array('type' => 'datetime'),
|
||||
'field_int' => array('type' => 'int'),
|
||||
);
|
||||
|
||||
public $indexes = array(
|
||||
'PRIMARY' => array('unique' => true, 'columns' => 'id'),
|
||||
'idx_test_1' => array('unique' => true, 'columns' => 'field_int'),
|
||||
'idx_test_2' => array('columns' => 'field_datetime'),
|
||||
);
|
||||
public $foreignKeys = array(
|
||||
);
|
||||
}
|
27
B8Framework/tests/data/generation/models/Tres.php
Executable file
27
B8Framework/tests/data/generation/models/Tres.php
Executable file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Test\Model\Base;
|
||||
use b8\Model;
|
||||
|
||||
class Tres extends Model
|
||||
{
|
||||
protected $_tableName = 'tres';
|
||||
|
||||
public $columns = array(
|
||||
'id' => array('type' => 'int'),
|
||||
'field_varchar' => array('type' => 'varchar', 'length' => '250'),
|
||||
'field_date' => array('type' => 'date'),
|
||||
'field_datetime'=> array('type' => 'datetime'),
|
||||
'field_int' => array('type' => 'int'),
|
||||
'field_int_2' => array('type' => 'int'),
|
||||
);
|
||||
|
||||
public $indexes = array(
|
||||
'fk_tres_uno' => array('columns' => 'field_int'),
|
||||
'fk_tres_dos' => array('columns' => 'field_int_2'),
|
||||
);
|
||||
public $foreignKeys = array(
|
||||
'fk_tres_uno' => array('local_col' => 'field_int', 'table' => 'uno', 'col' => 'id'),
|
||||
'fk_tres_dos' => array('local_col' => 'field_int_2', 'update' => 'NO ACTION', 'delete' => 'CASCADE', 'table' => 'dos', 'col' => 'id'),
|
||||
);
|
||||
}
|
28
B8Framework/tests/data/generation/models/Uno.php
Executable file
28
B8Framework/tests/data/generation/models/Uno.php
Executable file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Test\Model\Base;
|
||||
use b8\Model;
|
||||
|
||||
class Uno extends Model
|
||||
{
|
||||
protected $_tableName = 'uno';
|
||||
|
||||
public $columns = array(
|
||||
'id' => array('type' => 'int', 'primary_key' => true, 'auto_increment' => true),
|
||||
'field_varchar' => array('type' => 'varchar', 'length' => '250'),
|
||||
'field_text' => array('type' => 'text'),
|
||||
'field_ltext' => array('type' => 'longtext'),
|
||||
'field_mtext' => array('type' => 'mediumtext'),
|
||||
'field_date' => array('type' => 'date'),
|
||||
'field_datetime'=> array('type' => 'datetime'),
|
||||
'field_int' => array('type' => 'int'),
|
||||
'field_tinyint' => array('type' => 'tinyint', 'length' => '1'),
|
||||
'field_float' => array('type' => 'float'),
|
||||
'field_double' => array('type' => 'double', 'length' => '15,2'),
|
||||
);
|
||||
|
||||
public $indexes = array(
|
||||
);
|
||||
public $foreignKeys = array(
|
||||
);
|
||||
}
|
0
B8Framework/tests/data/generation/models/ignore.file
Executable file
0
B8Framework/tests/data/generation/models/ignore.file
Executable file
24
B8Framework/tests/data/generation/update_models/Dos.php
Executable file
24
B8Framework/tests/data/generation/update_models/Dos.php
Executable file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Update\Model\Base;
|
||||
use b8\Model;
|
||||
|
||||
class Dos extends Model
|
||||
{
|
||||
protected $_tableName = 'dos';
|
||||
|
||||
public $columns = array(
|
||||
'id' => array('type' => 'int', 'primary_key' => true, 'auto_increment' => true),
|
||||
'field_varchar' => array('type' => 'varchar', 'length' => '250', 'default' => 'Hello World'),
|
||||
'field_datetime'=> array('type' => 'datetime'),
|
||||
'field_int' => array('type' => 'int'),
|
||||
);
|
||||
|
||||
public $indexes = array(
|
||||
'PRIMARY' => array('unique' => true, 'columns' => 'id'),
|
||||
'idx_test_1' => array('unique' => false, 'columns' => 'field_int'),
|
||||
'idx_test_2' => array('columns' => 'field_datetime'),
|
||||
);
|
||||
public $foreignKeys = array(
|
||||
);
|
||||
}
|
32
B8Framework/tests/data/generation/update_models/Tres.php
Executable file
32
B8Framework/tests/data/generation/update_models/Tres.php
Executable file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Update\Model\Base;
|
||||
use b8\Model;
|
||||
|
||||
class Tres extends Model
|
||||
{
|
||||
protected $_tableName = 'tres';
|
||||
|
||||
public $columns = array(
|
||||
'key_col' => array('type' => 'int', 'primary_key' => true, 'auto_increment' => true),
|
||||
'id' => array('type' => 'int'),
|
||||
'field_varchar' => array('type' => 'varchar', 'length' => '250', 'default' => 'Hello World'),
|
||||
'field_datetime'=> array('type' => 'datetime'),
|
||||
'field_int' => array('type' => 'int'),
|
||||
'field_int_2' => array('type' => 'int'),
|
||||
'field_dt' => array('type' => 'date', 'rename' => 'field_date'),
|
||||
'field_float_1' => array('type' => 'float', 'default' => '1'),
|
||||
'field_varchar_2' => array('type' => 'varchar', 'length' => '10', 'default' => 'Hello'),
|
||||
'dosid' => array('type' => 'int'),
|
||||
);
|
||||
|
||||
public $indexes = array(
|
||||
'PRIMARY' => array('unique' => true, 'columns' => 'key_col'),
|
||||
'fk_tres_dos' => array('columns' => 'field_int_2'),
|
||||
'fk_tres_dos_2' => array('columns' => 'dosid'),
|
||||
);
|
||||
public $foreignKeys = array(
|
||||
'fk_tres_dos' => array('local_col' => 'field_int_2', 'update' => 'CASCADE', 'delete' => 'CASCADE', 'table' => 'dos', 'col' => 'id'),
|
||||
'fk_tres_dos_2' => array('local_col' => 'dosid', 'update' => 'CASCADE', 'delete' => 'CASCADE', 'table' => 'dos', 'col' => 'id'),
|
||||
);
|
||||
}
|
27
B8Framework/tests/data/generation/update_models/Uno.php
Executable file
27
B8Framework/tests/data/generation/update_models/Uno.php
Executable file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Update\Model\Base;
|
||||
use b8\Model;
|
||||
|
||||
class Uno extends Model
|
||||
{
|
||||
protected $_tableName = 'uno';
|
||||
|
||||
public $columns = array(
|
||||
'id' => array('type' => 'int', 'primary_key' => true),
|
||||
'field_varchar' => array('type' => 'varchar', 'length' => '250'),
|
||||
'field_text' => array('type' => 'text'),
|
||||
'field_ltext' => array('type' => 'longtext'),
|
||||
'field_mtext' => array('type' => 'mediumtext'),
|
||||
'field_datetime'=> array('type' => 'datetime'),
|
||||
'field_int' => array('type' => 'int'),
|
||||
'field_tinyint' => array('type' => 'tinyint', 'length' => '1'),
|
||||
'field_float' => array('type' => 'float'),
|
||||
'field_double' => array('type' => 'double', 'length' => '15,2'),
|
||||
);
|
||||
|
||||
public $indexes = array(
|
||||
);
|
||||
public $foreignKeys = array(
|
||||
);
|
||||
}
|
1
B8Framework/tests/data/view/Form/form.phtml
Executable file
1
B8Framework/tests/data/view/Form/form.phtml
Executable file
|
@ -0,0 +1 @@
|
|||
<?php print $action . $method; ?>
|
1
B8Framework/tests/data/view/format.phtml
Executable file
1
B8Framework/tests/data/view/format.phtml
Executable file
|
@ -0,0 +1 @@
|
|||
<?php print $this->Format()->Currency($number, $symbol); ?>
|
1
B8Framework/tests/data/view/simple.phtml
Executable file
1
B8Framework/tests/data/view/simple.phtml
Executable file
|
@ -0,0 +1 @@
|
|||
Hello
|
1
B8Framework/tests/data/view/vars.phtml
Executable file
1
B8Framework/tests/data/view/vars.phtml
Executable file
|
@ -0,0 +1 @@
|
|||
Hello <?php print $who; ?>
|
|
@ -24,13 +24,15 @@
|
|||
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PHPCI\\": "PHPCI"
|
||||
"PHPCI\\": "PHPCI/",
|
||||
"b8\\": "B8Framework/b8/"
|
||||
}
|
||||
},
|
||||
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\PHPCI\\": "Tests/PHPCI/"
|
||||
"Tests\\PHPCI\\": "Tests/PHPCI/",
|
||||
"Tests\\b8\\": "B8Framework/tests/"
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -38,7 +40,6 @@
|
|||
"php": ">=5.3.8",
|
||||
"ext-pdo": "*",
|
||||
"ext-pdo_mysql": "*",
|
||||
"block8/b8framework": "~1.0",
|
||||
"ircmaxell/password-compat": "~1.0",
|
||||
"swiftmailer/swiftmailer": "~5.0",
|
||||
"symfony/yaml": "~2.1",
|
||||
|
@ -57,6 +58,7 @@
|
|||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.5",
|
||||
"phpmd/phpmd": "~2.0",
|
||||
"sebastian/phpcpd": "~2.0",
|
||||
"squizlabs/php_codesniffer": "~2.3",
|
||||
"block8/php-docblock-checker": "~1.0",
|
||||
"phploc/phploc": "~2.0",
|
||||
|
|
138
composer.lock
generated
138
composer.lock
generated
|
@ -4,56 +4,9 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "de65276e03e231d7072c744a3c63662e",
|
||||
"content-hash": "1d9f6f487e6d906bbed73e2667c276d6",
|
||||
"hash": "4ab58f85da00db2f80ee2f0f4588339c",
|
||||
"content-hash": "13a76d8d0e7057023ac961bd9462122f",
|
||||
"packages": [
|
||||
{
|
||||
"name": "block8/b8framework",
|
||||
"version": "1.1.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Block8/b8framework.git",
|
||||
"reference": "5d2d2863ce15a6b91e0b2aed4250dd29c6224446"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Block8/b8framework/zipball/5d2d2863ce15a6b91e0b2aed4250dd29c6224446",
|
||||
"reference": "5d2d2863ce15a6b91e0b2aed4250dd29c6224446",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"symfony/yaml": "2.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"b8": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Block 8 Limited",
|
||||
"email": "hello@block8.co.uk",
|
||||
"homepage": "http://www.block8.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Simple, lightweight framework for high-throughput applications",
|
||||
"homepage": "https://github.com/block8/b8framework",
|
||||
"keywords": [
|
||||
"b8",
|
||||
"block8",
|
||||
"framework",
|
||||
"lightweight",
|
||||
"mvc",
|
||||
"php"
|
||||
],
|
||||
"time": "2015-10-05 10:50:20"
|
||||
},
|
||||
{
|
||||
"name": "guzzle/guzzle",
|
||||
"version": "v3.9.3",
|
||||
|
@ -264,16 +217,16 @@
|
|||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.3.0",
|
||||
"version": "1.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "31382fef2889136415751badebbd1cb022a4ed72"
|
||||
"reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/31382fef2889136415751badebbd1cb022a4ed72",
|
||||
"reference": "31382fef2889136415751badebbd1cb022a4ed72",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/2e89629ff057ebb49492ba08e6995d3a6a80021b",
|
||||
"reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -318,7 +271,7 @@
|
|||
"stream",
|
||||
"uri"
|
||||
],
|
||||
"time": "2016-04-13 19:56:01"
|
||||
"time": "2016-02-18 21:54:00"
|
||||
},
|
||||
{
|
||||
"name": "hipchat/hipchat-php",
|
||||
|
@ -455,16 +408,16 @@
|
|||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "1.19.0",
|
||||
"version": "1.18.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Seldaek/monolog.git",
|
||||
"reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf"
|
||||
"reference": "064b38c16790249488e7a8b987acf1c9d7383c09"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/5f56ed5212dc509c8dc8caeba2715732abb32dbf",
|
||||
"reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf",
|
||||
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/064b38c16790249488e7a8b987acf1c9d7383c09",
|
||||
"reference": "064b38c16790249488e7a8b987acf1c9d7383c09",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -529,7 +482,7 @@
|
|||
"logging",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2016-04-12 18:29:35"
|
||||
"time": "2016-04-02 13:12:58"
|
||||
},
|
||||
{
|
||||
"name": "mremi/flowdock",
|
||||
|
@ -663,9 +616,7 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com",
|
||||
"homepage": "http://fabien.potencier.org",
|
||||
"role": "Lead Developer"
|
||||
"email": "fabien@symfony.com"
|
||||
}
|
||||
],
|
||||
"description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
|
||||
|
@ -1551,20 +1502,20 @@
|
|||
},
|
||||
{
|
||||
"name": "phpmd/phpmd",
|
||||
"version": "2.4.3",
|
||||
"version": "2.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpmd/phpmd.git",
|
||||
"reference": "2b9c2417a18696dfb578b38c116cd0ddc19b256e"
|
||||
"reference": "fccbdb6b222f6d7a6d35af1c396ba5435cec76a9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpmd/phpmd/zipball/2b9c2417a18696dfb578b38c116cd0ddc19b256e",
|
||||
"reference": "2b9c2417a18696dfb578b38c116cd0ddc19b256e",
|
||||
"url": "https://api.github.com/repos/phpmd/phpmd/zipball/fccbdb6b222f6d7a6d35af1c396ba5435cec76a9",
|
||||
"reference": "fccbdb6b222f6d7a6d35af1c396ba5435cec76a9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"pdepend/pdepend": "^2.0.4",
|
||||
"pdepend/pdepend": "~2.0",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
|
@ -1612,7 +1563,7 @@
|
|||
"phpmd",
|
||||
"pmd"
|
||||
],
|
||||
"time": "2016-04-04 11:52:04"
|
||||
"time": "2016-03-10 17:17:44"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
|
@ -2411,6 +2362,57 @@
|
|||
],
|
||||
"time": "2015-10-12 03:26:01"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/phpcpd",
|
||||
"version": "2.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpcpd.git",
|
||||
"reference": "d3ad100fdf15805495f6ff19f473f4314c99390c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/d3ad100fdf15805495f6ff19f473f4314c99390c",
|
||||
"reference": "d3ad100fdf15805495f6ff19f473f4314c99390c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"phpunit/php-timer": "~1.0",
|
||||
"sebastian/finder-facade": "~1.1",
|
||||
"sebastian/version": "~1.0",
|
||||
"symfony/console": "~2.2",
|
||||
"theseer/fdomdocument": "~1.4"
|
||||
},
|
||||
"bin": [
|
||||
"phpcpd"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Copy/Paste Detector (CPD) for PHP code.",
|
||||
"homepage": "https://github.com/sebastianbergmann/phpcpd",
|
||||
"time": "2015-03-26 14:47:38"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/recursion-context",
|
||||
"version": "1.0.2",
|
||||
|
|
Loading…
Reference in a new issue