From 7c3d38b4e48c7abdb10ce3e0dd0a7e7d70658383 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 16 Nov 2014 13:40:05 +0100 Subject: [PATCH 001/231] Adding router example. --- src/Neuron/Router.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 1508f3a..60371bb 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -107,6 +107,10 @@ public function match($methods, $pattern, $fn) { } + public function controller ($pattern, \Neuron\FrontController $controller) + { + + } /** * Shorthand for a route accessed using GET From 7018c6df0d6147fdd4a9b588cda3150c489f009e Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 16 Nov 2014 16:33:19 +0100 Subject: [PATCH 002/231] Working on extending the Request model. --- src/Neuron/Interfaces/ModuleController.php | 23 ++++++++++ src/Neuron/Net/Request.php | 50 +++++++++++++++++++++- src/Neuron/Router.php | 2 +- 3 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 src/Neuron/Interfaces/ModuleController.php diff --git a/src/Neuron/Interfaces/ModuleController.php b/src/Neuron/Interfaces/ModuleController.php new file mode 100644 index 0000000..fa82988 --- /dev/null +++ b/src/Neuron/Interfaces/ModuleController.php @@ -0,0 +1,23 @@ +setMethod (self::getMethodFromInput ()); - $model->setMethod (isset($_SERVER['REQUEST_METHOD'])? $_SERVER['REQUEST_METHOD']: null); if (isset ($module)) { $model->setPath ($module); @@ -36,7 +36,7 @@ public static function fromInput () } $model->setBody (InputStream::getInput ()); - $model->setHeaders (getallheaders ()); + $model->setHeaders (self::getHeadersFromInput ()); $model->setParameters ($_GET); $model->setCookies ($_COOKIE); $model->setPost ($_POST); @@ -46,6 +46,52 @@ public static function fromInput () return $model; } + /** + * Get all request headers + * @return array The request headers + */ + private static function getHeadersFromInput () + { + // getallheaders available, use that + if (function_exists('getallheaders')) return getallheaders(); + + // getallheaders not available: manually extract 'm + $headers = array(); + foreach ($_SERVER as $name => $value) { + if ((substr($name, 0, 5) == 'HTTP_') || ($name == 'CONTENT_TYPE') || ($name == 'CONTENT_LENGTH')) { + $headers[str_replace(array(' ', 'Http'), array('-', 'HTTP'), ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; + } + } + return $headers; + } + + /** + * Get the request method used, taking overrides into account + * @return string The Request method to handle + */ + private static function getMethodFromInput () + { + // Take the method as found in $_SERVER + $method = $_SERVER['REQUEST_METHOD']; + + // If it's a HEAD request override it to being GET and prevent any output, as per HTTP Specification + // @url http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4 + if ($_SERVER['REQUEST_METHOD'] == 'HEAD') { + ob_start(); + $method = 'GET'; + } + + // If it's a POST request, check for a method override header + else if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $headers = self::getHeadersFromInput (); + if (isset($headers['X-HTTP-Method-Override']) && in_array($headers['X-HTTP-Method-Override'], array('PUT', 'DELETE', 'PATCH'))) { + $method = $headers['X-HTTP-Method-Override']; + } + } + + return $method; + } + /** * @param $json * @return Request diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 60371bb..3a80ac0 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -107,7 +107,7 @@ public function match($methods, $pattern, $fn) { } - public function controller ($pattern, \Neuron\FrontController $controller) + public function module ($pattern, \Neuron\FrontController $controller) { } From 23e682a4df874403d3675d41a653f21e0083c958 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 16 Nov 2014 19:01:03 +0100 Subject: [PATCH 003/231] Playing with templates. --- .../Controllers/TestController.php | 33 +++ example/ExampleModule/Module.php | 33 +++ .../templates/moduleexample.phpt | 3 + .../templates/sections/head.phpt | 1 + example/index.php | 18 +- example/templates/example.phpt | 3 + example/templates/index.phpt | 15 ++ example/templates/sections/head.phpt | 1 + src/Neuron/Core/Template.php | 214 ++++++++------- .../{ModuleController.php => Module.php} | 7 +- src/Neuron/Net/Request.php | 21 ++ src/Neuron/Net/Response.php | 24 +- src/Neuron/Router.php | 254 ++++++------------ src/Neuron/Tools/ControllerFactory.php | 51 ++++ src/templates/index.phpt | 14 + src/templates/sections/head.phpt | 1 + 16 files changed, 403 insertions(+), 290 deletions(-) create mode 100644 example/ExampleModule/Controllers/TestController.php create mode 100644 example/ExampleModule/Module.php create mode 100644 example/ExampleModule/templates/moduleexample.phpt create mode 100644 example/ExampleModule/templates/sections/head.phpt create mode 100644 example/templates/example.phpt create mode 100644 example/templates/index.phpt create mode 100644 example/templates/sections/head.phpt rename src/Neuron/Interfaces/{ModuleController.php => Module.php} (72%) create mode 100644 src/Neuron/Tools/ControllerFactory.php create mode 100644 src/templates/index.phpt create mode 100644 src/templates/sections/head.phpt diff --git a/example/ExampleModule/Controllers/TestController.php b/example/ExampleModule/Controllers/TestController.php new file mode 100644 index 0000000..93db858 --- /dev/null +++ b/example/ExampleModule/Controllers/TestController.php @@ -0,0 +1,33 @@ + 'yep')); + return $response; + } + + public function foo () + { + $response = \Neuron\Net\Response::json (array ('sdf' => 'yep')); + return $response; + } + + public function template () + { + $data = array ( + 'name' => 'Test variable ' . mt_rand (0, 5000) + ); + + $response = \Neuron\Net\Response::template ('example/moduleexample.phpt', $data); + return $response; + } + +} \ No newline at end of file diff --git a/example/ExampleModule/Module.php b/example/ExampleModule/Module.php new file mode 100644 index 0000000..a4399d8 --- /dev/null +++ b/example/ExampleModule/Module.php @@ -0,0 +1,33 @@ +get ($prefix . '/doSomething', 'TestController@doSomething'); + $router->get ($prefix . '/foo', 'TestController@foo'); + $router->get ($prefix . '/template', 'TestController@template'); + } +} \ No newline at end of file diff --git a/example/ExampleModule/templates/moduleexample.phpt b/example/ExampleModule/templates/moduleexample.phpt new file mode 100644 index 0000000..a1df87a --- /dev/null +++ b/example/ExampleModule/templates/moduleexample.phpt @@ -0,0 +1,3 @@ +layout ('index.phpt'); ?> + +

This is a module example page.

\ No newline at end of file diff --git a/example/ExampleModule/templates/sections/head.phpt b/example/ExampleModule/templates/sections/head.phpt new file mode 100644 index 0000000..3fe7fe5 --- /dev/null +++ b/example/ExampleModule/templates/sections/head.phpt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/example/index.php b/example/index.php index 6f0a395..ec78bed 100644 --- a/example/index.php +++ b/example/index.php @@ -4,24 +4,32 @@ require_once '../vendor/autoload.php'; +require_once 'ExampleModule/Module.php'; +require_once 'ExampleModule/Controllers/TestController.php'; + +// Register template directory +\Neuron\Core\Template::addTemplatePath (dirname (__FILE__) . '/templates/'); + $router = new \Neuron\Router (); $router->get ('/response', function () { - return \Neuron\Net\Response::json (array ('test')); - }); $router->get ('/string', function () { - return 'String'; - }); $router->get ('/void', function () { - echo 'void'; +}); +// Regular view, no module +$router->get ('/view', function () { + return \Neuron\Net\Response::template ('example.phpt'); }); +// Set module. +$router->module ('/module', new Module ()); + $router->run (); \ No newline at end of file diff --git a/example/templates/example.phpt b/example/templates/example.phpt new file mode 100644 index 0000000..fd26436 --- /dev/null +++ b/example/templates/example.phpt @@ -0,0 +1,3 @@ +layout ('index.phpt'); ?> + +

This is an example page.

\ No newline at end of file diff --git a/example/templates/index.phpt b/example/templates/index.phpt new file mode 100644 index 0000000..2e22d5f --- /dev/null +++ b/example/templates/index.phpt @@ -0,0 +1,15 @@ + + + + + combine ('sections/head.phpt'); ?> + + + + + +

EXAMPLE MAIN TEMPLATE

+ + + + \ No newline at end of file diff --git a/example/templates/sections/head.phpt b/example/templates/sections/head.phpt new file mode 100644 index 0000000..9a813c7 --- /dev/null +++ b/example/templates/sections/head.phpt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 53a9985..7ff774f 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -71,6 +71,8 @@ class Template private $sTextSection = null; private $objText = null; + + private $layoutRender = null; public static function load () { @@ -90,23 +92,14 @@ public static function setTemplatePath ($path) * @param $path: path to add * @param $prefix: only templates starting with given prefix will be loaded from this path. */ - public static function addTemplatePath ($path, $prefix, $priorize = false) + public static function addTemplatePath ($path, $prefix = '', $priorize = false) { + if (substr ($path, -1) !== '/') + $path .= '/'; + add_to_template_path ($path, $priorize, $prefix); } - public static function getUniqueId () - { - if (!isset ($_SESSION['tc'])) - { - $_SESSION['tc'] = time (); - } - - $_SESSION['tc'] ++; - - return $_SESSION['tc']; - } - private static function getTemplatePaths () { return explode (PATH_SEPARATOR, get_template_path ()); @@ -136,8 +129,7 @@ public function set ($var, $value, $overwrite = false, $first = false) // Intern function private function getText ($sKey, $sSection = null, $sFile = null, $sDefault = null) { - if (!isset ($this->objText)) - { + if (!isset ($this->objText)) { $this->objText = Text::__getInstance (); } @@ -162,68 +154,39 @@ private function getText ($sKey, $sSection = null, $sFile = null, $sDefault = nu public function setVariable ($var, $value, $overwrite = false, $first = false) { - if ($overwrite) - { + if ($overwrite) { $this->values[$var] = $value; } - else - { - if (isset ($this->values[$var])) - { - if ($first) - { + else { + if (isset ($this->values[$var])) { + if ($first) { $this->values[$var] = $value.$this->values[$var]; } - else - { + else { $this->values[$var].= $value; } } - else - { + else { $this->values[$var] = $value; } } } - - public function addListValue ($var, $value) - { - $this->lists[$var][] = $value; - } - - public function putIntoText ($txt, $params = array ()) - { - return Tools::putIntoText ($txt, $params); - } - - public function sortList ($var) - { - if (isset ($this->lists[$var])) - { - sort ($this->lists[$var]); - } - } - - public function usortList ($var, $function) - { - if (isset ($this->lists[$var])) - { - usort ($this->lists[$var], $function); - } - } - - public function isTrue ($var) - { - return isset ($this->values[$var]) && $this->values[$var]; - } - - private static function getFilename ($template) + + /** + * Return an array of all filenames, or FALSE if none are found. + * @param $template + * @param bool $all + * @return bool|string + */ + private static function getFilenames ($template, $all = false) { - foreach (self::getTemplatePaths () as $v) - { + $out = array (); + + foreach (self::getTemplatePaths () as $v) { + // Split prefix and folder $split = explode ('|', $v); @@ -235,80 +198,115 @@ private static function getFilename ($template) if ($templatefixed == $prefix) { - $templaterest = substr ($template, strlen ($templatefixed)); - if (is_readable ($folder . '/' . $templaterest)) + if (is_readable ($folder . $templaterest)) { - return $folder . '/' . $templaterest; + $out[] = $folder . $templaterest; + + if (!$all) + return $out; } } } else { - if (is_readable ($v . '/' . $template)) + if (is_readable ($v . $template)) { - return $v . '/' . $template; + $out[] = $v . $template; + + if (!$all) + return $out; } } } - + + if (count ($out) > 0) + { + return $out; + } return false; } public static function hasTemplate ($template) { - return self::getFilename ($template) != false; - } - - public function getClickTo ($sKey, $sSection = null, $sFile = null) - { - if (!isset ($this->objText)) - { - $this->objText = Text::__getInstance (); - } - - return $this->objText->getClickTo ($this->getText ($sKey, $sSection, $sFile)); + return self::getFilenames ($template) ? true : false; } public function parse ($template, $text = null) { - /* Set static url adress */ - $this->set ('STATIC_URL', TEMPLATE_DIR); - - // SEt unique id - $this->set ('templateID', self::getUniqueId ()); - - ob_start (); - - if (! $filename = $this->getFilename ($template)) + if (! $filenames = $this->getFilenames ($template)) { - echo '

Template not found

'; - echo '

The system could not find template "'.$template.'"

'; - - $filename = null; + $out = '

Template not found

'; + $out .= '

The system could not find template "'.$template.'"

'; + return $out; } + + ob_start (); - foreach ($this->values as $k => $v) - { + foreach ($this->values as $k => $v) { $$k = $v; } + + include $filenames[0]; - foreach ($this->lists as $k => $v) + $val = ob_get_contents(); + + ob_end_clean(); + + return $this->processRenderQueue (array ('content' => $val)); + } + + private function processRenderQueue ($contents = array ()) + { + if (isset ($this->layoutRender)) { - $n = 'list_'.$k; - $$n = $v; + $template = new self (); + + foreach ($contents as $k => $v) + { + $template->set ($k, $v); + } + + return $template->parse ($this->layoutRender); } - - - if (isset ($filename)) - { - include $filename; + else { + return $contents['content']; } - - $val = ob_get_contents(); - ob_end_clean(); + } - return $val; + /** + * Extend a parent theme. + * @param $layout + */ + private function layout ($layout) + { + $this->layoutRender = $layout; } -} -?> + + /** + * Go trough all set template directories and search for + * a specific template. Concat all of them. + */ + private function combine ($template) + { + $files = $this->getFilenames ($template, true); + if ($files) + { + ob_start (); + + foreach ($this->values as $k => $v) { + $$k = $v; + } + + foreach ($files as $file) { + include $file; + } + + $val = ob_get_contents(); + ob_end_clean(); + + return $val; + } + return ""; + } +} \ No newline at end of file diff --git a/src/Neuron/Interfaces/ModuleController.php b/src/Neuron/Interfaces/Module.php similarity index 72% rename from src/Neuron/Interfaces/ModuleController.php rename to src/Neuron/Interfaces/Module.php index fa82988..0d5ea43 100644 --- a/src/Neuron/Interfaces/ModuleController.php +++ b/src/Neuron/Interfaces/Module.php @@ -9,8 +9,13 @@ namespace Neuron\Interfaces; -interface ModuleController +interface Module { + /** + * Set template paths, config vars, etc + * @return void + */ + public function initialize (); /** * Register the routes required for this module. diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 3226b72..aefcca3 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -42,6 +42,7 @@ public static function fromInput () $model->setPost ($_POST); $model->setEnvironment ($_SERVER); $model->setStatus (http_response_code ()); + $model->setUrl (self::getCurrentUri ()); return $model; } @@ -92,6 +93,26 @@ private static function getMethodFromInput () return $method; } + /** + * Define the current relative URI + * @return string + */ + private static function getCurrentUri () + { + // Get the current Request URI and remove rewrite basepath from it (= allows one to run the router in a subfolder) + $basepath = implode('/', array_slice(explode('/', $_SERVER['SCRIPT_NAME']), 0, -1)) . '/'; + $uri = substr($_SERVER['REQUEST_URI'], strlen($basepath)); + + // Don't take query params into account on the URL + if (strstr($uri, '?')) $uri = substr($uri, 0, strpos($uri, '?')); + + // Remove trailing slash + enforce a slash at the start + $uri = '/' . trim($uri, '/'); + + return $uri; + + } + /** * @param $json * @return Request diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 43fb6cc..c1b7c3e 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -93,7 +93,29 @@ public static function error ($data) { $in = new self (); $in->setData ($data); - $in->setData (new HTML ()); + $in->setOutput (new HTML ()); + return $in; + } + + /** + * @param $name + * @param $data + * @return Response + */ + public static function template ($name, $data = array ()) + { + $in = new self (); + + $template = new \Neuron\Core\Template (); + + foreach ($data as $k => $v) + { + $template->set ($k, $v); + } + + $in->setBody ($template->parse ($name)); + $in->setOutput (new HTML ()); + return $in; } diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 3a80ac0..1d4201d 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -1,29 +1,5 @@ * @copyright Copyright (c), 2013 Bram(us) Van Damme @@ -32,6 +8,8 @@ namespace Neuron; +use Neuron\Exceptions\InvalidParameter; + class Router { @@ -40,13 +18,6 @@ class Router { */ private $routes = array(); - - /** - * @var array The before middleware route patterns and their handling functions - */ - private $befores = array(); - - /** * @var object The function to be executed when no route has been matched */ @@ -64,27 +35,10 @@ class Router { */ private $method = ''; - /** - * Store a before middleware route and a handling function to be executed when accessed using one of the specified methods - * - * @param string $methods Allowed methods, | delimited - * @param string $pattern A route pattern such as /about/system - * @param object $fn The handling function to be executed + * @var \Neuron\FrontController */ - public function before($methods, $pattern, $fn) { - - $pattern = $this->baseroute . '/' . trim($pattern, '/'); - $pattern = $this->baseroute ? rtrim($pattern, '/') : $pattern; - - foreach (explode('|', $methods) as $method) { - $this->befores[$method][] = array( - 'pattern' => $pattern, - 'fn' => $fn - ); - } - - } + private $frontController; /** * Store a route and a handling function to be executed when accessed using one of the specified methods @@ -107,10 +61,6 @@ public function match($methods, $pattern, $fn) { } - public function module ($pattern, \Neuron\FrontController $controller) - { - - } /** * Shorthand for a route accessed using GET @@ -166,7 +116,6 @@ public function put($pattern, $fn) { $this->match('PUT', $pattern, $fn); } - /** * Shorthand for a route accessed using OPTIONS * @@ -178,96 +127,38 @@ public function options($pattern, $fn) { } /** - * Mounts a collection of callables onto a base route - * - * @param string $baseroute The route subpattern to mount the callables on - * @param callable $fn The callabled to be called + * @param $prefix + * @param Interfaces\Module $module */ - public function mount($baseroute, $fn) { - - // Track current baseroute - $curBaseroute = $this->baseroute; - - // Build new baseroute string - $this->baseroute .= $baseroute; - - // Call the callable - call_user_func($fn); - - // Restore original baseroute - $this->baseroute = $curBaseroute; - - } - - - /** - * Get all request headers - * @return array The request headers - */ - public function getRequestHeaders() { - - // getallheaders available, use that - if (function_exists('getallheaders')) return getallheaders(); - - // getallheaders not available: manually extract 'm - $headers = array(); - foreach ($_SERVER as $name => $value) { - if ((substr($name, 0, 5) == 'HTTP_') || ($name == 'CONTENT_TYPE') || ($name == 'CONTENT_LENGTH')) { - $headers[str_replace(array(' ', 'Http'), array('-', 'HTTP'), ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; - } - } - return $headers; - + public function module ($prefix, \Neuron\Interfaces\Module $module) + { + $module->initialize (); + $module->setRoutes ($this, $prefix); } - /** - * Get the request method used, taking overrides into account - * @return string The Request method to handle + * Execute the router: Loop all defined before middlewares and routes, and execute the handling function if a mactch was found + * + * @param callable|null $callback Function to be executed after a matching route was handled (= after router middleware) + * @return \Neuron\Net\Response */ - public function getRequestMethod() { - - // Take the method as found in $_SERVER - $method = $_SERVER['REQUEST_METHOD']; + public function run (callable $callback = null) { - // If it's a HEAD request override it to being GET and prevent any output, as per HTTP Specification - // @url http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4 - if ($_SERVER['REQUEST_METHOD'] == 'HEAD') { - ob_start(); - $method = 'GET'; - } + // Set fallback template directory + \Neuron\Core\Template::addTemplatePath (dirname (dirname (__FILE__)) . '/templates/'); - // If it's a POST request, check for a method override header - else if ($_SERVER['REQUEST_METHOD'] == 'POST') { - $headers = $this->getRequestHeaders(); - if (isset($headers['X-HTTP-Method-Override']) && in_array($headers['X-HTTP-Method-Override'], array('PUT', 'DELETE', 'PATCH'))) { - $method = $headers['X-HTTP-Method-Override']; - } - } + $request = \Neuron\Net\Request::fromInput (); - return $method; - - } - - - /** - * Execute the router: Loop all defined before middlewares and routes, and execute the handling function if a mactch was found - * - * @param object $callback Function to be executed after a matching route was handled (= after router middleware) - */ - public function run($callback = null) { + $this->frontController = \Neuron\FrontController::getInstance (); + $this->frontController->setRequest ($request); // Define which method we need to handle - $this->method = $this->getRequestMethod(); - - // Handle all before middlewares - if (isset($this->befores[$this->method])) - $this->handle($this->befores[$this->method]); + $this->method = $request->getMethod (); // Handle all routes $numHandled = 0; if (isset($this->routes[$this->method])) - $numHandled = $this->handle($this->routes[$this->method], true); + $this->handle($this->routes[$this->method], true); // If no route was handled, trigger the 404 (if any) if ($numHandled == 0) { @@ -276,7 +167,7 @@ public function run($callback = null) { } // If a route was handled, perform the finish callback (if any) else { - if ($callback && is_callable ($callback)) $callback(); + if ($callback) $callback(); } // If it originally was a HEAD request, clean up after ourselves by emptying the output buffer @@ -298,18 +189,12 @@ public function set404($fn) { * Handle a a set of routes: if a match is found, execute the relating handling function * @param array $routes Collection of route patterns and their handling functions * @param boolean $quitAfterRun Does the handle function need to quit after one route was matched? - * @return int The number of routes handled + * @return \Neuron\Net\Response The response */ - private function handle($routes, $quitAfterRun = false) { - - // Counter to keep track of the number of routes we've handled - $numHandled = 0; + private function handle($routes) { // The current page URL - $uri = $this->getCurrentUri(); - - // Variables in the URL - $urlvars = array(); + $uri = $this->frontController->getRequest ()->getUrl (); // Loop all routes foreach ($routes as $route) { @@ -336,62 +221,81 @@ private function handle($routes, $quitAfterRun = false) { }, $matches, array_keys($matches)); // call the handling function with the URL parameters - $this->handleOutput (call_user_func_array($route['fn'], $params)); + $this->handleMatch ($route['fn'], $params); + //call_user_func_array($route['fn'], $params); // yay! - $numHandled++; + //$numHandled++; // If we need to quit, then quit - if ($quitAfterRun) break; + //if ($quitAfterRun) break; } } - // Return the number of routes handled - return $numHandled; + return false; } - private function handleOutput ($output) + /** + * @param $function + * @param $params + * @throws InvalidParameter + */ + private function handleMatch ($function, $params) { - if (!$output) + if (is_callable ($function)) { - // Nothing to do. - return; + $response = call_user_func_array($function, $params); } - - if ($output instanceof \Neuron\Net\Response) - { - $output->output (); + else { + if (strpos ($function, '@')) + { + $param = explode ('@', $function); + if (count ($param) !== 2) + { + throw new InvalidParameter ("Controller@method syntax not valid for " . $function); + } + + $response = $this->handleController ($param[0], $param[1], $params); + } + else { + throw new InvalidParameter ("Method not found."); + } } - else { - echo $output; + if ($response) + { + if ($response instanceof \Neuron\Net\Response) + { + $response->output (); + } + else { + echo $response; + } } } - /** - * Define the current relative URI - * @return string + * @param string $controller + * @param string $method + * @param array $params + * @throws Exceptions\DataNotFound + * @throws InvalidParameter + * @return mixed */ - private function getCurrentUri() { - - // Get the current Request URI and remove rewrite basepath from it (= allows one to run the router in a subfolder) - $basepath = implode('/', array_slice(explode('/', $_SERVER['SCRIPT_NAME']), 0, -1)) . '/'; - $uri = substr($_SERVER['REQUEST_URI'], strlen($basepath)); - - // Don't take query params into account on the URL - if (strstr($uri, '?')) $uri = substr($uri, 0, strpos($uri, '?')); - - // Remove trailing slash + enforce a slash at the start - $uri = '/' . trim($uri, '/'); - - return $uri; + private function handleController ($controller, $method, $params) + { + $controller = \Neuron\Tools\ControllerFactory::getInstance ()->getController ($controller); + if (is_callable (array ($controller, $method))) + { + return call_user_func_array(array ($controller, $method), $params); + } + else { + throw new InvalidParameter ("Method not found."); + } } -} - -// EOF \ No newline at end of file +} \ No newline at end of file diff --git a/src/Neuron/Tools/ControllerFactory.php b/src/Neuron/Tools/ControllerFactory.php new file mode 100644 index 0000000..562681b --- /dev/null +++ b/src/Neuron/Tools/ControllerFactory.php @@ -0,0 +1,51 @@ +controllers[$name] = new $name (); + } + else { + throw new DataNotFound ("Controller not found: " . $name); + } + + return $this->controllers[$name]; + } +} \ No newline at end of file diff --git a/src/templates/index.phpt b/src/templates/index.phpt new file mode 100644 index 0000000..3916b6e --- /dev/null +++ b/src/templates/index.phpt @@ -0,0 +1,14 @@ + + + + + combine ('sections/head.phpt'); ?> + + + + + + + + + \ No newline at end of file diff --git a/src/templates/sections/head.phpt b/src/templates/sections/head.phpt new file mode 100644 index 0000000..3ef5097 --- /dev/null +++ b/src/templates/sections/head.phpt @@ -0,0 +1 @@ + \ No newline at end of file From 4272825a623defc1e2fd5bbbd5937b7616984755 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 16 Nov 2014 19:50:59 +0100 Subject: [PATCH 004/231] Playing with routers and controllers and modules. --- .../Controllers/TestController.php | 9 +++ example/ExampleModule/Module.php | 2 + example/index.php | 6 ++ src/Neuron/Core/Template.php | 63 +++++++++++++------ src/Neuron/Environment.php | 1 + src/Neuron/Net/Response.php | 22 ++++++- src/Neuron/Router.php | 20 ++++-- src/templates/404.phpt | 1 + 8 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 src/templates/404.phpt diff --git a/example/ExampleModule/Controllers/TestController.php b/example/ExampleModule/Controllers/TestController.php index 93db858..ef00a3f 100644 --- a/example/ExampleModule/Controllers/TestController.php +++ b/example/ExampleModule/Controllers/TestController.php @@ -30,4 +30,13 @@ public function template () return $response; } + public function home () + { + $data = array ( + 'name' => 'Test variable ' . mt_rand (0, 5000) + ); + + $response = \Neuron\Net\Response::template ('example/moduleexample.phpt', $data); + return $response; + } } \ No newline at end of file diff --git a/example/ExampleModule/Module.php b/example/ExampleModule/Module.php index a4399d8..da3d67f 100644 --- a/example/ExampleModule/Module.php +++ b/example/ExampleModule/Module.php @@ -29,5 +29,7 @@ public function setRoutes (\Neuron\Router $router, $prefix) $router->get ($prefix . '/doSomething', 'TestController@doSomething'); $router->get ($prefix . '/foo', 'TestController@foo'); $router->get ($prefix . '/template', 'TestController@template'); + + $router->get ($prefix . '/', 'TestController@home'); } } \ No newline at end of file diff --git a/example/index.php b/example/index.php index ec78bed..3241592 100644 --- a/example/index.php +++ b/example/index.php @@ -29,6 +29,12 @@ return \Neuron\Net\Response::template ('example.phpt'); }); +$router->get ('/', function () { + $response = new \Neuron\Net\Response (); + $response->redirect (\Neuron\URLBuilder::getURL ('module')); + return $response; +}); + // Set module. $router->module ('/module', new Module ()); diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 7ff774f..8147811 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -73,12 +73,33 @@ class Template private $objText = null; private $layoutRender = null; + + // Yea, ugly. I know. + static $shares = array (); public static function load () { } + /** + * Clear all shared variables. + */ + public static function clearShares () + { + self::$shares = array (); + } + + /** + * Set a variable that will be shared across all templates. + * @param $name + * @param $value + */ + public static function share ($name, $value) + { + self::$shares[$name] = $value; + } + /** * I believe this is a nicer way to do the directory setting. */ @@ -234,7 +255,7 @@ public static function hasTemplate ($template) public function parse ($template, $text = null) { - if (! $filenames = $this->getFilenames ($template)) + if (! $ctlbtmpltfiles = $this->getFilenames ($template)) { $out = '

Template not found

'; $out .= '

The system could not find template "'.$template.'"

'; @@ -242,12 +263,17 @@ public function parse ($template, $text = null) } ob_start (); - + + foreach (self::$shares as $k => $v) + { + ${$k} = $v; + } + foreach ($this->values as $k => $v) { - $$k = $v; + ${$k} = $v; } - include $filenames[0]; + include $ctlbtmpltfiles[0]; $val = ob_get_contents(); @@ -289,24 +315,25 @@ private function layout ($layout) */ private function combine ($template) { - $files = $this->getFilenames ($template, true); - if ($files) - { - ob_start (); + ob_start(); - foreach ($this->values as $k => $v) { - $$k = $v; - } + foreach (self::$shares as $k => $v) { + ${$k} = $v; + } - foreach ($files as $file) { - include $file; + foreach ($this->values as $k => $v) { + ${$k} = $v; + } + + if ($ctlbtmpltfiles = $this->getFilenames($template, true)) { + foreach ($ctlbtmpltfiles as $ctlbtmpltfile) { + include $ctlbtmpltfile; } + } - $val = ob_get_contents(); - ob_end_clean(); + $val = ob_get_contents(); + ob_end_clean(); - return $val; - } - return ""; + return $val; } } \ No newline at end of file diff --git a/src/Neuron/Environment.php b/src/Neuron/Environment.php index eb4ddc0..4e05880 100644 --- a/src/Neuron/Environment.php +++ b/src/Neuron/Environment.php @@ -20,6 +20,7 @@ public static function destroy () \Neuron\Session::getInstance ()->disconnect (); \Neuron\Session::clearInstance (); \Neuron\FrontController::destroy (); + \Neuron\Core\Template::clearShares (); } } \ No newline at end of file diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index c1b7c3e..f8eca9a 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -121,11 +121,31 @@ public static function template ($name, $data = array ()) private $output; - public function redirect ($url) + /** + * Create a redirect response. + * @param $url + * @return Response + */ + public static function redirect ($url) + { + $response = new self (); + $response->setRedirect ($url); + + return $response; + } + + /** + * Set a response to be a redirect. + * @param $url + * @return $this + */ + public function setRedirect ($url) { $this->setHeader ('Location', $url); $this->setStatus (302); $this->setData (array ('message' => 'Redirecting to ' . $url)); + + return $this; } public function getJSONData () diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 1d4201d..8419b15 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -158,12 +158,20 @@ public function run (callable $callback = null) { // Handle all routes $numHandled = 0; if (isset($this->routes[$this->method])) - $this->handle($this->routes[$this->method], true); + $numHandled = $this->handle($this->routes[$this->method], true); // If no route was handled, trigger the 404 (if any) if ($numHandled == 0) { - if ($this->notFound && is_callable($this->notFound)) call_user_func($this->notFound); - else header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found'); + if ($this->notFound) { + //call_user_func($this->notFound); + $this->handleMatch ($this->notFound, array ()); + } + else { + + $request = \Neuron\Net\Response::template ('404.phpt'); + $request->setStatus (404); + $request->output (); + } } // If a route was handled, perform the finish callback (if any) else { @@ -196,6 +204,8 @@ private function handle($routes) { // The current page URL $uri = $this->frontController->getRequest ()->getUrl (); + $numHandled = 0; + // Loop all routes foreach ($routes as $route) { @@ -225,7 +235,7 @@ private function handle($routes) { //call_user_func_array($route['fn'], $params); // yay! - //$numHandled++; + $numHandled ++; // If we need to quit, then quit //if ($quitAfterRun) break; @@ -234,7 +244,7 @@ private function handle($routes) { } - return false; + return $numHandled; } diff --git a/src/templates/404.phpt b/src/templates/404.phpt new file mode 100644 index 0000000..d9f18f5 --- /dev/null +++ b/src/templates/404.phpt @@ -0,0 +1 @@ +

404 Not found

\ No newline at end of file From b990f81821e7978eefac0898b61c584f7a3d95fd Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 10:45:03 +0100 Subject: [PATCH 005/231] Playing with routers and controllers and modules. --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 739235b..090906f 100644 --- a/composer.json +++ b/composer.json @@ -14,8 +14,8 @@ } ], "autoload": { - "psr-0" : { - "Neuron" : "src" + "psr-4" : { + "Neuron" : "src/Neuron/" } } } \ No newline at end of file From 024b984d4a73ac81bff84d1eedcd287603ed79db Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 10:45:38 +0100 Subject: [PATCH 006/231] Playing with routers and controllers and modules. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 090906f..d28d011 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "autoload": { "psr-4" : { - "Neuron" : "src/Neuron/" + "Neuron\\" : "src/Neuron/" } } } \ No newline at end of file From 348534bd29d0bc0fae22bff7eee9b3a52f094b8a Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 11:07:09 +0100 Subject: [PATCH 007/231] Making template name assignment possible on template construction. --- src/Neuron/Core/Template.php | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 8147811..040096e 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -5,7 +5,7 @@ use Neuron\Core\Text; use Neuron\Core\Tools; - +use Neuron\Exceptions\DataNotSet; // A few ugly methods because this wasn't very well designed at first? ;-) @@ -76,12 +76,23 @@ class Template // Yea, ugly. I know. static $shares = array (); + + private $template; public static function load () { } + /** + * Create a template. + * @param $template + */ + public function __construct ($template) + { + $this->template = $template; + } + /** * Clear all shared variables. */ @@ -253,8 +264,19 @@ public static function hasTemplate ($template) return self::getFilenames ($template) ? true : false; } - public function parse ($template, $text = null) + public function parse ($template = null, $text = null) { + if (!isset ($template)) + { + if (isset ($this->template)) + { + $template = $this->template; + } + else { + throw new DataNotSet ("You must define a template name in constructor or as parse method parameter."); + } + } + if (! $ctlbtmpltfiles = $this->getFilenames ($template)) { $out = '

Template not found

'; From e80c4dc5442222f8fe7e8e87a0a1868ede37d0c7 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 11:12:54 +0100 Subject: [PATCH 008/231] Allowing passing a template object in response class. --- src/Neuron/Core/Template.php | 2 +- src/Neuron/Net/Response.php | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 040096e..516774b 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -88,7 +88,7 @@ public static function load () * Create a template. * @param $template */ - public function __construct ($template) + public function __construct ($template = null) { $this->template = $template; } diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index f8eca9a..255437f 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -9,6 +9,7 @@ namespace Neuron\Net; +use Neuron\Core\Template; use Neuron\Models\User; use Neuron\Net\Outputs\HTML; use Neuron\Net\Outputs\JSON; @@ -106,15 +107,20 @@ public static function template ($name, $data = array ()) { $in = new self (); - $template = new \Neuron\Core\Template (); - - foreach ($data as $k => $v) + if ($name instanceof Template) { - $template->set ($k, $v); + $in->setTemplate ($name); } + else { + $template = new Template ($name); - $in->setBody ($template->parse ($name)); - $in->setOutput (new HTML ()); + foreach ($data as $k => $v) + { + $template->set ($k, $v); + } + + $in->setTemplate ($template); + } return $in; } @@ -160,6 +166,12 @@ public function getJSONData () return $data; } + private function setTemplate (Template $template) + { + $this->setBody ($template->parse ()); + $this->setOutput (new HTML ()); + } + public function setOutput (Output $output) { $this->output = $output; From f644c644d22acc6dbada1247a8fa50c138083aef Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 11:15:15 +0100 Subject: [PATCH 009/231] Allowing passing a template object in response class. --- src/Neuron/Net/Response.php | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 255437f..0671bc9 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -99,29 +99,27 @@ public static function error ($data) } /** - * @param $name - * @param $data + * @param Template|string $template + * @param array $data * @return Response */ - public static function template ($name, $data = array ()) + public static function template ($template, $data = array ()) { $in = new self (); - if ($name instanceof Template) + if (! ($template instanceof Template)) { - $in->setTemplate ($name); - } - else { - $template = new Template ($name); + $template = new Template ($template); - foreach ($data as $k => $v) - { - $template->set ($k, $v); - } + } - $in->setTemplate ($template); + foreach ($data as $k => $v) + { + $template->set ($k, $v); } + $in->setTemplate ($template); + return $in; } From 41a7b2fd8301a29f110a2cfe44d4b615cf2b8c86 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 11:18:31 +0100 Subject: [PATCH 010/231] Cleaning up database module. --- src/Neuron/DB/DatabaseSQLite.php | 225 -------------- src/Neuron/DB/QuerySQLite.php | 499 ------------------------------- src/Neuron/DB/SQLite.php | 202 ------------- 3 files changed, 926 deletions(-) delete mode 100644 src/Neuron/DB/DatabaseSQLite.php delete mode 100644 src/Neuron/DB/QuerySQLite.php delete mode 100644 src/Neuron/DB/SQLite.php diff --git a/src/Neuron/DB/DatabaseSQLite.php b/src/Neuron/DB/DatabaseSQLite.php deleted file mode 100644 index b015dbd..0000000 --- a/src/Neuron/DB/DatabaseSQLite.php +++ /dev/null @@ -1,225 +0,0 @@ -logger = $logger; - } - - /** - * @return Database - */ - public static function getInstance () - { - return self::__getInstance (); - } - - public function getInsertId () - { - return $this->insert_id; - } - - public function getAffectedRows () - { - return $this->affected_rows; - } - - public function getQueryCounter () - { - return $this->query_counter; - } - - // Abstract functions - public abstract function query ($sSQL); - public abstract function multiQuery ($sSQL); - public abstract function escape ($txt); - - public function start () - { - $this->query ("START TRANSACTION"); - } - - public function commit () - { - $this->query ("COMMIT"); - } - - public function rollback () - { - $this->query ("ROLLBACK"); - } - - /** - * Just put a comment in the query log. - * Does not connect to database. - * @param $txt - */ - public function log ($txt) - { - $this->addQueryLog ("/* " . $txt . " */"); - } - - protected function addQueryLog ($sSQL, $duration = null) - { - - // SQL LOGGING :: BEGIN - if (defined ('DB_CUSTOM_LOG_SQLITE') && DB_CUSTOM_LOG_SQLITE) { - - $error_log_folder = str_replace('\\','/', dirname(__FILE__) .'/../../../../logs'); - $error_log_filename = "$error_log_folder/sqlite_log.txt"; - $error_log_extended_filename = "$error_log_folder/sqlite_log_extended.txt"; - - //$str_context = print_r($context, true); - - //$str_debug_backtrace = print_r(debug_backtrace(), true); - - $str_log = "-- ----------------------------------------------------------------------------\n$sSQL;\n"; - - file_put_contents($error_log_filename, $str_log, FILE_APPEND | LOCK_EX); - } - - // SQL LOGGING :: END - - - if (! (defined ('DEBUG') && DEBUG) && !isset ($_GET['debug'])) - { - return; - } - - if (count ($this->query_log) > 5000) - { - array_shift ($this->query_log); - } - - $stacktrace = debug_backtrace (); - $origin = $stacktrace[1]; - - //var_dump ($stacktrace[2]); - - if (isset ($stacktrace[2]['class']) && $stacktrace[2]['class'] == 'Neuron\DB\Query') - { - $origin = $stacktrace[2]; - } - - $txt = '[' . number_format ($duration, 3) . ' s] '; - //$txt .= $origin['class'] . ' '; - - // QUery took longer than 1 second? - /* - if ($duration > 0.1) - { - $txt = '' . $txt . ''; - } - */ - - $txt .= trim ($sSQL); - - $this->increaseOriginCounter ($origin['file'], $origin['line']); - //$txt .= '
' . $origin['file'] . ':' . $origin['line']; - - if (isset ($this->logger)) - { - $color = 'green'; - if (strpos ($txt, 'START') !== false || strpos ($txt, 'COMMIT') !== false || strpos ($txt, 'ROLLBACK') !== false) - { - $color = 'red'; - } - - $this->logger->log ('DB: ' . preg_replace('!\s+!', ' ', str_replace ("\t", " ", str_replace ("\n", "", $txt))), false, $color); - } - - $this->query_log[] = $txt; - } - - public function getLastQuery () - { - return $this->query_log[count ($this->query_log) - 1]; - } - - public function getAllQueries () - { - return $this->query_log; - } - - public function getConnection () - { - - } - - private function increaseOriginCounter ($file, $line) - { - if (!isset ($this->origin_counter[$file . ':' . $line])) - { - $this->origin_counter[$file . ':' . $line] = 1; - } - else - { - $this->origin_counter[$file . ':' . $line] ++; - } - } - - public function getOriginCounters () - { - arsort ($this->origin_counter, SORT_NUMERIC); - - $out = array (); - foreach ($this->origin_counter as $k => $v) - { - $out[] = 'Queries: ' . $v . ': ' . $k; - } - return $out; - } - - // Functions that should not be used... but well, we can't do without them at the moment - public abstract function fromUnixtime ($timestamp); - public abstract function toUnixtime ($date); -} -?> diff --git a/src/Neuron/DB/QuerySQLite.php b/src/Neuron/DB/QuerySQLite.php deleted file mode 100644 index a7ca588..0000000 --- a/src/Neuron/DB/QuerySQLite.php +++ /dev/null @@ -1,499 +0,0 @@ - $v) - { - $str_columns .= "$k,"; - - //TODO: Prepare binValues with SQLite3 - //$str_values .= $k . ' = ?, '; - - $str_values .= '\''. $v .'\', '; - - // No array? Then it's a simple string. - if (is_array ($v)) - { - $values[] = $v; - } - else - { - $values[] = array ($v); - } - } - - $str_columns = substr($str_columns, 0, -1); - - $str_values = substr($str_values, 0, -2); - - $query = "$query ( $str_columns ) VALUES ( $str_values )"; - - $query = new self ($query); - //$query->bindValues ($values); - - return $query; - } - - /** - * Generate an replace query - * @param $table: table to insert data to - * @param $set: a 2 dimensional array with syntax: { column_name : [ value, type, nullOnEmpty ]} - * @return Query - */ - public static function replace ($table, array $set) - { - $query = 'REPLACE INTO `' . $table . '` SET '; - $values = array (); - foreach ($set as $k => $v) - { - $query .= $k . ' = ?, '; - - // No array? Then it's a simple string. - if (is_array ($v)) - { - $values[] = $v; - } - else - { - $values[] = array ($v); - } - } - - $query = substr ($query, 0, -2); - - $query = new self ($query); - $query->bindValues ($values); - - return $query; - } - - /** - * Generate an insert query - * @param $table: table to insert data to - * @param $set: a 2 dimensional array with syntax: { column_name : [ value, type, nullOnEmpty ]} - * @param $where: a 2 dimensional array with syntax: { column_name : [ value, type, nullOnEmpty ]} - * nullOnEmpty may be omitted. - * @return Query - */ - public static function update ($table, array $set, array $where) - { - $query = 'UPDATE `' . $table . '` SET '; - $values = array (); - foreach ($set as $k => $v) - { - $query .= $k . ' = ?, '; - - // No array? Then it's a simple string. - if (is_array ($v)) - { - $values[] = $v; - } - else - { - $values[] = array ($v); - } - } - - $query = substr ($query, 0, -2) . ' '; - $query .= self::processWhere ($where, $values); - - $query = new self ($query); - $query->bindValues ($values); - - return $query; - } - - private static function processWhere (array $where, &$values) - { - $query = ''; - - if (count ($where) > 0) - { - $query .= 'WHERE '; - foreach ($where as $k => $v) - { - // No array? Then it's a simple string. - if (is_array ($v)) - { - $tmp = $v; - } - else - { - $tmp = array ($v, self::PARAM_STR); - } - - if (!is_array ($tmp[0]) && substr ($tmp[0], 0, 1) == '!') - { - $query .= $k . ' != ? AND '; - $tmp[0] = substr ($tmp[0], 1); - } - - else if (isset ($tmp[2]) && strtoupper ($tmp[2]) == 'LIKE') - { - $query .= $k . ' LIKE ? AND '; - $tmp = array ($tmp[0], $tmp[1]); - } - - else if (isset ($tmp[2]) && strtoupper ($tmp[2]) == 'NOT') - { - $query .= $k . ' != ? AND '; - $tmp = array ($tmp[0], $tmp[1]); - } - - else if (isset ($tmp[2]) - && ( - strtoupper ($tmp[2]) == '>' - || strtoupper ($tmp[2]) == '<' - || strtoupper ($tmp[2]) == '>=' - || strtoupper ($tmp[2]) == '<=' - || strtoupper ($tmp[2]) == '!=' - ) - ) - { - $query .= $k . ' ' . $tmp[2] . ' ? AND '; - $tmp = array ($tmp[0], $tmp[1]); - } - - else if (isset ($tmp[2]) && strtoupper ($tmp[2]) == 'IN') - { - $query .= $k . ' ' . $tmp[2] . ' ? AND '; - $tmp = array ($tmp[0], $tmp[1]); - } - - else if (is_array ($tmp[0])) - { - $query .= $k . ' IN ? AND '; - } - - else - { - $query .= $k . ' = ? AND '; - } - - $values[] = $tmp; - } - - $query = substr ($query, 0, -5); - } - - return $query; - } - - /** - * Select data from a message - * @param $table - * @param array $data : array of column names [ column1, column2 ] - * @param array $where : a 2 dimensional array with syntax: { column_name : [ value, type, nullOnEmpty ]} - * @param array $order - * @param null $limit - * @return Query - */ - public static function select ($table, array $data = array (), array $where = array (), $order = array (), $limit = null) - { - $query = 'SELECT '; - $values = array (); - - if (count ($data) > 0) - { - foreach ($data as $v) - { - $query .= $v . ', '; - } - $query = substr ($query, 0, -2) . ' '; - } - else - { - $query .= '* '; - } - - $query .= 'FROM `' . $table . '` '; - $query .= self::processWhere ($where, $values); - - // Order - if (count ($order) > 0) - { - $query .= " ORDER BY "; - foreach ($order as $v) - { - $query .= $v . ", "; - } - $query = substr ($query, 0, -2); - } - - // Limit - if ($limit) - { - $query .= " LIMIT " . $limit; - } - - $query = new self ($query); - $query->bindValues ($values); - - return $query; - } - - /** - * @param $table - * @param array $where - * @return Query|string - */ - public static function delete ($table, array $where) - { - $query = 'DELETE FROM `' . $table . '`'; - - $values = array (); - $query .= self::processWhere ($where, $values); - - $query = new self ($query); - $query->bindValues ($values); - - return $query; - } - - /** - * And construct. - */ - public function __construct ($query) - { - $this->query = $query; - } - - public function bindValues ($values) - { - $this->values = $values; - } - - public function bindValue ($index, $value, $type = self::PARAM_STR, $canBeNull = false) - { - $this->values[$index] = array ($value, $type, $canBeNull); - - // Chaining - return $this; - } - - public function getParsedQuery () - { - $db = DatabaseSQLite::getInstance (); - - $keys = array (); - $values = array (); - - foreach ($this->values as $k => $v) - { - // Column type? - if (!isset ($v[1])) - { - // Check for known "special types" - if ($v[0] instanceof Point) - { - $v[1] = self::PARAM_POINT; - } - else - { - $v[1] = self::PARAM_STR; - } - } - - // NULL on empty? - if (!isset ($v[2])) - { - $v[2] = false; - } - - // Empty and should set NULL? - if ($v[2] && empty ($v[0])) - { - $value = "NULL"; - } - else - { - // Array? - if (is_array ($v[0])) - { - switch ($v[1]) - { - case self::PARAM_NUMBER: - foreach ($v[0] as $kk => $vv) - { - if (!is_numeric ($vv)) - { - throw new InvalidParameter ("Parameter " . $k . "[" . $kk . "] should be numeric in query " . $this->query); - } - } - $value = '(' . implode (',', $v[0]) . ')'; - break; - - case self::PARAM_DATE: - - $tmp = array (); - foreach ($v[0] as $kk => $vv) - { - if (!is_numeric ($vv)) - { - throw new InvalidParameter ("Parameter " . $k . "[" . $kk . "] should be a valid timestamp in query " . $this->query); - } - $tmp[] = "FROM_UNIXTIME(" . $vv . ")"; - } - $value = '(' . implode (',', $tmp) . ')'; - - break; - - case self::PARAM_POINT: - $tmp = array (); - foreach ($v[0] as $kk => $vv) - { - if (! ($vv instanceof Point)) - { - throw new InvalidParameter ("Parameter " . $k . "[" . $kk . "] should be a valid \\Neuron\\Models\\Point " . $this->query); - } - $tmp[] = "POINT(" . $vv->getLongtitude() . "," . $vv->getLatitude() .")"; - } - $value = '(' . implode (',', $tmp) . ')'; - break; - - case self::PARAM_STR: - default: - $tmp = array (); - foreach ($v[0] as $kk => $vv) - { - $tmp[] = "'" . $db->escape (strval ($vv)) . "'"; - } - $value = '(' . implode (',', $tmp) . ')'; - break; - } - } - else - { - switch ($v[1]) - { - case self::PARAM_NUMBER: - if (!is_numeric ($v[0])) - { - throw new InvalidParameter ("Parameter " . $k . " should be numeric in query " . $this->query); - } - $value = $v[0]; - break; - - case self::PARAM_DATE: - if (!is_numeric ($v[0])) - { - throw new InvalidParameter ("Parameter " . $k . " should be a valid timestamp in query " . $this->query); - } - $value = "FROM_UNIXTIME(" . $v[0] . ")"; - break; - - case self::PARAM_POINT: - if (! ($v[0] instanceof Point)) - { - throw new InvalidParameter ("Parameter " . $k . " should be a valid \\Neuron\\Models\\Point " . $this->query); - } - else - { - $value = "POINT(" . $v[0]->getLongtitude() . "," . $v[0]->getLatitude() .")"; - } - break; - - case self::PARAM_STR: - default: - $value = "'" . $db->escape (strval ($v[0])) . "'"; - break; - } - } - } - - $values[$k] = $value; - - // Replace question marks or tokens? - if (is_string ($k)) - { - $keys[] = '/:'.$k.'/'; - } - else - { - $keys[] = '/[?]/'; - } - } - - // First we make a list with placeholders which we will later repalce with values - $fakeValues = array (); - foreach ($values as $k => $v) - { - $fakeValues[$k] = '{{{ctlb-custom-placeholder-' . $k . '}}}'; - } - - // And replace - $query = preg_replace ($keys, $fakeValues, $this->query, 1); - - // And now replace the tokens with the actual values - foreach ($values as $k => $v) - { - $query = str_replace ($fakeValues[$k], $v, $query); - } - - return $query; - } - - public function execute () - { - $db = DatabaseSQLite::getInstance (); - $query = $this->getParsedQuery (); - - // SQL LOGGING :: BEGIN - if (defined ('DB_CUSTOM_LOG_SQLITE') && DB_CUSTOM_LOG_SQLITE) { - - $sSQL = $query; - - $error_log_folder = str_replace('\\','/', dirname(__FILE__) .'/../../../../logs'); - $error_log_filename = "$error_log_folder/sqlite_log.txt"; - $error_log_extended_filename = "$error_log_folder/sqlite_log_extended.txt"; - - //$str_context = print_r($context, true); - - //$str_debug_backtrace = print_r(debug_backtrace(), true); - - $str_log = "-- ----------------------------------------------------------------------------\n$sSQL;\n"; - - file_put_contents($error_log_filename, $str_log, FILE_APPEND | LOCK_EX); - } - - // SQL LOGGING :: END - - return $db->query ($query); - } -} -?> diff --git a/src/Neuron/DB/SQLite.php b/src/Neuron/DB/SQLite.php deleted file mode 100644 index 3dd26d1..0000000 --- a/src/Neuron/DB/SQLite.php +++ /dev/null @@ -1,202 +0,0 @@ -connection)) - { - try - { - - $this->connection = new \PDO(DB_OAUTH2_DSN); // success - - } - catch (Exception $e) - { - echo $e; - } - - /* - if (mysqli_connect_errno ()) - { - printf ("Connect failed: %s\n", mysqli_connect_error()); - exit(); - } - */ - } - } - - public function disconnect () - { - Logger::getInstance ()->log ('Disconnecting database.'); - if (isset ($this->connection)) - { - $this->connection->close (); - } - $this->connection = null; - } - - public function getConnection () - { - return $this->connection; - } - - public function multiQuery ($sSQL) - { - $start = microtime (true); - - $this->connect (); - - // Increase the counter - $this->query_counter ++; - - $result = $this->connection->multi_query (trim ($sSQL)); - - // FLUSH RESULTS - // @TODO make these usable - do { - $r = $this->connection->store_result (); - if ($r) - { - $r->free (); - } - - if (!$this->connection->more_results ()) - { - break; - } - - //$this->connection->next_result(); - } while ($this->connection->next_result ()); - - $duration = microtime (true) - $start; - $this->addQueryLog ($sSQL, $duration); - - if ($result === false) - { - //var_dump (debug_backtrace ()); - //$data = debug_backtrace (); - //print_r ($data); - - - echo $sSQL; - throw new DbException ('SQLite Error: '.$this->connection->error); - } - - elseif ($result instanceof MySQLi_Result) - { - return new Result ($result); - } - - // Insert ID will return zero if this query was not insert or update. - $this->insert_id = intval ($this->connection->insert_id); - - // Affected rows - $this->affected_rows = intval ($this->connection->affected_rows); - - if ($this->insert_id > 0) - return $this->insert_id; - - if ($this->affected_rows > 0) - return $this->affected_rows; - - return $result; - } - - /* - Execute a query and return a result - */ - public function query ($sSQL) - { - $start = microtime (true); - - $this->connect (); - - // Increase the counter - $this->query_counter ++; - - //$result = $this->connection->query (trim ($sSQL)); - - $result = $this->connection->exec(trim($sSQL)); - - $duration = microtime (true) - $start; - $this->addQueryLog ($sSQL, $duration); - - if ($result === false) - { - //var_dump (debug_backtrace ()); - //$data = debug_backtrace (); - //print_r ($data); - - - echo $sSQL; - - throw new DbException ('SQLite Error: '. implode("\n",$this->connection->errorInfo())); - - //throw new DbException ('SQLite Error: '.$this->connection->error); - } - - elseif ($result instanceof \SQLite3Result) - { - return new Result ($result); - } - - // Insert ID will return zero if this query was not insert or update. - $this->insert_id = intval ($this->connection->lastInsertId()); - - // Affected rows - //$this->affected_rows = intval ($this->connection->rowCount()); - - $this->affected_rows = $result; - - - if ($this->insert_id > 0) - return $this->insert_id; - - if ($this->affected_rows > 0) - return $this->affected_rows; - - return $result; - } - - public function escape ($txt) - { - if (is_array ($txt)) - { - throw new Error ('Invalid parameter: escape cannot handle arrays.'); - } - $this->connect (); - - // TODO: SQLite escape string - //return $this->connection->real_escape_string ($txt); - - return $txt; - } - - public function fromUnixtime ($timestamp) - { - $query = $this->query ("SELECT FROM_UNIXTIME('{$timestamp}') AS datum"); - return $query[0]['datum']; - } - - public function toUnixtime ($date) - { - $query = $this->query ("SELECT UNIX_TIMESTAMP('{$date}') AS datum"); - return $query[0]['datum']; - } -} -?> From e6b8b6871d4460b89f1739b02d98aab4426e17a6 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 11:40:24 +0100 Subject: [PATCH 011/231] Preparing configuration with environments. --- example/config/app.php | 7 +++ example/config/database.php | 7 +++ src/Neuron/Config.php | 90 +++++++++++++++++++++++++++++++++++++ src/Neuron/URLBuilder.php | 4 +- 4 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 example/config/app.php create mode 100644 example/config/database.php create mode 100644 src/Neuron/Config.php diff --git a/example/config/app.php b/example/config/app.php new file mode 100644 index 0000000..6d2897e --- /dev/null +++ b/example/config/app.php @@ -0,0 +1,7 @@ + '/' + +); \ No newline at end of file diff --git a/example/config/database.php b/example/config/database.php new file mode 100644 index 0000000..dfb6b70 --- /dev/null +++ b/example/config/database.php @@ -0,0 +1,7 @@ +getValue ($name, $default); + } + + /** + * @param string $folder + */ + public static function folder ($folder) + { + self::getInstance ()->setFolder ($folder); + } + + /** + * Set the environment (sub folder) + * @param $environment + */ + public static function environment ($environment) + { + self::getInstance ()->setEnvironment ($environment); + } + + /** + * Get an instance. + * @return Config + */ + private static function getInstance () + { + if (!isset (self::$in)) + { + self::$in = new self (); + } + return self::$in; + } + + /** + * @param string $folder + */ + private function setFolder ($folder) + { + $this->folder = $folder; + } + + /** + * @param string $environment + */ + private function setEnvironment ($environment) + { + $this->environment = $environment; + } + + /** + * Find a config variable and return it. + * @param string $name + * @param string $default + * @return mixed + */ + private function getValue ($name, $default) + { + return $default; + } +} \ No newline at end of file diff --git a/src/Neuron/URLBuilder.php b/src/Neuron/URLBuilder.php index 247d784..74d7ab8 100644 --- a/src/Neuron/URLBuilder.php +++ b/src/Neuron/URLBuilder.php @@ -22,12 +22,12 @@ public static function getURL ($module = '', $data = array ()) if (!empty ($params)) { - return BASE_URL . $module . '?' . $params; + return Config::get ('app.url', '/') . $module . '?' . $params; } else { // Google likes these. - return BASE_URL . $module; + return Config::get ('app.url', '/') . $module; } } } \ No newline at end of file From 7085cd120d7839a4d1f5edbb92f0b51edc0d91b2 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 12:38:33 +0100 Subject: [PATCH 012/231] Adding Application class. Doesn't do much. Just encapsulates the router for now. --- src/Neuron/Application.php | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/Neuron/Application.php diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php new file mode 100644 index 0000000..78b7e7e --- /dev/null +++ b/src/Neuron/Application.php @@ -0,0 +1,44 @@ +router = $router; + } + + /** + * @throws DataNotSet + */ + public function run () + { + if (!isset ($this->router)) + { + throw new DataNotSet ("Application needs a router."); + } + + $this->router->run (); + } +} \ No newline at end of file From 2dcab56bad997a78955537b3fa0be02eda372f3a Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 13:10:01 +0100 Subject: [PATCH 013/231] Adding example app. --- .../Controllers/TestController.php | 42 ------------------- example/ExampleModule/Module.php | 35 ---------------- .../templates/moduleexample.phpt | 3 -- .../templates/sections/head.phpt | 1 - .../Example/Controllers/HomeController.php | 22 ++++++++++ example/bootstrap/router.php | 8 ++++ example/bootstrap/start.php | 18 ++++++++ example/config/app.php | 7 ---- example/config/database.php | 7 ---- example/index.php | 41 ------------------ example/{ => public}/.htaccess | 0 example/public/assets/css/style.css | 9 ++++ example/public/assets/js/main.js | 1 + example/public/index.php | 7 ++++ example/templates/example.phpt | 9 +++- example/templates/index.phpt | 14 +++---- example/templates/sections/head.phpt | 3 +- src/Neuron/Core/Template.php | 10 +++++ 18 files changed, 92 insertions(+), 145 deletions(-) delete mode 100644 example/ExampleModule/Controllers/TestController.php delete mode 100644 example/ExampleModule/Module.php delete mode 100644 example/ExampleModule/templates/moduleexample.phpt delete mode 100644 example/ExampleModule/templates/sections/head.phpt create mode 100644 example/app/Example/Controllers/HomeController.php create mode 100644 example/bootstrap/router.php create mode 100644 example/bootstrap/start.php delete mode 100644 example/config/app.php delete mode 100644 example/config/database.php delete mode 100644 example/index.php rename example/{ => public}/.htaccess (100%) create mode 100644 example/public/assets/css/style.css create mode 100644 example/public/assets/js/main.js create mode 100644 example/public/index.php diff --git a/example/ExampleModule/Controllers/TestController.php b/example/ExampleModule/Controllers/TestController.php deleted file mode 100644 index ef00a3f..0000000 --- a/example/ExampleModule/Controllers/TestController.php +++ /dev/null @@ -1,42 +0,0 @@ - 'yep')); - return $response; - } - - public function foo () - { - $response = \Neuron\Net\Response::json (array ('sdf' => 'yep')); - return $response; - } - - public function template () - { - $data = array ( - 'name' => 'Test variable ' . mt_rand (0, 5000) - ); - - $response = \Neuron\Net\Response::template ('example/moduleexample.phpt', $data); - return $response; - } - - public function home () - { - $data = array ( - 'name' => 'Test variable ' . mt_rand (0, 5000) - ); - - $response = \Neuron\Net\Response::template ('example/moduleexample.phpt', $data); - return $response; - } -} \ No newline at end of file diff --git a/example/ExampleModule/Module.php b/example/ExampleModule/Module.php deleted file mode 100644 index da3d67f..0000000 --- a/example/ExampleModule/Module.php +++ /dev/null @@ -1,35 +0,0 @@ -get ($prefix . '/doSomething', 'TestController@doSomething'); - $router->get ($prefix . '/foo', 'TestController@foo'); - $router->get ($prefix . '/template', 'TestController@template'); - - $router->get ($prefix . '/', 'TestController@home'); - } -} \ No newline at end of file diff --git a/example/ExampleModule/templates/moduleexample.phpt b/example/ExampleModule/templates/moduleexample.phpt deleted file mode 100644 index a1df87a..0000000 --- a/example/ExampleModule/templates/moduleexample.phpt +++ /dev/null @@ -1,3 +0,0 @@ -layout ('index.phpt'); ?> - -

This is a module example page.

\ No newline at end of file diff --git a/example/ExampleModule/templates/sections/head.phpt b/example/ExampleModule/templates/sections/head.phpt deleted file mode 100644 index 3fe7fe5..0000000 --- a/example/ExampleModule/templates/sections/head.phpt +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/example/app/Example/Controllers/HomeController.php b/example/app/Example/Controllers/HomeController.php new file mode 100644 index 0000000..0347ad9 --- /dev/null +++ b/example/app/Example/Controllers/HomeController.php @@ -0,0 +1,22 @@ +get ('/', '\Example\Controllers\HomeController@main'); + +return $router; \ No newline at end of file diff --git a/example/bootstrap/start.php b/example/bootstrap/start.php new file mode 100644 index 0000000..05e881c --- /dev/null +++ b/example/bootstrap/start.php @@ -0,0 +1,18 @@ +add ('Example\\', __DIR__ . '/../app/'); + +// Start the app +$app = new \Neuron\Application (); + +// Load the router +$app->setRouter (include ('router.php')); + +// Set the template folder +\Neuron\Core\Template::addTemplatePath (__DIR__ . '/../templates/'); + +// Return app +return $app; \ No newline at end of file diff --git a/example/config/app.php b/example/config/app.php deleted file mode 100644 index 6d2897e..0000000 --- a/example/config/app.php +++ /dev/null @@ -1,7 +0,0 @@ - '/' - -); \ No newline at end of file diff --git a/example/config/database.php b/example/config/database.php deleted file mode 100644 index dfb6b70..0000000 --- a/example/config/database.php +++ /dev/null @@ -1,7 +0,0 @@ -get ('/response', function () { - return \Neuron\Net\Response::json (array ('test')); -}); - -$router->get ('/string', function () { - return 'String'; -}); - -$router->get ('/void', function () { - echo 'void'; -}); - -// Regular view, no module -$router->get ('/view', function () { - return \Neuron\Net\Response::template ('example.phpt'); -}); - -$router->get ('/', function () { - $response = new \Neuron\Net\Response (); - $response->redirect (\Neuron\URLBuilder::getURL ('module')); - return $response; -}); - -// Set module. -$router->module ('/module', new Module ()); - -$router->run (); \ No newline at end of file diff --git a/example/.htaccess b/example/public/.htaccess similarity index 100% rename from example/.htaccess rename to example/public/.htaccess diff --git a/example/public/assets/css/style.css b/example/public/assets/css/style.css new file mode 100644 index 0000000..bb9bcc6 --- /dev/null +++ b/example/public/assets/css/style.css @@ -0,0 +1,9 @@ +h1 +{ + color: red; +} + +h2 +{ + color: blue; +} \ No newline at end of file diff --git a/example/public/assets/js/main.js b/example/public/assets/js/main.js new file mode 100644 index 0000000..de04db9 --- /dev/null +++ b/example/public/assets/js/main.js @@ -0,0 +1 @@ +console.log ('javascript ok'); \ No newline at end of file diff --git a/example/public/index.php b/example/public/index.php new file mode 100644 index 0000000..817ab6c --- /dev/null +++ b/example/public/index.php @@ -0,0 +1,7 @@ +run (); \ No newline at end of file diff --git a/example/templates/example.phpt b/example/templates/example.phpt index fd26436..2904a59 100644 --- a/example/templates/example.phpt +++ b/example/templates/example.phpt @@ -1,3 +1,10 @@ layout ('index.phpt'); ?> -

This is an example page.

\ No newline at end of file +

Example structure

+

+ This is just an example structure. + We want to give you all the freedom you need. + No rigid structure. + Just a bunch of classes that you can instanciate in any way you like. +

+ diff --git a/example/templates/index.phpt b/example/templates/index.phpt index 2e22d5f..1eb8367 100644 --- a/example/templates/index.phpt +++ b/example/templates/index.phpt @@ -1,15 +1,15 @@ - + - combine ('sections/head.phpt'); ?> + combine ('sections/head.phpt'); ?> - + - + -

EXAMPLE MAIN TEMPLATE

- +

Neuron framework

+ - + \ No newline at end of file diff --git a/example/templates/sections/head.phpt b/example/templates/sections/head.phpt index 9a813c7..d3fe733 100644 --- a/example/templates/sections/head.phpt +++ b/example/templates/sections/head.phpt @@ -1 +1,2 @@ - \ No newline at end of file +css ('assets/css/style.css'); ?> +js ('assets/js/main.js'); ?> \ No newline at end of file diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 516774b..57af94d 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -358,4 +358,14 @@ private function combine ($template) return $val; } + + private function css ($path) + { + return ''; + } + + private function js ($path) + { + return ''; + } } \ No newline at end of file From aefc8b7b502a00b97cb408dfa289c9571f781f7b Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 13:10:33 +0100 Subject: [PATCH 014/231] Adding example app. --- example/config/app.php | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 example/config/app.php diff --git a/example/config/app.php b/example/config/app.php new file mode 100644 index 0000000..45ffe8d --- /dev/null +++ b/example/config/app.php @@ -0,0 +1,6 @@ + '/' + +); \ No newline at end of file From f7785f34fa6653c20b3526e7e6e36ea56ea4d09a Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 13:56:00 +0100 Subject: [PATCH 015/231] Rudimentary configuration; merge is not okay yet. --- .../Example/Controllers/HomeController.php | 3 + example/bootstrap/start.php | 6 ++ example/config/app.php | 4 +- example/config/development/app.php | 6 ++ example/templates/example.phpt | 1 + src/Neuron/Config.php | 70 ++++++++++++++++++- 6 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 example/config/development/app.php diff --git a/example/app/Example/Controllers/HomeController.php b/example/app/Example/Controllers/HomeController.php index 0347ad9..3ee0feb 100644 --- a/example/app/Example/Controllers/HomeController.php +++ b/example/app/Example/Controllers/HomeController.php @@ -8,6 +8,7 @@ namespace Example\Controllers; +use Neuron\Config; use Neuron\Core\Template; class HomeController { @@ -16,6 +17,8 @@ public function main () { $template = new Template ('example.phpt'); + $template->set ('title', Config::get ('app.name')); + return \Neuron\Net\Response::template ($template); } diff --git a/example/bootstrap/start.php b/example/bootstrap/start.php index 05e881c..0f22cd8 100644 --- a/example/bootstrap/start.php +++ b/example/bootstrap/start.php @@ -11,6 +11,12 @@ // Load the router $app->setRouter (include ('router.php')); +// Set config folder +\Neuron\Config::folder (__DIR__ . '/../config/'); + +// Optionally, set an environment +\Neuron\Config::environment ('development'); + // Set the template folder \Neuron\Core\Template::addTemplatePath (__DIR__ . '/../templates/'); diff --git a/example/config/app.php b/example/config/app.php index 45ffe8d..70e4af4 100644 --- a/example/config/app.php +++ b/example/config/app.php @@ -1,6 +1,8 @@ '/' + 'url' => '/', + + 'name' => 'Neuron example' ); \ No newline at end of file diff --git a/example/config/development/app.php b/example/config/development/app.php new file mode 100644 index 0000000..e7aab65 --- /dev/null +++ b/example/config/development/app.php @@ -0,0 +1,6 @@ + 'Neuron example development environment' + +); \ No newline at end of file diff --git a/example/templates/example.phpt b/example/templates/example.phpt index 2904a59..8141886 100644 --- a/example/templates/example.phpt +++ b/example/templates/example.phpt @@ -8,3 +8,4 @@ Just a bunch of classes that you can instanciate in any way you like.

+

Config example: .

\ No newline at end of file diff --git a/src/Neuron/Config.php b/src/Neuron/Config.php index cd832b0..cb153d9 100644 --- a/src/Neuron/Config.php +++ b/src/Neuron/Config.php @@ -12,7 +12,7 @@ class Config { /** @var Config $in */ - static $in; + private static $in; /** @var string $folder */ private $folder = '.'; @@ -20,6 +20,9 @@ class Config { /** @var string $environment */ private $environment; + /** @var mixed[] $files */ + private $files; + /** * Get a config variable * @param $name @@ -77,6 +80,47 @@ private function setEnvironment ($environment) $this->environment = $environment; } + /** + * Load a file in case it's not loaded yet. + * @param $file + */ + private function loadFile ($file) + { + if (!isset ($this->files[$file])) + { + $filename = $this->folder . $file . '.php'; + + // First load these + if (file_exists ($filename)) + { + $this->files[$file] = include ($filename); + } + + // Now overload with environment values + if (isset ($this->environment)) + { + $filename = $this->folder . $this->environment . '/' . $file . '.php'; + if (file_exists ($filename)) + { + $this->merge ($file, include ($filename)); + } + } + + } + } + + /** + * @param string $file + * @param mixed[] $newData + */ + private function merge ($file, $newData) + { + foreach ($newData as $key => $value) + { + $this->files[$file][$key] = $value; + } + } + /** * Find a config variable and return it. * @param string $name @@ -85,6 +129,28 @@ private function setEnvironment ($environment) */ private function getValue ($name, $default) { - return $default; + $parts = explode ('.', $name); + $file = array_shift ($parts); + + $this->loadFile ($file); + + if (! isset ($this->files[$file])) { + return $default; + } + else { + $out = $this->files[$file]; + foreach ($parts as $part) + { + if (!isset ($out[$part])) + { + return $default; + } + else { + $out = $out[$part]; + } + } + } + + return $out; } } \ No newline at end of file From 09b5b1081064887e6718b63e1b77cc96155eedc9 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 13:57:51 +0100 Subject: [PATCH 016/231] Rudimentary configuration; merge is not okay yet. --- example/app/Example/Controllers/HomeController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/example/app/Example/Controllers/HomeController.php b/example/app/Example/Controllers/HomeController.php index 3ee0feb..743d8b0 100644 --- a/example/app/Example/Controllers/HomeController.php +++ b/example/app/Example/Controllers/HomeController.php @@ -10,6 +10,7 @@ use Neuron\Config; use Neuron\Core\Template; +use Neuron\Net\Response; class HomeController { @@ -19,7 +20,7 @@ public function main () $template->set ('title', Config::get ('app.name')); - return \Neuron\Net\Response::template ($template); + return Response::template ($template); } } \ No newline at end of file From 4c6f1eaaa6e7039f24946238ca4733496968958b Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 13:58:47 +0100 Subject: [PATCH 017/231] Rudimentary configuration; merge is not okay yet. --- example/templates/index.phpt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/example/templates/index.phpt b/example/templates/index.phpt index 1eb8367..3215911 100644 --- a/example/templates/index.phpt +++ b/example/templates/index.phpt @@ -1,15 +1,15 @@ - + - combine ('sections/head.phpt'); ?> + combine ('sections/head.phpt'); ?> - + - + -

Neuron framework

- +

Neuron framework

+ - + \ No newline at end of file From 99d97e3d6db3c9db53bcde77c829069bb43bf6b9 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 14:00:54 +0100 Subject: [PATCH 018/231] Rudimentary configuration; merge is not okay yet. --- example/bootstrap/start.php | 2 ++ example/public/index.php | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/example/bootstrap/start.php b/example/bootstrap/start.php index 0f22cd8..6e39731 100644 --- a/example/bootstrap/start.php +++ b/example/bootstrap/start.php @@ -1,5 +1,7 @@ run (); \ No newline at end of file From 54107672c1eae70d59ac0a9704f907548daab681 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 14:10:31 +0100 Subject: [PATCH 019/231] Removing page --- src/Neuron/Page.php | 38 -------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 src/Neuron/Page.php diff --git a/src/Neuron/Page.php b/src/Neuron/Page.php deleted file mode 100644 index 92e4b1d..0000000 --- a/src/Neuron/Page.php +++ /dev/null @@ -1,38 +0,0 @@ -content = $content; - } - - public function setTitle ($title) - { - $this->title = $title; - } - - public function getOutput () - { - $html = new Template (); - - $html->set ('title', $this->title); - $html->set ('content', $this->content); - - return $html->parse ('index.phpt'); - } -} \ No newline at end of file From bff2c330b12345250fdb8a82e5eca9276ffcf1f2 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 14:48:25 +0100 Subject: [PATCH 020/231] Adding a more precise Template priority. Setting the basic Neuron templates as priority -1. --- .../Example/Controllers/HomeController.php | 14 ++ example/bootstrap/router.php | 1 + example/bootstrap/start.php | 4 +- example/config/app.php | 9 +- example/config/development/app.php | 8 +- example/public/index.php | 2 +- example/templates/example.phpt | 9 +- src/Neuron/Application.php | 29 +++- src/Neuron/Core/Template.php | 137 +++++++-------- src/Neuron/FrontController.php | 157 ------------------ src/Neuron/Interfaces/FrontController.php | 38 ----- src/Neuron/{ => Net}/InputStream.php | 2 +- src/Neuron/Net/Request.php | 2 +- src/Neuron/Router.php | 29 ++-- 14 files changed, 144 insertions(+), 297 deletions(-) delete mode 100644 src/Neuron/FrontController.php delete mode 100644 src/Neuron/Interfaces/FrontController.php rename src/Neuron/{ => Net}/InputStream.php (97%) diff --git a/example/app/Example/Controllers/HomeController.php b/example/app/Example/Controllers/HomeController.php index 743d8b0..5254b3c 100644 --- a/example/app/Example/Controllers/HomeController.php +++ b/example/app/Example/Controllers/HomeController.php @@ -20,7 +20,21 @@ public function main () $template->set ('title', Config::get ('app.name')); + $template->set ('first', Config::get ('app.example.first')); + $template->set ('second', Config::get ('app.example.second')); + $template->set ('third', Config::get ('app.example.third')); + + $template->set ('counts', Config::get ('app.example')); + return Response::template ($template); } + public function templates () + { + Template::addPath ('lowpriority', '', -5); + Template::addPath ('regularpriority', '', 0); + Template::addPath ('highpriority', '', 5); + + return Response::table (Template::getPaths()); + } } \ No newline at end of file diff --git a/example/bootstrap/router.php b/example/bootstrap/router.php index 4674c05..ce29347 100644 --- a/example/bootstrap/router.php +++ b/example/bootstrap/router.php @@ -4,5 +4,6 @@ $router = new \Neuron\Router (); $router->get ('/', '\Example\Controllers\HomeController@main'); +$router->get ('/templates', '\Example\Controllers\HomeController@templates'); return $router; \ No newline at end of file diff --git a/example/bootstrap/start.php b/example/bootstrap/start.php index 6e39731..c7dbe9d 100644 --- a/example/bootstrap/start.php +++ b/example/bootstrap/start.php @@ -8,7 +8,7 @@ $loader->add ('Example\\', __DIR__ . '/../app/'); // Start the app -$app = new \Neuron\Application (); +$app = \Neuron\Application::getInstance (); // Load the router $app->setRouter (include ('router.php')); @@ -20,7 +20,7 @@ \Neuron\Config::environment ('development'); // Set the template folder -\Neuron\Core\Template::addTemplatePath (__DIR__ . '/../templates/'); +\Neuron\Core\Template::addPath (__DIR__ . '/../templates/'); // Return app return $app; \ No newline at end of file diff --git a/example/config/app.php b/example/config/app.php index 70e4af4..eda23f4 100644 --- a/example/config/app.php +++ b/example/config/app.php @@ -3,6 +3,13 @@ 'url' => '/', - 'name' => 'Neuron example' + 'name' => 'Neuron example', + + 'example' => array ( + + 'first' => 'First value', + 'second' => 'Second value' + + ) ); \ No newline at end of file diff --git a/example/config/development/app.php b/example/config/development/app.php index e7aab65..989bfe6 100644 --- a/example/config/development/app.php +++ b/example/config/development/app.php @@ -1,6 +1,12 @@ 'Neuron example development environment' + 'name' => 'Neuron example development environment', + + 'example' => array ( + + 'third' => 'Third value' + + ) ); \ No newline at end of file diff --git a/example/public/index.php b/example/public/index.php index e4c7b27..a46b437 100644 --- a/example/public/index.php +++ b/example/public/index.php @@ -1,4 +1,4 @@ run (); \ No newline at end of file +$app->dispatch (); \ No newline at end of file diff --git a/example/templates/example.phpt b/example/templates/example.phpt index 8141886..a4f040e 100644 --- a/example/templates/example.phpt +++ b/example/templates/example.phpt @@ -8,4 +8,11 @@ Just a bunch of classes that you can instanciate in any way you like.

-

Config example: .

\ No newline at end of file +

Configuration

+

Config example: .

+
    + $v) { ?> +
  • :
  • + +
+ diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index 78b7e7e..ed0acb5 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -9,6 +9,7 @@ namespace Neuron; use Neuron\Exceptions\DataNotSet; +use Neuron\Net\Request; use Neuron\Router; class Application { @@ -16,9 +17,26 @@ class Application { /** @var Router $router */ private $router; - public function __construct () + private static $in; + + /** + * @return Application + */ + public static function getInstance () { + if (!isset (self::$in)) + { + self::$in = new self (); + } + return self::$in; + } + /** + * + */ + private function __construct () + { + \Neuron\Core\Template::addPath (dirname (dirname (__FILE__)) . '/templates/', '', -1); } /** @@ -32,13 +50,18 @@ public function setRouter (Router $router) /** * @throws DataNotSet */ - public function run () + public function dispatch (\Neuron\Net\Request $request = null) { if (!isset ($this->router)) { throw new DataNotSet ("Application needs a router."); } - $this->router->run (); + if (!isset ($request)) + { + $request = Request::fromInput (); + } + + $this->router->run ($request); } } \ No newline at end of file diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 57af94d..b026dde 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -1,71 +1,15 @@ sTextSection = $sTextSection; @@ -147,8 +129,11 @@ public function setTextSection ($sTextSection, $sTextFile = null) $this->sTextFile = $sTextFile; } } - - public function setTextFile ($sTextFile) + + /** + * @param $sTextFile + */ + private function setTextFile ($sTextFile) { $this->sTextFile = $sTextFile; } @@ -184,7 +169,13 @@ private function getText ($sKey, $sSection = null, $sFile = null, $sDefault = nu return $txt; } - public function setVariable ($var, $value, $overwrite = false, $first = false) + /** + * @param $var + * @param $value + * @param bool $overwrite + * @param bool $first + */ + private function setVariable ($var, $value, $overwrite = false, $first = false) { if ($overwrite) { $this->values[$var] = $value; @@ -217,7 +208,7 @@ private static function getFilenames ($template, $all = false) { $out = array (); - foreach (self::getTemplatePaths () as $v) { + foreach (self::getPaths () as $v) { // Split prefix and folder $split = explode ('|', $v); diff --git a/src/Neuron/FrontController.php b/src/Neuron/FrontController.php deleted file mode 100644 index d2c1196..0000000 --- a/src/Neuron/FrontController.php +++ /dev/null @@ -1,157 +0,0 @@ -controllers[] = $controller; - $controller->setParentController ($this); - } - - public function canDispatch () - { - return true; - } - - public function setInput (array $fields) - { - $this->input = $fields; - } - - public function getInput ($id = null) - { - if ($id !== null) - { - if (isset ($this->input[$id])) - { - return $this->input[$id]; - } - return null; - } - return $this->input; - } - - public function setPage (Page $page) - { - $this->page = $page; - } - - public function getPage () - { - if (!isset ($this->page)) - { - $this->page = new Page (); - } - return $this->page; - } - - public function dispatch (Page $page = null) - { - Tracker::getInstance ()->setModule ('Neuron'); - - foreach ($this->controllers as $v) - { - if ($v->canDispatch ()) - { - return $v->dispatch ($this->getPage ()); - } - } - - // Nothing found? Last one it is. - if (count ($this->controllers) > 0) - { - return $this->controllers[count ($this->controllers) - 1]->dispatch ($this->getPage ()); - } - else - { - return Response::error ('No controllers set.'); - } - } - - public function setParentController (NeuronInterfacesFrontController $input) - { - // Nothing to do here. - } - - public function getName () - { - return 'Neuron front controller'; - } - - /** - * @param Request $request - */ - public function setRequest (Request $request) - { - $this->request = $request; - } - - /** - * @return Request - */ - public function getRequest () - { - return $this->request; - } - - /** - * @param Response $response - */ - public function setResponse (Response $response) - { - $this->response = $response; - } - - /** - * @return Response - */ - public function getResponse () - { - if (!isset ($this->response)) - { - $this->response = new Response (); - } - return $this->response; - } -} \ No newline at end of file diff --git a/src/Neuron/Interfaces/FrontController.php b/src/Neuron/Interfaces/FrontController.php deleted file mode 100644 index 3eb4d59..0000000 --- a/src/Neuron/Interfaces/FrontController.php +++ /dev/null @@ -1,38 +0,0 @@ -frontController = \Neuron\FrontController::getInstance (); - $this->frontController->setRequest ($request); + public function run (Request $request) + { // Define which method we need to handle $this->method = $request->getMethod (); + // Set request + $this->request = $request; + // Handle all routes $numHandled = 0; if (isset($this->routes[$this->method])) @@ -173,10 +170,6 @@ public function run (callable $callback = null) { $request->output (); } } - // If a route was handled, perform the finish callback (if any) - else { - if ($callback) $callback(); - } // If it originally was a HEAD request, clean up after ourselves by emptying the output buffer if ($_SERVER['REQUEST_METHOD'] == 'HEAD') ob_end_clean(); @@ -199,10 +192,10 @@ public function set404($fn) { * @param boolean $quitAfterRun Does the handle function need to quit after one route was matched? * @return \Neuron\Net\Response The response */ - private function handle($routes) { + private function handle ($routes) { // The current page URL - $uri = $this->frontController->getRequest ()->getUrl (); + $uri = $this->request->getUrl (); $numHandled = 0; From f72ef57d86cc41572b69eacd9bfb820d908b2860 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 14:53:46 +0100 Subject: [PATCH 021/231] Fixing the configuration merger. --- src/Neuron/Config.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Neuron/Config.php b/src/Neuron/Config.php index cb153d9..d709992 100644 --- a/src/Neuron/Config.php +++ b/src/Neuron/Config.php @@ -115,10 +115,7 @@ private function loadFile ($file) */ private function merge ($file, $newData) { - foreach ($newData as $key => $value) - { - $this->files[$file][$key] = $value; - } + $this->files[$file] = array_replace_recursive ($this->files[$file], $newData); } /** From 4d7e7c101097df594a524f5da0a75aacc38695d7 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 14:58:18 +0100 Subject: [PATCH 022/231] Using hostname for environment selection in example. --- example/bootstrap/start.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/example/bootstrap/start.php b/example/bootstrap/start.php index c7dbe9d..5f8d262 100644 --- a/example/bootstrap/start.php +++ b/example/bootstrap/start.php @@ -17,7 +17,15 @@ \Neuron\Config::folder (__DIR__ . '/../config/'); // Optionally, set an environment -\Neuron\Config::environment ('development'); +$hostname = trim (file_get_contents ('/etc/hostname')); + +switch ($hostname) +{ + case 'my-computer': + case 'thijs-home-i7': + \Neuron\Config::environment ('development'); + break; +} // Set the template folder \Neuron\Core\Template::addPath (__DIR__ . '/../templates/'); From 20fe7a6b29fdd49ec82e0ae61411a05a1b81c9a6 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 15:09:28 +0100 Subject: [PATCH 023/231] Using hostname for environment selection in example. --- src/templates/sections/head.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/templates/sections/head.phpt b/src/templates/sections/head.phpt index 3ef5097..8dfb33a 100644 --- a/src/templates/sections/head.phpt +++ b/src/templates/sections/head.phpt @@ -1 +1,2 @@ + \ No newline at end of file From cbd22bed9a521506d2453582c788489e03cdc1c7 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 15:09:35 +0100 Subject: [PATCH 024/231] Using hostname for environment selection in example. --- src/templates/sections/head.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/sections/head.phpt b/src/templates/sections/head.phpt index 8dfb33a..ccb50bb 100644 --- a/src/templates/sections/head.phpt +++ b/src/templates/sections/head.phpt @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file From c38e02b88c0824df55370b7d404c2972a19e9885 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 15:09:54 +0100 Subject: [PATCH 025/231] Using hostname for environment selection in example. --- src/templates/sections/head.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/templates/sections/head.phpt b/src/templates/sections/head.phpt index ccb50bb..9e7d5f1 100644 --- a/src/templates/sections/head.phpt +++ b/src/templates/sections/head.phpt @@ -1,2 +1,3 @@ + \ No newline at end of file From 631f22fedc107c925bf753eb2e1d64c0b5bb8950 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 15:10:31 +0100 Subject: [PATCH 026/231] Using hostname for environment selection in example. --- src/templates/sections/head.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/sections/head.phpt b/src/templates/sections/head.phpt index 9e7d5f1..2362ed9 100644 --- a/src/templates/sections/head.phpt +++ b/src/templates/sections/head.phpt @@ -1,3 +1,3 @@ - \ No newline at end of file + From f283c139614cf4ba084bab3415bb9747cef20c30 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 15:11:31 +0100 Subject: [PATCH 027/231] Cleaning up some source code. --- example/templates/sections/head.phpt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/example/templates/sections/head.phpt b/example/templates/sections/head.phpt index d3fe733..3b1dc31 100644 --- a/example/templates/sections/head.phpt +++ b/example/templates/sections/head.phpt @@ -1,2 +1,7 @@ -css ('assets/css/style.css'); ?> -js ('assets/js/main.js'); ?> \ No newline at end of file + + + css ('assets/css/style.css'); ?> + + + + js ('assets/js/main.js'); ?> \ No newline at end of file From 4a8e85a17666466dc00ad0f2088bf84f1297fa2c Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 17:06:56 +0100 Subject: [PATCH 028/231] Cleaning up some source code. --- src/Neuron/Core/Template.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index b026dde..b2f0293 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -352,11 +352,11 @@ private function combine ($template) private function css ($path) { - return ''; + return ''; } private function js ($path) { - return ''; + return ''; } } \ No newline at end of file From c7ba1b9da038ecde787e6020c1bed95fafe99c06 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 17:34:53 +0100 Subject: [PATCH 029/231] Adding helper functionality to templates. --- src/Neuron/Core/Template.php | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index b2f0293..d0f6ba8 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -29,6 +29,9 @@ class Template /** @var string $template */ private $template; + + /** @var array $helpers */ + static $helpers = array (); public static function load () { @@ -62,6 +65,16 @@ public static function share ($name, $value) self::$shares[$name] = $value; } + /** + * Add a helper that is available inside the templates. + * @param $name + * @param $helper + */ + public static function addHelper ($name, $helper) + { + self::$helpers[$name] = $helper; + } + /** * I believe this is a nicer way to do the directory setting. */ @@ -350,6 +363,33 @@ private function combine ($template) return $val; } + /** + * @param string $name + * @param string $method + * @return string + */ + private function help ($name, $method) + { + $args = func_get_args (); + array_shift ($args); + array_shift ($args); + + if (isset (self::$helpers[$name])) + { + $call = array ($name, $method); + if (is_callable ($call)) + { + return call_user_func_array ($call, $args); + } + else { + return '

Method ' . $method . ' on helper ' . $name . ' is not callable.

'; + } + } + else { + return '

Could not find helper ' . $name . '

'; + } + } + private function css ($path) { return ''; From 0d126175c4fff9bee9fe4a772fdee20dedd38018 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 19:49:37 +0100 Subject: [PATCH 030/231] Adding helper functionality to templates. --- src/Neuron/Core/Template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index d0f6ba8..7aeeb45 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -376,7 +376,7 @@ private function help ($name, $method) if (isset (self::$helpers[$name])) { - $call = array ($name, $method); + $call = array (self::$helpers[$name], $method); if (is_callable ($call)) { return call_user_func_array ($call, $args); From 194fe48adb58e854bfa1fcc5389c195809600c18 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 22:47:51 +0100 Subject: [PATCH 031/231] Adding locales to test with. --- example/bootstrap/start.php | 6 ++ example/locales/en_UK/LC_MESSAGES/example.mo | Bin 0 -> 644 bytes example/locales/en_UK/LC_MESSAGES/example.po | 20 +++++ example/locales/nl_BE/LC_MESSAGES/example.mo | Bin 0 -> 645 bytes example/locales/nl_BE/LC_MESSAGES/example.po | 20 +++++ example/templates/example.phpt | 7 +- src/Neuron/Application.php | 36 +++++++++ src/Neuron/Core/Template.php | 36 +++------ src/Neuron/Tools/Text.php | 75 +++++++++++++++++++ 9 files changed, 173 insertions(+), 27 deletions(-) create mode 100644 example/locales/en_UK/LC_MESSAGES/example.mo create mode 100644 example/locales/en_UK/LC_MESSAGES/example.po create mode 100644 example/locales/nl_BE/LC_MESSAGES/example.mo create mode 100644 example/locales/nl_BE/LC_MESSAGES/example.po create mode 100644 src/Neuron/Tools/Text.php diff --git a/example/bootstrap/start.php b/example/bootstrap/start.php index 5f8d262..9462dc0 100644 --- a/example/bootstrap/start.php +++ b/example/bootstrap/start.php @@ -30,5 +30,11 @@ // Set the template folder \Neuron\Core\Template::addPath (__DIR__ . '/../templates/'); +// Set the locale +$app->setLocale ('nl_BE'); + +// Set our own domain +\Neuron\Tools\Text::getInstance ()->addPath ('example', __DIR__ . '/../locales/'); + // Return app return $app; \ No newline at end of file diff --git a/example/locales/en_UK/LC_MESSAGES/example.mo b/example/locales/en_UK/LC_MESSAGES/example.mo new file mode 100644 index 0000000000000000000000000000000000000000..71154feeae2d85007e603cf09dbcaf302f849a21 GIT binary patch literal 644 zcmah{&2AGh5MB^m_Q;vT+&F;U-6)lcTM!}y6m<&=*;d@5$?mZ0D79Diq%;rG*XuLz z2+TI6IRPVovPbjd@ALTf*^`?@?6Kgv;FaL1;6yN3DFDG&!LLV267Kz43dFs$q4vQF z;ujHGdqu#Vl@l@3H3I^Nt=2jzgI`h2YSyR=3ekFJ;4^K4cQC!i%YIF1`K3~mK*$nQ zACSqwD9gtx&(-KPj7DaB_%h40OcK>My0Sx)f94e!SycgDTqFBnpz7=@!UZ~LD8Rh# zklK#mL@2M~yBc|oOTDDGX@RcYU`whZyfiRDE^rAm#}u&ULFM0T43Jx#pQdNCv*})I zuCsLFrGXPl+g`K{?{mF3XJ0t)`+fF%jMO7{2DCodt$lFrH=(A< ej-i1a#fOXLgrV+ADOTB_NhT?ii)r%TAMqOz>An;I literal 0 HcmV?d00001 diff --git a/example/locales/en_UK/LC_MESSAGES/example.po b/example/locales/en_UK/LC_MESSAGES/example.po new file mode 100644 index 0000000..d4f3a93 --- /dev/null +++ b/example/locales/en_UK/LC_MESSAGES/example.po @@ -0,0 +1,20 @@ +msgid "" +msgstr "" +"Project-Id-Version: Neuron Example\n" +"POT-Creation-Date: 2014-11-29 22:45+0100\n" +"PO-Revision-Date: 2014-11-29 22:45+0100\n" +"Last-Translator: Thijs Van der Schaeghe \n" +"Language-Team: CatLab Interactive \n" +"Language: en_UK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" +"X-Poedit-KeywordsList: _;gettext;gettext_noop\n" +"X-Poedit-Basepath: ../../../\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-SearchPath-0: templates\n" + +#: templates/example.phpt:23 +msgid "Let's give this gettext a try..." +msgstr "Let's give this gettext a try..." diff --git a/example/locales/nl_BE/LC_MESSAGES/example.mo b/example/locales/nl_BE/LC_MESSAGES/example.mo new file mode 100644 index 0000000000000000000000000000000000000000..6470e346ce27cba95e933ce65957cf85eec7ae51 GIT binary patch literal 645 zcmaJ<&2H2%5Do|~IdbMOoH&5fWVMLm7KFN8(25iS8!B$ANirl}rFLY`w%rHe_4*8b z1SVbRo?zrpV{3l=eIDODdGsq1dnkA+cqw=+I2Mdn2te>vaQh&Ny!dB=S_3r#ybo1YrGhGiiFXD1mZp-ZzR{%_oBTH~$H1!eXhVj39yp&<{; zx9HcX5uk-C#?qB)rftL(Z{+g=O+s^QiLQH5zQcI+@33i?jJ& zYnG((%t-?)l(vIt8{g+(=+W3C5GFnlzx`f*P>1`xk@`>aYHn-S7~5(%tPICL)JL+y zDT_MFP9W}`$WpW{oa&Z=}2u60+wLoM84Bl1b$&O#*H^!X4eE\n" +"Language-Team: CatLab Interactive \n" +"Language: nl_BE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" +"X-Poedit-KeywordsList: _;gettext;gettext_noop\n" +"X-Poedit-Basepath: ../../../\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-SearchPath-0: templates\n" + +#: templates/example.phpt:23 +msgid "Let's give this gettext a try..." +msgstr "Laten we dit nog eens proberen..." diff --git a/example/templates/example.phpt b/example/templates/example.phpt index a4f040e..46d9c09 100644 --- a/example/templates/example.phpt +++ b/example/templates/example.phpt @@ -1,4 +1,7 @@ -layout ('index.phpt'); ?> +layout ('index.phpt'); + $this->textdomain ('example'); +?>

Example structure

@@ -16,3 +19,5 @@ +

Text

+

gettext ('Let\'s give this gettext a try...'); ?>

\ No newline at end of file diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index ed0acb5..c385e4e 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -17,6 +17,9 @@ class Application { /** @var Router $router */ private $router; + /** @var string $locale */ + private $locale; + private static $in; /** @@ -47,11 +50,44 @@ public function setRouter (Router $router) $this->router = $router; } + /** + * @param string $locale + */ + public function setLocale ($locale) + { + $this->locale = $locale; + + // Also let php know + putenv ("LANG=" . $this->locale); + setlocale (LC_ALL, $this->locale); + } + + /** + * @return string + */ + public function getLocale () + { + return $this->locale; + } + + /** + * Check if locale is set, and if not, set it to english. + */ + private function checkLocale () + { + if (!isset ($this->locale)) + { + $this->setLocale ('en'); + } + } + /** * @throws DataNotSet */ public function dispatch (\Neuron\Net\Request $request = null) { + $this->checkLocale (); + if (!isset ($this->router)) { throw new DataNotSet ("Application needs a router."); diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 7aeeb45..6482350 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -155,32 +155,6 @@ public function set ($var, $value, $overwrite = false, $first = false) { $this->setVariable ($var, $value, $overwrite, $first); } - - // Intern function - private function getText ($sKey, $sSection = null, $sFile = null, $sDefault = null) - { - if (!isset ($this->objText)) { - $this->objText = Text::__getInstance (); - } - - $txt = Tools::output_varchar - ( - $this->objText->get - ( - $sKey, - isset ($sSection) ? $sSection : $this->sTextSection, - isset ($sFile) ? $sFile : $this->sTextFile, - false - ) - ); - - if (!$txt) - { - return $sDefault; - } - - return $txt; - } /** * @param $var @@ -399,4 +373,14 @@ private function js ($path) { return ''; } + + private function textdomain ($domain) + { + \Neuron\Tools\Text::getInstance ()->setDomain ($domain); + } + + private function gettext ($message1, $message2 = null, $n = null) + { + return \Neuron\Tools\Text::getInstance ()->getText ($message1, $message2, $n); + } } \ No newline at end of file diff --git a/src/Neuron/Tools/Text.php b/src/Neuron/Tools/Text.php new file mode 100644 index 0000000..d3aa8f2 --- /dev/null +++ b/src/Neuron/Tools/Text.php @@ -0,0 +1,75 @@ +domain = $domain; + } + + /** + * @param string $message1 + * @param string|null $message2 + * @param int|null $n + * @return string + */ + public function getText ($message1, $message2 = null, $n = null) + { + if (!isset ($message2)) { + return dcgettext ($this->domain, $message1, null); + } + else { + return dcngettext ($this->domain, $message1, $message2, $n, null); + } + } + + /** + * Little helper method. + * @param string $message1 + * @param string|null $message2 + * @param string|null $n + * @return string + */ + public static function get ($message1, $message2 = null, $n = null) + { + $in = self::getInstance (); + return $in->getText ($message1, $message2, $n); + } +} \ No newline at end of file From 760eeca8a6c915a31444981412214050c0f7f354 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 22:53:56 +0100 Subject: [PATCH 032/231] Adding locales to test with. --- example/locales/nl_BE/LC_MESSAGES/example.mo | Bin 645 -> 781 bytes example/locales/nl_BE/LC_MESSAGES/example.po | 12 ++++++++++-- example/templates/example.phpt | 7 ++++++- src/Neuron/Core/Template.php | 7 ++++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/example/locales/nl_BE/LC_MESSAGES/example.mo b/example/locales/nl_BE/LC_MESSAGES/example.mo index 6470e346ce27cba95e933ce65957cf85eec7ae51..18b56b407247f6f42beb6b9d45d370c78aa4d0b3 100644 GIT binary patch delta 241 zcmZo=?PZI-C&V(90SK6ZSO$nqfS47CeSjDQ5`b6%h!cTW1&Et~Sdoc=VL6Bf;*&r& zh<**E8G$qi0GVLGJkeKGIV2;sC{-b|SV6T|At^Prhyfyy2o!{h6i+O0V=^_GxI>M} z)Oh2AL`H*voYJDi99_5kqTFIDg}eeVx7gOmS^>he%~P\n" "Language-Team: CatLab Interactive \n" "Language: nl_BE\n" @@ -13,8 +13,16 @@ msgstr "" "X-Poedit-KeywordsList: _;gettext;gettext_noop\n" "X-Poedit-Basepath: ../../../\n" "X-Poedit-SourceCharset: UTF-8\n" +"Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;\n" "X-Poedit-SearchPath-0: templates\n" #: templates/example.phpt:23 msgid "Let's give this gettext a try..." msgstr "Laten we dit nog eens proberen..." + +#: templates/example.phpt:28 +#, php-format +msgid "There is %s beer" +msgid_plural "There are %s beers." +msgstr[0] "Er is %s bier." +msgstr[1] "Er zijn %s bieren." diff --git a/example/templates/example.phpt b/example/templates/example.phpt index 46d9c09..4a9372a 100644 --- a/example/templates/example.phpt +++ b/example/templates/example.phpt @@ -20,4 +20,9 @@

Text

-

gettext ('Let\'s give this gettext a try...'); ?>

\ No newline at end of file +

gettext ('Let\'s give this gettext a try...'); ?>

+ +

Multiple text

+ + +

ngettext ('There is %s beer', 'There are %s beers.', $beers), $beers); ?>

\ No newline at end of file diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 6482350..c8cca94 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -379,7 +379,12 @@ private function textdomain ($domain) \Neuron\Tools\Text::getInstance ()->setDomain ($domain); } - private function gettext ($message1, $message2 = null, $n = null) + private function gettext ($message1) + { + return \Neuron\Tools\Text::getInstance ()->getText ($message1); + } + + private function ngettext ($message1, $message2 = null, $n = null) { return \Neuron\Tools\Text::getInstance ()->getText ($message1, $message2, $n); } From 685761904e5b67bafb500dcae23a6316f4ca34d7 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 23:13:32 +0100 Subject: [PATCH 033/231] Implementing a proper gettext infrastructure? Wow. We're good. --- example/bootstrap/start.php | 2 +- example/locales/nl_BE/LC_MESSAGES/example.mo | Bin 781 -> 786 bytes example/locales/nl_BE/LC_MESSAGES/example.po | 2 +- src/Neuron/Application.php | 8 +++++++- src/Neuron/Tools/Text.php | 6 ++++-- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/example/bootstrap/start.php b/example/bootstrap/start.php index 9462dc0..a542363 100644 --- a/example/bootstrap/start.php +++ b/example/bootstrap/start.php @@ -31,7 +31,7 @@ \Neuron\Core\Template::addPath (__DIR__ . '/../templates/'); // Set the locale -$app->setLocale ('nl_BE'); +$app->setLocale ('nl_BE.utf8'); // Set our own domain \Neuron\Tools\Text::getInstance ()->addPath ('example', __DIR__ . '/../locales/'); diff --git a/example/locales/nl_BE/LC_MESSAGES/example.mo b/example/locales/nl_BE/LC_MESSAGES/example.mo index 18b56b407247f6f42beb6b9d45d370c78aa4d0b3..e8787db0395c6df33bd02a8037c726fb4ed4560e 100644 GIT binary patch delta 51 zcmeBWo5VK3L{yE5fnhlV1A`(Ep98W%^oNO_Cs>TF3=AiWGB&g7m6oJgY@Web$_M}w CfeZ2g delta 45 wcmbQl*2^}*L{yQ9fnhlV1A`(Ep9Hc&^y`V9Cs>TEOpPatGB$6X%UH??0MM2SGynhq diff --git a/example/locales/nl_BE/LC_MESSAGES/example.po b/example/locales/nl_BE/LC_MESSAGES/example.po index 2c78699..fe1435d 100644 --- a/example/locales/nl_BE/LC_MESSAGES/example.po +++ b/example/locales/nl_BE/LC_MESSAGES/example.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Neuron Example\n" "POT-Creation-Date: 2014-11-29 22:52+0100\n" -"PO-Revision-Date: 2014-11-29 22:53+0100\n" +"PO-Revision-Date: 2014-11-29 23:01+0100\n" "Last-Translator: Thijs Van der Schaeghe \n" "Language-Team: CatLab Interactive \n" "Language: nl_BE\n" diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index c385e4e..7d5819a 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -52,6 +52,7 @@ public function setRouter (Router $router) /** * @param string $locale + * @throws DataNotSet */ public function setLocale ($locale) { @@ -59,7 +60,12 @@ public function setLocale ($locale) // Also let php know putenv ("LANG=" . $this->locale); - setlocale (LC_ALL, $this->locale); + + $result = setlocale (LC_ALL, $this->locale); + if (!$result) + { + throw new DataNotSet ("Locale " . $locale . " is not available on this platform."); + } } /** diff --git a/src/Neuron/Tools/Text.php b/src/Neuron/Tools/Text.php index d3aa8f2..8967f79 100644 --- a/src/Neuron/Tools/Text.php +++ b/src/Neuron/Tools/Text.php @@ -52,11 +52,13 @@ public function setDomain ($domain) */ public function getText ($message1, $message2 = null, $n = null) { + //textdomain ($this->domain); + if (!isset ($message2)) { - return dcgettext ($this->domain, $message1, null); + return dgettext ($this->domain, $message1); } else { - return dcngettext ($this->domain, $message1, $message2, $n, null); + return dngettext ($this->domain, $message1, $message2, $n); } } From 33c0b34471ff7cd098a37b587259d6c0b877c575 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 23:14:00 +0100 Subject: [PATCH 034/231] Yolo. --- src/Neuron/Tools/Text.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Neuron/Tools/Text.php b/src/Neuron/Tools/Text.php index 8967f79..de2625d 100644 --- a/src/Neuron/Tools/Text.php +++ b/src/Neuron/Tools/Text.php @@ -52,8 +52,6 @@ public function setDomain ($domain) */ public function getText ($message1, $message2 = null, $n = null) { - //textdomain ($this->domain); - if (!isset ($message2)) { return dgettext ($this->domain, $message1); } From 1ca55a15dbd7fc09aa208fb17801506e2a4668d0 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 23:19:16 +0100 Subject: [PATCH 035/231] Removing the english translation. Updating the example page. --- example/locales/en_UK/LC_MESSAGES/example.mo | Bin 644 -> 0 bytes example/locales/en_UK/LC_MESSAGES/example.po | 20 ----------- example/locales/nl_BE/LC_MESSAGES/example.mo | Bin 786 -> 1365 bytes example/locales/nl_BE/LC_MESSAGES/example.po | 35 ++++++++++++++++--- example/templates/example.phpt | 13 +++---- 5 files changed, 36 insertions(+), 32 deletions(-) delete mode 100644 example/locales/en_UK/LC_MESSAGES/example.mo delete mode 100644 example/locales/en_UK/LC_MESSAGES/example.po diff --git a/example/locales/en_UK/LC_MESSAGES/example.mo b/example/locales/en_UK/LC_MESSAGES/example.mo deleted file mode 100644 index 71154feeae2d85007e603cf09dbcaf302f849a21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 644 zcmah{&2AGh5MB^m_Q;vT+&F;U-6)lcTM!}y6m<&=*;d@5$?mZ0D79Diq%;rG*XuLz z2+TI6IRPVovPbjd@ALTf*^`?@?6Kgv;FaL1;6yN3DFDG&!LLV267Kz43dFs$q4vQF z;ujHGdqu#Vl@l@3H3I^Nt=2jzgI`h2YSyR=3ekFJ;4^K4cQC!i%YIF1`K3~mK*$nQ zACSqwD9gtx&(-KPj7DaB_%h40OcK>My0Sx)f94e!SycgDTqFBnpz7=@!UZ~LD8Rh# zklK#mL@2M~yBc|oOTDDGX@RcYU`whZyfiRDE^rAm#}u&ULFM0T43Jx#pQdNCv*})I zuCsLFrGXPl+g`K{?{mF3XJ0t)`+fF%jMO7{2DCodt$lFrH=(A< ej-i1a#fOXLgrV+ADOTB_NhT?ii)r%TAMqOz>An;I diff --git a/example/locales/en_UK/LC_MESSAGES/example.po b/example/locales/en_UK/LC_MESSAGES/example.po deleted file mode 100644 index d4f3a93..0000000 --- a/example/locales/en_UK/LC_MESSAGES/example.po +++ /dev/null @@ -1,20 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Neuron Example\n" -"POT-Creation-Date: 2014-11-29 22:45+0100\n" -"PO-Revision-Date: 2014-11-29 22:45+0100\n" -"Last-Translator: Thijs Van der Schaeghe \n" -"Language-Team: CatLab Interactive \n" -"Language: en_UK\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.5.4\n" -"X-Poedit-KeywordsList: _;gettext;gettext_noop\n" -"X-Poedit-Basepath: ../../../\n" -"X-Poedit-SourceCharset: UTF-8\n" -"X-Poedit-SearchPath-0: templates\n" - -#: templates/example.phpt:23 -msgid "Let's give this gettext a try..." -msgstr "Let's give this gettext a try..." diff --git a/example/locales/nl_BE/LC_MESSAGES/example.mo b/example/locales/nl_BE/LC_MESSAGES/example.mo index e8787db0395c6df33bd02a8037c726fb4ed4560e..cf1951b33a6e7a7af987c8f6bd4bc227da2f2f54 100644 GIT binary patch delta 727 zcmZ8eJ#Q015M4V?KztNL&>)Z|1X3VmWKn=Ds0fOL5Ht}qH0!(Z-TKzMWvJk(( zSQJQ5($G@!2cV#&L;L_FghWljySo@ijPBjro0)yH_x9z+*Auhvo2^#@aU8e+JOxey zZ-6pB0h_>Q;56_JI0O6u2>1iEfQtqtDS6Ji4Xi0{{6?5$!0?_5~aP7QL#FK0YPI#pbjj7@Pd zIrl=F_DV5rha\n" "Language-Team: CatLab Interactive \n" "Language: nl_BE\n" @@ -16,11 +16,38 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;\n" "X-Poedit-SearchPath-0: templates\n" -#: templates/example.phpt:23 +#: templates/example.phpt:6 +msgid "Example structure" +msgstr "Voorbeeldstructuur" + +#: templates/example.phpt:8 +msgid "" +"This is just an example structure. We want to give you all the freedom you " +"need. No rigid structure. Just a bunch of classes that you can instanciate " +"in any way you like." +msgstr "" +"Dit is slechts een voorbeeldstructuur. We willen je alle vrijheid geven die " +"je nodig hebt. Geen lompe, verplichte structuren. Gewoon een hoop klasses " +"die je naar goeddunken kan gebruiken." + +#: templates/example.phpt:11 +msgid "Configuration" +msgstr "Configuratie" + +#: templates/example.phpt:12 +#, php-format +msgid "Config example: %s" +msgstr "Configuratie voorbeeld: %s" + +#: templates/example.phpt:19 +msgid "Text" +msgstr "Tekst" + +#: templates/example.phpt:20 msgid "Let's give this gettext a try..." msgstr "Laten we dit nog eens proberen..." -#: templates/example.phpt:28 +#: templates/example.phpt:25 #, php-format msgid "There is %s beer" msgid_plural "There are %s beers." diff --git a/example/templates/example.phpt b/example/templates/example.phpt index 4a9372a..ba25ce1 100644 --- a/example/templates/example.phpt +++ b/example/templates/example.phpt @@ -3,23 +3,20 @@ $this->textdomain ('example'); ?> -

Example structure

+

gettext ('Example structure'); ?>

- This is just an example structure. - We want to give you all the freedom you need. - No rigid structure. - Just a bunch of classes that you can instanciate in any way you like. + gettext ('This is just an example structure. We want to give you all the freedom you need. No rigid structure. Just a bunch of classes that you can instanciate in any way you like.'); ?>

-

Configuration

-

Config example: .

+

gettext ('Configuration'); ?>

+

gettext ('Config example: %s'), $title); ?>.

    $v) { ?>
  • :
-

Text

+

gettext ('Text'); ?>

gettext ('Let\'s give this gettext a try...'); ?>

Multiple text

From 3707094b046d81a9f5f048210470791da25d8d90 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 23:24:04 +0100 Subject: [PATCH 036/231] Removing the english translation. Updating the example page. --- src/Neuron/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index 7d5819a..4956e63 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -83,7 +83,7 @@ private function checkLocale () { if (!isset ($this->locale)) { - $this->setLocale ('en'); + $this->setLocale ('en-US'); } } From 386b58734562eb0f12d81f44c3421c9c1c3b15bf Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 23:25:48 +0100 Subject: [PATCH 037/231] Removing the english translation. Updating the example page. --- src/Neuron/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index 4956e63..86988de 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -83,7 +83,7 @@ private function checkLocale () { if (!isset ($this->locale)) { - $this->setLocale ('en-US'); + $this->setLocale (locale_get_default ()); } } From 1dc0b41ed76a66c9645b53d735e7dbd8b64aa27c Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 23:28:08 +0100 Subject: [PATCH 038/231] Removing the english translation. Updating the example page. --- src/Neuron/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index 86988de..f204d7a 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -83,7 +83,7 @@ private function checkLocale () { if (!isset ($this->locale)) { - $this->setLocale (locale_get_default ()); + $this->setLocale (\Locale::getDefault ()); } } From 25e9b4a4fc11ec0e3f2c6688bd7cf7b5a8eafdc9 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 23:30:11 +0100 Subject: [PATCH 039/231] Removing the english translation. Updating the example page. --- src/Neuron/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index f204d7a..6c0d2a6 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -83,7 +83,7 @@ private function checkLocale () { if (!isset ($this->locale)) { - $this->setLocale (\Locale::getDefault ()); + $this->setLocale ('en_GB'); } } From e89c482bdb9c7e0bc6ab1ed29afc498502606f97 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 23:31:26 +0100 Subject: [PATCH 040/231] Removing the english translation. Updating the example page. --- src/Neuron/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index 6c0d2a6..820c30a 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -83,7 +83,7 @@ private function checkLocale () { if (!isset ($this->locale)) { - $this->setLocale ('en_GB'); + $this->setLocale ('en_GB.utf8'); } } From f4ed17061506a76dbad6a97dbd6be3226a4307ef Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 29 Nov 2014 23:53:46 +0100 Subject: [PATCH 041/231] Removing the english translation. Updating the example page. --- src/Neuron/Router.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 07a7c09..21b5815 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -46,7 +46,7 @@ class Router { * * @param string $methods Allowed methods, | delimited * @param string $pattern A route pattern such as /about/system - * @param object $fn The handling function to be executed + * @param mixed $fn The handling function to be executed */ public function match($methods, $pattern, $fn) { @@ -67,7 +67,7 @@ public function match($methods, $pattern, $fn) { * Shorthand for a route accessed using GET * * @param string $pattern A route pattern such as /about/system - * @param object $fn The handling function to be executed + * @param mixed $fn The handling function to be executed */ public function get($pattern, $fn) { $this->match('GET', $pattern, $fn); @@ -78,7 +78,7 @@ public function get($pattern, $fn) { * Shorthand for a route accessed using POST * * @param string $pattern A route pattern such as /about/system - * @param object $fn The handling function to be executed + * @param mixed $fn The handling function to be executed */ public function post($pattern, $fn) { $this->match('POST', $pattern, $fn); @@ -89,7 +89,7 @@ public function post($pattern, $fn) { * Shorthand for a route accessed using PATCH * * @param string $pattern A route pattern such as /about/system - * @param object $fn The handling function to be executed + * @param mixed $fn The handling function to be executed */ public function patch($pattern, $fn) { $this->match('PATCH', $pattern, $fn); @@ -100,7 +100,7 @@ public function patch($pattern, $fn) { * Shorthand for a route accessed using DELETE * * @param string $pattern A route pattern such as /about/system - * @param object $fn The handling function to be executed + * @param mixed $fn The handling function to be executed */ public function delete($pattern, $fn) { $this->match('DELETE', $pattern, $fn); @@ -111,7 +111,7 @@ public function delete($pattern, $fn) { * Shorthand for a route accessed using PUT * * @param string $pattern A route pattern such as /about/system - * @param object $fn The handling function to be executed + * @param mixed $fn The handling function to be executed */ public function put($pattern, $fn) { $this->match('PUT', $pattern, $fn); @@ -121,7 +121,7 @@ public function put($pattern, $fn) { * Shorthand for a route accessed using OPTIONS * * @param string $pattern A route pattern such as /about/system - * @param object $fn The handling function to be executed + * @param mixed $fn The handling function to be executed */ public function options($pattern, $fn) { $this->match('OPTIONS', $pattern, $fn); From 050d75c5ecace14783dd96a2ff553eb770740ff6 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 10:59:35 +0100 Subject: [PATCH 042/231] Adding bootstrap for testing. --- example/templates/sections/head.phpt | 6 ++++-- src/Neuron/Core/Template.php | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/example/templates/sections/head.phpt b/example/templates/sections/head.phpt index 3b1dc31..e9a2461 100644 --- a/example/templates/sections/head.phpt +++ b/example/templates/sections/head.phpt @@ -1,7 +1,9 @@ - css ('assets/css/style.css'); ?> + css ('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'); ?> + + css ('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css'); ?> - js ('assets/js/main.js'); ?> \ No newline at end of file + js ('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js'); ?> \ No newline at end of file diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index c8cca94..b495d75 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -366,12 +366,12 @@ private function help ($name, $method) private function css ($path) { - return ''; + return ''; } private function js ($path) { - return ''; + return ''; } private function textdomain ($domain) From a07c91b46b5b09cce25dceb05df75fd89fcdd421 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 12:43:38 +0100 Subject: [PATCH 043/231] Adding constructor to controller that allows passing the module. --- src/Neuron/Interfaces/Controller.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/Neuron/Interfaces/Controller.php diff --git a/src/Neuron/Interfaces/Controller.php b/src/Neuron/Interfaces/Controller.php new file mode 100644 index 0000000..bdb6ba8 --- /dev/null +++ b/src/Neuron/Interfaces/Controller.php @@ -0,0 +1,20 @@ + Date: Sun, 30 Nov 2014 12:48:21 +0100 Subject: [PATCH 044/231] Adding constructor to controller that allows passing the module. --- src/Neuron/Router.php | 22 +++++++++++++++++++--- src/Neuron/Tools/ControllerFactory.php | 16 +++++++++------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 21b5815..ac3f3c9 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -9,7 +9,9 @@ namespace Neuron; use Neuron\Exceptions\InvalidParameter; +use Neuron\Interfaces\Module; use Neuron\Net\Request; +use Neuron\Tools\ControllerFactory; class Router { @@ -41,6 +43,9 @@ class Router { */ private $request; + /** @var Module|null */ + private $module = null; + /** * Store a route and a handling function to be executed when accessed using one of the specified methods * @@ -56,12 +61,22 @@ public function match($methods, $pattern, $fn) { foreach (explode('|', $methods) as $method) { $this->routes[$method][] = array( 'pattern' => $pattern, - 'fn' => $fn + 'fn' => $fn, + 'module' => $this->module ); } } + /** + * Set the module that will be used in the constructor for all Controllers + * that match the path of all future matches. + * @param Module $module + */ + public function setModule (Module $module = null) + { + $this->module = $module; + } /** * Shorthand for a route accessed using GET @@ -284,13 +299,14 @@ private function handleMatch ($function, $params) * @param string $controller * @param string $method * @param array $params + * @param Module $module * @throws Exceptions\DataNotFound * @throws InvalidParameter * @return mixed */ - private function handleController ($controller, $method, $params) + private function handleController ($controller, $method, $params, $module = null) { - $controller = \Neuron\Tools\ControllerFactory::getInstance ()->getController ($controller); + $controller = ControllerFactory::getInstance ()->getController ($controller, $module); if (is_callable (array ($controller, $method))) { diff --git a/src/Neuron/Tools/ControllerFactory.php b/src/Neuron/Tools/ControllerFactory.php index 562681b..b08ea76 100644 --- a/src/Neuron/Tools/ControllerFactory.php +++ b/src/Neuron/Tools/ControllerFactory.php @@ -10,6 +10,7 @@ use Neuron\Exceptions\DataNotFound; +use Neuron\Interfaces\Module; class ControllerFactory { @@ -33,17 +34,18 @@ private function __construct () /** * @param $name + * @param Module $module * @return mixed * @throws DataNotFound */ - public function getController ($name) + public function getController ($name, Module $module = null) { - if (class_exists ($name)) - { - $this->controllers[$name] = new $name (); - } - else { - throw new DataNotFound ("Controller not found: " . $name); + if (!isset ($this->controllers[$name])) { + if (class_exists ($name)) { + $this->controllers[$name] = new $name ($module); + } else { + throw new DataNotFound ("Controller not found: " . $name); + } } return $this->controllers[$name]; From f605b52247c1f9740a3c9ac9e8a7a3fd82592eab Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 12:50:03 +0100 Subject: [PATCH 045/231] Adding constructor to controller that allows passing the module. --- src/Neuron/Router.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index ac3f3c9..d8e3334 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -176,7 +176,7 @@ public function run (Request $request) if ($numHandled == 0) { if ($this->notFound) { //call_user_func($this->notFound); - $this->handleMatch ($this->notFound, array ()); + $this->handleMatch ($this->notFound, array (), null); } else { @@ -239,7 +239,7 @@ private function handle ($routes) { }, $matches, array_keys($matches)); // call the handling function with the URL parameters - $this->handleMatch ($route['fn'], $params); + $this->handleMatch ($route['fn'], $params, $route['module']); //call_user_func_array($route['fn'], $params); // yay! @@ -259,9 +259,10 @@ private function handle ($routes) { /** * @param $function * @param $params + * @param Module $module * @throws InvalidParameter */ - private function handleMatch ($function, $params) + private function handleMatch ($function, $params, Module $module = null) { if (is_callable ($function)) { From 68d40cacc261b2c907f162e2eb29662048fc76d6 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 13:44:42 +0100 Subject: [PATCH 046/231] Adding constructor to controller that allows passing the module. --- src/Neuron/Router.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index d8e3334..929113d 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -11,6 +11,7 @@ use Neuron\Exceptions\InvalidParameter; use Neuron\Interfaces\Module; use Neuron\Net\Request; +use Neuron\Net\Response; use Neuron\Tools\ControllerFactory; class Router { @@ -73,7 +74,7 @@ public function match($methods, $pattern, $fn) { * that match the path of all future matches. * @param Module $module */ - public function setModule (Module $module = null) + private function setModule (Module $module = null) { $this->module = $module; } @@ -146,17 +147,20 @@ public function options($pattern, $fn) { * @param $prefix * @param Interfaces\Module $module */ - public function module ($prefix, \Neuron\Interfaces\Module $module) + public function module ($prefix, Module $module) { $module->initialize (); + + $this->setModule ($module); $module->setRoutes ($this, $prefix); + $this->setModule (null); } /** * Execute the router: Loop all defined before middlewares and routes, and execute the handling function if a mactch was found * * @param Request $request - * @return \Neuron\Net\Response + * @return Response */ public function run (Request $request) { @@ -180,7 +184,7 @@ public function run (Request $request) } else { - $request = \Neuron\Net\Response::template ('404.phpt'); + $request = Response::template ('404.phpt'); $request->setStatus (404); $request->output (); } @@ -204,8 +208,7 @@ public function set404($fn) { /** * Handle a a set of routes: if a match is found, execute the relating handling function * @param array $routes Collection of route patterns and their handling functions - * @param boolean $quitAfterRun Does the handle function need to quit after one route was matched? - * @return \Neuron\Net\Response The response + * @return Response The response */ private function handle ($routes) { @@ -277,7 +280,7 @@ private function handleMatch ($function, $params, Module $module = null) throw new InvalidParameter ("Controller@method syntax not valid for " . $function); } - $response = $this->handleController ($param[0], $param[1], $params); + $response = $this->handleController ($param[0], $param[1], $params, $module); } else { throw new InvalidParameter ("Method not found."); @@ -286,7 +289,7 @@ private function handleMatch ($function, $params, Module $module = null) if ($response) { - if ($response instanceof \Neuron\Net\Response) + if ($response instanceof Response) { $response->output (); } From 4d3677dd2d340169d171bea584cb6992db356c60 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 14:10:42 +0100 Subject: [PATCH 047/231] Passing the request to the controller as well. --- src/Neuron/Interfaces/Controller.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Neuron/Interfaces/Controller.php b/src/Neuron/Interfaces/Controller.php index bdb6ba8..a457f23 100644 --- a/src/Neuron/Interfaces/Controller.php +++ b/src/Neuron/Interfaces/Controller.php @@ -9,6 +9,8 @@ namespace Neuron\Interfaces; +use Neuron\Net\Request; + interface Controller { /** @@ -17,4 +19,10 @@ interface Controller */ public function __construct (Module $module = null); + /** + * Set (or clear) the request object. + * @param Request $request + * @return void + */ + public function setRequest (Request $request = null); } \ No newline at end of file From edc47569a8cbee27e038832ff962f1ecbaa31c84 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 14:12:42 +0100 Subject: [PATCH 048/231] Passing the request to the controller as well. --- src/Neuron/Router.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 929113d..ca4dfcb 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -9,6 +9,7 @@ namespace Neuron; use Neuron\Exceptions\InvalidParameter; +use Neuron\Interfaces\Controller; use Neuron\Interfaces\Module; use Neuron\Net\Request; use Neuron\Net\Response; @@ -312,6 +313,12 @@ private function handleController ($controller, $method, $params, $module = null { $controller = ControllerFactory::getInstance ()->getController ($controller, $module); + // If the found controller implements the Controller interface, we set the request. + if ($controller instanceof Controller) + { + $controller->setRequest ($this->request); + } + if (is_callable (array ($controller, $method))) { return call_user_func_array(array ($controller, $method), $params); From fc3e36ba5f5f0af78e48d2662347855d86e123f8 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 14:22:46 +0100 Subject: [PATCH 049/231] Passing the request to the controller as well. --- src/Neuron/Interfaces/Module.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Neuron/Interfaces/Module.php b/src/Neuron/Interfaces/Module.php index 0d5ea43..4001914 100644 --- a/src/Neuron/Interfaces/Module.php +++ b/src/Neuron/Interfaces/Module.php @@ -9,20 +9,23 @@ namespace Neuron\Interfaces; +use Neuron\Router; + interface Module { /** * Set template paths, config vars, etc + * @param string $routepath The prefix that should be added to all route paths. * @return void */ - public function initialize (); + public function initialize ($routepath); /** * Register the routes required for this module. - * @param \Neuron\Router $router + * @param Router $router * @param $prefix * @return mixed */ - public function setRoutes (\Neuron\Router $router, $prefix); + public function setRoutes (Router $router, $prefix); } \ No newline at end of file From bc2e8a2f0453d82599994cc870e486f192bb47b7 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 14:24:32 +0100 Subject: [PATCH 050/231] Passing the request to the controller as well. --- src/Neuron/Interfaces/Module.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Neuron/Interfaces/Module.php b/src/Neuron/Interfaces/Module.php index 4001914..731bf41 100644 --- a/src/Neuron/Interfaces/Module.php +++ b/src/Neuron/Interfaces/Module.php @@ -23,9 +23,8 @@ public function initialize ($routepath); /** * Register the routes required for this module. * @param Router $router - * @param $prefix - * @return mixed + * @return void */ - public function setRoutes (Router $router, $prefix); + public function setRoutes (Router $router); } \ No newline at end of file From 6817671217abc43f4c0ad635e9b1d94943b8c4b7 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 14:25:36 +0100 Subject: [PATCH 051/231] Passing the request to the controller as well. --- src/Neuron/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index ca4dfcb..03f749a 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -150,7 +150,7 @@ public function options($pattern, $fn) { */ public function module ($prefix, Module $module) { - $module->initialize (); + $module->initialize ($prefix); $this->setModule ($module); $module->setRoutes ($this, $prefix); From 204dab86f1e9b738434771254922b77ddeb7010a Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 14:29:04 +0100 Subject: [PATCH 052/231] Passing the request to the controller as well. --- src/Neuron/URLBuilder.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Neuron/URLBuilder.php b/src/Neuron/URLBuilder.php index 74d7ab8..2ea7d08 100644 --- a/src/Neuron/URLBuilder.php +++ b/src/Neuron/URLBuilder.php @@ -13,6 +13,11 @@ class URLBuilder { public static function getURL ($module = '', $data = array ()) { + if (substr ($module, 0, 1) === '/') + { + $module = substr ($module, 1); + } + $params = ''; foreach ($data as $k => $v) { From 6a5dac9d8280c048f5bf216fd377c7541d175918 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 14:43:33 +0100 Subject: [PATCH 053/231] Adding input() to Request parameter. --- src/Neuron/Core/Tools.php | 2 +- src/Neuron/Net/Request.php | 73 +++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index b4540ea..66499f7 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -12,7 +12,7 @@ class Tools { - public static function getInput ($dat, $key, $type, $default = false) + public static function getInput ($dat, $key, $type, $default = null) { if (is_string ($dat)) { diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index a33e1d7..276c80f 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -9,6 +9,7 @@ namespace Neuron\Net; +use Neuron\Core\Tools; use Neuron\Exceptions\InvalidParameter; use Neuron\Net\InputStream; use Neuron\MapperFactory; @@ -17,6 +18,12 @@ class Request extends Entity { + const METHOD_POST = 'POST'; + const METHOD_GET = 'GET'; + const METHOD_PATCH = 'PATCH'; + const METHOD_PUT = 'PUT'; + const METHOD_OPTIONS = 'OPTIONS'; + /** * @return Request */ @@ -138,7 +145,7 @@ public static function fromJSON ($json) { $model->setSegments ($data['segments']); } - + if (isset ($data['environment'])) { $model->setEnvironment ($data['environment']); @@ -267,4 +274,68 @@ public function getEnvironment () { return $this->environment; } + + /** + * @return bool + */ + public function isPost () + { + return $this->getMethod () === self::METHOD_POST; + } + + /** + * @return bool + */ + public function isGet () + { + return $this->getMethod () === self::METHOD_GET; + } + + /** + * @return bool + */ + public function isPut () + { + return $this->getMethod () === self::METHOD_PUT; + } + + /** + * @return bool + */ + public function isPatch () + { + return $this->getMethod () === self::METHOD_PATCH; + } + + /** + * @return bool + */ + public function isOptions () + { + return $this->getMethod () === self::METHOD_OPTIONS; + } + + /** + * Similar to fetching a value from $_REQUEST + * @param $field + * @param string $type + * @param mixed $default + * @return mixed|null + */ + public function input ($field, $type = 'string', $default = null) + { + // Check post + $value = Tools::getInput ($this->getPost (), $field, $type); + if ($value === null) + { + // Check get + $value = Tools::getInput ($this->getParameters (), $field, $type); + } + + if ($value === null) + { + return $default; + } + return $value; + } } \ No newline at end of file From ff56f571843ec73f8e609b42e53f6f80ce2da3b8 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 14:52:01 +0100 Subject: [PATCH 054/231] Adding input() to Request parameter. --- src/Neuron/Core/Tools.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index 66499f7..efb0b01 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -66,7 +66,7 @@ public static function checkInput ($value, $type) return $value == 1 || $value == 'true'; } - elseif ($type == 'varchar') + elseif ($type == 'varchar' || $type == 'string') { return self::isValidUTF8 ($value); } From 9f4cc5ab314ba6d6ac3d88f763d2a55bfd9aa8fd Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 15:03:09 +0100 Subject: [PATCH 055/231] Allowing including templates inside of other templates. --- src/Neuron/Core/Template.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index b495d75..2bd4ba8 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -337,6 +337,33 @@ private function combine ($template) return $val; } + /** + * Include a single template inside another template. + */ + private function template ($template) + { + ob_start(); + + foreach (self::$shares as $k => $v) { + ${$k} = $v; + } + + foreach ($this->values as $k => $v) { + ${$k} = $v; + } + + if ($ctlbtmpltfiles = $this->getFilenames($template)) { + foreach ($ctlbtmpltfiles as $ctlbtmpltfile) { + include $ctlbtmpltfile; + } + } + + $val = ob_get_contents(); + ob_end_clean(); + + return $val; + } + /** * @param string $name * @param string $method From 6b809b2083b106fc008c0593434af5a7a2af8454 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 18:31:29 +0100 Subject: [PATCH 056/231] Adding observable. --- src/Neuron/Collections/Collection.php | 16 +- src/Neuron/Core/DataUri.php | 264 ----------------- src/Neuron/Core/Error.php | 13 - src/Neuron/Core/Text.php | 274 ------------------ src/Neuron/Exceptions/DataNotFound.php | 5 +- src/Neuron/Exceptions/DataNotSet.php | 4 +- src/Neuron/Exceptions/DbException.php | 4 +- src/Neuron/Exceptions/Deprecated.php | 5 +- src/Neuron/Exceptions/InvalidParameter.php | 7 +- src/Neuron/Exceptions/NotImplemented.php | 4 +- .../Exceptions/OutputAlreadyStarted.php | 5 +- src/Neuron/Interfaces/Observer.php | 16 + src/Neuron/Models/Observable.php | 72 +++++ src/Neuron/{Core => Tools}/Memcache.php | 4 +- 14 files changed, 113 insertions(+), 580 deletions(-) delete mode 100644 src/Neuron/Core/DataUri.php delete mode 100644 src/Neuron/Core/Error.php delete mode 100644 src/Neuron/Core/Text.php create mode 100644 src/Neuron/Interfaces/Observer.php create mode 100644 src/Neuron/Models/Observable.php rename src/Neuron/{Core => Tools}/Memcache.php (97%) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 7796ea3..2847c70 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -11,8 +11,10 @@ use ArrayAccess; use Countable; use Iterator; +use Neuron\Models\Observable; abstract class Collection + extends Observable implements Iterator, ArrayAccess, Countable { private $position = 0; @@ -70,11 +72,20 @@ public function offsetSet($offset, $value) { if (is_null ($offset)) { - $this->data[] = $value; + $index = array_push ($this->data, $value); + $this->trigger ('add', $value, $index); } else { - $this->data[$offset] = $value; + if (isset ($this->data[$offset])) + { + $this->trigger ('add', $value, $offset); + } + else { + $this->trigger ('set', $value, $offset); + } + + $this->data[$offset] = $value; } } @@ -90,6 +101,7 @@ public function offsetSet($offset, $value) public function offsetUnset($offset) { unset ($this->data[$offset]); + $this->trigger ('remove', $offset); } /** diff --git a/src/Neuron/Core/DataUri.php b/src/Neuron/Core/DataUri.php deleted file mode 100644 index b115a32..0000000 --- a/src/Neuron/Core/DataUri.php +++ /dev/null @@ -1,264 +0,0 @@ -Lucas - */ -class DataUri { - - /** @var Regular expression used for decomposition of data URI scheme */ - private static $REGEX_URI = '/^data:(.+?){0,1}(?:(?:;(base64)\,){1}|\,)(.+){0,1}$/'; - - const DEFAULT_TYPE = 'text/plain;charset=US-ASCII'; - - const ENCODING_URL_ENCODED_OCTETS = 0; - const ENCODING_BASE64 = 1; - - /** @var Keyword used in the data URI to signify base64 encoding */ - const BASE64_KEYWORD = 'base64'; - - private $mediaType; - private $encoding; - private $encodedData; - - /** - * Instantiates an instance of the DataURI class, initialised with the - * default values defined in RFC 2397. That is the media-type of - * text/plain;charset=US-ASCII and encoding type of URL encoded octets. - * - * @param string $mediaType - * @param string $data Unencoded data - * @param integer $encoding Class constant of either - * {@link DataUri::ENCODING_URL_ENCODED_OCTETS} or - * {@link DataUri::ENCODING_BASE64} - * - * @throws InvalidArgumentException - */ - public function __construct($mediaType = DataUri::DEFAULT_TYPE, - $data = '', - $encoding = DataUri::ENCODING_URL_ENCODED_OCTETS - ) { - try { - $this->setMediaType($mediaType); - $this->setData($data, $encoding); - } catch (InvalidArgumentException $e) { - throw $e; - } - } - - /** - * Returns the data URI's media-type. If none was provided then in - * accordance to RFC 2397 it will default to text/plain;charset=US-ASCII - * - * @return string Media-type - */ - public function getMediaType() { - return empty($this->mediaType) === false - ? $this->mediaType - : DataUri::DEFAULT_TYPE; - } - - /** - * Sets the media-type. - * - * @param string $mediaType Media-type - */ - public function setMediaType($mediaType) { - $this->mediaType = $mediaType; - } - - /** - * Returns the method of encoding used for the data. - * - * @return int Class constant of either - * {@link DataUri::ENCODING_URL_ENCODED_OCTETS} or - * {@link DataUri::ENCODING_BASE64} - */ - public function getEncoding() { - return $this->encoding; - } - - /** - * Returns the data in its encoded form. - * - * @return string Encoded data - */ - public function getEncodedData() { - return $this->encodedData; - } - - /** - * Sets the encoded data and the encoding scheme used to encode/decode it. - * Be aware that the data is not validated, so ensure that the correct - * encoding scheme is provided otherwise the method - * {@link DataUri::tryDecodeData($decodedData)} will fail. - - * @param int $encoding Class constant of either - * {@link DataUri::ENCODING_URL_ENCODED_OCTETS} or - * {@link DataUri::ENCODING_BASE64} - * @param string $data Data encoded with the encoding scheme provided - * @throws InvalidArgumentException - */ - public function setEncodedData($encoding, $data) { - if(($encoding !== DataUri::ENCODING_URL_ENCODED_OCTETS) && - ($encoding !== DataUri::ENCODING_BASE64)) { - throw new InvalidArgumentException('Unsupported encoding scheme'); - } - - $this->encoding = $encoding; - $this->encodedData = $data; - } - - - /** - * Sets the data for the data URI, which it stores in encoded form using - * the encoding scheme provided. - * - * @param string $data Data to encode then store - * @param int $encoding Class constant of either - * {@link DataUri::ENCODING_URL_ENCODED_OCTETS} or - * {@link DataUri::ENCODING_BASE64} - * @throws InvalidArgumentException - */ - public function setData($data, $encoding = DataUri::ENCODING_URL_ENCODED_OCTETS) { - switch($encoding) { - case DataUri::ENCODING_URL_ENCODED_OCTETS: - $this->encoding = DataUri::ENCODING_URL_ENCODED_OCTETS; - $this->encodedData = rawurlencode($data); - break; - case DataUri::ENCODING_BASE64: - $this->encoding = DataUri::ENCODING_BASE64; - $this->encodedData = base64_encode($data); - break; - default: - throw new InvalidArgumentException('Unsupported encoding scheme'); - break; - } - } - - /** - * Tries to decode the URI's data using the encoding scheme set. - * - * @param null $decodedData Stores the decoded data - * @return boolean true if data was output, - * else false - */ - public function tryDecodeData(&$decodedData) { - $hasOutput = false; - - switch($this->getEncoding()) { - case DataUri::ENCODING_URL_ENCODED_OCTETS: - $decodedData = rawurldecode($this->getEncodedData()); - $hasOutput = true; - break; - case DataUri::ENCODING_BASE64: - $b64Decoded = base64_decode($this->getEncodedData(), true); - - if($b64Decoded !== false) { - $decodedData = $b64Decoded; - $hasOutput = true; - } - break; - default: - // NOP - break; - } - - return $hasOutput; - } - - /** - * Generates a data URI string representation of the object. - * - * @return string - */ - public function toString() { - $output = 'data:'; - - if(($this->getMediaType() !== DataUri::DEFAULT_TYPE) || - ($this->getEncoding() !== DataUri::ENCODING_URL_ENCODED_OCTETS)) { - $output .= $this->getMediaType(); - - if($this->getEncoding() === DataUri::ENCODING_BASE64) { - $output .= ';'.DataUri::BASE64_KEYWORD; - } - } - - $output .= ','.$this->getEncodedData(); - return $output; - } - - public function __toString() - { - return $this->toString(); - } - - /** - * Determines whether a string is data URI with the components necessary for - * it to be parsed by the {@link DataUri::tryParse($s, &$out)} method. - * - * @param string $string Data URI - * @return boolean true if possible to parse, - * else false - */ - public static function isParsable ($dataUriString) { - return (preg_match(DataUri::$REGEX_URI, $dataUriString) === 1); - } - - /** - * Parses a string data URI into an instance of a DataUri object. - * - * @param string $dataUriString Data URI to be parsed - * @param DataUri $out Output DataUri of the method - * @return boolean true if successful, else false - */ - public static function tryParse($dataUriString, &$out) { - $hasOutput = false; - - if(DataUri::isParsable($dataUriString)) { - $matches = null; - if(preg_match_all(DataUri::$REGEX_URI, - $dataUriString, - $matches, - PREG_SET_ORDER) !== false) { - - $mediatype = isset($matches[0][1]) - ? $matches[0][1] - : DataUri::DEFAULT_TYPE; - - $matchedEncoding = isset($matches[0][2]) ? $matches[0][2] : ''; - $encoding = (strtolower($matchedEncoding) === DataUri::BASE64_KEYWORD) - ? DataUri::ENCODING_BASE64 - : DataUri::ENCODING_URL_ENCODED_OCTETS; - - $data = isset($matches[0][3]) - ? $matches[0][3] - : ''; - - $dataUri = new DataUri(); - $dataUri->setMediaType($mediatype); - $dataUri->setEncodedData($encoding, $data); - - $out = $dataUri; - $hasOutput = true; - } - } - - return $hasOutput; - } -} \ No newline at end of file diff --git a/src/Neuron/Core/Error.php b/src/Neuron/Core/Error.php deleted file mode 100644 index 7c0c0f8..0000000 --- a/src/Neuron/Core/Error.php +++ /dev/null @@ -1,13 +0,0 @@ -backup = new NeuronCoreText ($language, $baseText, CATLAB_LANGUAGE_PATH); - } - - else if ($baseText && $baseText != $language) - { - $this->backup = new NeuronCoreText ($baseText, false); - } - - // Take text - if (isset ($language)) - { - $this->root_dir = $pathname.$language; - $this->tag = $language; - } - - else - { - echo 'Language directory not defined.'; - exit (); - } - - } - - public function setLanguage ($language) - { - $this->root_dir = LANGUAGE_DIR.$language; - $this->tag = $language; - - // Remove cache - $this->cache = array (); - } - - public function setFile ($file) - { - - $this->inFile = $file; - - } - - public function setSection ($section) - { - $this->inSection = $section; - } - - public function get ($id, $section = null, $file = null, $alternative = null) - { - throw new Deprecated ("Nope. Use gettext."); - - // Section & fill - if (empty ($section)) - { - $section = $this->inSection; - } - - if (empty ($file)) - { - $file = $this->inFile; - } - - // Check if the file is loaded already - if (empty ($this->cache[$file])) - { - $this->load_file ($file); - } - - // Check if the id exist - if (empty ($this->cache[$file][$section][$id])) - { - if ($this->backup && $this->backup->get ($id, $section, $file, false)) - { - return $this->backup->get ($id, $section, $file, false); - } - elseif ($alternative === null) - { - return 'Text Not Found: '.$id.' ('.$file.', '.$section.', '.$this->root_dir.')'; - } - else - { - return $alternative; - } - } - else { - return $this->cache[$file][$section][$id]; - } - } - - public function getSection ($section, $file) - { - - // Check if the file is loaded already - if (empty ($this->cache[$file])) - { - $this->load_file ($file); - } - - $output = array (); - - if (!empty ($this->cache[$file][$section])) - { - foreach ($this->cache[$file][$section] as $k => $v) - { - if (!empty ($v)) { - $output[$k] = $v; - } - } - } - - if (count ($output) == 0) - { - $output = $this->backup->getSection ($section, $file); - } - - return $output; - } - - public function getRandomLine ($section, $file, $iNumber = false) - { - $section = array_values ($this->getSection ($section, $file)); - - $total = count ($section); - - if ($total < 1) - { - return null; - } - - if (!$iNumber) - { - $iNumber = mt_rand (0, $total); - } - - return $section[$iNumber % $total]; - } - - public function getFile ($inFile, $return = 'error') - { - - $file = $this->root_dir.'/templates/'.$inFile.'.txt'; - - if (is_readable ($file)) - { - return file_get_contents ($file); - } - - elseif ($this->backup && $this->backup->getFile ($inFile, false)) - { - return $this->backup->getFile ($inFile); - } - - else { - if ($return === 'error') - { - return ('404: Unable to load file '.$file.'.'); - } - - else return $return; - } - } - - public function getTemplate ($file, $fields = array ()) - { - return Tools::putIntoText - ( - $this->getFile ($file), - $fields - ); - } - - protected function load_file ($file) - { - $f = $this->root_dir.'/'.$file.'.lng'; - - if (is_readable ($f)) - { - $this->cache[$file] = parse_ini_file ($f, true); - } - } - - /* - Return the abasolute path to the - text file. - */ - public function getPath () - { - return $this->root_dir . '/'; - } - - public function getClickto ($txt) - { - return Array - ( - $this->get ('clickto1', 'main', 'main').' ', - $this->get ('clickto2', 'main', 'main'), - ' '.$txt - ); - } - - public static function getLanguages () - { - $o = array (); - $dir = scandir (LANGUAGE_DIR); - foreach ($dir as $file) - { - if ($file != '.' && $file != '..' && strlen ($file) == 2) - { - $o[] = $file; - } - } - return $o; - } - - public function getCurrentLanguage () - { - return $this->tag; - } -} diff --git a/src/Neuron/Exceptions/DataNotFound.php b/src/Neuron/Exceptions/DataNotFound.php index 5607a1b..d53e61c 100644 --- a/src/Neuron/Exceptions/DataNotFound.php +++ b/src/Neuron/Exceptions/DataNotFound.php @@ -3,11 +3,8 @@ namespace Neuron\Exceptions; -use Neuron\Core\Error; - - class DataNotFound - extends Error + extends \Exception { } diff --git a/src/Neuron/Exceptions/DataNotSet.php b/src/Neuron/Exceptions/DataNotSet.php index f39474d..841e271 100644 --- a/src/Neuron/Exceptions/DataNotSet.php +++ b/src/Neuron/Exceptions/DataNotSet.php @@ -3,11 +3,9 @@ namespace Neuron\Exceptions; -use Neuron\Core\Error; - class DataNotSet - extends Error + extends \Exception { } diff --git a/src/Neuron/Exceptions/DbException.php b/src/Neuron/Exceptions/DbException.php index 702440c..ea804c5 100644 --- a/src/Neuron/Exceptions/DbException.php +++ b/src/Neuron/Exceptions/DbException.php @@ -3,11 +3,9 @@ namespace Neuron\Exceptions; -use Neuron\Core\Error; - class DbException - extends Error + extends \Exception { private $query; diff --git a/src/Neuron/Exceptions/Deprecated.php b/src/Neuron/Exceptions/Deprecated.php index 442759c..5e1ef7e 100644 --- a/src/Neuron/Exceptions/Deprecated.php +++ b/src/Neuron/Exceptions/Deprecated.php @@ -3,15 +3,12 @@ namespace Neuron\Exceptions; -use Neuron\Core\Error; - /** * Class Deprecated * @package Neuron\Exceptions */ class Deprecated - extends Error + extends \Exception { } -?> diff --git a/src/Neuron/Exceptions/InvalidParameter.php b/src/Neuron/Exceptions/InvalidParameter.php index d3d0f7c..524201e 100755 --- a/src/Neuron/Exceptions/InvalidParameter.php +++ b/src/Neuron/Exceptions/InvalidParameter.php @@ -3,12 +3,9 @@ namespace Neuron\Exceptions; -use Neuron\Core\Error; - class InvalidParameter - extends Error + extends \Exception { -} -?> +} \ No newline at end of file diff --git a/src/Neuron/Exceptions/NotImplemented.php b/src/Neuron/Exceptions/NotImplemented.php index 37c426d..d8b48ba 100755 --- a/src/Neuron/Exceptions/NotImplemented.php +++ b/src/Neuron/Exceptions/NotImplemented.php @@ -3,12 +3,10 @@ namespace Neuron\Exceptions; -use Neuron\Core\Error; class NotImplemented - extends Error + extends \Exception { } -?> diff --git a/src/Neuron/Exceptions/OutputAlreadyStarted.php b/src/Neuron/Exceptions/OutputAlreadyStarted.php index b5cd9a1..8cbda89 100644 --- a/src/Neuron/Exceptions/OutputAlreadyStarted.php +++ b/src/Neuron/Exceptions/OutputAlreadyStarted.php @@ -7,7 +7,7 @@ class OutputAlreadyStarted - extends Error + extends \Exception { private $output; @@ -15,5 +15,4 @@ public function __construct ($output) { $this->output = $output; } -} -?> +} \ No newline at end of file diff --git a/src/Neuron/Interfaces/Observer.php b/src/Neuron/Interfaces/Observer.php new file mode 100644 index 0000000..b8d97e6 --- /dev/null +++ b/src/Neuron/Interfaces/Observer.php @@ -0,0 +1,16 @@ +events[$event])) + { + foreach ($this->events[$event] as $call) + { + call_user_func_array ($call, $arguments); + } + } + + // Notify everyone + foreach ($this->observing as $observer) + { + $observer->update (); + } + } + + /** + * Listen to specific events + * @param $event + * @param callable $callback + */ + public function on ($event, callable $callback) + { + $this->events[$event] = $callback; + } + + /** + * @param Observer $observer + */ + public function observe (Observer $observer) + { + $this->observing[] = $observer; + } +} \ No newline at end of file diff --git a/src/Neuron/Core/Memcache.php b/src/Neuron/Tools/Memcache.php similarity index 97% rename from src/Neuron/Core/Memcache.php rename to src/Neuron/Tools/Memcache.php index 73972dd..eae4b44 100644 --- a/src/Neuron/Core/Memcache.php +++ b/src/Neuron/Tools/Memcache.php @@ -1,6 +1,6 @@ Date: Sun, 30 Nov 2014 18:38:28 +0100 Subject: [PATCH 057/231] Adding observable. --- src/Neuron/Collections/Collection.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 2847c70..c8590ce 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -18,7 +18,7 @@ abstract class Collection implements Iterator, ArrayAccess, Countable { private $position = 0; - private $data; + private $data = array (); protected function setCollectionValues (array $data) { @@ -73,7 +73,7 @@ public function offsetSet($offset, $value) if (is_null ($offset)) { $index = array_push ($this->data, $value); - $this->trigger ('add', $value, $index); + $this->trigger ('add', $value, $iundex); } else { @@ -101,7 +101,6 @@ public function offsetSet($offset, $value) public function offsetUnset($offset) { unset ($this->data[$offset]); - $this->trigger ('remove', $offset); } /** From 8d69e5ed0581f4e39b31934610be874aad801c11 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 18:38:54 +0100 Subject: [PATCH 058/231] Adding observable. --- src/Neuron/Collections/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index c8590ce..2dcee97 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -73,7 +73,7 @@ public function offsetSet($offset, $value) if (is_null ($offset)) { $index = array_push ($this->data, $value); - $this->trigger ('add', $value, $iundex); + $this->trigger ('add', $value, $index); } else { From 8fe10472b69b7c8db03524c5549fde85a6dbf212 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 18:40:12 +0100 Subject: [PATCH 059/231] Adding observable. --- src/Neuron/Models/Observable.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Models/Observable.php b/src/Neuron/Models/Observable.php index 0a1cb6c..6100582 100644 --- a/src/Neuron/Models/Observable.php +++ b/src/Neuron/Models/Observable.php @@ -59,7 +59,11 @@ protected function trigger ($event) */ public function on ($event, callable $callback) { - $this->events[$event] = $callback; + if (!isset ($this->events[$event])) + { + $this->events[$event] = array (); + } + $this->events[$event][] = $callback; } /** From 82097ebc85c9d202d9e53895fc0dc9bfe76acd8f Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 18:55:51 +0100 Subject: [PATCH 060/231] Adding tokenized collection. --- .../Collections/TokenizedCollection.php | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/Neuron/Collections/TokenizedCollection.php diff --git a/src/Neuron/Collections/TokenizedCollection.php b/src/Neuron/Collections/TokenizedCollection.php new file mode 100644 index 0000000..4bac2cf --- /dev/null +++ b/src/Neuron/Collections/TokenizedCollection.php @@ -0,0 +1,51 @@ +tokens[$token])) + { + $i = 1; + $tmp = $token . $i; + while (isset ($this->tokens[$tmp])) + { + $i ++; + } + $token = $tmp; + } + + $this->tokens[$token] = true; + return $token; + } + +} \ No newline at end of file From 6b796452c0cf1a2adc6c350d2713ea29799ead68 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 19:09:15 +0100 Subject: [PATCH 061/231] Adding tokenized collection. --- example/bootstrap/router.php | 4 ++++ src/Neuron/Router.php | 3 +++ 2 files changed, 7 insertions(+) diff --git a/example/bootstrap/router.php b/example/bootstrap/router.php index ce29347..f601ed3 100644 --- a/example/bootstrap/router.php +++ b/example/bootstrap/router.php @@ -6,4 +6,8 @@ $router->get ('/', '\Example\Controllers\HomeController@main'); $router->get ('/templates', '\Example\Controllers\HomeController@templates'); +$router->get ('/test/{something}', function ($a) { + return \Neuron\Net\Response::json ($a); +}); + return $router; \ No newline at end of file diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 03f749a..b71fbd5 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -57,6 +57,9 @@ class Router { */ public function match($methods, $pattern, $fn) { + // Regex are too pro, bro! + $pattern = preg_replace ('/\{\w+\}/', '(\w+)', $pattern); + $pattern = $this->baseroute . '/' . trim($pattern, '/'); $pattern = $this->baseroute ? rtrim($pattern, '/') : $pattern; From 5c2d383b48e230d9da006ef5870497b80a6f2760 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 19:10:44 +0100 Subject: [PATCH 062/231] Adding tokenized collection. --- src/Neuron/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index b71fbd5..05b07e7 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -58,7 +58,7 @@ class Router { public function match($methods, $pattern, $fn) { // Regex are too pro, bro! - $pattern = preg_replace ('/\{\w+\}/', '(\w+)', $pattern); + $pattern = preg_replace ('/\{\w+\}/', '(\w+)?', $pattern); $pattern = $this->baseroute . '/' . trim($pattern, '/'); $pattern = $this->baseroute ? rtrim($pattern, '/') : $pattern; From 218aecb0354a72def816b4c0a539e231793df553 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 19:45:39 +0100 Subject: [PATCH 063/231] Allowing for easy url parameters. --- src/Neuron/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 05b07e7..95624c4 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -58,7 +58,7 @@ class Router { public function match($methods, $pattern, $fn) { // Regex are too pro, bro! - $pattern = preg_replace ('/\{\w+\}/', '(\w+)?', $pattern); + $pattern = preg_replace ('/\{\w+\}/', '(/\w+)?', $pattern); $pattern = $this->baseroute . '/' . trim($pattern, '/'); $pattern = $this->baseroute ? rtrim($pattern, '/') : $pattern; From f9c7a6f10f654612d58ef74b9166573948707ae0 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 19:47:56 +0100 Subject: [PATCH 064/231] Allowing for easy url parameters. --- src/Neuron/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 95624c4..2a396fb 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -58,7 +58,7 @@ class Router { public function match($methods, $pattern, $fn) { // Regex are too pro, bro! - $pattern = preg_replace ('/\{\w+\}/', '(/\w+)?', $pattern); + $pattern = preg_replace ('//\{\w+\}/', '(/\w+)?', $pattern); $pattern = $this->baseroute . '/' . trim($pattern, '/'); $pattern = $this->baseroute ? rtrim($pattern, '/') : $pattern; From e73c5cbd4bc83cb7c3abf03d2d400e4c472ec651 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 19:51:10 +0100 Subject: [PATCH 065/231] Allowing for easy url parameters. --- example/bootstrap/router.php | 2 +- src/Neuron/Router.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/example/bootstrap/router.php b/example/bootstrap/router.php index f601ed3..4b52b6e 100644 --- a/example/bootstrap/router.php +++ b/example/bootstrap/router.php @@ -6,7 +6,7 @@ $router->get ('/', '\Example\Controllers\HomeController@main'); $router->get ('/templates', '\Example\Controllers\HomeController@templates'); -$router->get ('/test/{something}', function ($a) { +$router->get ('/test/{something?}', function ($a) { return \Neuron\Net\Response::json ($a); }); diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 2a396fb..f0b7280 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -58,7 +58,8 @@ class Router { public function match($methods, $pattern, $fn) { // Regex are too pro, bro! - $pattern = preg_replace ('//\{\w+\}/', '(/\w+)?', $pattern); + $pattern = preg_replace ('/\/\{\w+\\?}/', '(/\w+)?', $pattern); + $pattern = preg_replace ('/\/\{\w+\}/', '(/\w+)', $pattern); $pattern = $this->baseroute . '/' . trim($pattern, '/'); $pattern = $this->baseroute ? rtrim($pattern, '/') : $pattern; From 2f85880d17187f47802e4b990a6d4614549ff21f Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 19:51:40 +0100 Subject: [PATCH 066/231] Allowing for easy url parameters. --- src/Neuron/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index f0b7280..197fc34 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -57,7 +57,7 @@ class Router { */ public function match($methods, $pattern, $fn) { - // Regex are too pro, bro! + // Regex are too pro, bro! Give us some simple {param} and {param?} parameters. $pattern = preg_replace ('/\/\{\w+\\?}/', '(/\w+)?', $pattern); $pattern = preg_replace ('/\/\{\w+\}/', '(/\w+)', $pattern); From 041511ed6c6dae81a1229ffd91c793c483623581 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 20:06:51 +0100 Subject: [PATCH 067/231] Allowing for easy url parameters. --- src/Neuron/Collections/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 2dcee97..4796ad0 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -72,7 +72,7 @@ public function offsetSet($offset, $value) { if (is_null ($offset)) { - $index = array_push ($this->data, $value); + $index = array_push ($this->data, $value) - 1; $this->trigger ('add', $value, $index); } else From eeda4add4d736ad106ca8c95f166a71a43d72443 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 20:09:08 +0100 Subject: [PATCH 068/231] Allowing for easy url parameters. --- src/Neuron/Net/Entity.php | 2 ++ src/Neuron/Net/Response.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index bc0ec5b..02f0a08 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -32,6 +32,8 @@ abstract class Entity { private $application; + const STATUS_NOTFOUND = 404; + /** * Serialize & deserialize requests * @param $data diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 0671bc9..6659388 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -90,7 +90,7 @@ public static function json ($data) return $in; } - public static function error ($data) + public static function error ($data, $error_code = 500) { $in = new self (); $in->setData ($data); From 374cf0c89cfc43639ec9cff474bade3bf79786e0 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 20:28:44 +0100 Subject: [PATCH 069/231] Playing with error messages a bit. --- src/Neuron/Net/Response.php | 20 +++++++++++++++----- src/Neuron/Router.php | 5 ++--- src/templates/error.phpt | 6 ++++++ 3 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 src/templates/error.phpt diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 6659388..df5cb24 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -90,12 +90,22 @@ public static function json ($data) return $in; } - public static function error ($data, $error_code = 500) + /** + * @param string $message + * @param int $statuscode + * @return Response + */ + public static function error ($message, $statuscode = 500) { - $in = new self (); - $in->setData ($data); - $in->setOutput (new HTML ()); - return $in; + $template = new Template ('error.phpt'); + $template->set ('message', $message); + $template->set ('status', $statuscode); + + $response = self::template ($template); + $response->setStatus ($statuscode); + + + return $response; } /** diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 197fc34..25544a7 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -55,7 +55,7 @@ class Router { * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed */ - public function match($methods, $pattern, $fn) { + public function match ($methods, $pattern, $fn) { // Regex are too pro, bro! Give us some simple {param} and {param?} parameters. $pattern = preg_replace ('/\/\{\w+\\?}/', '(/\w+)?', $pattern); @@ -189,8 +189,7 @@ public function run (Request $request) } else { - $request = Response::template ('404.phpt'); - $request->setStatus (404); + $request = Response::error ('Page not found.', Response::STATUS_NOTFOUND); $request->output (); } } diff --git a/src/templates/error.phpt b/src/templates/error.phpt new file mode 100644 index 0000000..1189611 --- /dev/null +++ b/src/templates/error.phpt @@ -0,0 +1,6 @@ +layout ('index.phpt'); +?> + +

+ \ No newline at end of file From 4ea826d78a006e75cb9a1c3860edf34747132eae Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 20:35:10 +0100 Subject: [PATCH 070/231] Playing with error messages a bit. --- src/templates/404.phpt | 1 - src/templates/error.phpt | 31 ++++++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) delete mode 100644 src/templates/404.phpt diff --git a/src/templates/404.phpt b/src/templates/404.phpt deleted file mode 100644 index d9f18f5..0000000 --- a/src/templates/404.phpt +++ /dev/null @@ -1 +0,0 @@ -

404 Not found

\ No newline at end of file diff --git a/src/templates/error.phpt b/src/templates/error.phpt index 1189611..a28849e 100644 --- a/src/templates/error.phpt +++ b/src/templates/error.phpt @@ -1,6 +1,27 @@ -layout ('index.phpt'); -?> + + + -

- \ No newline at end of file + + css ('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'); ?> + + + css ('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css'); ?> + + + js ('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js'); ?> + + + + + +
+ +
+

+

+
+
+ + + \ No newline at end of file From b9415424bd366894bc2becce5b8bb10346eb8cdd Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 21:18:31 +0100 Subject: [PATCH 071/231] Preparing database configuration. --- src/Neuron/DB/MySQL.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Neuron/DB/MySQL.php b/src/Neuron/DB/MySQL.php index 228a974..c9c7d8e 100755 --- a/src/Neuron/DB/MySQL.php +++ b/src/Neuron/DB/MySQL.php @@ -1,6 +1,7 @@ connection = new MySQLi (DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME); - - $this->connection->query ('SET names "' . DB_CHARSET . '"'); + $this->connection = new MySQLi + ( + Config::get ('database.mysql.host'), + Config::get ('database.mysql.username'), + Config::get ('database.mysql.password'), + Config::get ('database.mysql.database') + ); + + $this->connection->query ('SET names "' . Config::get ('database.mysql.charset') . '"'); //$this->connection->query ("SET time_zone = '+00:00'"); } catch (Exception $e) From c38d56aeb55772111d0b24290335401d2c34a628 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 30 Nov 2014 21:29:05 +0100 Subject: [PATCH 072/231] Adding little basemapper model. --- example/config/database.php | 14 ++++++++ src/Neuron/Mappers/BaseMapper.php | 54 +++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 example/config/database.php create mode 100644 src/Neuron/Mappers/BaseMapper.php diff --git a/example/config/database.php b/example/config/database.php new file mode 100644 index 0000000..1e4195b --- /dev/null +++ b/example/config/database.php @@ -0,0 +1,14 @@ + array ( + 'host' => 'localhost', + 'username' => 'myuser', + 'password' => 'myuser', + 'database' => 'catlab_accounts', + 'charset' => 'utf8', + 'prefix' => 'neuron_' + ) + +); \ No newline at end of file diff --git a/src/Neuron/Mappers/BaseMapper.php b/src/Neuron/Mappers/BaseMapper.php new file mode 100644 index 0000000..f084783 --- /dev/null +++ b/src/Neuron/Mappers/BaseMapper.php @@ -0,0 +1,54 @@ + 0) + { + return $this->getObjectFromData ($data[0]); + } + return null; + } + + /** + * @param $data + * @return array|mixed[] + */ + protected function getObjectsFromData ($data) + { + $out = array (); + foreach ($data as $v) + { + $out[] = $this->getObjectFromData ($v); + } + return $out; + } + + protected abstract function getObjectFromData ($data); + +} \ No newline at end of file From 9291117bf0cc5d8c9896a0e9921f3f2e1b160492 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 15 Dec 2014 23:03:28 +0100 Subject: [PATCH 073/231] Namespace change --- src/Neuron/Tools/Text.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Tools/Text.php b/src/Neuron/Tools/Text.php index de2625d..afeb89f 100644 --- a/src/Neuron/Tools/Text.php +++ b/src/Neuron/Tools/Text.php @@ -33,7 +33,7 @@ public static function getInstance () */ public function addPath ($domain, $path) { - bindtextdomain ($domain, $path); + \bindtextdomain ($domain, $path); } /** From ffdb12a5819274e2698c029741cf5f25527d704d Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 15 Dec 2014 23:19:23 +0100 Subject: [PATCH 074/231] Namespace change --- composer.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/composer.json b/composer.json index d28d011..8a299b9 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,11 @@ "role" : "Developer" } ], + + "require" : { + "ext-gettext" : "*" + }, + "autoload": { "psr-4" : { "Neuron\\" : "src/Neuron/" From a47f90c2d4e0fbccf60a6b04e317af99d8761335 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 01:10:58 +0100 Subject: [PATCH 075/231] Playing around with sessions. --- src/Neuron/Application.php | 73 +++- src/Neuron/Environment.php | 26 -- src/Neuron/EventManager.php | 72 --- src/Neuron/Interfaces/Models/User.php | 21 + src/Neuron/MapperFactory.php | 63 --- src/Neuron/Mappers/EmailMapper.php | 150 ------- src/Neuron/Mappers/UserMapper.php | 413 ------------------ src/Neuron/Models/User.php | 320 -------------- src/Neuron/Net/Entity.php | 76 ++-- src/Neuron/Net/Request.php | 49 ++- src/Neuron/Net/Session.php | 80 ++++ src/Neuron/Router.php | 9 +- src/Neuron/Session.php | 205 --------- .../SessionHandlers/DefaultSessionHandler.php | 51 +++ src/Neuron/SessionHandlers/SessionHandler.php | 15 +- 15 files changed, 301 insertions(+), 1322 deletions(-) delete mode 100644 src/Neuron/Environment.php delete mode 100644 src/Neuron/EventManager.php create mode 100644 src/Neuron/Interfaces/Models/User.php delete mode 100644 src/Neuron/MapperFactory.php delete mode 100644 src/Neuron/Mappers/EmailMapper.php delete mode 100644 src/Neuron/Mappers/UserMapper.php delete mode 100644 src/Neuron/Models/User.php create mode 100644 src/Neuron/Net/Session.php delete mode 100644 src/Neuron/Session.php create mode 100644 src/Neuron/SessionHandlers/DefaultSessionHandler.php diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index 820c30a..87af405 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -8,11 +8,17 @@ namespace Neuron; +use Neuron\Core\Template; use Neuron\Exceptions\DataNotSet; +use Neuron\Models\Observable; use Neuron\Net\Request; -use Neuron\Router; +use Neuron\Net\Session; +use Neuron\SessionHandlers\DefaultSessionHandler; +use Neuron\SessionHandlers\SessionHandler; -class Application { +class Application + extends Observable +{ /** @var Router $router */ private $router; @@ -20,6 +26,9 @@ class Application { /** @var string $locale */ private $locale; + /** @var SessionHandler $sessionHandler */ + private $sessionHandler; + private static $in; /** @@ -39,7 +48,7 @@ public static function getInstance () */ private function __construct () { - \Neuron\Core\Template::addPath (dirname (dirname (__FILE__)) . '/templates/', '', -1); + Template::addPath (dirname (dirname (__FILE__)) . '/templates/', '', -1); } /** @@ -48,6 +57,15 @@ private function __construct () public function setRouter (Router $router) { $this->router = $router; + $this->trigger ('router:set'); + } + + /** + * @return Router + */ + public function getRouter () + { + return $this->router; } /** @@ -66,6 +84,7 @@ public function setLocale ($locale) { throw new DataNotSet ("Locale " . $locale . " is not available on this platform."); } + $this->trigger ('locale:set'); } /** @@ -88,10 +107,36 @@ private function checkLocale () } /** + * @param SessionHandler $handler + */ + public function setSessionHandler (SessionHandler $handler) + { + $this->sessionHandler = $handler; + } + + /** + * @return SessionHandler + */ + private function getSessionHandler () + { + if (!isset ($this->sessionHandler)) + { + $this->sessionHandler = new DefaultSessionHandler (); + } + + return $this->sessionHandler; + } + + /** + * @param Request $request * @throws DataNotSet */ - public function dispatch (\Neuron\Net\Request $request = null) + public function dispatch (Request $request = null) { + // Trigger initialize + $this->trigger ('dispatch:initialize'); + + // Check locales $this->checkLocale (); if (!isset ($this->router)) @@ -104,6 +149,26 @@ public function dispatch (\Neuron\Net\Request $request = null) $request = Request::fromInput (); } + // Set session from the session handler + $session = new Session ($this->getSessionHandler ()); + $session->connect (); + + // Set session in request + $request->setSession ($session); + + // Trigger before + $this->trigger ('dispatch:before', $request); + + // Run router $this->router->run ($request); + + // Trigger dispatch + $this->trigger ('dispatch:after', $request); + + // Disconnect the session + $session->disconnect (); + + // End + $this->trigger ('dispatch:terminate'); } } \ No newline at end of file diff --git a/src/Neuron/Environment.php b/src/Neuron/Environment.php deleted file mode 100644 index 4e05880..0000000 --- a/src/Neuron/Environment.php +++ /dev/null @@ -1,26 +0,0 @@ -disconnect (); - \Neuron\Session::clearInstance (); - \Neuron\FrontController::destroy (); - \Neuron\Core\Template::clearShares (); - } - -} \ No newline at end of file diff --git a/src/Neuron/EventManager.php b/src/Neuron/EventManager.php deleted file mode 100644 index 580176c..0000000 --- a/src/Neuron/EventManager.php +++ /dev/null @@ -1,72 +0,0 @@ -events)) - { - $args = func_get_args (); - foreach ($in->events as $method) - { - call_user_func_array ($method, $args); - } - } - } - - public static function on ($event, $callback) - { - if (!is_callable ($callback)) - { - throw new InvalidParameter ("All callbacks of events must be callables."); - } - - $in = self::getInstance (); - if (!isset ($in->triggers[$event])) - { - $in->triggers[$event] = array (); - } - $in->triggers[$event] = $callback; - } - - public static function off ($event) - { - $in = self::getInstance (); - $in->triggers[$event] = array (); - } - -} \ No newline at end of file diff --git a/src/Neuron/Interfaces/Models/User.php b/src/Neuron/Interfaces/Models/User.php new file mode 100644 index 0000000..45a0743 --- /dev/null +++ b/src/Neuron/Interfaces/Models/User.php @@ -0,0 +1,21 @@ +mapped[$key] = $mapper; - } - - public function getMapper ($key, $default) - { - if (isset ($this->mapped[$key])) - { - return $this->mapped[$key]; - } - else - { - $this->mapped[$key] = new $default (); - } - return $this->mapped[$key]; - } - - /** - * @return \Neuron\Mappers\UserMapper - */ - public static function getUserMapper () - { - return self::getInstance ()->getMapper ('user', 'Neuron\Mappers\UserMapper'); - } - - /** - * @return \Neuron\Mappers\EmailMapper - */ - public static function getEmailMapper () - { - return self::getInstance ()->getMapper ('email', 'Neuron\Mappers\EmailMapper'); - } - - /** - * @return \Neuron\Mappers\AccountsMapper - */ - public static function getAccountMapper () - { - return self::getInstance ()->getMapper ('account', 'Neuron\Mappers\AccountsMapper'); - } -} \ No newline at end of file diff --git a/src/Neuron/Mappers/EmailMapper.php b/src/Neuron/Mappers/EmailMapper.php deleted file mode 100644 index 3139278..0000000 --- a/src/Neuron/Mappers/EmailMapper.php +++ /dev/null @@ -1,150 +0,0 @@ -isConfirmed () ? 1 : 0; - - $id = $db->query - (" - INSERT INTO - users_email - SET - u_id = {$email->getUser ()->getId ()}, - ue_email = '{$db->escape ($email->getEmail ())}', - ue_code = '{$db->escape ($email->getCode ())}', - ue_confirmed = {$confirmed} - "); - - $email->setId ($id); - - return $email; - } - - public static function update (BMGroup_Models_Email $email) - { - $db = Neuron\DB\Database::getInstance (); - - $confirmed = $email->isConfirmed () ? 1 : 0; - - $db->query - (" - UPDATE - users_email - SET - ue_confirmed = {$confirmed} - WHERE - ue_id = {$email->getId ()} - "); - } - - public static function getEmails (BMGroup_Models_User $user) - { - $db = Neuron\DB\Database::getInstance (); - - $data = $db->query - (" - SELECT - * - FROM - users_email - WHERE - u_id = {$user->getId ()} - "); - - return self::getObjectsFromData ($data); - } - - public static function getFromCode ($id, $code) - { - $db = Neuron\DB\Database::getInstance (); - - $id = intval ($id); - - $data = $db->query - (" - SELECT - * - FROM - users_email - WHERE - ue_id = '{$id}' AND - ue_code = '{$db->escape ($code)}' - "); - - return self::getSingle ($data); - } - - public static function getPendingEmail (BMGroup_Models_User $user) - { - $db = Neuron\DB\Database::getInstance (); - - $data = $db->query - (" - SELECT - * - FROM - users_email - WHERE - u_id = {$user->getId ()} AND - ue_confirmed = 0 - "); - - return self::getObjectsFromData ($data); - } - - public static function removePendingEmails (BMGroup_Models_User $user) - { - $db = Neuron\DB\Database::getInstance (); - - $data = $db->query - (" - DELETE FROM - users_email - WHERE - u_id = {$user->getId ()} AND - ue_confirmed = 0 - "); - } - - private static function getSingle ($data) - { - if (count ($data) > 0) - { - return self::getObjectFromData ($data[0]); - } - return null; - } - - private static function getObjectsFromData ($data) - { - $out = array (); - foreach ($data as $v) - { - $out[] = self::getObjectFromData ($v); - } - return $out; - } - - private static function getObjectFromData ($v) - { - $tmp = new BMGroup_Models_Email ($v['ue_id']); - - $tmp->setUser (BMGroup_Mappers_UserMapper::getFromId ($v['u_id'])); - $tmp->setEmail ($v['ue_email']); - $tmp->setCode ($v['ue_code']); - $tmp->setConfirmed ($v['ue_confirmed'] == 1); - - return $tmp; - } - */ -} \ No newline at end of file diff --git a/src/Neuron/Mappers/UserMapper.php b/src/Neuron/Mappers/UserMapper.php deleted file mode 100644 index 8b25928..0000000 --- a/src/Neuron/Mappers/UserMapper.php +++ /dev/null @@ -1,413 +0,0 @@ -query - (" - SELECT - * - FROM - users - WHERE - u_id = '{$db->escape ($id)}' - "); - - $data = $this->getObjectsFromData ($data); - if (count ($data) > 0) - { - return $data[0]; - } - return null; - } - - /** - * @param int[] $ids - * @return User[] - */ - public function getFromIds ($ids) - { - if (count ($ids) == 0) - { - return array (); - } - - $list = array (); - foreach ($ids as $v) - { - $list[] = intval ($v); - } - $list = implode (',', $list); - - $db = Database::getInstance (); - - $data = $db->query - (" - SELECT - * - FROM - users - WHERE - u_id IN ({$list}) - "); - - return $this->getObjectsFromData ($data); - } - - /** - * @param $email - * @return User|null - */ - public function getFromEmail ($email) - { - $db = Database::getInstance (); - - $data = $db->query - (" - SELECT - * - FROM - users - WHERE - u_email = '{$db->escape ($email)}' - "); - - $data = $this->getObjectsFromData ($data); - if (count ($data) > 0) - { - return $data[0]; - } - return null; - } - - /** - * @param $email - * @param $password - * @return User|null - */ - public function getFromLogin ($email, $password) - { - $db = Database::getInstance (); - - $data = $db->query - (" - SELECT - * - FROM - users - WHERE - u_email = '{$db->escape ($email)}' AND - u_password = MD5(CONCAT('{$db->escape ($password)}', u_salt)) - "); - - $data = $this->getObjectsFromData ($data); - if (count ($data) > 0) - { - return $data[0]; - } - return null; - } - - /** - * Return hashed password & salt. - */ - private function hashPassword ($password) - { - // To be replaced by something more ... smart. - $salt = md5 (mt_rand (0, 1000000) . ' ' . time ()); - $password .= $salt; - return array (md5 ($password), $salt); - } - - /** - * @param User $user - * @return array - */ - protected function prepareFields (User $user) - { - // Hash the password & add some salt. - $out = array (); - - $password = $user->getPassword (); - if (!empty ($password)) - { - $hashes = $this->hashPassword ($user->getPassword ()); - - $out['u_password'] = $hashes[0]; - $out['u_salt'] = $hashes[1]; - } - - // Name & firstname - $name = $user->getName (); - $firstname = $user->getFirstname (); - if (!empty ($name)) - { - //$sql .= "u_name = '{$db->escape ($name)}', "; - $out['u_name'] = $name; - } - - if (!empty ($firstname)) - { - //$sql .= "u_firstname = '{$db->escape ($user->getFirstname ())}', "; - $out['u_firstname'] = $firstname; - } - - $email = $user->getEmail (); - if (!empty ($email)) - { - $out['u_email'] = $email; - } - else - { - //$sql .= "u_email = NULL, "; - $out['u_email'] = array (null, Query::PARAM_NULL, true); - } - - $mobile = $user->getMobile (); - if (!empty ($mobile)) - { - $out['u_mobile'] = $mobile; - } - else - { - $out['u_mobile'] = array (null, Query::PARAM_NULL, true); - } - - $out['u_isEmailValidated'] = 0; - $out['updated_at'] = array (time (), Query::PARAM_DATE); - - return $out; - } - - /** - * @param User $user - * @return User - */ - public function create (User $user) - { - $data = $this->prepareFields ($user); - - $data['created_at'] = array (time (), Query::PARAM_DATE); - - $query = Query::insert ('users', $data); - $id = $query->execute (); - - // Set ID in object - //$user->setId ($id); - - //return $user; - - return $this->getFromId ($id); - } - - /** - * @param User $user - */ - public function update (User $user) - { - $where = array ( - 'u_id' => $user->getId () - ); - - $query = Query::update ('users', $this->prepareFields ($user), $where); - $query->execute (); - } - - /** - * @param User $user - * @param $password - * @return bool - */ - public function checkPassword (User $user, $password) - { - $db = Database::getInstance (); - - $chk = $db->query - (" - SELECT - * - FROM - users - WHERE - u_id = {$user->getId ()} AND - u_password = MD5(CONCAT('{$db->escape ($password)}', u_salt)) - "); - - return count ($chk) > 0; - } - - /** - * @param User $user - * @return bool - */ - public function hasPassword (User $user) - { - $db = Database::getInstance (); - - $chk = $db->query - (" - SELECT - * - FROM - users - WHERE - u_id = {$user->getId ()} AND - u_password IS NOT NULL - "); - - return count ($chk) > 0; - } - - /** - * - */ - public function removeExpiredPasswordResetTokens () - { - $db = Database::getInstance (); - - $db->query - (" - DELETE FROM - users_passwordreset - WHERE - upw_date < NOW() - INTERVAL 1 DAY - "); - } - - /** - * @param User $user - * @param $token - * @param $ip - */ - public function addPasswordResetToken (User $user, $token, $ip) - { - $this->removeExpiredPasswordResetTokens (); - - $db = Database::getInstance (); - - $ip = inet_pton ($ip); - - $db->query - (" - INSERT INTO - users_passwordreset - SET - u_id = {$user->getId ()}, - upw_token = '{$db->escape ($token)}', - upw_date = NOW(), - upw_ip = '{$db->escape ($ip)}' - "); - } - - /** - * @param User $user - * @return array - */ - public function getPasswordResetTokens (User $user) - { - $db = Database::getInstance (); - - $data = $db->query - (" - SELECT - *, - UNIX_TIMESTAMP(upw_date) AS datum - FROM - users_passwordreset - WHERE - u_id = {$user->getId ()} AND - upw_date > NOW() - INTERVAL 1 DAY - "); - - $out = array (); - foreach ($data as $v) - { - $out[] = array - ( - 'code' => $v['upw_token'], - 'date' => $v['datum'], - 'ip' => inet_ntop ($v['upw_ip']) - ); - } - return $out; - } - - /** - * @param $data - * @return User[] - */ - public function getObjectsFromData ($data) - { - $out = array (); - foreach ($data as $v) - { - $out[] = $this->getObjectFromData ($v); - } - return $out; - } - - /** - * Return the name of the models that will be instanciated - * @return string - */ - public function getObjectClassname () - { - return 'Neuron\Models\User'; - } - - /** - * @param $data - * @return User|null - */ - public function getSingle ($data) - { - if (count ($data) > 0) - { - return $this->getObjectFromData ($data[0]); - } - return null; - } - - /** - * @param $data - * @return User - */ - public function getObjectFromData ($data) - { - $classname = $this->getObjectClassname (); - - /** @var \Neuron\Models\User $user */ - $user = new $classname ($data['u_id']); - - if (!empty ($data['u_email'])) - $user->setEmail ($data['u_email']); - - if (!empty ($data['u_name'])) - $user->setName ($data['u_name']); - - if (!empty ($data['u_firstname'])) - $user->setFirstname ($data['u_firstname']); - - if (!empty ($data['u_admin_status'])) - $user->setAdmin ($data['u_admin_status']); - - $user->setEmailValidated ($data['u_isEmailValidated'] == 1); - - return $user; - } -} \ No newline at end of file diff --git a/src/Neuron/Models/User.php b/src/Neuron/Models/User.php deleted file mode 100644 index 5631bcc..0000000 --- a/src/Neuron/Models/User.php +++ /dev/null @@ -1,320 +0,0 @@ -setId ($id); - } - - public function setId ($id) - { - $this->id = $id; - } - - public function getId () - { - return intval ($this->id); - } - - public function setEmail ($email) - { - $this->email = $email; - } - - public function getEmail () - { - return $this->email; - } - - public function setMobile ($mobile) - { - $this->mobile = $mobile; - } - - public function getMobile () - { - return $this->mobile; - } - - /** - * get user is admin previleges level - * this is not related with admin of accounts - */ - public function getAdminRights () - { - return $this->admin; - } - - /** - * Only used during registration. - */ - public function setPassword ($password) - { - $this->password = $password; - } - - /** - * Only used during registration. - */ - public function getPassword () - { - return $this->password; - } - - public function setName ($name) - { - $this->name = $name; - } - - public function getName () - { - return $this->name; - } - - public function setFirstname ($name) - { - $this->firstname = $name; - } - - public function getFirstname () - { - return $this->firstname; - } - - public function getFullName () - { - return $this->getFirstname () . ' ' . $this->getName (); - } - - public function setAdmin ($admin_id) - { - $this->admin = $admin_id; - } - - public function getDisplayName () - { - return Tools::output_varchar ($this->getFullName ()); - } - - /** - * Return a list of all accounts this user has. - * Lazy loading, mysql query is done first time the accounts are requested. - * @return Account[] - */ - public function getAccounts () - { - if (!isset ($this->accounts)) - { - $this->accounts = MapperFactory::getAccountMapper ()->getFromUser ($this); - } - return $this->accounts; - } - - public function hasAccount (Account $type) - { - $typename = get_class ($type); - - foreach ($this->getAccounts () as $v) - { - if ($v instanceof $typename) - { - return true; - } - } - return false; - } - - /** - * Password. Now here is something special. - * It is possible that no password is set (when logged in through third party) - */ - public function hasPassword () - { - return MapperFactory::getUserMapper ()->hasPassword ($this); - } - - public function hasEmail () - { - $email = $this->getEmail (); - return !empty ($email); - } - - public function doesPasswordMatch ($password) - { - return MapperFactory::getUserMapper ()->checkPassword ($this, $password); - } - - public function changePassword ($oldpassword, $password, $repeatpassword, $ignoreOldPassword = false) - { - if (!$this->hasEmail ()) - { - $this->addError ('Please first set an email address before setting a password.'); - return false; - } - - if (empty ($password) || strlen ($password) < 6) - { - $this->addError ('Your password is too short. Please pick a password of at least 6 characters.'); - return false; - } - - if ($password != $repeatpassword) - { - $this->addError ('Your passwords do not match.'); - return false; - } - - if ($this->hasPassword () && !$ignoreOldPassword && !$this->doesPasswordMatch ($oldpassword)) - { - $this->addError ('Your old password is not correct.'); - return false; - } - - // Aaaand we change the password. - $this->addFeedback ('Your password was changed.'); - - $this->setPassword ($password); - MapperFactory::getUserMapper ()->update ($this); - - return true; - } - - public function getIp () - { - return isset ($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null; - } - - /** - * Initialise a reset password procedure: - * send an email to the user. - */ - public function startResetPassword () - { - // Create the code - $code = TokenGenerator::getToken (10); - MapperFactory::getUserMapper ()->addPasswordResetToken ($this, $code, $this->getIp ()); - - $mail = Mailer::getInstance() - ->toUser($this) - ->setTemplate('reset_password/reset_password') - ->setAttribute('code_url', URLBuilder::getUrl ('login/lostpassword', array ('id' => $this->getId (), 'code' => $code))) - ->setAttribute('user-firstname', $this->getFirstname()) - ->setAttribute('logo', URLBuilder::getURL('assets/img/logo.png')) - ->schedule(); - } - - public function hasResetToken ($strcode) - { - $codes = MapperFactory::getUserMapper ()->getPasswordResetTokens ($this); - foreach ($codes as $code) - { - if ($code['code'] == $strcode) - { - return true; - } - } - - return false; - } - - private function addError ($message) - { - $this->errors[] = $message; - } - - public function getErrors () - { - return $this->errors; - } - - private function addFeedback ($message) - { - $this->feedbacks[] = $message; - } - - public function getFeedback () - { - return $this->feedbacks; - } - - public function setEmailValidated ($validated) - { - $this->emailValidated = $validated; - } - - /** - * Return true if email is validated - */ - public function isEmailValidated () - { - return $this->emailValidated; - } - - public function equals ($other) - { - return $this->getId () === $other->getId (); - } - - public function getData () - { - return array ( - 'id' => $this->getId (), - 'firstname' => $this->getFirstName (), - 'name' => $this->getName () - ); - } -} - -/** - * @SWG\Model( - * id="UserPasswordInput", - * @SWG\Property(name="oldpassword",type="string",required=true), - * @SWG\Property(name="newpassword",type="string",required=true) - * ) - */ \ No newline at end of file diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index 02f0a08..b1d47bc 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -9,21 +9,25 @@ namespace Neuron\Net; +use Neuron\Application; +use Neuron\Config; +use Neuron\Exceptions\DataNotSet; use Neuron\Exceptions\InvalidParameter; use Neuron\MapperFactory; use Neuron\Models\User; +use Neuron\Net\Session; abstract class Entity { const CHECK_SIGNATURE = false; - - /** @var User */ - private $user; + + /** @var Session $session */ + private $session; + private $body; private $path; private $post; private $headers; - private $session; private $data; private $cookies; @@ -57,15 +61,6 @@ public function setFromData ($data) throw new InvalidParameter ("Leave now, and Never come Back! *gollem, gollem* (Decoded request signature mismatch)."); } - if (isset ($data['session']) && isset ($data['session']['user'])) - { - $user = MapperFactory::getUserMapper ()->getFromId ($data['session']['user']); - if ($user) - { - $model->setUser ($user); - } - } - // The body. If data is found, body is not used. if (isset ($data['data']) && !empty ($data['data'])) { @@ -77,11 +72,6 @@ public function setFromData ($data) $model->setBody ($data['body']); } - if (isset ($data['session'])) - { - $model->setSession ($data['session']); - } - if (isset ($data['headers'])) { $model->setHeaders ($data['headers']); @@ -123,7 +113,6 @@ public function getJSONData () $data['body'] = $this->getBody (); - $data['session'] = $this->getSession (); $data['headers'] = $this->getHeaders (); $data['cookies'] = $this->getCookies (); $data['post'] = $this->getPost (); @@ -152,7 +141,7 @@ private static function calculateBaseString (array $data) $txt .= $k . ":" . json_encode ($v) . "|"; } - $txt .= APP_SECRET_KEY; + $txt .= Config::get ('app.secret'); return $txt; } @@ -170,48 +159,33 @@ public function toJSON () } /** - * @param array|string $key - * @param mixed $value + * @throws DataNotSet + * @return \Neuron\Net\Session */ - public function setSession ($key, $value = null) + public function getSession () { - if (is_array ($key) && is_null ($value)) - { - $this->session = $key; - } - else + if (!isset ($this->session)) { - if (!isset ($this->session)) - { - $this->session = array (); + // First check the router + if ($this instanceof Response) { + $router = Application::getInstance ()->getRouter (); + if ($router) { + $this->session = $router->getRequest ()->getSession (); + } + } + else { + throw new DataNotSet ("No session is set in the request."); } - $this->session[$key] = $value; } - } - - /** - * @return mixed - */ - public function getSession () - { return $this->session; } /** - * @param User $user - */ - public function setUser (User $user) - { - $this->user = $user; - $this->setSession ('user', $user->getId ()); - } - - /** - * @return User + * @param Session $session */ - public function getUser () + public function setSession (Session $session) { - return $this->user; + $this->session = $session; } /** diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 276c80f..35fcfd5 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -10,10 +10,7 @@ use Neuron\Core\Tools; -use Neuron\Exceptions\InvalidParameter; -use Neuron\Net\InputStream; -use Neuron\MapperFactory; -use Neuron\Models\User; +use Neuron\Interfaces\Models\User; class Request extends Entity { @@ -24,6 +21,14 @@ class Request const METHOD_PUT = 'PUT'; const METHOD_OPTIONS = 'OPTIONS'; + /** @var User $user */ + private $user; + + /** @var callable $usercallback */ + private $usercallback; + + private $usercallbackcalled = false; + /** * @return Request */ @@ -338,4 +343,40 @@ public function input ($field, $type = 'string', $default = null) } return $value; } + + /** + * Helper method to make it easier for authentication modules + * @param User $user + */ + public function setUser (User $user) + { + if (!isset ($this->user) && !$this->usercallbackcalled) + { + $this->usercallbackcalled = true; + + if (isset ($this->usercallback)) { + $this->user = call_user_func ($this->usercallback, $this); + } + } + + $this->user = $user; + } + + /** + * To allow lazy loading of the user object, set a callback here. + * Method will be called with request as parameter and only once a script. + * @param callable $callback + */ + public function setUserCallback (callable $callback) + { + $this->usercallback = $callback; + } + + /** + * @return User + */ + public function getUser() + { + return $this->user; + } } \ No newline at end of file diff --git a/src/Neuron/Net/Session.php b/src/Neuron/Net/Session.php new file mode 100644 index 0000000..56d218d --- /dev/null +++ b/src/Neuron/Net/Session.php @@ -0,0 +1,80 @@ +handler = $handler; + } + + public function getSessionId () + { + return session_id (); + } + + /** + * Start a session + * @param string $sessionId + */ + public function connect ($sessionId = null) + { + $this->handler->start ($sessionId); + } + + /** + * Disconnect session handler + */ + public function disconnect () + { + if ($this->handler) + { + $this->handler->stop (); + } + } + + /** + * Destroy a session + */ + public function destroy () + { + // Unset all of the session variables. + $_SESSION = array(); + + // If it's desired to kill the session, also delete the session cookie. + // Note: This will destroy the session, and not just the session data! + if (ini_get("session.use_cookies")) { + $params = session_get_cookie_params(); + setcookie(session_name(), '', time() - 42000, + $params["path"], $params["domain"], + $params["secure"], $params["httponly"] + ); + } + + // Finally, destroy the session. + session_destroy(); + } + + public function set ($key, $value) + { + $this->values[$key] = $value; + } + + public function get ($key) + { + if (isset ($this->values[$key])) + { + return $this->values[$key]; + } + return null; + } +} \ No newline at end of file diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 25544a7..fe0be6e 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -169,7 +169,6 @@ public function module ($prefix, Module $module) */ public function run (Request $request) { - // Define which method we need to handle $this->method = $request->getMethod (); @@ -199,6 +198,14 @@ public function run (Request $request) } + /** + * During execution of the dispatch, this method will return the request. + * @return Request|null + */ + public function getRequest () + { + return $this->request; + } /** * Set the 404 handling function diff --git a/src/Neuron/Session.php b/src/Neuron/Session.php deleted file mode 100644 index 15ce6a8..0000000 --- a/src/Neuron/Session.php +++ /dev/null @@ -1,205 +0,0 @@ -handler)) - { - $this->handler = new \Neuron\SessionHandlers\DbSessionHandler (); - $this->handler->register (); - } - $this->handler->start ($sessionId); - - //$this->handler = $handler; - - /* - if (isset($_GET['session_id'])) - { - session_id($_GET['session_id']); - } - - session_start (); - */ - } - - public function disconnect () - { - if ($this->handler) - { - $this->handler->stop (); - } - } - - /** - * Destroy a session - */ - public function destroy () - { - // Unset all of the session variables. - $_SESSION = array(); - - // If it's desired to kill the session, also delete the session cookie. - // Note: This will destroy the session, and not just the session data! - if (ini_get("session.use_cookies")) { - $params = session_get_cookie_params(); - setcookie(session_name(), '', time() - 42000, - $params["path"], $params["domain"], - $params["secure"], $params["httponly"] - ); - } - - // Finally, destroy the session. - session_destroy(); - } - - public function setUser (User $user) - { - $this->user = $user; - } - - public function isLogin () - { - return isset ($_SESSION['user']); - } - - private function loadUser () - { - if (!isset ($this->user)) - { - if (isset ($_SESSION['user'])) - { - $this->setUser (MapperFactory::getUserMapper()->getFromId ($_SESSION['user'])); - } - else - { - $this->user = false; - } - } - } - - /** - * @return \Neuron\Models\User - */ - public function getUser() - { - $this->loadUser (); - return $this->user; - } - - public function login (User $user) - { - $_SESSION['user'] = $user->getId (); - $this->user = $user; - - $_SESSION['user_admin_status'] = $user->getAdminRights (); - - // Events! - EventManager::getInstance ()->trigger ('signin:login', $user); - - return $user; - } - - public function logout ($destroySession = true) - { - $_SESSION['user'] = null; - $this->user = null; - - EventManager::getInstance ()->trigger ('signin:logout'); - - if ($destroySession) - { - $this->destroy (); - } - } - - public function register (User $user) - { - // Create the user - $user = MapperFactory::getUserMapper()->create ($user); - - EventManager::getInstance ()->trigger ('signin:register', $user); - - // Login the user - $this->login ($user); - - return $user; - } - - public function isEmailUnique ($email) - { - $user = MapperFactory::getUserMapper()->getFromEmail ($email); - if ($user) - { - return false; - } - return true; - } - - public function setApplication ($application) - { - $this->application = $application; - } - - public function getApplication () - { - return $this->application; - } - - public function set ($key, $value) - { - $this->values[$key] = $value; - } - - public function get ($key) - { - if (isset ($this->values[$key])) - { - return $this->values[$key]; - } - return null; - } -} \ No newline at end of file diff --git a/src/Neuron/SessionHandlers/DefaultSessionHandler.php b/src/Neuron/SessionHandlers/DefaultSessionHandler.php new file mode 100644 index 0000000..8fac2ae --- /dev/null +++ b/src/Neuron/SessionHandlers/DefaultSessionHandler.php @@ -0,0 +1,51 @@ +started) { - /* - var_dump ($_COOKIE); - var_dump ($_REQUEST); - */ - if (isset($sessionId)) { session_id ($sessionId); @@ -43,14 +38,8 @@ public final function start ($sessionId = null) else { - /** - * @TODO check if this is proper - * - * We're using uniqid to set the session id. - */ - $sid = uniqid ('session', true); - session_id ($sid); - Logger::getInstance()->log ("Starting brand new session with id " . $sid, false, 'cyan'); + session_regenerate_id (); + Logger::getInstance()->log ("Starting brand new session with id " . session_id (), false, 'cyan'); } session_start (); From 4ebf0aef65ec396d607098c3a5007af8b73de26f Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 01:16:09 +0100 Subject: [PATCH 076/231] Playing around with sessions. --- src/Neuron/Net/Entity.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index b1d47bc..072f484 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -13,9 +13,6 @@ use Neuron\Config; use Neuron\Exceptions\DataNotSet; use Neuron\Exceptions\InvalidParameter; -use Neuron\MapperFactory; -use Neuron\Models\User; -use Neuron\Net\Session; abstract class Entity { From 8b8b1b8854f8e3103c1799390897cf1a92ab06cc Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 01:37:42 +0100 Subject: [PATCH 077/231] Playing around with sessions some more. --- .../SessionHandlers/DbSessionHandler.php | 5 +- .../SessionHandlers/DefaultSessionHandler.php | 51 -------------- src/Neuron/SessionHandlers/SessionHandler.php | 69 ++++++++++++------- 3 files changed, 46 insertions(+), 79 deletions(-) delete mode 100644 src/Neuron/SessionHandlers/DefaultSessionHandler.php diff --git a/src/Neuron/SessionHandlers/DbSessionHandler.php b/src/Neuron/SessionHandlers/DbSessionHandler.php index e6a130c..dc4d44e 100644 --- a/src/Neuron/SessionHandlers/DbSessionHandler.php +++ b/src/Neuron/SessionHandlers/DbSessionHandler.php @@ -8,12 +8,13 @@ namespace Neuron\SessionHandlers; +use Neuron\DB\Database; use Neuron\DB\Query; class DbSessionHandler extends SessionHandler { - /** @var \Neuron\DB\Database $db */ + /** @var Database $db */ private $db; private $sessions = array (); @@ -21,7 +22,7 @@ class DbSessionHandler public function open ( $save_path , $name ) { // Force loading of query. - $this->db = \Neuron\DB\Database::getInstance (); + $this->db = Database::getInstance (); // Nothing to do. return true; diff --git a/src/Neuron/SessionHandlers/DefaultSessionHandler.php b/src/Neuron/SessionHandlers/DefaultSessionHandler.php deleted file mode 100644 index 8fac2ae..0000000 --- a/src/Neuron/SessionHandlers/DefaultSessionHandler.php +++ /dev/null @@ -1,51 +0,0 @@ -started) - { - if (isset($sessionId)) - { + if (!$this->started) { + if (isset($sessionId)) { session_id ($sessionId); - ini_set("session.use_cookies",0); - ini_set("session.use_only_cookies",0); - ini_set("session.use_trans_sid",0); # Forgot this one! + ini_set ("session.use_cookies", 0); + ini_set ("session.use_only_cookies", 0); + ini_set ("session.use_trans_sid", 0); # Forgot this one! - Logger::getInstance()->log ("Starting session with provided id " . $sessionId, false, 'cyan'); - } - - else if ($defaultSession = Tools::getInput ($_COOKIE, 'PHPSESSID', 'varchar')) - { - Logger::getInstance()->log ("Starting session with default cookie " . $defaultSession, false, 'cyan'); + Logger::getInstance ()->log ("Starting session with provided id " . $sessionId, false, 'cyan'); + } else if ($defaultSession = Tools::getInput ($_COOKIE, 'PHPSESSID', 'varchar')) { + Logger::getInstance ()->log ("Starting session with default cookie " . $defaultSession, false, 'cyan'); session_id ($defaultSession); - } - - else - { + } else { session_regenerate_id (); - Logger::getInstance()->log ("Starting brand new session with id " . session_id (), false, 'cyan'); + Logger::getInstance ()->log ("Starting brand new session with id " . session_id (), false, 'cyan'); } session_start (); @@ -50,19 +43,43 @@ public final function start ($sessionId = null) public final function stop () { - Logger::getInstance()->log ("Closing session with id " . session_id (), false, 'cyan'); + Logger::getInstance ()->log ("Closing session with id " . session_id (), false, 'cyan'); session_write_close (); $this->started = false; } /* Methods */ - abstract public function close ( ); - abstract public function destroy ( $session_id ); - abstract public function gc ( $maxlifetime ); - abstract public function open ( $save_path , $name ); - abstract public function read ( $session_id ); - abstract public function write ( $session_id , $session_data ); + public function close () + { + return parent::close (); + } + + public function destroy ($session_id) + { + return parent::destroy ($session_id); + } + + public function gc ( $maxlifetime ) + { + return parent::gc ($maxlifetime); + } + + public function open ( $save_path , $name ) + { + return parent::open ( $save_path, $name ); + } + + public function read ( $session_id ) + { + return parent::read ($session_id); + } + + + public function write ( $session_id , $session_data ) + { + return parent::write ($session_id, $session_data); + } public function register () { From 15dde2184a039233faadc144baa6ad97ba4989d4 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 01:38:07 +0100 Subject: [PATCH 078/231] Playing around with sessions some more. --- src/Neuron/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index 87af405..ed34550 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -121,7 +121,7 @@ private function getSessionHandler () { if (!isset ($this->sessionHandler)) { - $this->sessionHandler = new DefaultSessionHandler (); + $this->sessionHandler = new SessionHandler (); } return $this->sessionHandler; From cce9a928d01ed14d6fe4a636901e71612a4d592b Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 01:40:00 +0100 Subject: [PATCH 079/231] Playing around with sessions some more. --- src/Neuron/Net/Session.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Neuron/Net/Session.php b/src/Neuron/Net/Session.php index 56d218d..c522f39 100644 --- a/src/Neuron/Net/Session.php +++ b/src/Neuron/Net/Session.php @@ -69,6 +69,11 @@ public function set ($key, $value) $this->values[$key] = $value; } + public function all () + { + return $this->values; + } + public function get ($key) { if (isset ($this->values[$key])) From 876763cb25eb27c4ffa299ad2d6954d3b7250e43 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 01:42:05 +0100 Subject: [PATCH 080/231] Playing around with sessions some more. --- src/Neuron/Net/Entity.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index 072f484..10bc073 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -33,6 +33,7 @@ abstract class Entity { private $application; + const STATUS_OKAY = 200; const STATUS_NOTFOUND = 404; /** From 9b1d68808304e8e5e8372a9b17fa8e8ce471939a Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 01:53:42 +0100 Subject: [PATCH 081/231] Playing around with sessions some more. --- src/Neuron/Net/Session.php | 10 ++++------ src/Neuron/SessionHandlers/SessionHandler.php | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Neuron/Net/Session.php b/src/Neuron/Net/Session.php index c522f39..6552d0b 100644 --- a/src/Neuron/Net/Session.php +++ b/src/Neuron/Net/Session.php @@ -7,8 +7,6 @@ class Session { - private $values; - /** @var SessionHandler */ private $handler; @@ -66,19 +64,19 @@ public function destroy () public function set ($key, $value) { - $this->values[$key] = $value; + $_SESSION[$key] = $value; } public function all () { - return $this->values; + return $_SESSION; } public function get ($key) { - if (isset ($this->values[$key])) + if (isset ($_SESSION[$key])) { - return $this->values[$key]; + return $_SESSION[$key]; } return null; } diff --git a/src/Neuron/SessionHandlers/SessionHandler.php b/src/Neuron/SessionHandlers/SessionHandler.php index 593932f..db8a8ae 100644 --- a/src/Neuron/SessionHandlers/SessionHandler.php +++ b/src/Neuron/SessionHandlers/SessionHandler.php @@ -83,6 +83,7 @@ public function write ( $session_id , $session_data ) public function register () { + session_set_save_handler( array($this, 'open'), array($this, 'close'), From 39d36177a0770321033fd79d6a7c3264f9b8fb57 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 01:56:45 +0100 Subject: [PATCH 082/231] Woop woop, little mistake in the user request. --- src/Neuron/Net/Request.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 35fcfd5..79a6d20 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -350,15 +350,6 @@ public function input ($field, $type = 'string', $default = null) */ public function setUser (User $user) { - if (!isset ($this->user) && !$this->usercallbackcalled) - { - $this->usercallbackcalled = true; - - if (isset ($this->usercallback)) { - $this->user = call_user_func ($this->usercallback, $this); - } - } - $this->user = $user; } @@ -377,6 +368,15 @@ public function setUserCallback (callable $callback) */ public function getUser() { + if (!isset ($this->user) && !$this->usercallbackcalled) + { + $this->usercallbackcalled = true; + + if (isset ($this->usercallback)) { + $this->user = call_user_func ($this->usercallback, $this); + } + } + return $this->user; } } \ No newline at end of file From 066aded1086018c9c846859a496aa1f199607f5a Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 02:09:23 +0100 Subject: [PATCH 083/231] Now playing with helpers that return templates. --- src/Neuron/Core/Template.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 2bd4ba8..b5adb51 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -380,7 +380,14 @@ private function help ($name, $method) $call = array (self::$helpers[$name], $method); if (is_callable ($call)) { - return call_user_func_array ($call, $args); + $out = call_user_func_array ($call, $args); + if ($out instanceof Template) + { + return $out->parse (); + } + else { + return $out; + } } else { return '

Method ' . $method . ' on helper ' . $name . ' is not callable.

'; From 75114170e52d3cec8d523c4c9eee3820c8a98d80 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 16 Dec 2014 02:43:12 +0100 Subject: [PATCH 084/231] Now playing with helpers that return templates. --- src/Neuron/Core/Template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index b5adb51..e2dedd0 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -369,7 +369,7 @@ private function template ($template) * @param string $method * @return string */ - private function help ($name, $method) + private function help ($name, $method = 'helper') { $args = func_get_args (); array_shift ($args); From f99b082b51010e42bb67936a67794a22466bd868 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 23 Dec 2014 22:47:54 +0100 Subject: [PATCH 085/231] Adding TokenGenerator. --- src/Neuron/Tools/TokenGenerator.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/Neuron/Tools/TokenGenerator.php diff --git a/src/Neuron/Tools/TokenGenerator.php b/src/Neuron/Tools/TokenGenerator.php new file mode 100644 index 0000000..1716616 --- /dev/null +++ b/src/Neuron/Tools/TokenGenerator.php @@ -0,0 +1,26 @@ + Date: Thu, 25 Dec 2014 16:33:31 +0100 Subject: [PATCH 086/231] Adding getId Model Interface --- src/Neuron/Interfaces/Model.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/Neuron/Interfaces/Model.php diff --git a/src/Neuron/Interfaces/Model.php b/src/Neuron/Interfaces/Model.php new file mode 100644 index 0000000..e10d3bd --- /dev/null +++ b/src/Neuron/Interfaces/Model.php @@ -0,0 +1,16 @@ + Date: Thu, 25 Dec 2014 17:05:17 +0100 Subject: [PATCH 087/231] Adding ModelCollection. --- src/Neuron/Collections/Collection.php | 2 + src/Neuron/Collections/ModelCollection.php | 48 ++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/Neuron/Collections/ModelCollection.php diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 4796ad0..daa4553 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -100,7 +100,9 @@ public function offsetSet($offset, $value) */ public function offsetUnset($offset) { + $value = isset ($this->data[$offset]) ? $this->data[$offset] : null; unset ($this->data[$offset]); + $this->trigger ('unset', $value, $offset); } /** diff --git a/src/Neuron/Collections/ModelCollection.php b/src/Neuron/Collections/ModelCollection.php new file mode 100644 index 0000000..fa69041 --- /dev/null +++ b/src/Neuron/Collections/ModelCollection.php @@ -0,0 +1,48 @@ +on ('add', array ($this, 'onAdd')); + $this->on ('set', array ($this, 'onAdd')); + $this->on ('unset', array ($this, 'onUnset')); + } + + protected function onAdd (Model $model, $offset) + { + $this->map[$model->getId ()] = $model; + } + + protected function onUnset (Model $model = null, $offset = null) + { + if ($model) + unset ($this->map[$model->getId ()]); + } + + public function getFromId ($id) + { + if (isset ($this->map[$id])) + { + return $this->map[$id]; + } + return null; + } +} \ No newline at end of file From dadccc9fcb3a5006d9dd7e038e7a6cc1193f2f00 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 25 Dec 2014 17:14:52 +0100 Subject: [PATCH 088/231] Adding ModelCollection. --- src/Neuron/Net/Entity.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index 10bc073..54cd24a 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -36,6 +36,8 @@ abstract class Entity { const STATUS_OKAY = 200; const STATUS_NOTFOUND = 404; + const STATUS_UNAUTHORIZED = 403; + /** * Serialize & deserialize requests * @param $data From 4a58fec2ef9bc0d7e9426ed9989aa30e543f072d Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 3 Jan 2015 15:31:26 +0100 Subject: [PATCH 089/231] Adding normalize & partify to URLBuilder. --- src/Neuron/URLBuilder.php | 42 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/Neuron/URLBuilder.php b/src/Neuron/URLBuilder.php index 2ea7d08..5b58ad9 100644 --- a/src/Neuron/URLBuilder.php +++ b/src/Neuron/URLBuilder.php @@ -11,7 +11,7 @@ class URLBuilder { - public static function getURL ($module = '', $data = array ()) + public static function getURL ($module = '', $data = array (), $normalize = true) { if (substr ($module, 0, 1) === '/') { @@ -27,12 +27,48 @@ public static function getURL ($module = '', $data = array ()) if (!empty ($params)) { - return Config::get ('app.url', '/') . $module . '?' . $params; + if ($normalize) + $url = self::normalize (Config::get ('app.url', '/') . $module) . '?' . $params; + else + $url = Config::get ('app.url', '/') . $module . '?' . $params; + + return $url; } else { // Google likes these. - return Config::get ('app.url', '/') . $module; + if ($normalize) + return self::normalize (Config::get ('app.url', '/') . $module); + else + return Config::get ('app.url', '/') . $module; + } + } + + /** + * Make sure the string does not end with a / + * @param $path + * @return string + */ + public static function normalize ($path) + { + if (substr ($path, 0, -1) === '/') + { + return substr ($path, 0, -1); + } + return $path; + } + + /** + * Make sure that the string ends with a slash. + * @param string $path + * @return string + */ + public static function partify ($path) + { + if (substr ($path, -1) !== '/') + { + return $path . '/'; } + return $path; } } \ No newline at end of file From c1f98a83f3e1af4ec44c4852d3873bd41df35448 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 5 Jan 2015 17:41:27 +0100 Subject: [PATCH 090/231] Fixing the database session handler. --- src/Neuron/SessionHandlers/SessionHandler.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Neuron/SessionHandlers/SessionHandler.php b/src/Neuron/SessionHandlers/SessionHandler.php index db8a8ae..daa3130 100644 --- a/src/Neuron/SessionHandlers/SessionHandler.php +++ b/src/Neuron/SessionHandlers/SessionHandler.php @@ -18,7 +18,10 @@ class SessionHandler public final function start ($sessionId = null) { - if (!$this->started) { + if (!$this->started) + { + $this->register (); + if (isset($sessionId)) { session_id ($sessionId); From 7443168ccdf64365b16e41ea4d07007e0f00e577 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 8 Jan 2015 15:59:42 +0100 Subject: [PATCH 091/231] Adding more routing options. --- src/Neuron/Models/Route.php | 98 +++++++++++++++++++++++++++++++++++++ src/Neuron/Router.php | 84 +++++++++++++++++++++++-------- 2 files changed, 162 insertions(+), 20 deletions(-) create mode 100644 src/Neuron/Models/Route.php diff --git a/src/Neuron/Models/Route.php b/src/Neuron/Models/Route.php new file mode 100644 index 0000000..27ff361 --- /dev/null +++ b/src/Neuron/Models/Route.php @@ -0,0 +1,98 @@ +setRoute ($path); + } + + /** + * @return string + */ + public function getRoute () + { + return $this->route; + } + + /** + * @param string $route + */ + public function setRoute ($route) + { + $this->route = $route; + } + + /** + * @return callable + */ + public function getFunction () + { + return $this->function; + } + + /** + * @param callable $function + */ + public function setFunction ($function) + { + $this->function = $function; + } + + /** + * @return Module + */ + public function getModule () + { + return $this->module; + } + + /** + * @param Module $module + */ + public function setModule ($module) + { + $this->module = $module; + } + + /** + * Add a filter + * @param $filtername + */ + public function filter ($filtername) + { + $this->filters[] = $filtername; + } + + /** + * @return string[] + */ + public function getFilters () + { + return $this->filters; + } + +} \ No newline at end of file diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index fe0be6e..023185a 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -11,6 +11,7 @@ use Neuron\Exceptions\InvalidParameter; use Neuron\Interfaces\Controller; use Neuron\Interfaces\Module; +use Neuron\Models\Route; use Neuron\Net\Request; use Neuron\Net\Response; use Neuron\Tools\ControllerFactory; @@ -48,6 +49,9 @@ class Router { /** @var Module|null */ private $module = null; + /** @var callable[] */ + private $filters = array (); + /** * Store a route and a handling function to be executed when accessed using one of the specified methods * @@ -64,12 +68,12 @@ public function match ($methods, $pattern, $fn) { $pattern = $this->baseroute . '/' . trim($pattern, '/'); $pattern = $this->baseroute ? rtrim($pattern, '/') : $pattern; + $route = new Route ($pattern); + $route->setFunction ($fn); + $route->setModule ($this->module); + foreach (explode('|', $methods) as $method) { - $this->routes[$method][] = array( - 'pattern' => $pattern, - 'fn' => $fn, - 'module' => $this->module - ); + $this->routes[$method][] = $route; } } @@ -91,7 +95,7 @@ private function setModule (Module $module = null) * @param mixed $fn The handling function to be executed */ public function get($pattern, $fn) { - $this->match('GET', $pattern, $fn); + return $this->match('GET', $pattern, $fn); } @@ -102,7 +106,7 @@ public function get($pattern, $fn) { * @param mixed $fn The handling function to be executed */ public function post($pattern, $fn) { - $this->match('POST', $pattern, $fn); + return $this->match('POST', $pattern, $fn); } @@ -113,7 +117,7 @@ public function post($pattern, $fn) { * @param mixed $fn The handling function to be executed */ public function patch($pattern, $fn) { - $this->match('PATCH', $pattern, $fn); + return $this->match('PATCH', $pattern, $fn); } @@ -124,7 +128,7 @@ public function patch($pattern, $fn) { * @param mixed $fn The handling function to be executed */ public function delete($pattern, $fn) { - $this->match('DELETE', $pattern, $fn); + return $this->match('DELETE', $pattern, $fn); } @@ -135,7 +139,7 @@ public function delete($pattern, $fn) { * @param mixed $fn The handling function to be executed */ public function put($pattern, $fn) { - $this->match('PUT', $pattern, $fn); + return $this->match('PUT', $pattern, $fn); } /** @@ -145,7 +149,7 @@ public function put($pattern, $fn) { * @param mixed $fn The handling function to be executed */ public function options($pattern, $fn) { - $this->match('OPTIONS', $pattern, $fn); + return $this->match('OPTIONS', $pattern, $fn); } /** @@ -184,7 +188,7 @@ public function run (Request $request) if ($numHandled == 0) { if ($this->notFound) { //call_user_func($this->notFound); - $this->handleMatch ($this->notFound, array (), null); + $this->handleMatch ($this->notFound, array ()); } else { @@ -212,14 +216,16 @@ public function getRequest () * @param object $fn The function to be executed */ public function set404($fn) { - $this->notFound = $fn; + $this->notFound = new Route ("404"); + $this->notFound->setFunction ($fn); } /** * Handle a a set of routes: if a match is found, execute the relating handling function * @param array $routes Collection of route patterns and their handling functions - * @return Response The response + * @throws InvalidParameter + * @return \Neuron\Net\Response The response */ private function handle ($routes) { @@ -231,8 +237,11 @@ private function handle ($routes) { // Loop all routes foreach ($routes as $route) { + if (!$route instanceof Route) + throw new InvalidParameter ("Route contains invalid models."); + // we have a match! - if (preg_match_all('#^' . $route['pattern'] . '$#', $uri, $matches, PREG_OFFSET_CAPTURE)) { + if (preg_match_all('#^' . $route->getRoute () . '$#', $uri, $matches, PREG_OFFSET_CAPTURE)) { // Rework matches to only contain the matches, not the orig string $matches = array_slice($matches, 1); @@ -253,7 +262,7 @@ private function handle ($routes) { }, $matches, array_keys($matches)); // call the handling function with the URL parameters - $this->handleMatch ($route['fn'], $params, $route['module']); + $this->handleMatch ($route, $params); //call_user_func_array($route['fn'], $params); // yay! @@ -271,13 +280,43 @@ private function handle ($routes) { } /** - * @param $function + * Add a filter that can be added. + * @param string $filtername + * @param callable $method + */ + public function addFilter ($filtername, $method) + { + $this->filters[$filtername] = $method; + } + + /** + * @param Route $route * @param $params - * @param Module $module * @throws InvalidParameter */ - private function handleMatch ($function, $params, Module $module = null) + private function handleMatch (Route $route, $params) { + $function = $route->getFunction (); + + // First handle the filters + foreach ($route->getFilters () as $filter) + { + // Check if exist + if (!isset ($this->filters[$filter])) + throw new InvalidParameter ("Filter " . $filter . " is not registered in the router."); + + if (!is_callable ($this->filters[$filter])) + throw new InvalidParameter ("Filter " . $filter . " is not callable."); + + $response = call_user_func_array ($this->filters[$filter], array ($this->request)); + + // If output was not TRUE, handle the filter return value as output. + if ($response !== true) { + $this->output ($response); + return; + } + } + if (is_callable ($function)) { $response = call_user_func_array($function, $params); @@ -291,13 +330,18 @@ private function handleMatch ($function, $params, Module $module = null) throw new InvalidParameter ("Controller@method syntax not valid for " . $function); } - $response = $this->handleController ($param[0], $param[1], $params, $module); + $response = $this->handleController ($param[0], $param[1], $params, $route->getModule ()); } else { throw new InvalidParameter ("Method not found."); } } + $this->output ($response); + } + + private function output ($response) + { if ($response) { if ($response instanceof Response) From 63412de13cd6ad09bf7d2c34ec702a715ee2466f Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 8 Jan 2015 16:07:26 +0100 Subject: [PATCH 092/231] Adding more routing options. --- src/Neuron/Router.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 023185a..1bd8be0 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -58,6 +58,7 @@ class Router { * @param string $methods Allowed methods, | delimited * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed + * @return \Neuron\Models\Route */ public function match ($methods, $pattern, $fn) { @@ -76,6 +77,7 @@ public function match ($methods, $pattern, $fn) { $this->routes[$method][] = $route; } + return $route; } /** From b63541fbd4e9a4178e340b5b8885fa42779bc763 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 8 Jan 2015 16:09:13 +0100 Subject: [PATCH 093/231] Adding more routing options. --- src/Neuron/Router.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 1bd8be0..46fe462 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -95,6 +95,7 @@ private function setModule (Module $module = null) * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed + * @return \Neuron\Models\Route */ public function get($pattern, $fn) { return $this->match('GET', $pattern, $fn); @@ -106,6 +107,7 @@ public function get($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed + * @return \Neuron\Models\Route */ public function post($pattern, $fn) { return $this->match('POST', $pattern, $fn); @@ -117,6 +119,7 @@ public function post($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed + * @return \Neuron\Models\Route */ public function patch($pattern, $fn) { return $this->match('PATCH', $pattern, $fn); @@ -128,6 +131,7 @@ public function patch($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed + * @return \Neuron\Models\Route */ public function delete($pattern, $fn) { return $this->match('DELETE', $pattern, $fn); @@ -139,6 +143,7 @@ public function delete($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed + * @return \Neuron\Models\Route */ public function put($pattern, $fn) { return $this->match('PUT', $pattern, $fn); @@ -149,6 +154,7 @@ public function put($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed + * @return \Neuron\Models\Route */ public function options($pattern, $fn) { return $this->match('OPTIONS', $pattern, $fn); @@ -286,7 +292,7 @@ private function handle ($routes) { * @param string $filtername * @param callable $method */ - public function addFilter ($filtername, $method) + public function addFilter ($filtername, callable $method) { $this->filters[$filtername] = $method; } @@ -307,9 +313,6 @@ private function handleMatch (Route $route, $params) if (!isset ($this->filters[$filter])) throw new InvalidParameter ("Filter " . $filter . " is not registered in the router."); - if (!is_callable ($this->filters[$filter])) - throw new InvalidParameter ("Filter " . $filter . " is not callable."); - $response = call_user_func_array ($this->filters[$filter], array ($this->request)); // If output was not TRUE, handle the filter return value as output. From c295315e930ac8aeae3730f9a7b4a3165ad95e97 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 9 Jan 2015 18:42:06 +0100 Subject: [PATCH 094/231] Adding XML output type (for fnu) --- src/Neuron/Core/Tools.php | 126 ------------------------- src/Neuron/Net/Outputs/XML.php | 162 +++++++++++++++++++++++++++++++++ src/Neuron/Net/Response.php | 9 ++ 3 files changed, 171 insertions(+), 126 deletions(-) create mode 100644 src/Neuron/Net/Outputs/XML.php diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index efb0b01..7ea7e54 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -239,132 +239,6 @@ public static function output_varchar ($text) return htmlspecialchars (($text), ENT_QUOTES, 'UTF-8'); } - - public static function writexml (XMLWriter $xml, $data, $item_name = 'item') - { - foreach($data as $key => $value) - { - if (is_int ($key)) - { - $key = $item_name; - } - - if (is_array($value)) - { - if ($key != 'items') - { - $xml->startElement($key); - } - - if (isset ($value['attributes']) && is_array ($value['attributes'])) - { - foreach ($value['attributes'] as $k => $v) - { - $xml->writeAttribute ($k, $v); - } - - unset ($value['attributes']); - } - - NeuronCoreTools::writexml ($xml, $value, substr ($key, 0, -1)); - - if ($key != 'items') - { - $xml->endElement(); - } - } - - elseif ($key == 'element-content') - { - $xml->text ($value); - } - - else - { - $xml->writeElement($key, $value); - } - } - } - - public static function output_xml ($data, $version = '0.1', $root = 'root', $parameters = array (), $sItemName = 'item') - { - $xml = new XmlWriter(); - $xml->openMemory(); - $xml->startDocument('1.0', 'UTF-8'); - $xml->startElement($root); - $xml->setIndent (true); - - if (!empty ($version)) - { - $xml->writeAttribute ('version', $version); - } - - foreach ($parameters as $paramk => $paramv) - { - $xml->writeAttribute ($paramk, $paramv); - } - - NeuronCoreTools::writexml ($xml, $data, $sItemName); - - $xml->endElement(); - return $xml->outputMemory(true); - } - - private static function xml_escape ($input) - { - //$input = str_replace ('"', '"', $input); - //$input = str_replace ("'", ''', $input); - - - $input = str_replace ('<', '<', $input); - $input = str_replace ('>', '>', $input); - $input = str_replace ('&', '&', $input); - - - return $input; - } - - public static function output_partly_xml ($data, $key = null) - { - $output = '<'.$key; - - if (isset ($data['attributes']) && is_array ($data['attributes'])) - { - foreach ($data['attributes'] as $k => $v) - { - $output .= ' '.$k.'="'.$v.'"'; - } - - unset ($data['attributes']); - } - - $output .= '>'; - if (!is_array ($data)) - { - $output .= self::xml_escape ($data); - } - - elseif (count ($data) == 1 && isset ($data['element-content'])) - { - $output .= self::xml_escape ($data['element-content']); - } - - else - { - foreach ($data as $k => $v) - { - if (is_numeric ($k)) - { - $k = substr ($key, 0, -1); - } - - $output .= self::output_partly_xml ($v, $k); - } - } - $output .= ''."\n"; - - return $output; - } } ?> diff --git a/src/Neuron/Net/Outputs/XML.php b/src/Neuron/Net/Outputs/XML.php new file mode 100644 index 0000000..8e350ee --- /dev/null +++ b/src/Neuron/Net/Outputs/XML.php @@ -0,0 +1,162 @@ + $value) + { + if (is_int ($key)) + { + $key = $item_name; + } + + if (is_array($value)) + { + if ($key != 'items') + { + $xml->startElement($key); + } + + if (isset ($value['attributes']) && is_array ($value['attributes'])) + { + foreach ($value['attributes'] as $k => $v) + { + $xml->writeAttribute ($k, $v); + } + + unset ($value['attributes']); + } + + self::writexml ($xml, $value, substr ($key, 0, -1)); + + if ($key != 'items') + { + $xml->endElement(); + } + } + + elseif ($key == 'element-content') + { + $xml->text ($value); + } + + else + { + $xml->writeElement($key, $value); + } + } + } + + public static function output_xml ($data, $version = '0.1', $root = 'root', $parameters = array (), $sItemName = 'item') + { + $xml = new XmlWriter(); + $xml->openMemory(); + $xml->startDocument('1.0', 'UTF-8'); + $xml->startElement($root); + $xml->setIndent (true); + + if (!empty ($version)) + { + $xml->writeAttribute ('version', $version); + } + + foreach ($parameters as $paramk => $paramv) + { + $xml->writeAttribute ($paramk, $paramv); + } + + self::writexml ($xml, $data, $sItemName); + + $xml->endElement(); + return $xml->outputMemory(true); + } + + private static function xml_escape ($input) + { + //$input = str_replace ('"', '"', $input); + //$input = str_replace ("'", ''', $input); + + + $input = str_replace ('<', '<', $input); + $input = str_replace ('>', '>', $input); + $input = str_replace ('&', '&', $input); + + + return $input; + } + + public static function output_partly_xml ($data, $key = null) + { + $output = '<'.$key; + + if (isset ($data['attributes']) && is_array ($data['attributes'])) + { + foreach ($data['attributes'] as $k => $v) + { + $output .= ' '.$k.'="'.$v.'"'; + } + + unset ($data['attributes']); + } + + $output .= '>'; + if (!is_array ($data)) + { + $output .= self::xml_escape ($data); + } + + elseif (count ($data) == 1 && isset ($data['element-content'])) + { + $output .= self::xml_escape ($data['element-content']); + } + + else + { + foreach ($data as $k => $v) + { + if (is_numeric ($k)) + { + $k = substr ($key, 0, -1); + } + + $output .= self::output_partly_xml ($v, $k); + } + } + $output .= ''."\n"; + + return $output; + } + + public function outputContent (Response $response) + { + if (!is_string ($response->getData ())) + { + echo self::output_xml ($response->getData ()); + } + + else + { + echo $response->getData (); + } + } + + +} \ No newline at end of file diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index df5cb24..039586b 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -16,6 +16,7 @@ use Neuron\Net\Outputs\Output; use Neuron\Net\Outputs\PrintR; use Neuron\Net\Outputs\Table; +use Neuron\Net\Outputs\XML; class Response extends Entity { @@ -90,6 +91,14 @@ public static function json ($data) return $in; } + public static function xml ($data) + { + $in = new self (); + $in->setData ($data); + $in->setOutput (new XML ()); + return $in; + } + /** * @param string $message * @param int $statuscode From a16544c74ee7ea70e5b5b03d3b9517d5e4691978 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 9 Jan 2015 18:46:51 +0100 Subject: [PATCH 095/231] Adding XML output type (for fnu) --- src/Neuron/Net/Outputs/XML.php | 14 +++++++++++--- src/Neuron/Net/Response.php | 10 +++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Neuron/Net/Outputs/XML.php b/src/Neuron/Net/Outputs/XML.php index 8e350ee..e2ea3b2 100644 --- a/src/Neuron/Net/Outputs/XML.php +++ b/src/Neuron/Net/Outputs/XML.php @@ -14,9 +14,17 @@ class XML extends HTML { - public function __construct () + private $version; + private $root; + private $parameters; + private $itemName; + + public function __construct ($root = 'root', $version = '1.0', array $parameters = array (), $itemName = 'item') { - + $this->root = $root; + $this->version = $version; + $this->itemName = $itemName; + $this->parameters = $parameters; } public static function writexml (XMLWriter $xml, $data, $item_name = 'item') @@ -149,7 +157,7 @@ public function outputContent (Response $response) { if (!is_string ($response->getData ())) { - echo self::output_xml ($response->getData ()); + echo self::output_xml ($response->getData (), $this->version, $this->root, $this->parameters, $this->itemName); } else diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 039586b..883bfab 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -91,7 +91,15 @@ public static function json ($data) return $in; } - public static function xml ($data) + /** + * @param $data + * @param string $root XML Root element name + * @param string $version Root element version number + * @param array $parameters Array of root element attributes + * @param string $itemName Generic item name. + * @return Response + */ + public static function xml ($data, $root = 'root', $version = '1.0', array $parameters = array (), $itemName = 'item') { $in = new self (); $in->setData ($data); From d25a90a264a0d89af4dc2c5e81c6e6e15ed83bed Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 9 Jan 2015 18:47:54 +0100 Subject: [PATCH 096/231] Adding XML output type (for fnu) --- src/Neuron/Net/Outputs/XML.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Neuron/Net/Outputs/XML.php b/src/Neuron/Net/Outputs/XML.php index e2ea3b2..1f0cb40 100644 --- a/src/Neuron/Net/Outputs/XML.php +++ b/src/Neuron/Net/Outputs/XML.php @@ -155,6 +155,8 @@ public static function output_partly_xml ($data, $key = null) public function outputContent (Response $response) { + header ('Content-type: application/xml'); + if (!is_string ($response->getData ())) { echo self::output_xml ($response->getData (), $this->version, $this->root, $this->parameters, $this->itemName); From 036f840116561b7220ed6e07a2c36b4a8bce0531 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 11 Jan 2015 13:38:41 +0100 Subject: [PATCH 097/231] Automatically setting data based on headers. --- src/Neuron/Net/Request.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 79a6d20..81161d1 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -56,6 +56,21 @@ public static function fromInput () $model->setStatus (http_response_code ()); $model->setUrl (self::getCurrentUri ()); + $headers = $model->getHeaders (); + if (isset ($headers['Content-Type'])) + { + switch (strtolower ($headers['Content-Type'])) + { + case 'application/json': + case 'text/json': + + $data = json_decode ($model->getBody (), true); + $model->setData ($data); + + break; + } + } + return $model; } From 621aeb24edbb257d2929f12749deafb7a5339e0b Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 11 Jan 2015 13:42:12 +0100 Subject: [PATCH 098/231] Automatically setting data based on headers. --- src/Neuron/Net/Entity.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index 54cd24a..59d357c 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -35,6 +35,7 @@ abstract class Entity { const STATUS_OKAY = 200; const STATUS_NOTFOUND = 404; + const STATUS_INVALID_INPUT = 400; const STATUS_UNAUTHORIZED = 403; From 425b46420b800b8c75239a258b95137fb745536c Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 11 Jan 2015 13:49:49 +0100 Subject: [PATCH 099/231] Automatically setting data based on headers. --- src/Neuron/Net/Entity.php | 35 +++++++++++++++++++++++++++++++++++ src/Neuron/Net/Request.php | 11 +++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index 59d357c..404a23d 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -27,6 +27,9 @@ abstract class Entity { private $headers; private $data; private $cookies; + + /** @var string $error */ + private $error; /** @var integer $status */ private $status; @@ -269,6 +272,23 @@ public function getData () return $this->data; } + /** + * Check if request has data + */ + public function hasData () + { + if (!isset ($this->data)) + { + if (!isset ($this->error)) + $this->setError ('No input data set'); + + return false; + } + else { + return true; + } + } + /** * @param string $name * @param string $value @@ -327,4 +347,19 @@ public function getStatus () return 200; } + /** + * @param $error + */ + public function setError ($error) + { + $this->error = $error; + } + + /** + * @return string + */ + public function getError () + { + return $this->error; + } } \ No newline at end of file diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 81161d1..35f853f 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -9,6 +9,7 @@ namespace Neuron\Net; +use Exception; use Neuron\Core\Tools; use Neuron\Interfaces\Models\User; @@ -65,9 +66,15 @@ public static function fromInput () case 'text/json': $data = json_decode ($model->getBody (), true); - $model->setData ($data); - break; + if (!$data) { + $model->setError ('JSON decode error: ' . json_last_error_msg ()); + } + else { + $model->setData ($data); + } + + break; } } From 498107f4bc38634d9d2315af52f3d41112b734b5 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 11 Jan 2015 13:50:49 +0100 Subject: [PATCH 100/231] Automatically setting data based on headers. --- src/Neuron/Net/Entity.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index 404a23d..46920e8 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -362,4 +362,13 @@ public function getError () { return $this->error; } + + /** + * Return an error response. + * @return Response + */ + public function getErrorResponse () + { + return Response::error ($this->getError (), self::STATUS_INVALID_INPUT); + } } \ No newline at end of file From 7ebe755a8e338269928ba0f0e9fb629eec299d60 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 11 Jan 2015 14:08:53 +0100 Subject: [PATCH 101/231] Changing filter a bit more. --- src/Neuron/Models/Router/Filter.php | 85 ++++++++++++++++++++++++ src/Neuron/Models/{ => Router}/Route.php | 14 +++- src/Neuron/Router.php | 18 ++--- 3 files changed, 106 insertions(+), 11 deletions(-) create mode 100644 src/Neuron/Models/Router/Filter.php rename src/Neuron/Models/{ => Router}/Route.php (80%) diff --git a/src/Neuron/Models/Router/Filter.php b/src/Neuron/Models/Router/Filter.php new file mode 100644 index 0000000..0b09c02 --- /dev/null +++ b/src/Neuron/Models/Router/Filter.php @@ -0,0 +1,85 @@ +setName ($name); + } + + /** + * @return string + */ + public function getName () + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName ($name) + { + $this->name = $name; + } + + /** + * @return \mixed[] + */ + public function getArguments () + { + return $this->arguments; + } + + /** + * @param \mixed[] $arguments + */ + public function setArguments ($arguments) + { + $this->arguments = $arguments; + } + + /** + * @param Request $request + */ + public function setRequest (Request $request) + { + $this->request = $request; + } + + /** + * Clear the request + */ + public function clearRequest () + { + $this->request = null; + } + + /** + * @return Request + */ + public function getRequest () + { + return $this->request; + } +} \ No newline at end of file diff --git a/src/Neuron/Models/Route.php b/src/Neuron/Models/Router/Route.php similarity index 80% rename from src/Neuron/Models/Route.php rename to src/Neuron/Models/Router/Route.php index 27ff361..8458d83 100644 --- a/src/Neuron/Models/Route.php +++ b/src/Neuron/Models/Router/Route.php @@ -6,7 +6,7 @@ * Time: 15:44 */ -namespace Neuron\Models; +namespace Neuron\Models\Router; use Neuron\Interfaces\Module; @@ -84,7 +84,17 @@ public function setModule ($module) */ public function filter ($filtername) { - $this->filters[] = $filtername; + $arguments = func_get_args (); + array_shift ($arguments); + + $filters = explode (',', $filtername); + foreach ($filters as $filter) + { + $objfilter = new Filter ($filter); + $objfilter->setArguments ($arguments); + + $this->filters[] = $objfilter; + } } /** diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 46fe462..8489047 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -11,7 +11,7 @@ use Neuron\Exceptions\InvalidParameter; use Neuron\Interfaces\Controller; use Neuron\Interfaces\Module; -use Neuron\Models\Route; +use Neuron\Models\Router\Route; use Neuron\Net\Request; use Neuron\Net\Response; use Neuron\Tools\ControllerFactory; @@ -58,7 +58,7 @@ class Router { * @param string $methods Allowed methods, | delimited * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed - * @return \Neuron\Models\Route + * @return Route */ public function match ($methods, $pattern, $fn) { @@ -95,7 +95,7 @@ private function setModule (Module $module = null) * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed - * @return \Neuron\Models\Route + * @return Route */ public function get($pattern, $fn) { return $this->match('GET', $pattern, $fn); @@ -107,7 +107,7 @@ public function get($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed - * @return \Neuron\Models\Route + * @return Route */ public function post($pattern, $fn) { return $this->match('POST', $pattern, $fn); @@ -119,7 +119,7 @@ public function post($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed - * @return \Neuron\Models\Route + * @return Route */ public function patch($pattern, $fn) { return $this->match('PATCH', $pattern, $fn); @@ -131,7 +131,7 @@ public function patch($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed - * @return \Neuron\Models\Route + * @return Route */ public function delete($pattern, $fn) { return $this->match('DELETE', $pattern, $fn); @@ -143,7 +143,7 @@ public function delete($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed - * @return \Neuron\Models\Route + * @return Route */ public function put($pattern, $fn) { return $this->match('PUT', $pattern, $fn); @@ -154,7 +154,7 @@ public function put($pattern, $fn) { * * @param string $pattern A route pattern such as /about/system * @param mixed $fn The handling function to be executed - * @return \Neuron\Models\Route + * @return Route */ public function options($pattern, $fn) { return $this->match('OPTIONS', $pattern, $fn); @@ -313,7 +313,7 @@ private function handleMatch (Route $route, $params) if (!isset ($this->filters[$filter])) throw new InvalidParameter ("Filter " . $filter . " is not registered in the router."); - $response = call_user_func_array ($this->filters[$filter], array ($this->request)); + $response = call_user_func_array ($this->filters[$filter], array ($filter)); // If output was not TRUE, handle the filter return value as output. if ($response !== true) { From 942248256e892754a0d4a30f4980d584f6416778 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 11 Jan 2015 14:17:03 +0100 Subject: [PATCH 102/231] Changing filter a bit more. --- src/Neuron/Models/Router/Filter.php | 9 +++++++++ src/Neuron/Models/Router/Route.php | 2 +- src/Neuron/Router.php | 8 +++++--- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Neuron/Models/Router/Filter.php b/src/Neuron/Models/Router/Filter.php index 0b09c02..63f30e3 100644 --- a/src/Neuron/Models/Router/Filter.php +++ b/src/Neuron/Models/Router/Filter.php @@ -82,4 +82,13 @@ public function getRequest () { return $this->request; } + + /** + * @param $callback + * @return mixed + */ + public function check ($callback) + { + return call_user_func_array ($callback, array ($this)); + } } \ No newline at end of file diff --git a/src/Neuron/Models/Router/Route.php b/src/Neuron/Models/Router/Route.php index 8458d83..d0f5857 100644 --- a/src/Neuron/Models/Router/Route.php +++ b/src/Neuron/Models/Router/Route.php @@ -98,7 +98,7 @@ public function filter ($filtername) } /** - * @return string[] + * @return Filter[] */ public function getFilters () { diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 8489047..a82f727 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -310,10 +310,12 @@ private function handleMatch (Route $route, $params) foreach ($route->getFilters () as $filter) { // Check if exist - if (!isset ($this->filters[$filter])) - throw new InvalidParameter ("Filter " . $filter . " is not registered in the router."); + if (!isset ($this->filters[$filter->getName ()])) + throw new InvalidParameter ("Filter " . $filter->getName () . " is not registered in the router."); - $response = call_user_func_array ($this->filters[$filter], array ($filter)); + $filter->setRequest ($this->request); + $response = $filter->check ($this->filters[$filter->getName ()]); + $filter->clearRequest (); // If output was not TRUE, handle the filter return value as output. if ($response !== true) { From f03c1363cc517f937f0675cec30df6789b3f5dcf Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 11 Jan 2015 14:19:18 +0100 Subject: [PATCH 103/231] Changing filter a bit more. --- src/Neuron/Models/Router/Route.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Neuron/Models/Router/Route.php b/src/Neuron/Models/Router/Route.php index d0f5857..eeda983 100644 --- a/src/Neuron/Models/Router/Route.php +++ b/src/Neuron/Models/Router/Route.php @@ -81,6 +81,7 @@ public function setModule ($module) /** * Add a filter * @param $filtername + * @return $this */ public function filter ($filtername) { @@ -95,6 +96,8 @@ public function filter ($filtername) $this->filters[] = $objfilter; } + + return $this; } /** From 931ba570a20feb592f53aeaa5ed8d8991cbf63ae Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 11 Jan 2015 16:18:36 +0100 Subject: [PATCH 104/231] Changing filter a bit more. --- src/Neuron/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index a82f727..b2616ae 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -292,7 +292,7 @@ private function handle ($routes) { * @param string $filtername * @param callable $method */ - public function addFilter ($filtername, callable $method) + public function addFilter ($filtername, callable $method = null) { $this->filters[$filtername] = $method; } From 0bd756d4e781d349a4e54ba8214d6c08c41f7334 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 11 Jan 2015 22:19:04 +0100 Subject: [PATCH 105/231] Allow for chain setting in Net entities. --- src/Neuron/Net/Entity.php | 20 ++++++++++++++++++++ src/Neuron/Net/Request.php | 15 +++++++++++++++ src/Neuron/Net/Response.php | 3 +++ 3 files changed, 38 insertions(+) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index 46920e8..e72b43c 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -186,18 +186,22 @@ public function getSession () /** * @param Session $session + * @return $this */ public function setSession (Session $session) { $this->session = $session; + return $this; } /** * @param $body + * @return $this */ public function setBody ($body) { $this->body = $body; + return $this; } /** @@ -210,10 +214,12 @@ public function getBody () /** * @param $id + * @return $this */ public function setApplication ($id) { $this->setSession ('application', $id); + return $this; } /** @@ -226,10 +232,12 @@ public function getApplication () /** * @param $path + * @return $this */ public function setPath ($path) { $this->path = $path; + return $this; } /** @@ -242,10 +250,12 @@ public function getPath () /** * @param array $post + * @return $this */ public function setPost ($post) { $this->post = $post; + return $this; } /** @@ -258,10 +268,12 @@ public function getPost () /** * @param mixed $data + * @return $this */ public function setData ($data) { $this->data = $data; + return $this; } /** @@ -292,6 +304,7 @@ public function hasData () /** * @param string $name * @param string $value + * @return $this */ public function setHeader ($name, $value = null) { @@ -300,14 +313,17 @@ public function setHeader ($name, $value = null) $this->headers = array (); } $this->headers[$name] = $value; + return $this; } /** * @param array $headers + * @return $this */ public function setHeaders ($headers) { $this->headers = $headers; + return $this; } /** @@ -321,6 +337,7 @@ public function getHeaders () public function setCookies ($cookies) { $this->cookies = $cookies; + return $this; } public function getCookies () @@ -331,6 +348,7 @@ public function getCookies () public function setStatus ($status) { $this->status = $status; + return $this; } public function isStatusSet () @@ -349,10 +367,12 @@ public function getStatus () /** * @param $error + * @return $this */ public function setError ($error) { $this->error = $error; + return $this; } /** diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 35f853f..9a2b9e1 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -189,10 +189,12 @@ public static function fromJSON ($json) /** * @param $method + * @return $this */ public function setMethod ($method) { $this->method = $method; + return $this; } /** @@ -205,10 +207,12 @@ public function getMethod () /** * @param $url + * @return $this */ public function setUrl ($url) { $this->url = $url; + return $this; } /** @@ -221,18 +225,22 @@ public function getUrl () /** * @param array $parameters + * @return $this */ public function setParameters (array $parameters) { $this->parameters = $parameters; + return $this; } /** * @param $string + * @return $this */ public function setQueryString ($string) { $this->parameters = parse_url ($string); + return $this; } /** @@ -245,10 +253,12 @@ public function getParameters () /** * @param $input + * @return $this */ public function setSegments ($input) { $this->input = $input; + return $this; } /** @@ -295,6 +305,7 @@ public function getJSONData () public function setEnvironment ($data) { $this->environment = $data; + return $this; } public function getEnvironment () @@ -369,20 +380,24 @@ public function input ($field, $type = 'string', $default = null) /** * Helper method to make it easier for authentication modules * @param User $user + * @return $this */ public function setUser (User $user) { $this->user = $user; + return $this; } /** * To allow lazy loading of the user object, set a callback here. * Method will be called with request as parameter and only once a script. * @param callable $callback + * @return $this */ public function setUserCallback (callable $callback) { $this->usercallback = $callback; + return $this; } /** diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 883bfab..82504b6 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -195,11 +195,14 @@ private function setTemplate (Template $template) { $this->setBody ($template->parse ()); $this->setOutput (new HTML ()); + + return $this; } public function setOutput (Output $output) { $this->output = $output; + return $this; } public function isOutputSet () From cdc5dba4aa842d722d728ab7c46f7f54fc54bd11 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 14 Jan 2015 15:34:30 +0100 Subject: [PATCH 106/231] Allow for setting custom collections in BaseMapper. --- src/Neuron/Mappers/BaseMapper.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Mappers/BaseMapper.php b/src/Neuron/Mappers/BaseMapper.php index f084783..4f29109 100644 --- a/src/Neuron/Mappers/BaseMapper.php +++ b/src/Neuron/Mappers/BaseMapper.php @@ -35,13 +35,22 @@ protected function getSingle ($data) return null; } + /** + * Override this to set an alternative object collection. + * @return array + */ + protected function getObjectCollection () + { + return array (); + } + /** * @param $data * @return array|mixed[] */ protected function getObjectsFromData ($data) { - $out = array (); + $out = $this->getObjectCollection (); foreach ($data as $v) { $out[] = $this->getObjectFromData ($v); From 902e25507a45a88dabd560812b0d7c49750bfdcc Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 15 Jan 2015 20:53:47 +0100 Subject: [PATCH 107/231] Allow for setting custom collections in BaseMapper. --- src/Neuron/Net/Request.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 9a2b9e1..11d0e5b 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -91,10 +91,12 @@ private static function getHeadersFromInput () if (function_exists('getallheaders')) return getallheaders(); // getallheaders not available: manually extract 'm - $headers = array(); - foreach ($_SERVER as $name => $value) { - if ((substr($name, 0, 5) == 'HTTP_') || ($name == 'CONTENT_TYPE') || ($name == 'CONTENT_LENGTH')) { - $headers[str_replace(array(' ', 'Http'), array('-', 'HTTP'), ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; + $headers = ''; + foreach ($_SERVER as $name => $value) + { + if (substr($name, 0, 5) == 'HTTP_') + { + $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; } } return $headers; From 07c3a75f0114b88a74533fb9a982ddb31309a78c Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 15 Jan 2015 21:08:40 +0100 Subject: [PATCH 108/231] Allow for setting custom collections in BaseMapper. --- src/Neuron/Net/Request.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 11d0e5b..8414f05 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -98,6 +98,11 @@ private static function getHeadersFromInput () { $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; } + + else if (substr ($name, 0, 7) == 'REQUEST') + { + $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $name))))] = $value; + } } return $headers; } From 6bc8d696333af34669439c36cb835d22a6f8b7be Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 15 Jan 2015 21:13:12 +0100 Subject: [PATCH 109/231] Allow for setting custom collections in BaseMapper. --- src/Neuron/Net/Request.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 8414f05..7cf29f9 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -99,7 +99,7 @@ private static function getHeadersFromInput () $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; } - else if (substr ($name, 0, 7) == 'REQUEST') + else if (strtolower (substr ($name, 0, 7)) == 'content') { $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $name))))] = $value; } From cb3d14eb3cd3f86a1b37e5c1f84e667f697934ac Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 17 Jan 2015 16:28:33 +0100 Subject: [PATCH 110/231] Allow for setting custom collections in BaseMapper. --- src/Neuron/Exceptions/ExpectedType.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100755 src/Neuron/Exceptions/ExpectedType.php diff --git a/src/Neuron/Exceptions/ExpectedType.php b/src/Neuron/Exceptions/ExpectedType.php new file mode 100755 index 0000000..d5c9647 --- /dev/null +++ b/src/Neuron/Exceptions/ExpectedType.php @@ -0,0 +1,16 @@ + Date: Sun, 18 Jan 2015 20:23:14 +0100 Subject: [PATCH 111/231] Allow for setting custom collections in BaseMapper. --- src/Neuron/Models/Logger.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Neuron/Models/Logger.php b/src/Neuron/Models/Logger.php index c492636..f4ee11f 100644 --- a/src/Neuron/Models/Logger.php +++ b/src/Neuron/Models/Logger.php @@ -120,6 +120,11 @@ public function log ($string, $replace = false, $color = null) return new Timer ($string); } + public function start ($string, $replace = false, $color = null) + { + return $this->log ($string, $replace, $color); + } + public function replace ($string) { $this->log ($string, true); From 6624d959d52cb0c155c00e3bae14fe7ea568c7e5 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 18 Jan 2015 20:25:39 +0100 Subject: [PATCH 112/231] Allow for setting custom collections in BaseMapper. --- src/Neuron/Models/Logger.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Neuron/Models/Logger.php b/src/Neuron/Models/Logger.php index f4ee11f..9ca4024 100644 --- a/src/Neuron/Models/Logger.php +++ b/src/Neuron/Models/Logger.php @@ -30,6 +30,11 @@ public static function getInstance () private $temporary = array (); private $temporarystart = array (); + public static function start ($string, $replace = false, $color = null) + { + return self::getInstance ()->log ($string, $replace, $color); + } + private function __construct () { $this->start = microtime(true); @@ -120,11 +125,6 @@ public function log ($string, $replace = false, $color = null) return new Timer ($string); } - public function start ($string, $replace = false, $color = null) - { - return $this->log ($string, $replace, $color); - } - public function replace ($string) { $this->log ($string, true); From 37338c376c8f2d2b6be2f9be7813c825bb074bec Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 25 Jan 2015 20:25:27 +0100 Subject: [PATCH 113/231] Adding a check method to ExpectedType. --- src/Neuron/Exceptions/ExpectedType.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Neuron/Exceptions/ExpectedType.php b/src/Neuron/Exceptions/ExpectedType.php index d5c9647..54b8244 100755 --- a/src/Neuron/Exceptions/ExpectedType.php +++ b/src/Neuron/Exceptions/ExpectedType.php @@ -7,6 +7,16 @@ class ExpectedType extends InvalidParameter { + /** + * @param $obj + * @param $className + * @throws ExpectedType + */ + public static function check ($obj, $className) + { + if (! ($obj instanceof $className)) + throw new self ($className); + } public function __construct ($class) { From 5d502b41f97424c388e67b0540d6ce595712d903 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 25 Jan 2015 20:46:44 +0100 Subject: [PATCH 114/231] testing phpstorm --- example/public/datatype.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 example/public/datatype.php diff --git a/example/public/datatype.php b/example/public/datatype.php new file mode 100644 index 0000000..1cef5f3 --- /dev/null +++ b/example/public/datatype.php @@ -0,0 +1,24 @@ +doSomething (); +} + +$mi = new Bar (); + From cd82114c4614a49f584592edd4bad9463a6ada01 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 26 Jan 2015 11:48:04 +0100 Subject: [PATCH 115/231] Allowing multiple user callbacks. --- src/Neuron/Net/Request.php | 54 +++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 7cf29f9..579c887 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -11,6 +11,7 @@ use Exception; use Neuron\Core\Tools; +use Neuron\Exceptions\InvalidParameter; use Neuron\Interfaces\Models\User; class Request @@ -25,8 +26,8 @@ class Request /** @var User $user */ private $user; - /** @var callable $usercallback */ - private $usercallback; + /** @var callable[] $usercallback */ + private $usercallback = array (); private $usercallbackcalled = false; @@ -399,25 +400,64 @@ public function setUser (User $user) * To allow lazy loading of the user object, set a callback here. * Method will be called with request as parameter and only once a script. * @param callable $callback + * @throws InvalidParameter * @return $this */ public function setUserCallback (callable $callback) { - $this->usercallback = $callback; + //$this->usercallback = $callback; + + if (count ($this->usercallback) > 0) + throw new InvalidParameter ("A usercallback was already set. Use addUserCallback to add multiple callbacks"); + + $this->addUserCallback ('default', $callback); + + return $this; + } + + /** + * To allow for multiple authentication methods, extra user callbacks can be set. + * Each callback must have a unique name. This name can be used in getUser to force + * @param $name + * @param callable $callback + * @throws InvalidParameter + * @return $this + */ + public function addUserCallback ($name, callable $callback) + { + if (isset ($this->usercallback[$name])) + throw new InvalidParameter ("A usercallback with name " . $name . " is already set. Each callback must have a unique name."); + + $this->usercallback[$name] = $callback; + return $this; } /** - * @return User + * @param string $callbackName To force a specific callback + * @return \Neuron\Interfaces\Models\User */ - public function getUser() + public function getUser ($callbackName) { if (!isset ($this->user) && !$this->usercallbackcalled) { $this->usercallbackcalled = true; - if (isset ($this->usercallback)) { - $this->user = call_user_func ($this->usercallback, $this); + if (isset ($this->usercallback[$callbackName])) + { + $this->user = call_user_func ($this->usercallback[$callbackName], $this); + } + + else { + // Loop trough all callbacks until we find one that returns something + $user = null; + foreach ($this->usercallback as $cb) + { + $user = call_user_func ($cb, $this); + if ($user) + break; + } + $this->user = $user; } } From 574e8b2ae57b5733e41f5e69d401aa516719ef8c Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 26 Jan 2015 11:48:33 +0100 Subject: [PATCH 116/231] Merge --- composer.lock | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 composer.lock diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..bcea672 --- /dev/null +++ b/composer.lock @@ -0,0 +1,86 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "ca41efe99c3e4590680705dc6122711e", + "packages": [ + { + "name": "justinrainbow/json-schema", + "version": "1.3.7", + "source": { + "type": "git", + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "87b54b460febed69726c781ab67462084e97a105" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/87b54b460febed69726c781ab67462084e97a105", + "reference": "87b54b460febed69726c781ab67462084e97a105", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "json-schema/json-schema-test-suite": "1.1.0", + "phpdocumentor/phpdocumentor": "~2", + "phpunit/phpunit": "~3.7" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "JsonSchema": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "time": "2014-08-25 02:48:14" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "ext-gettext": "*" + }, + "platform-dev": [] +} From 0518ce1ab075f0028da0d50ef18b5f5b82ea6267 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 26 Jan 2015 11:58:05 +0100 Subject: [PATCH 117/231] Allowing multiple user callbacks. --- composer.lock | 86 -------------------- src/Neuron/Interfaces/Mappers/UserMapper.php | 20 +++++ src/Neuron/MapperFactory.php | 54 ++++++++++++ 3 files changed, 74 insertions(+), 86 deletions(-) delete mode 100644 composer.lock create mode 100644 src/Neuron/Interfaces/Mappers/UserMapper.php create mode 100644 src/Neuron/MapperFactory.php diff --git a/composer.lock b/composer.lock deleted file mode 100644 index bcea672..0000000 --- a/composer.lock +++ /dev/null @@ -1,86 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "hash": "ca41efe99c3e4590680705dc6122711e", - "packages": [ - { - "name": "justinrainbow/json-schema", - "version": "1.3.7", - "source": { - "type": "git", - "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "87b54b460febed69726c781ab67462084e97a105" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/87b54b460febed69726c781ab67462084e97a105", - "reference": "87b54b460febed69726c781ab67462084e97a105", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "json-schema/json-schema-test-suite": "1.1.0", - "phpdocumentor/phpdocumentor": "~2", - "phpunit/phpunit": "~3.7" - }, - "bin": [ - "bin/validate-json" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "psr-0": { - "JsonSchema": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Bruno Prieto Reis", - "email": "bruno.p.reis@gmail.com" - }, - { - "name": "Justin Rainbow", - "email": "justin.rainbow@gmail.com" - }, - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - }, - { - "name": "Robert Schönthal", - "email": "seroscho@googlemail.com" - } - ], - "description": "A library to validate a json schema.", - "homepage": "https://github.com/justinrainbow/json-schema", - "keywords": [ - "json", - "schema" - ], - "time": "2014-08-25 02:48:14" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "ext-gettext": "*" - }, - "platform-dev": [] -} diff --git a/src/Neuron/Interfaces/Mappers/UserMapper.php b/src/Neuron/Interfaces/Mappers/UserMapper.php new file mode 100644 index 0000000..97d6b5e --- /dev/null +++ b/src/Neuron/Interfaces/Mappers/UserMapper.php @@ -0,0 +1,20 @@ +mapped[$key])) + throw new InvalidParameter ("Mapper with name " . $key . " is already set."); + + $this->mapped[$key] = $mapper; + } + + public function getMapper ($key) + { + if (isset ($this->mapped[$key])) { + return $this->mapped[$key]; + } else { + throw new DataNotSet ("Mapper " . $key . " was not registered."); + } + } + + /** + * @return \Neuron\Interfaces\Mappers\UserMapper + */ + public static function getUserMapper () + { + return self::getInstance ()->getMapper ('user'); + } + +} \ No newline at end of file From d092c1c86aa452eee0e337d3717d53c76cddce69 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 26 Jan 2015 12:01:14 +0100 Subject: [PATCH 118/231] Allowing multiple user callbacks. --- src/Neuron/Net/Request.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 579c887..46287cc 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -437,7 +437,7 @@ public function addUserCallback ($name, callable $callback) * @param string $callbackName To force a specific callback * @return \Neuron\Interfaces\Models\User */ - public function getUser ($callbackName) + public function getUser ($callbackName = null) { if (!isset ($this->user) && !$this->usercallbackcalled) { From 9bd055ddf009ebce6d9a67c6729063f01fec2063 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 26 Jan 2015 12:06:41 +0100 Subject: [PATCH 119/231] Allowing multiple user callbacks. --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 8a299b9..5dd56df 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,7 @@ ], "require" : { + "php": ">=5.5.0", "ext-gettext" : "*" }, From 4757455c7bfb51f9598a8db0bae5755eaaa704d7 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 11 Feb 2015 16:45:46 +0100 Subject: [PATCH 120/231] Allowing a direct "get array input" --- src/Neuron/Application.php | 8 ++++++++ src/Neuron/Net/Request.php | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index ed34550..ce1452c 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -29,6 +29,9 @@ class Application /** @var SessionHandler $sessionHandler */ private $sessionHandler; + /** @var bool */ + private $isFirstDispatch = true; + private static $in; /** @@ -133,6 +136,11 @@ private function getSessionHandler () */ public function dispatch (Request $request = null) { + if ($this->isFirstDispatch) { + $this->isFirstDispatch = false; + $this->trigger ('dispatch:first'); + } + // Trigger initialize $this->trigger ('dispatch:initialize'); diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 46287cc..0d6326c 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -366,10 +366,18 @@ public function isOptions () * @param $field * @param string $type * @param mixed $default + * @param string $separator * @return mixed|null */ - public function input ($field, $type = 'string', $default = null) + public function input ($field, $type = 'string', $default = null, $separator = ',') { + // Check for array type + $array = false; + if (substr ($type, -2) === '[]') { + $type = substr ($type, 0, -2); + $array = true; + } + // Check post $value = Tools::getInput ($this->getPost (), $field, $type); if ($value === null) @@ -382,6 +390,12 @@ public function input ($field, $type = 'string', $default = null) { return $default; } + + // Check if array? + if ($array) { + $value = explode ($separator, $value); + } + return $value; } From 2699270149333e1beca3e46a81fd1bf721dc9d61 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 12 Feb 2015 17:39:54 +0100 Subject: [PATCH 121/231] Allowing a direct "get array input" --- src/Neuron/Collections/Collection.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index daa4553..cfe197e 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -192,4 +192,9 @@ public function peek() } return null; } + + public function reverse () + { + $this->data = array_reverse ($this->data); + } } \ No newline at end of file From 42865b16755893a4abb6b4969aa2458a92f88f97 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 12 Feb 2015 18:32:36 +0100 Subject: [PATCH 122/231] Adding base64 datatype. --- src/Neuron/Core/Tools.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index 7ea7e54..edafeb7 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -36,6 +36,10 @@ public static function getInput ($dat, $key, $type, $default = null) return mktime (0, 0, 1, $time[1], $time[2], $time[0]); break; + case 'base64': + return base64_decode ($dat[$key]); + break; + default: return $dat[$key]; break; @@ -98,6 +102,10 @@ public static function checkInput ($value, $type) return self::isValidUTF8 ($value) && strlen ($value) == 32; } + elseif ($type == 'base64') { + return self::isValidBase64 ($value); + } + elseif ($type == 'url') { $regex = '/((https?:\/\/|[w]{3})?[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?)/i'; @@ -150,6 +158,11 @@ public static function isValidUTF8 ($str) return (bool) preg_match('//u', $str); } + public static function isValidBase64 ($str) + { + return base64_encode(base64_decode($str, true)) === $str; + } + public static function putIntoText ($text, $ar = array(), $delimiter = '@@') { foreach ($ar as $k => $v) From 079a919b8cbec41151644778ff09bcc6023e1362 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 13 Feb 2015 16:46:07 +0100 Subject: [PATCH 123/231] Adding a "with" function in the router that allows you to add parameters to controller calls. --- src/Neuron/Models/Router/Route.php | 21 +++++++++++++++++++++ src/Neuron/Router.php | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/src/Neuron/Models/Router/Route.php b/src/Neuron/Models/Router/Route.php index eeda983..20de719 100644 --- a/src/Neuron/Models/Router/Route.php +++ b/src/Neuron/Models/Router/Route.php @@ -25,6 +25,9 @@ class Route { /** @var string[] */ private $filters = array (); + /** @var mixed[] */ + private $extraParameters = array (); + public function __construct ($path) { $this->setRoute ($path); @@ -100,6 +103,24 @@ public function filter ($filtername) return $this; } + /** + * @return \mixed[] + */ + public function getParameters () + { + return $this->extraParameters; + } + + /** + * Add additional parameters that will be added to the controller call. + * @return $this + */ + public function with () { + + $this->extraParameters = func_get_args (); + return $this; + } + /** * @return Filter[] */ diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index b2616ae..4e105f2 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -306,6 +306,11 @@ private function handleMatch (Route $route, $params) { $function = $route->getFunction (); + // Check for additional parameters + foreach ($route->getParameters () as $v) { + $params[] = $v; + } + // First handle the filters foreach ($route->getFilters () as $filter) { From 3b83fac2125f2968e4a775b1ff609a6ef87f41fe Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 20 Feb 2015 15:06:49 +0100 Subject: [PATCH 124/231] Adding setERrors to Errorable. --- src/Neuron/Models/Helpers/Errorable.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Neuron/Models/Helpers/Errorable.php b/src/Neuron/Models/Helpers/Errorable.php index 94ac44b..64b38d5 100644 --- a/src/Neuron/Models/Helpers/Errorable.php +++ b/src/Neuron/Models/Helpers/Errorable.php @@ -31,6 +31,14 @@ public function setError ($error) $this->addError ($error); } + /** + * Set the error array. By reference! + * @param array $errors + */ + public function setErrors (array &$errors){ + $this->errors = $errors; + } + /** * @return string|null */ From 7f55abbd528d0c3de076ac837bf3a564b5aa4af3 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 20 Feb 2015 15:12:17 +0100 Subject: [PATCH 125/231] Turning errors into a collection. --- src/Neuron/Collections/ErrorCollection.php | 15 +++++++++++++++ src/Neuron/Models/Helpers/Errorable.php | 16 +++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 src/Neuron/Collections/ErrorCollection.php diff --git a/src/Neuron/Collections/ErrorCollection.php b/src/Neuron/Collections/ErrorCollection.php new file mode 100644 index 0000000..c77eacf --- /dev/null +++ b/src/Neuron/Collections/ErrorCollection.php @@ -0,0 +1,15 @@ +error)) { + $this->setErrors (new ErrorCollection ()); + } + } /** * @param string $error @@ -33,9 +41,8 @@ public function setError ($error) /** * Set the error array. By reference! - * @param array $errors */ - public function setErrors (array &$errors){ + public function setErrors (ErrorCollection $errors){ $this->errors = $errors; } @@ -44,6 +51,7 @@ public function setErrors (array &$errors){ */ public function getError () { + $this->touchErrors (); if (count ($this->errors) > 0) { return end ($this->errors); @@ -56,6 +64,7 @@ public function getError () */ public function addError ($error) { + $this->touchErrors (); $this->errors[] = $error; } @@ -64,6 +73,7 @@ public function addError ($error) */ public function getErrors () { + $this->touchErrors (); return $this->errors; } From 7a399e4d1e05f4e4c5994103902d84250d008542 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 20 Feb 2015 16:04:59 +0100 Subject: [PATCH 126/231] Turning errors into a collection. --- src/Neuron/Models/Helpers/Errorable.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Models/Helpers/Errorable.php b/src/Neuron/Models/Helpers/Errorable.php index 572397c..94d7f97 100644 --- a/src/Neuron/Models/Helpers/Errorable.php +++ b/src/Neuron/Models/Helpers/Errorable.php @@ -26,7 +26,7 @@ abstract class Errorable private function touchErrors () { - if (!isset ($this->error)) { + if (!isset ($this->errors)) { $this->setErrors (new ErrorCollection ()); } } @@ -69,7 +69,7 @@ public function addError ($error) } /** - * @return string[] + * @return ErrorCollection */ public function getErrors () { From 07a69a66d6d6de5e822c7af37fa8a3f6ba5b6872 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 20 Feb 2015 16:30:27 +0100 Subject: [PATCH 127/231] Turning errors into a collection. --- src/Neuron/Collections/ErrorCollection.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Neuron/Collections/ErrorCollection.php b/src/Neuron/Collections/ErrorCollection.php index c77eacf..bb19fdd 100644 --- a/src/Neuron/Collections/ErrorCollection.php +++ b/src/Neuron/Collections/ErrorCollection.php @@ -12,4 +12,14 @@ class ErrorCollection extends Collection { + public function getData () + { + $out = array (); + + foreach ($this as $v) + $out[] = (string) $v; + + return $out; + } + } \ No newline at end of file From 41ec1dbaa61e9f4deb292381a09dc5b55e1b15af Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 20 Feb 2015 16:35:26 +0100 Subject: [PATCH 128/231] Adding sprintf functionality to Errorable. --- src/Neuron/Models/Helpers/Errorable.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Models/Helpers/Errorable.php b/src/Neuron/Models/Helpers/Errorable.php index 94d7f97..f71d7f7 100644 --- a/src/Neuron/Models/Helpers/Errorable.php +++ b/src/Neuron/Models/Helpers/Errorable.php @@ -64,8 +64,11 @@ public function getError () */ public function addError ($error) { + $args = func_get_args (); + array_shift ($args); + $this->touchErrors (); - $this->errors[] = $error; + $this->errors[] = sprintf ($error, $args); } /** From 44c3da1f7b2536558d1dad1fccc9d6a4e7d06dce Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 20 Feb 2015 16:39:54 +0100 Subject: [PATCH 129/231] Adding sprintf functionality to Errorable. --- src/Neuron/Models/Helpers/Errorable.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Models/Helpers/Errorable.php b/src/Neuron/Models/Helpers/Errorable.php index f71d7f7..c59e318 100644 --- a/src/Neuron/Models/Helpers/Errorable.php +++ b/src/Neuron/Models/Helpers/Errorable.php @@ -36,7 +36,7 @@ private function touchErrors () */ public function setError ($error) { - $this->addError ($error); + call_user_func_array (array ($this, 'addError'), func_get_args ()); } /** @@ -68,7 +68,7 @@ public function addError ($error) array_shift ($args); $this->touchErrors (); - $this->errors[] = sprintf ($error, $args); + $this->errors[] = vsprintf ($error, $args); } /** From c7eb37fd22129bc317adc94cbf1a62ea801a24f2 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 24 Feb 2015 18:07:39 +0100 Subject: [PATCH 130/231] He fixed the array input checker, what happened next will amaze you. --- src/Neuron/Net/Request.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 0d6326c..8a6e961 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -374,7 +374,8 @@ public function input ($field, $type = 'string', $default = null, $separator = ' // Check for array type $array = false; if (substr ($type, -2) === '[]') { - $type = substr ($type, 0, -2); + $arrtype = substr ($type, 0, -2); + $type = 'string'; $array = true; } @@ -393,7 +394,14 @@ public function input ($field, $type = 'string', $default = null, $separator = ' // Check if array? if ($array) { - $value = explode ($separator, $value); + $values = explode ($separator, $value); + + $value = array (); + foreach ($values as $v) { + if (Tools::checkInput ($v, $arrtype)) { + $value[] = $v; + } + } } return $value; From e1c245540517270cdf851c0b291b90943a6bed30 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 25 Feb 2015 12:53:39 +0100 Subject: [PATCH 131/231] Adding "remove" method to collections. --- src/Neuron/Collections/Collection.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index cfe197e..10cd94c 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -197,4 +197,30 @@ public function reverse () { $this->data = array_reverse ($this->data); } + + private function isAssociative () { + return array_values ($this->data) === $this->data; + } + + /** + * Remove an element from the collection. + * @param $entry + * @return bool + */ + public function remove ($entry) { + foreach ($this->data as $k => $v) { + if ($v === $entry) { + $associative = $this->isAssociative (); + + unset ($this->data[$k]); + if ($associative) { + $this->data = array_values ($this->data); + } + + return true; + + } + } + return false; + } } \ No newline at end of file From 9dce2dd3a23736299aae60be77fd927db7e19685 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 8 Apr 2015 15:00:15 +0200 Subject: [PATCH 132/231] Adding interface for guest users. --- src/Neuron/Interfaces/Models/Guest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/Neuron/Interfaces/Models/Guest.php diff --git a/src/Neuron/Interfaces/Models/Guest.php b/src/Neuron/Interfaces/Models/Guest.php new file mode 100644 index 0000000..a4a767e --- /dev/null +++ b/src/Neuron/Interfaces/Models/Guest.php @@ -0,0 +1,15 @@ + Date: Sat, 25 Apr 2015 14:03:38 +0200 Subject: [PATCH 133/231] Adding a getIds method to ModelCollection. --- src/Neuron/Collections/ModelCollection.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Neuron/Collections/ModelCollection.php b/src/Neuron/Collections/ModelCollection.php index fa69041..898969f 100644 --- a/src/Neuron/Collections/ModelCollection.php +++ b/src/Neuron/Collections/ModelCollection.php @@ -37,6 +37,14 @@ protected function onUnset (Model $model = null, $offset = null) unset ($this->map[$model->getId ()]); } + /** + * Return all ids. + * @return array + */ + public function getIds () { + return array_keys ($this->map); + } + public function getFromId ($id) { if (isset ($this->map[$id])) From 07df0c726db6108e88af397f42b14d5358fc1056 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 25 Apr 2015 14:10:38 +0200 Subject: [PATCH 134/231] A few rudimentary array methods. --- src/Neuron/Collections/Collection.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 10cd94c..3a3e689 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -25,6 +25,18 @@ protected function setCollectionValues (array $data) $this->data = $data; } + public function push ($value) { + array_push ($this, $value); + } + + public function pop () { + array_pop ($this); + } + + public function shift ($value) { + array_shift ($this, $value); + } + /** * (PHP 5 >= 5.0.0)
* Whether a offset exists From 9f11448b748ae3d651c37a0932a8fce9448e314e Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 25 Apr 2015 14:14:38 +0200 Subject: [PATCH 135/231] A few rudimentary array methods. --- src/Neuron/Collections/Collection.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 3a3e689..60ab5be 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -25,16 +25,8 @@ protected function setCollectionValues (array $data) $this->data = $data; } - public function push ($value) { - array_push ($this, $value); - } - - public function pop () { - array_pop ($this); - } - - public function shift ($value) { - array_shift ($this, $value); + public function add ($value) { + $this[] = $value; } /** From 6b13fc4a56c3b80b68f2a87ba205dab4b222fbbe Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 25 Apr 2015 14:32:34 +0200 Subject: [PATCH 136/231] Adding SingleLoadMapper thing. --- src/Neuron/Mappers/SingleLoadMapper.php | 91 +++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/Neuron/Mappers/SingleLoadMapper.php diff --git a/src/Neuron/Mappers/SingleLoadMapper.php b/src/Neuron/Mappers/SingleLoadMapper.php new file mode 100644 index 0000000..5a8cd59 --- /dev/null +++ b/src/Neuron/Mappers/SingleLoadMapper.php @@ -0,0 +1,91 @@ +models[$id]); + } + + /** + * Return model. + * @param $id + * @return Model|null + */ + protected function getModel ($id) { + return isset ($this->models[$id]) ? $this->models[$id] : null; + } + + /** + * @param $name + * @return bool + */ + protected function hasCollection ($name) { + return isset ($this->collections[$name]); + } + + /** + * @param $name + * @return null + */ + protected function getCollection ($name) { + return isset ($this->collections[$name]) ? $this->collections[$name] : null; + } + + protected function cache ($value, $name = null) { + if ($value instanceof Collection) { + + if (!isset ($name)) { + throw new InvalidParameter ("When caching a collection, you must provide a unique name."); + } + + // Set the collection. + $this->collections[$name] = $value; + + foreach ($value as $v) { + $this->cache ($v); + } + } + + else if ($value instanceof Model) { + $this->models[$value->getId ()] = $value; + } + + else if ($value === null) { + + if (!isset ($name)) { + throw new InvalidParameter ("When caching a null vlaue, you must provide a unique id."); + } + + $this->models[$name] = $value; + } + + else { + throw new InvalidParameter ("You must always cache collections or models."); + } + } + +} \ No newline at end of file From e5ace47ac1ad5b69b5d95bb739941e505b765458 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 25 Apr 2015 14:34:34 +0200 Subject: [PATCH 137/231] Adding SingleLoadMapper thing. --- src/Neuron/Mappers/SingleLoadMapper.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Neuron/Mappers/SingleLoadMapper.php b/src/Neuron/Mappers/SingleLoadMapper.php index 5a8cd59..b710783 100644 --- a/src/Neuron/Mappers/SingleLoadMapper.php +++ b/src/Neuron/Mappers/SingleLoadMapper.php @@ -6,13 +6,11 @@ * Time: 14:19 */ -namespace QuizWitz\Mappers; - +namespace Neuron\Mappers; use Neuron\Collections\Collection; use Neuron\Exceptions\InvalidParameter; use Neuron\Interfaces\Model; -use Neuron\Mappers\BaseMapper; abstract class SingleLoadMapper extends BaseMapper { From d4ffa132a14644e32b9225e1bf3f75aa25ece69f Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 25 Apr 2015 14:38:26 +0200 Subject: [PATCH 138/231] Renaming SingleLoadMapper to CachedMapper. --- src/Neuron/Mappers/{SingleLoadMapper.php => CachedMapper.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/Neuron/Mappers/{SingleLoadMapper.php => CachedMapper.php} (98%) diff --git a/src/Neuron/Mappers/SingleLoadMapper.php b/src/Neuron/Mappers/CachedMapper.php similarity index 98% rename from src/Neuron/Mappers/SingleLoadMapper.php rename to src/Neuron/Mappers/CachedMapper.php index b710783..8c774d9 100644 --- a/src/Neuron/Mappers/SingleLoadMapper.php +++ b/src/Neuron/Mappers/CachedMapper.php @@ -12,7 +12,7 @@ use Neuron\Exceptions\InvalidParameter; use Neuron\Interfaces\Model; -abstract class SingleLoadMapper +abstract class CachedMapper extends BaseMapper { private $models = array (); From af51f6d20d2992853cd793a431420318ec0f1c4f Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 27 Apr 2015 11:05:39 +0200 Subject: [PATCH 139/231] The default mapper now returns a collection by default. --- src/Neuron/Collections/Collection.php | 2 +- src/Neuron/Mappers/BaseMapper.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 60ab5be..866755c 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -13,7 +13,7 @@ use Iterator; use Neuron\Models\Observable; -abstract class Collection +class Collection extends Observable implements Iterator, ArrayAccess, Countable { diff --git a/src/Neuron/Mappers/BaseMapper.php b/src/Neuron/Mappers/BaseMapper.php index 4f29109..18506ce 100644 --- a/src/Neuron/Mappers/BaseMapper.php +++ b/src/Neuron/Mappers/BaseMapper.php @@ -9,6 +9,7 @@ namespace Neuron\Mappers; +use Neuron\Collections\Collection; use Neuron\Config; abstract class BaseMapper { @@ -37,11 +38,12 @@ protected function getSingle ($data) /** * Override this to set an alternative object collection. - * @return array + * @return Collection */ protected function getObjectCollection () { - return array (); + //return array (); + return new Collection (); } /** From f3d746d1ddbcc4462228281b483578f8f3b17dfc Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 27 Apr 2015 13:15:56 +0200 Subject: [PATCH 140/231] Using http_build_query in the http client. The http client seems very incomplete... --- src/Neuron/Net/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Net/Client.php b/src/Neuron/Net/Client.php index b367c32..26105c1 100644 --- a/src/Neuron/Net/Client.php +++ b/src/Neuron/Net/Client.php @@ -54,7 +54,7 @@ private function api (Request $request, $method) $post = $request->getBody (); - curl_setopt($ch, CURLOPT_URL, $request->getUrl () . '?' . $request->getParameters ()); + curl_setopt($ch, CURLOPT_URL, $request->getUrl () . '?' . http_build_query ($request->getParameters ())); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $headers = array (); From 7deae84cbc4c60c80dd9af72b148e95535742d5a Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 27 Apr 2015 13:31:45 +0200 Subject: [PATCH 141/231] Using http_build_query in the http client. The http client seems very incomplete... --- src/Neuron/Net/Client.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Net/Client.php b/src/Neuron/Net/Client.php index 26105c1..4fa45d0 100644 --- a/src/Neuron/Net/Client.php +++ b/src/Neuron/Net/Client.php @@ -54,7 +54,9 @@ private function api (Request $request, $method) $post = $request->getBody (); - curl_setopt($ch, CURLOPT_URL, $request->getUrl () . '?' . http_build_query ($request->getParameters ())); + $parsedUrl = $request->getUrl () . '?' . http_build_query ($request->getParameters ()); + + curl_setopt($ch, CURLOPT_URL, $parsedUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $headers = array (); From 26f6ed4762f383293c0ea27d25c9946d0e4541da Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 27 Apr 2015 14:46:13 +0200 Subject: [PATCH 142/231] Fixing the curl get requests in clients. --- src/Neuron/Net/Client.php | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Neuron/Net/Client.php b/src/Neuron/Net/Client.php index 4fa45d0..66f74dd 100644 --- a/src/Neuron/Net/Client.php +++ b/src/Neuron/Net/Client.php @@ -59,29 +59,33 @@ private function api (Request $request, $method) curl_setopt($ch, CURLOPT_URL, $parsedUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - $headers = array (); - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + if ($request->getHeaders ()) { + $headers = $request->getHeaders (); + curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers); + } switch ($method) { case 'GET': - break; + break; case 'POST': curl_setopt($ch, CURLOPT_POST, 1); - break; + curl_setopt($ch, CURLOPT_POSTFIELDS, $post); + break; case 'DELETE': throw new NotImplemented ("Not implemented."); - break; + break; case 'PUT': curl_setopt($ch, CURLOPT_PUT, 1); - break; - } - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $post); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $post); + break; + + } $output = curl_exec($ch); From d2abf74e53c88aabe3e47f8dbca6643377794fcb Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 27 Apr 2015 15:04:29 +0200 Subject: [PATCH 143/231] Some more tweaking on the http client. --- src/Neuron/Net/Client.php | 53 +++++++++++++++++++++++++++++++++++-- src/Neuron/Net/Entity.php | 32 +++++++++++++++++++--- src/Neuron/Net/Request.php | 21 +-------------- src/Neuron/Net/Response.php | 11 ++++++++ 4 files changed, 91 insertions(+), 26 deletions(-) diff --git a/src/Neuron/Net/Client.php b/src/Neuron/Net/Client.php index 66f74dd..5cdcd25 100644 --- a/src/Neuron/Net/Client.php +++ b/src/Neuron/Net/Client.php @@ -23,6 +23,45 @@ public static function getInstance () return $in; } + public static function http_parse_headers ($raw_headers) { + $headers = array(); + $key = ''; // [+] + + foreach(explode("\n", $raw_headers) as $i => $h) + { + $h = explode(':', $h, 2); + + if (isset($h[1])) + { + if (!isset($headers[$h[0]])) + $headers[$h[0]] = trim($h[1]); + elseif (is_array($headers[$h[0]])) + { + // $tmp = array_merge($headers[$h[0]], array(trim($h[1]))); // [-] + // $headers[$h[0]] = $tmp; // [-] + $headers[$h[0]] = array_merge($headers[$h[0]], array(trim($h[1]))); // [+] + } + else + { + // $tmp = array_merge(array($headers[$h[0]]), array(trim($h[1]))); // [-] + // $headers[$h[0]] = $tmp; // [-] + $headers[$h[0]] = array_merge(array($headers[$h[0]]), array(trim($h[1]))); // [+] + } + + $key = $h[0]; // [+] + } + else // [+] + { // [+] + if (substr($h[0], 0, 1) == "\t") // [+] + $headers[$key] .= "\r\n\t".trim($h[0]); // [+] + elseif (!$key) // [+] + $headers[0] = trim($h[0]);trim($h[0]); // [+] + } // [+] + } + + return $headers; + } + private function __construct () { @@ -58,6 +97,7 @@ private function api (Request $request, $method) curl_setopt($ch, CURLOPT_URL, $parsedUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 1); if ($request->getHeaders ()) { $headers = $request->getHeaders (); @@ -70,6 +110,8 @@ private function api (Request $request, $method) break; case 'POST': + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); break; @@ -90,8 +132,15 @@ private function api (Request $request, $method) $output = curl_exec($ch); // Response - $response = new Response (); - $response->setBody ($output); + + + $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); + $header = substr($output, 0, $header_size); + $body = substr($output, $header_size); + + $response = Response::fromRaw ($body, self::http_parse_headers ($header)); + curl_close ($ch); + return $response; } diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index e72b43c..ff771dc 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -30,7 +30,7 @@ abstract class Entity { /** @var string $error */ private $error; - + /** @var integer $status */ private $status; @@ -52,7 +52,7 @@ public function setFromData ($data) { // Check signature $model = $this; - + $chk = self::CHECK_SIGNATURE; if ($chk && !isset ($data['signature'])) @@ -90,7 +90,7 @@ public function setFromData ($data) { $model->setPost ($data['post']); } - + if (isset ($data['status'])) { $model->setStatus ($data['status']); @@ -99,6 +99,30 @@ public function setFromData ($data) return $model; } + protected function parseData () { + + $headers = $this->getHeaders (); + if (isset ($headers['Content-Type'])) + { + switch (strtolower ($headers['Content-Type'])) + { + case 'application/json': + case 'text/json': + + $data = json_decode ($this->getBody (), true); + + if (!$data) { + $this->setError ('JSON decode error: ' . json_last_error_msg ()); + } + else { + $this->setData ($data); + } + + break; + } + } + } + /** * @return array */ @@ -114,7 +138,7 @@ public function getJSONData () $data['data'] = $this->getData (); } } - + $data['body'] = $this->getBody (); $data['headers'] = $this->getHeaders (); diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 8a6e961..5746e33 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -58,26 +58,7 @@ public static function fromInput () $model->setStatus (http_response_code ()); $model->setUrl (self::getCurrentUri ()); - $headers = $model->getHeaders (); - if (isset ($headers['Content-Type'])) - { - switch (strtolower ($headers['Content-Type'])) - { - case 'application/json': - case 'text/json': - - $data = json_decode ($model->getBody (), true); - - if (!$data) { - $model->setError ('JSON decode error: ' . json_last_error_msg ()); - } - else { - $model->setData ($data); - } - - break; - } - } + $model->parseData (); return $model; } diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 82504b6..8de68f1 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -57,6 +57,17 @@ public static function fromJSON ($json) return $model; } + public static function fromRaw ($body, $headers) { + + $out = new self (); + $out->setBody ($body); + $out->setHeaders ($headers); + $out->parseData (); + + return $out; + + } + /** * Show the data in a html table. * @param $data From 03f3d46e98acc5ca870585e779a8c41b29c6555d Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 27 Apr 2015 19:02:22 +0200 Subject: [PATCH 144/231] Adding getAbsoluteURL method to the urlbuilder. --- example/public/urlbuilder.php | 5 +++++ src/Neuron/URLBuilder.php | 34 +++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 example/public/urlbuilder.php diff --git a/example/public/urlbuilder.php b/example/public/urlbuilder.php new file mode 100644 index 0000000..48b2a03 --- /dev/null +++ b/example/public/urlbuilder.php @@ -0,0 +1,5 @@ + 'bar')); \ No newline at end of file diff --git a/src/Neuron/URLBuilder.php b/src/Neuron/URLBuilder.php index 5b58ad9..eb57dff 100644 --- a/src/Neuron/URLBuilder.php +++ b/src/Neuron/URLBuilder.php @@ -11,8 +11,11 @@ class URLBuilder { - public static function getURL ($module = '', $data = array (), $normalize = true) + public static function getURL ($module = '', $data = array (), $normalize = true, $appurl = null) { + if (!isset ($appurl)) + $appurl = Config::get ('app.url', '/'); + if (substr ($module, 0, 1) === '/') { $module = substr ($module, 1); @@ -28,9 +31,9 @@ public static function getURL ($module = '', $data = array (), $normalize = true if (!empty ($params)) { if ($normalize) - $url = self::normalize (Config::get ('app.url', '/') . $module) . '?' . $params; + $url = self::normalize ($appurl . $module) . '?' . $params; else - $url = Config::get ('app.url', '/') . $module . '?' . $params; + $url = $appurl . $module . '?' . $params; return $url; } @@ -38,10 +41,31 @@ public static function getURL ($module = '', $data = array (), $normalize = true { // Google likes these. if ($normalize) - return self::normalize (Config::get ('app.url', '/') . $module); + return self::normalize ($appurl . $module); else - return Config::get ('app.url', '/') . $module; + return $appurl . $module; + } + } + + public static function getAbsoluteURL ($module = '', $data = array ()) { + + if (self::isAbsolute (Config::get ('app.url'))) { + return self::getURL ($module, $data, true); + } + else { + return self::getURL ($module, $data, true, self::guessAbsoluteURL ()); + } + } + + private static function guessAbsoluteURL () { + return $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . '/'; + } + + private static function isAbsolute ($url) { + if (substr (strtolower ($url), 0, 4) == 'http') { + return true; } + return false; } /** From e18a40c4ae070dd11e888168b17449a5d8b7d2cc Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 29 Apr 2015 18:49:05 +0200 Subject: [PATCH 145/231] Adding Carbon support in query builder. --- composer.json | 5 +- src/Neuron/DB/Query.php | 178 ++++++++++++++++------------------------ 2 files changed, 75 insertions(+), 108 deletions(-) diff --git a/composer.json b/composer.json index 5dd56df..8e432c1 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "require" : { "php": ">=5.5.0", - "ext-gettext" : "*" + "ext-gettext" : "*", + "nesbot/carbon": "~1.18" }, "autoload": { @@ -24,4 +25,4 @@ "Neuron\\" : "src/Neuron/" } } -} \ No newline at end of file +} diff --git a/src/Neuron/DB/Query.php b/src/Neuron/DB/Query.php index 4d6832c..48fc0a6 100644 --- a/src/Neuron/DB/Query.php +++ b/src/Neuron/DB/Query.php @@ -7,6 +7,7 @@ namespace Neuron\DB; +use Carbon\Carbon; use Neuron\Exceptions\InvalidParameter; use Neuron\Models\Geo\Point; @@ -295,8 +296,6 @@ public function bindValue ($index, $value, $type = self::PARAM_STR, $canBeNull = public function getParsedQuery () { - $db = Database::getInstance (); - $keys = array (); $values = array (); @@ -306,12 +305,15 @@ public function getParsedQuery () if (!isset ($v[1])) { // Check for known "special types" - if ($v[0] instanceof Point) - { + if ($v[0] instanceof Point) { $v[1] = self::PARAM_POINT; } - else - { + + else if ($v[0] instanceof Carbon) { + $v[1] = self::PARAM_DATE; + } + + else { $v[1] = self::PARAM_STR; } } @@ -323,115 +325,20 @@ public function getParsedQuery () } // Empty and should set NULL? - if ($v[2] && empty ($v[0])) - { + if ($v[2] && empty ($v[0])) { $value = "NULL"; } - else - { - // Array? - if (is_array ($v[0])) - { - switch ($v[1]) - { - case self::PARAM_NUMBER: - foreach ($v[0] as $kk => $vv) - { - if (!is_numeric ($vv)) - { - throw new InvalidParameter ("Parameter " . $k . "[" . $kk . "] should be numeric in query " . $this->query); - } - } - $value = '(' . implode (',', $v[0]) . ')'; - break; - - case self::PARAM_DATE: - - $tmp = array (); - foreach ($v[0] as $kk => $vv) - { - if (!is_numeric ($vv)) - { - throw new InvalidParameter ("Parameter " . $k . "[" . $kk . "] should be a valid timestamp in query " . $this->query); - } - $tmp[] = "FROM_UNIXTIME(" . $vv . ")"; - } - $value = '(' . implode (',', $tmp) . ')'; - - break; - - case self::PARAM_POINT: - $tmp = array (); - foreach ($v[0] as $kk => $vv) - { - if (! ($vv instanceof Point)) - { - throw new InvalidParameter ("Parameter " . $k . "[" . $kk . "] should be a valid \\Neuron\\Models\\Point " . $this->query); - } - $tmp[] = "POINT(" . $vv->getLongtitude() . "," . $vv->getLatitude() .")"; - } - $value = '(' . implode (',', $tmp) . ')'; - break; - - case self::PARAM_STR: - default: - $tmp = array (); - foreach ($v[0] as $kk => $vv) - { - $tmp[] = "'" . $db->escape (strval ($vv)) . "'"; - } - $value = '(' . implode (',', $tmp) . ')'; - break; - } - } - else - { - switch ($v[1]) - { - case self::PARAM_NUMBER: - if (!is_numeric ($v[0])) - { - throw new InvalidParameter ("Parameter " . $k . " should be numeric in query " . $this->query); - } - $value = $v[0]; - break; - - case self::PARAM_DATE: - if (!is_numeric ($v[0])) - { - throw new InvalidParameter ("Parameter " . $k . " should be a valid timestamp in query " . $this->query); - } - $value = "FROM_UNIXTIME(" . $v[0] . ")"; - break; - - case self::PARAM_POINT: - if (! ($v[0] instanceof Point)) - { - throw new InvalidParameter ("Parameter " . $k . " should be a valid \\Neuron\\Models\\Point " . $this->query); - } - else - { - $value = "POINT(" . $v[0]->getLongtitude() . "," . $v[0]->getLatitude() .")"; - } - break; - - case self::PARAM_STR: - default: - $value = "'" . $db->escape (strval ($v[0])) . "'"; - break; - } - } + else { + $value = $this->getValues ($k, $v); } $values[$k] = $value; // Replace question marks or tokens? - if (is_string ($k)) - { + if (is_string ($k)) { $keys[] = '/:'.$k.'/'; } - else - { + else { $keys[] = '/[?]/'; } } @@ -455,6 +362,65 @@ public function getParsedQuery () return $query; } + private function getValue ($value, $type, $parameterName) { + $db = Database::getInstance (); + + switch ($type) + { + case self::PARAM_NUMBER: + if (!is_numeric ($value)) { + throw new InvalidParameter ("Parameter " . $parameterName . " should be numeric in query " . $this->query); + } + return $value; + break; + + case self::PARAM_DATE: + + if ($value instanceof Carbon) { + return "'" . $value->toDateTimeString () . "'"; + } + + else if (is_numeric ($value)) { + return "FROM_UNIXTIME(" . $value . ")"; + } + else { + throw new InvalidParameter ("Parameter " . $parameterName . " should be a valid timestamp in query " . $this->query); + } + + break; + + case self::PARAM_POINT: + if (! ($value instanceof Point)) + { + throw new InvalidParameter ("Parameter " . $parameterName . " should be a valid \\Neuron\\Models\\Point " . $this->query); + } + return $value = "POINT(" . $value->getLongtitude() . "," . $value->getLatitude() .")"; + break; + + case self::PARAM_STR: + default: + $value = "'" . $db->escape (strval ($value)) . "'"; + return $value; + break; + } + } + + private function getValues ($k, $v) { + + if (is_array ($v[0])) { + $tmp = array (); + + foreach ($v[0] as $kk => $vv) { + $tmp[] = $this->getValue ($vv, $v[1], $k . '[' . $kk . ']'); + } + + return '(' . implode (',', $tmp) . ')'; + } + else { + return $this->getValue ($v[0], $v[1], $k); + } + } + public function execute () { $db = Database::getInstance (); From a4486a9650404336d6a0684dd6ba5b234f4863b6 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 29 Apr 2015 18:59:13 +0200 Subject: [PATCH 146/231] Working with DateTime instead of Carbon. --- src/Neuron/DB/Query.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Neuron/DB/Query.php b/src/Neuron/DB/Query.php index 48fc0a6..2558b70 100644 --- a/src/Neuron/DB/Query.php +++ b/src/Neuron/DB/Query.php @@ -7,7 +7,7 @@ namespace Neuron\DB; -use Carbon\Carbon; +use DateTime; use Neuron\Exceptions\InvalidParameter; use Neuron\Models\Geo\Point; @@ -309,7 +309,7 @@ public function getParsedQuery () $v[1] = self::PARAM_POINT; } - else if ($v[0] instanceof Carbon) { + else if ($v[0] instanceof DateTime) { $v[1] = self::PARAM_DATE; } @@ -376,8 +376,8 @@ private function getValue ($value, $type, $parameterName) { case self::PARAM_DATE: - if ($value instanceof Carbon) { - return "'" . $value->toDateTimeString () . "'"; + if ($value instanceof DateTime) { + return "'" . $value->format ('Y-m-d H:i:s') . "'"; } else if (is_numeric ($value)) { From 33270f439565748d00c1378ee9a85a84a22b3bba Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 29 Apr 2015 20:06:08 +0200 Subject: [PATCH 147/231] Fixing the test framework. --- .gitignore | 1 + phpunit.xml | 15 ++++++ src/Neuron/Tests/SyntaxTest.php | 57 --------------------- {src/Neuron/Tests => tests}/DbQueryTest.php | 0 {src/Neuron/Tests => tests}/FilterTest.php | 0 {src/Neuron/Tests => tests}/ToolsTest.php | 0 tests/bootstrap.php | 9 ++++ 7 files changed, 25 insertions(+), 57 deletions(-) create mode 100644 phpunit.xml delete mode 100644 src/Neuron/Tests/SyntaxTest.php rename {src/Neuron/Tests => tests}/DbQueryTest.php (100%) rename {src/Neuron/Tests => tests}/FilterTest.php (100%) rename {src/Neuron/Tests => tests}/ToolsTest.php (100%) create mode 100644 tests/bootstrap.php diff --git a/.gitignore b/.gitignore index 4c36e38..cdb3d20 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/ vendor/ +composer.lock \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..7362ee9 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,15 @@ + + + + + + src/Neuron + + + + + + tests + + + diff --git a/src/Neuron/Tests/SyntaxTest.php b/src/Neuron/Tests/SyntaxTest.php deleted file mode 100644 index 3781c40..0000000 --- a/src/Neuron/Tests/SyntaxTest.php +++ /dev/null @@ -1,57 +0,0 @@ -scanDirectory ($directory . '/' . $v); - } - - elseif (is_file ($directory . '/' . $v)) - { - // Check the file - $result = $this->isValidPHP ($directory .'/' . $v); - - $this->assertTrue ($result); - if (!$result) - { - echo "Syntax error found in " . $directory . '/' . $v . "\n\n\n"; - } - } - } - } - - public function testCodeSyntax () - { - $this->scanDirectory (dirname (dirname (__FILE__))); - } -} \ No newline at end of file diff --git a/src/Neuron/Tests/DbQueryTest.php b/tests/DbQueryTest.php similarity index 100% rename from src/Neuron/Tests/DbQueryTest.php rename to tests/DbQueryTest.php diff --git a/src/Neuron/Tests/FilterTest.php b/tests/FilterTest.php similarity index 100% rename from src/Neuron/Tests/FilterTest.php rename to tests/FilterTest.php diff --git a/src/Neuron/Tests/ToolsTest.php b/tests/ToolsTest.php similarity index 100% rename from src/Neuron/Tests/ToolsTest.php rename to tests/ToolsTest.php diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..40d4e80 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,9 @@ + Date: Thu, 30 Apr 2015 10:34:51 +0200 Subject: [PATCH 148/231] Allowing templates to be used as strings. --- src/Neuron/Core/Template.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index e2dedd0..2eba9a7 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -422,4 +422,8 @@ private function ngettext ($message1, $message2 = null, $n = null) { return \Neuron\Tools\Text::getInstance ()->getText ($message1, $message2, $n); } + + public function __toString () { + return $this->parse (); + } } \ No newline at end of file From ce3033032ba1f0e01dab2058e56b3f968b5449e9 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 30 Apr 2015 12:19:09 +0200 Subject: [PATCH 149/231] Adding a "simplifiedToken" generator. --- src/Neuron/Tools/TokenGenerator.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Neuron/Tools/TokenGenerator.php b/src/Neuron/Tools/TokenGenerator.php index 1716616..cf8c12a 100644 --- a/src/Neuron/Tools/TokenGenerator.php +++ b/src/Neuron/Tools/TokenGenerator.php @@ -23,4 +23,16 @@ public static function getToken ($length) return $out; } + public static function getSimplifiedToken ($length) + { + $range = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + $out = ''; + for ($i = 0; $i < $length; $i ++) + { + $out .= substr ($range, mt_rand (0, strlen ($range)), 1); + } + return $out; + } + } \ No newline at end of file From f9a3e78bd3661777a15e995de1cf9df63ffce506 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 30 Apr 2015 12:33:01 +0200 Subject: [PATCH 150/231] Woops, fixing the token generator. --- src/Neuron/Tools/TokenGenerator.php | 4 ++-- tests/DbQueryTest.php | 1 + tests/TokenGeneratorTest.php | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/TokenGeneratorTest.php diff --git a/src/Neuron/Tools/TokenGenerator.php b/src/Neuron/Tools/TokenGenerator.php index cf8c12a..e1bc0ee 100644 --- a/src/Neuron/Tools/TokenGenerator.php +++ b/src/Neuron/Tools/TokenGenerator.php @@ -18,7 +18,7 @@ public static function getToken ($length) $out = ''; for ($i = 0; $i < $length; $i ++) { - $out .= substr ($range, mt_rand (0, strlen ($range)), 1); + $out .= substr ($range, mt_rand (0, strlen ($range) - 1), 1); } return $out; } @@ -30,7 +30,7 @@ public static function getSimplifiedToken ($length) $out = ''; for ($i = 0; $i < $length; $i ++) { - $out .= substr ($range, mt_rand (0, strlen ($range)), 1); + $out .= substr ($range, mt_rand (0, strlen ($range) - 1), 1); } return $out; } diff --git a/tests/DbQueryTest.php b/tests/DbQueryTest.php index 6f68c94..e95f723 100644 --- a/tests/DbQueryTest.php +++ b/tests/DbQueryTest.php @@ -12,6 +12,7 @@ class DbQueryTest { public function testQueryBuilder () { + // Regular query. $query = new Query ("SELECT * FROM `table` WHERE m_date = ? AND m_id = ? AND m_string = ?"); $query->bindValue (1, gmmktime (0, 0, 0, 9, 16, 2013), Query::PARAM_DATE); diff --git a/tests/TokenGeneratorTest.php b/tests/TokenGeneratorTest.php new file mode 100644 index 0000000..2f301e9 --- /dev/null +++ b/tests/TokenGeneratorTest.php @@ -0,0 +1,19 @@ +assertTrue (strlen ($token) === 50); + } + } +} \ No newline at end of file From 2c1b34c1cfd876e14fd3fc37e53124ed7d91600e Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 30 Apr 2015 15:12:12 +0200 Subject: [PATCH 151/231] Fixing the xml output response. --- src/Neuron/Net/Response.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 8de68f1..4c58f07 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -114,7 +114,7 @@ public static function xml ($data, $root = 'root', $version = '1.0', array $para { $in = new self (); $in->setData ($data); - $in->setOutput (new XML ()); + $in->setOutput (new XML ($root, $version, $parameters, $itemName)); return $in; } From 6367d95be25f7ebd36a94d18c88d62fbf5cddd94 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 13:51:38 +0200 Subject: [PATCH 152/231] Adding a proxy response type. --- src/Neuron/Net/Client.php | 4 ++++ src/Neuron/Net/Response.php | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/Neuron/Net/Client.php b/src/Neuron/Net/Client.php index 5cdcd25..4d422ce 100644 --- a/src/Neuron/Net/Client.php +++ b/src/Neuron/Net/Client.php @@ -87,6 +87,10 @@ public function delete (Request $request) return $this->api ($request, 'DELETE'); } + public function process (Request $request) { + return $this->api ($request, $request->getMethod ()); + } + private function api (Request $request, $method) { $ch = curl_init(); diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 4c58f07..4406f29 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -161,6 +161,24 @@ public static function template ($template, $data = array ()) return $in; } + /** + * Proxy a request. + * @param string|Request $request Url or Request object. + * @return Response + */ + public static function proxy ($request) { + + if (!$request instanceof Request) { + $url = $request; + + $request = new Request (); + $request->setUrl ($url); + $request->setMethod (Request::METHOD_GET); + } + + return Client::getInstance ()->process ($request); + } + private $output; /** From ed9723d66d802beee04febdeb5e5add602cce1b1 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 13:58:09 +0200 Subject: [PATCH 153/231] Adding a proxy response type. --- src/Neuron/Net/Client.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Net/Client.php b/src/Neuron/Net/Client.php index 4d422ce..82ed6b7 100644 --- a/src/Neuron/Net/Client.php +++ b/src/Neuron/Net/Client.php @@ -97,7 +97,19 @@ private function api (Request $request, $method) $post = $request->getBody (); - $parsedUrl = $request->getUrl () . '?' . http_build_query ($request->getParameters ()); + $parsedUrl = $request->getUrl (); + + if ($request->getParameters ()) { + + if (strpos ($parsedUrl, '?')) { + $parsedUrl .= '&'; + } + else { + $parsedUrl .= '?'; + } + + $parsedUrl .= http_build_query ($request->getParameters (); + }; curl_setopt($ch, CURLOPT_URL, $parsedUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); From 6e60db4bf3f7b39d36a4cb3ac39cca916dde913e Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 13:58:23 +0200 Subject: [PATCH 154/231] Adding a proxy response type. --- src/Neuron/Net/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Net/Client.php b/src/Neuron/Net/Client.php index 82ed6b7..f4601ff 100644 --- a/src/Neuron/Net/Client.php +++ b/src/Neuron/Net/Client.php @@ -108,7 +108,7 @@ private function api (Request $request, $method) $parsedUrl .= '?'; } - $parsedUrl .= http_build_query ($request->getParameters (); + $parsedUrl .= http_build_query ($request->getParameters ()); }; curl_setopt($ch, CURLOPT_URL, $parsedUrl); From 63828b1daf0c4f3c182b7afaaa0b4b4a91fa9ec4 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 14:39:16 +0200 Subject: [PATCH 155/231] Adding a proxy response type. --- src/Neuron/Net/Request.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 5746e33..d9cef43 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -170,6 +170,28 @@ public static function fromJSON ($json) return $model; } + public static function fromURL ($url) { + + $data = parse_url ($url); + + $parameters = array (); + + if (!empty ($data['query'])) + parse_str ($data['query'], $parameters); + + $request = new self (); + $request->setUrl ( + $data['scheme'] . '://' . + $data['host'] . (isset ($data['port']) ? ':' . $data['port'] : '') . + '/' . $data['path'] + ); + + $request->setParameters ($parameters); + + return $request; + + } + private $method = 'GET'; private $url; private $parameters; From fd564767d62ab17b09f581aef6a703a25b3f3d5b Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 14:49:06 +0200 Subject: [PATCH 156/231] Moving some code around. --- src/Neuron/Models/Router/Route.php | 4 ++++ src/Neuron/Net/Request.php | 34 ++++++++++++++++++++++++++++++ src/Neuron/Router.php | 26 +---------------------- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/Neuron/Models/Router/Route.php b/src/Neuron/Models/Router/Route.php index 20de719..351c790 100644 --- a/src/Neuron/Models/Router/Route.php +++ b/src/Neuron/Models/Router/Route.php @@ -30,6 +30,10 @@ class Route { public function __construct ($path) { + // Regex are too pro, bro! Give us some simple {param} and {param?} parameters. + $path = preg_replace ('/\/\{\w+\\?}/', '(/\w+)?', $path); + $path = preg_replace ('/\/\{\w+\}/', '(/\w+)', $path); + $this->setRoute ($path); } diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index d9cef43..fcb7a68 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -13,6 +13,7 @@ use Neuron\Core\Tools; use Neuron\Exceptions\InvalidParameter; use Neuron\Interfaces\Models\User; +use Neuron\Models\Router\Route; class Request extends Entity { @@ -488,4 +489,37 @@ public function getUser ($callbackName = null) return $this->user; } + + /** + * Evaluate a route and return the parameters. + * @param Route $route + * @return array|bool + */ + public function parseRoute (Route $route) { + + if (preg_match_all('#^' . $route->getRoute () . '$#', $this->getUrl (), $matches, PREG_OFFSET_CAPTURE)) { + + // Rework matches to only contain the matches, not the orig string + $matches = array_slice($matches, 1); + + // Extract the matched URL parameters (and only the parameters) + $params = array_map(function($match, $index) use ($matches) { + + // We have a following parameter: take the substring from the current param position until the next one's position (thank you PREG_OFFSET_CAPTURE) + if (isset($matches[$index+1]) && isset($matches[$index+1][0]) && is_array($matches[$index+1][0])) { + return trim(substr($match[0][0], 0, $matches[$index+1][0][1] - $match[0][1]), '/'); + } + + // We have no following paramete: return the whole lot + else { + return (isset($match[0][0]) ? trim($match[0][0], '/') : null); + } + + }, $matches, array_keys($matches)); + + return $params; + } + + return false; + } } \ No newline at end of file diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 4e105f2..168115a 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -62,10 +62,6 @@ class Router { */ public function match ($methods, $pattern, $fn) { - // Regex are too pro, bro! Give us some simple {param} and {param?} parameters. - $pattern = preg_replace ('/\/\{\w+\\?}/', '(/\w+)?', $pattern); - $pattern = preg_replace ('/\/\{\w+\}/', '(/\w+)', $pattern); - $pattern = $this->baseroute . '/' . trim($pattern, '/'); $pattern = $this->baseroute ? rtrim($pattern, '/') : $pattern; @@ -238,8 +234,6 @@ public function set404($fn) { private function handle ($routes) { // The current page URL - $uri = $this->request->getUrl (); - $numHandled = 0; // Loop all routes @@ -249,25 +243,7 @@ private function handle ($routes) { throw new InvalidParameter ("Route contains invalid models."); // we have a match! - if (preg_match_all('#^' . $route->getRoute () . '$#', $uri, $matches, PREG_OFFSET_CAPTURE)) { - - // Rework matches to only contain the matches, not the orig string - $matches = array_slice($matches, 1); - - // Extract the matched URL parameters (and only the parameters) - $params = array_map(function($match, $index) use ($matches) { - - // We have a following parameter: take the substring from the current param position until the next one's position (thank you PREG_OFFSET_CAPTURE) - if (isset($matches[$index+1]) && isset($matches[$index+1][0]) && is_array($matches[$index+1][0])) { - return trim(substr($match[0][0], 0, $matches[$index+1][0][1] - $match[0][1]), '/'); - } - - // We have no following paramete: return the whole lot - else { - return (isset($match[0][0]) ? trim($match[0][0], '/') : null); - } - - }, $matches, array_keys($matches)); + if ($params = $this->request->parseRoute ($route)) { // call the handling function with the URL parameters $this->handleMatch ($route, $params); From 51cb47b37392d1e9d01aefbab070512d9c05ed10 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 14:54:36 +0200 Subject: [PATCH 157/231] Moving some code around. --- src/Neuron/Net/Request.php | 7 ++++++- src/Neuron/Router.php | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index fcb7a68..0247240 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -517,7 +517,12 @@ public function parseRoute (Route $route) { }, $matches, array_keys($matches)); - return $params; + if (empty ($params)) { + return true; + } + else { + return $params; + } } return false; diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 168115a..c737b39 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -245,6 +245,10 @@ private function handle ($routes) { // we have a match! if ($params = $this->request->parseRoute ($route)) { + if (!is_array ($params)) { + $params = array (); + } + // call the handling function with the URL parameters $this->handleMatch ($route, $params); //call_user_func_array($route['fn'], $params); From ee71f48554996082a230ec883d31c90d5b756ef0 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 14:58:00 +0200 Subject: [PATCH 158/231] Moving some code around. --- src/Neuron/Net/Request.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 0247240..28587de 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -171,7 +171,13 @@ public static function fromJSON ($json) return $model; } - public static function fromURL ($url) { + /** + * Return a request based on a simple url. + * @param string $url + * @param string $stripHost + * @return Request + */ + public static function fromURL ($url, $stripHost) { $data = parse_url ($url); @@ -181,11 +187,18 @@ public static function fromURL ($url) { parse_str ($data['query'], $parameters); $request = new self (); - $request->setUrl ( - $data['scheme'] . '://' . - $data['host'] . (isset ($data['port']) ? ':' . $data['port'] : '') . - '/' . $data['path'] - ); + + if ($stripHost) { + $request->setUrl ($data['path']); + } + + else { + $request->setUrl ( + $data['scheme'] . '://' . + $data['host'] . (isset ($data['port']) ? ':' . $data['port'] : '') . + $data['path'] + ); + } $request->setParameters ($parameters); From eba3158daf6acf89b3e69cc6e59bc0ec2726d5c1 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 15:19:02 +0200 Subject: [PATCH 159/231] Adding cache manipulators in request. --- src/Neuron/Net/Request.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 28587de..52d43e6 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -9,6 +9,7 @@ namespace Neuron\Net; +use DateTime; use Exception; use Neuron\Core\Tools; use Neuron\Exceptions\InvalidParameter; @@ -540,4 +541,39 @@ public function parseRoute (Route $route) { return false; } + + public function setETag ($tag) { + $this->setHeader ('etag', $tag); + } + + public function setNoCache () { + $this->setHeader ('Cache-Control', 'private, max-age=0, no-cache'); + $this->setHeader ('Pragma', 'no-cache'); + + $date = time (); + $date -= (60 * 60 * 24 * 7); + + $this->setHeader ('Expires', date ('c', $date)); + } + + public function setCache ($maxAge = 86400, $privacy = 'public') { + + switch ($privacy) { + case 'public': + case 'private': + break; + + default: + $privacy = 'private'; + break; + } + + $this->setHeader ('Cache-Control', $privacy); + + $date = time (); + $date += $maxAge; + + $this->setHeader ('Expires', date ('c', $date)); + + } } \ No newline at end of file From 536640dc9bae29ead0250368c766fefa9827e2c9 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 15:19:53 +0200 Subject: [PATCH 160/231] Adding cache manipulators in request. --- src/Neuron/Net/Request.php | 35 ----------------------------------- src/Neuron/Net/Response.php | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 52d43e6..41aa38f 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -541,39 +541,4 @@ public function parseRoute (Route $route) { return false; } - - public function setETag ($tag) { - $this->setHeader ('etag', $tag); - } - - public function setNoCache () { - $this->setHeader ('Cache-Control', 'private, max-age=0, no-cache'); - $this->setHeader ('Pragma', 'no-cache'); - - $date = time (); - $date -= (60 * 60 * 24 * 7); - - $this->setHeader ('Expires', date ('c', $date)); - } - - public function setCache ($maxAge = 86400, $privacy = 'public') { - - switch ($privacy) { - case 'public': - case 'private': - break; - - default: - $privacy = 'private'; - break; - } - - $this->setHeader ('Cache-Control', $privacy); - - $date = time (); - $date += $maxAge; - - $this->setHeader ('Expires', date ('c', $date)); - - } } \ No newline at end of file diff --git a/src/Neuron/Net/Response.php b/src/Neuron/Net/Response.php index 4406f29..18f9709 100644 --- a/src/Neuron/Net/Response.php +++ b/src/Neuron/Net/Response.php @@ -258,4 +258,39 @@ public function output () { $this->getOutput ()->output ($this); } + + public function setETag ($tag) { + $this->setHeader ('etag', $tag); + } + + public function setNoCache () { + $this->setHeader ('Cache-Control', 'private, max-age=0, no-cache'); + $this->setHeader ('Pragma', 'no-cache'); + + $date = time (); + $date -= (60 * 60 * 24 * 7); + + $this->setHeader ('Expires', date ('c', $date)); + } + + public function setCache ($maxAge = 86400, $privacy = 'public') { + + switch ($privacy) { + case 'public': + case 'private': + break; + + default: + $privacy = 'private'; + break; + } + + $this->setHeader ('Cache-Control', $privacy); + + $date = time (); + $date += $maxAge; + + $this->setHeader ('Expires', date ('c', $date)); + + } } \ No newline at end of file From d0d8324c1dbfdcc3efab0c353ef7c6eb749273ce Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 4 May 2015 15:32:46 +0200 Subject: [PATCH 161/231] Adding raw output type. --- src/Neuron/Net/Outputs/Raw.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/Neuron/Net/Outputs/Raw.php diff --git a/src/Neuron/Net/Outputs/Raw.php b/src/Neuron/Net/Outputs/Raw.php new file mode 100644 index 0000000..a063f1b --- /dev/null +++ b/src/Neuron/Net/Outputs/Raw.php @@ -0,0 +1,28 @@ +getBody ()) + { + echo $response->getBody (); + } + else + { + echo $response->getData (); + } + } + +} \ No newline at end of file From 7d3b6c6c9951385a9e1b1369df85a87cfbcaa104 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 5 May 2015 02:02:22 +0200 Subject: [PATCH 162/231] Encountered a rather strange issue with locales in the query builder. --- src/Neuron/DB/Query.php | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Neuron/DB/Query.php b/src/Neuron/DB/Query.php index 2558b70..f33e795 100644 --- a/src/Neuron/DB/Query.php +++ b/src/Neuron/DB/Query.php @@ -11,7 +11,7 @@ use Neuron\Exceptions\InvalidParameter; use Neuron\Models\Geo\Point; -class Query +class Query { const PARAM_NUMBER = 1; const PARAM_DATE = 2; @@ -33,7 +33,7 @@ class Query public static function insert ($table, array $set) { $query = 'INSERT INTO `' . $table . '` SET '; - $values = array (); + $values = array (); foreach ($set as $k => $v) { $query .= $k . ' = ?, '; @@ -274,8 +274,8 @@ public static function delete ($table, array $where) } /** - * And construct. - */ + * And construct. + */ public function __construct ($query) { $this->query = $query; @@ -371,8 +371,8 @@ private function getValue ($value, $type, $parameterName) { if (!is_numeric ($value)) { throw new InvalidParameter ("Parameter " . $parameterName . " should be numeric in query " . $this->query); } - return $value; - break; + return (string)str_replace (',', '.', $value); + break; case self::PARAM_DATE: @@ -387,7 +387,7 @@ private function getValue ($value, $type, $parameterName) { throw new InvalidParameter ("Parameter " . $parameterName . " should be a valid timestamp in query " . $this->query); } - break; + break; case self::PARAM_POINT: if (! ($value instanceof Point)) @@ -395,13 +395,18 @@ private function getValue ($value, $type, $parameterName) { throw new InvalidParameter ("Parameter " . $parameterName . " should be a valid \\Neuron\\Models\\Point " . $this->query); } return $value = "POINT(" . $value->getLongtitude() . "," . $value->getLatitude() .")"; - break; + break; case self::PARAM_STR: default: + + if (is_numeric ($value)) { + $value = (string)str_replace (',', '.', $value); + } + $value = "'" . $db->escape (strval ($value)) . "'"; return $value; - break; + break; } } @@ -427,5 +432,4 @@ public function execute () $query = $this->getParsedQuery (); return $db->query ($query); } -} -?> +} \ No newline at end of file From cf2b115f0bbd65398cc87b61a3b88b62274459d3 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 5 May 2015 11:45:57 +0200 Subject: [PATCH 163/231] A user is a model too. --- src/Neuron/Interfaces/Models/User.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Neuron/Interfaces/Models/User.php b/src/Neuron/Interfaces/Models/User.php index 45a0743..f2d406a 100644 --- a/src/Neuron/Interfaces/Models/User.php +++ b/src/Neuron/Interfaces/Models/User.php @@ -1,12 +1,8 @@ Date: Wed, 6 May 2015 14:58:27 +0200 Subject: [PATCH 164/231] Adding datetime input type. --- src/Neuron/Core/Tools.php | 10 ++++++++++ tests/ToolsTest.php | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index edafeb7..8fe7d24 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -3,6 +3,7 @@ namespace Neuron\Core; +use DateTime; use Neuron\Core\Tools as NeuronCoreTools; use Exception; use Neuron\Core\Text; @@ -36,6 +37,10 @@ public static function getInput ($dat, $key, $type, $default = null) return mktime (0, 0, 1, $time[1], $time[2], $time[0]); break; + case 'datetime': + return new DateTime ($dat[$key]); + break; + case 'base64': return base64_decode ($dat[$key]); break; @@ -96,6 +101,11 @@ public static function checkInput ($value, $type) $time = explode ('-', $value); return self::isValidUTF8 ($value) && (count ($time) == 3); } + + elseif ($type == 'datetime') { + $regex = '/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/'; + return (bool)preg_match ($regex, $value); + } elseif ($type == 'md5') { diff --git a/tests/ToolsTest.php b/tests/ToolsTest.php index 11af55e..26cae51 100644 --- a/tests/ToolsTest.php +++ b/tests/ToolsTest.php @@ -97,4 +97,9 @@ public function testIntInput () $this->assertFalse (Tools::checkInput ('23,5', 'int')); } + + public function testDateInput () { + $this->assertTrue (Tools::checkInput ('2015-06-01T10:00', 'datetime')); + $this->assertFalse (Tools::checkInput ('06-01-2015T10:00', 'datetime')); + } } \ No newline at end of file From afc164ad9cf14ec854fdf965972c74b41524c845 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 23 May 2015 12:20:38 +0200 Subject: [PATCH 165/231] Adding a getURL method in templates. --- src/Neuron/Core/Template.php | 11 +++++++++++ src/Neuron/URLBuilder.php | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 2eba9a7..11ee293 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -423,6 +423,17 @@ private function ngettext ($message1, $message2 = null, $n = null) return \Neuron\Tools\Text::getInstance ()->getText ($message1, $message2, $n); } + /** + * @param $path + * @param array $params + * @param bool $normalize + * @param null $appurl + * @return string + */ + private function getURL ($path, array $params = null, $normalize = true, $appurl = null) { + return \Neuron\URLBuilder::getURL ($path, $params, $normalize, $appurl); + } + public function __toString () { return $this->parse (); } diff --git a/src/Neuron/URLBuilder.php b/src/Neuron/URLBuilder.php index eb57dff..808cff5 100644 --- a/src/Neuron/URLBuilder.php +++ b/src/Neuron/URLBuilder.php @@ -11,6 +11,13 @@ class URLBuilder { + /** + * @param string $module Path name + * @param array $data Query string + * @param bool $normalize Should the url be normalized? + * @param null $appurl Override the app url + * @return string + */ public static function getURL ($module = '', $data = array (), $normalize = true, $appurl = null) { if (!isset ($appurl)) From 7e06162f6b084c746813861ed2719c055991d1f0 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 23 May 2015 12:25:46 +0200 Subject: [PATCH 166/231] Adding a getURL method in templates. --- src/Neuron/URLBuilder.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Neuron/URLBuilder.php b/src/Neuron/URLBuilder.php index 808cff5..07c9c0f 100644 --- a/src/Neuron/URLBuilder.php +++ b/src/Neuron/URLBuilder.php @@ -29,9 +29,10 @@ public static function getURL ($module = '', $data = array (), $normalize = true } $params = ''; - foreach ($data as $k => $v) - { - $params .= urlencode ($k) . '=' . urlencode ($v) . '&'; + if (isset ($data)) { + foreach ($data as $k => $v) { + $params .= urlencode ($k) . '=' . urlencode ($v) . '&'; + } } $params = substr ($params, 0, -1); From 1ad3bfa368fcaa7d6ad0fe61806dc998ff520a08 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 25 May 2015 21:51:20 +0200 Subject: [PATCH 167/231] Adding HttpAuth class, jsut for funsies. --- src/Neuron/Auth/HttpAuth.php | 77 +++++++++++++++++++++++++++++++++ src/Neuron/Net/Outputs/HTML.php | 7 ++- 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/Neuron/Auth/HttpAuth.php diff --git a/src/Neuron/Auth/HttpAuth.php b/src/Neuron/Auth/HttpAuth.php new file mode 100644 index 0000000..b55ade4 --- /dev/null +++ b/src/Neuron/Auth/HttpAuth.php @@ -0,0 +1,77 @@ +addFilter ('basicauth', array ($checker, 'check')); + } + + /** + * @param array $users + */ + public function __construct (array $users) + { + $this->setUsers ($users); + } + + /** + * @return array[] + */ + public function getUsers () + { + return $this->users; + } + + /** + * @param array[] $users + * @return HttpAuth + */ + public function setUsers ($users) + { + $this->users = $users; + return $this; + } + + private function getUser ($username) + { + foreach ($this->users as $user) + { + if ($user[0] === $username) { + return $user; + } + } + return null; + } + + public function check (\Neuron\Net\Request $request) + { + $error = new \Neuron\Net\Response (); + $error->setBody ('Authorization not accepted'); + $error->setHeader ('WWW-Authenticate', 'Basic realm="Secured zone"'); + $error->setHeader ('HTTP/1.0 401 Unauthorized'); + + if (!isset($_SERVER['PHP_AUTH_USER'])) { + return $error; + } + + else { + + $user = $this->getUser ($_SERVER['PHP_AUTH_USER']); + if (!$user) { + return $error; + } + + else { + if ($_SERVER['PHP_AUTH_PW'] === $user[1]) { + return $error; + } + return true; + } + } + } + +} \ No newline at end of file diff --git a/src/Neuron/Net/Outputs/HTML.php b/src/Neuron/Net/Outputs/HTML.php index 6c397da..bb3118d 100644 --- a/src/Neuron/Net/Outputs/HTML.php +++ b/src/Neuron/Net/Outputs/HTML.php @@ -29,7 +29,12 @@ public function output (Response $response) { foreach ($response->getHeaders () as $k => $v) { - header ($k . ': ' . $v); + if (!empty ($v)) { + header ($k . ': ' . $v); + } + else { + header ($k); + } } } From fd1ebf6131acdf73f9ebf1ad4b27c175e7c62823 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 25 May 2015 21:54:05 +0200 Subject: [PATCH 168/231] Adding HttpAuth class, jsut for funsies. --- src/Neuron/Auth/HttpAuth.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Neuron/Auth/HttpAuth.php b/src/Neuron/Auth/HttpAuth.php index b55ade4..09f41d2 100644 --- a/src/Neuron/Auth/HttpAuth.php +++ b/src/Neuron/Auth/HttpAuth.php @@ -1,4 +1,7 @@ Date: Mon, 25 May 2015 22:02:58 +0200 Subject: [PATCH 169/231] Adding HttpAuth class, jsut for funsies. --- src/Neuron/Auth/HttpAuth.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Neuron/Auth/HttpAuth.php b/src/Neuron/Auth/HttpAuth.php index 09f41d2..fe4b101 100644 --- a/src/Neuron/Auth/HttpAuth.php +++ b/src/Neuron/Auth/HttpAuth.php @@ -43,14 +43,14 @@ private function getUser ($username) { foreach ($this->users as $user) { - if ($user[0] === $username) { + if ($user['username'] === $username) { return $user; } } return null; } - public function check (\Neuron\Net\Request $request) + public function check (\Neuron\Models\Router\Filter $filter) { $error = new \Neuron\Net\Response (); $error->setBody ('Authorization not accepted'); @@ -69,7 +69,7 @@ public function check (\Neuron\Net\Request $request) } else { - if ($_SERVER['PHP_AUTH_PW'] === $user[1]) { + if ($_SERVER['PHP_AUTH_PW'] === $user['password']) { return $error; } return true; From 06532614c502643155abcd700557ca726e26c710 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 25 May 2015 22:10:36 +0200 Subject: [PATCH 170/231] Adding HttpAuth class, jsut for funsies. --- src/Neuron/Auth/HttpAuth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Auth/HttpAuth.php b/src/Neuron/Auth/HttpAuth.php index fe4b101..a1a0def 100644 --- a/src/Neuron/Auth/HttpAuth.php +++ b/src/Neuron/Auth/HttpAuth.php @@ -69,7 +69,7 @@ public function check (\Neuron\Models\Router\Filter $filter) } else { - if ($_SERVER['PHP_AUTH_PW'] === $user['password']) { + if ($_SERVER['PHP_AUTH_PW'] !== $user['password']) { return $error; } return true; From 1cc05545cfc95108b4c66694e86afbc03e4702ad Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 31 May 2015 12:27:27 +0200 Subject: [PATCH 171/231] Collection should trigger event AFTER setting. --- src/Neuron/Collections/Collection.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 866755c..8d98d29 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -81,15 +81,15 @@ public function offsetSet($offset, $value) } else { - if (isset ($this->data[$offset])) - { - $this->trigger ('add', $value, $offset); - } - else { - $this->trigger ('set', $value, $offset); - } - $this->data[$offset] = $value; + + if (isset ($this->data[$offset])) + { + $this->trigger ('add', $value, $offset); + } + else { + $this->trigger ('set', $value, $offset); + } } } From a74eee4c9cd08cf08354ee36061169ad7bb9459d Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 31 May 2015 12:41:07 +0200 Subject: [PATCH 172/231] Template set methods should return the template itself. --- src/Neuron/Core/Template.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 11ee293..6fefc9a 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -132,6 +132,7 @@ public static function getPaths () /** * @param $sTextSection * @param null $sTextFile + * @return $this */ private function setTextSection ($sTextSection, $sTextFile = null) { @@ -141,19 +142,31 @@ private function setTextSection ($sTextSection, $sTextFile = null) { $this->sTextFile = $sTextFile; } + + return $this; } /** * @param $sTextFile + * @return $this */ private function setTextFile ($sTextFile) { $this->sTextFile = $sTextFile; + return $this; } + /** + * @param $var + * @param $value + * @param bool $overwrite + * @param bool $first + * @return $this + */ public function set ($var, $value, $overwrite = false, $first = false) { $this->setVariable ($var, $value, $overwrite, $first); + return $this; } /** From d879e61343f1c6d35963722be652ea155917ebc7 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 31 May 2015 12:42:36 +0200 Subject: [PATCH 173/231] Template set methods should return the template itself. --- src/Neuron/Core/Template.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 6fefc9a..34539ca 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -42,9 +42,13 @@ public static function load () * Create a template. * @param $template */ - public function __construct ($template = null) + public function __construct ($template = null, $values = array ()) { $this->template = $template; + + foreach ($values as $name => $value) { + $this->set ($name, $value); + } } /** From 7871bb72b2ac44fd5981c94e0a3db6012ff8e0cc Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 31 May 2015 13:03:03 +0200 Subject: [PATCH 174/231] Small change to the templates: parent templates (layouts) now also contains all template set variables. --- src/Neuron/Core/Template.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 34539ca..e1bac7f 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -301,15 +301,20 @@ public function parse ($template = null, $text = null) private function processRenderQueue ($contents = array ()) { - if (isset ($this->layoutRender)) - { + if (isset ($this->layoutRender)) { $template = new self (); - foreach ($contents as $k => $v) - { + // Set the variables that have been set here. + foreach ($this->values as $k => $v) { $template->set ($k, $v); } + // And now set the content blocks. + // This might overwrite other sets. + foreach ($contents as $k => $v) { + $template->set ($k, $v, true); + } + return $template->parse ($this->layoutRender); } else { From 42cc63798d82160ed4312a3119c1ab4f6417e1b0 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 13 Jun 2015 11:03:59 +0200 Subject: [PATCH 175/231] Adding first & last methods to collection. --- src/Neuron/Collections/Collection.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 8d98d29..1e744d8 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -227,4 +227,26 @@ public function remove ($entry) { } return false; } + + /** + * Return the very first element. + */ + public function first () + { + if (!is_array($this->data)) return $this->data; + if (!count($this->data)) return null; + reset($this->data); + return $this->data[key($this->data)]; + } + + /** + * Return the very last element. + */ + public function last () + { + if (!is_array($this->data)) return $this->data; + if (!count($this->data)) return null; + end($this->data); + return $this->data[key($this->data)]; + } } \ No newline at end of file From 6f50670a0c338c6839b1fabe0a6f2fb8dfc50339 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 16 Jan 2016 13:55:36 +0100 Subject: [PATCH 176/231] Playing with some small updates to query builder. --- composer.json | 4 + src/Neuron/DB/Database.php | 16 +- src/Neuron/DB/Query.php | 354 +++++++++++++++++++------------------ src/Neuron/DB/Result.php | 6 +- tests/DbQueryTest.php | 91 +++++++++- 5 files changed, 285 insertions(+), 186 deletions(-) diff --git a/composer.json b/composer.json index 8e432c1..0afb7da 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,10 @@ "nesbot/carbon": "~1.18" }, + "require-dev": { + "phpunit/phpunit": "5.1.*" + }, + "autoload": { "psr-4" : { "Neuron\\" : "src/Neuron/" diff --git a/src/Neuron/DB/Database.php b/src/Neuron/DB/Database.php index b9f0fb9..1b3a470 100755 --- a/src/Neuron/DB/Database.php +++ b/src/Neuron/DB/Database.php @@ -67,19 +67,31 @@ public function getInsertId () return $this->insert_id; } + /** + * @return int + */ public function getAffectedRows () { return $this->affected_rows; } + /** + * @return int + */ public function getQueryCounter () { return $this->query_counter; } // Abstract functions - public abstract function query ($sSQL); - public abstract function multiQuery ($sSQL); + /** + * @param $sSQL + * @return Result|int + */ + public abstract function query($sSQL); + + public abstract function multiQuery($sSQL); + public abstract function escape ($txt); public function start () diff --git a/src/Neuron/DB/Query.php b/src/Neuron/DB/Query.php index f33e795..f674d93 100644 --- a/src/Neuron/DB/Query.php +++ b/src/Neuron/DB/Query.php @@ -1,9 +1,4 @@ $v) - { + foreach ($set as $k => $v) { $query .= $k . ' = ?, '; // No array? Then it's a simple string. - if (is_array ($v)) - { + if (is_array ($v)) { $values[] = $v; - } - else - { - $values[] = array ($v); + } else { + $values[] = array($v); } } - $query = substr ($query, 0, -2); + $query = substr($query, 0, -2); - $query = new self ($query); - $query->bindValues ($values); + $query = new self($query); + $query->bindValues($values); return $query; } /** * Generate an replace query - * @param $table: table to insert data to - * @param $set: a 2 dimensional array with syntax: { column_name : [ value, type, nullOnEmpty ]} + * @param string $table: table to insert data to + * @param mixed[] $set: a 2 dimensional array with syntax: { column_name : [ value, type, nullOnEmpty ]} * @return Query */ - public static function replace ($table, array $set) + public static function replace($table, array $set) { - $query = 'REPLACE INTO `' . $table . '` SET '; + $query = 'REPLACE INTO ' . self::escapeTableName($table) . ' SET '; $values = array (); foreach ($set as $k => $v) { $query .= $k . ' = ?, '; // No array? Then it's a simple string. - if (is_array ($v)) + if (is_array($v)) { $values[] = $v; } else { - $values[] = array ($v); + $values[] = array($v); } } - $query = substr ($query, 0, -2); + $query = substr($query, 0, -2); - $query = new self ($query); - $query->bindValues ($values); + $query = new self($query); + $query->bindValues($values); return $query; } @@ -98,105 +94,86 @@ public static function replace ($table, array $set) * nullOnEmpty may be omitted. * @return Query */ - public static function update ($table, array $set, array $where) + public static function update($table, array $set, array $where) { - $query = 'UPDATE `' . $table . '` SET '; - $values = array (); - foreach ($set as $k => $v) - { + $query = 'UPDATE ' . self::escapeTableName($table) . ' SET '; + $values = array(); + foreach ($set as $k => $v) { $query .= $k . ' = ?, '; // No array? Then it's a simple string. - if (is_array ($v)) - { + if (is_array($v)) { $values[] = $v; - } - else - { - $values[] = array ($v); + } else { + $values[] = array($v); } } - $query = substr ($query, 0, -2) . ' '; - $query .= self::processWhere ($where, $values); + $query = substr($query, 0, -2) . ' '; + $query .= self::processWhere($where, $values); - $query = new self ($query); - $query->bindValues ($values); + $query = new self($query); + $query->bindValues($values); return $query; } - private static function processWhere (array $where, &$values) + /** + * @param mixed[] $where + * @param mixed[] $values + * @return string + */ + private static function processWhere(array $where, &$values) { $query = ''; - if (count ($where) > 0) - { + if (count($where) > 0) { $query .= 'WHERE '; - foreach ($where as $k => $v) - { + foreach ($where as $k => $v) { // No array? Then it's a simple string. - if (is_array ($v)) - { + if (is_array($v)) { $tmp = $v; - } - else - { - $tmp = array ($v, self::PARAM_STR); + } else { + $tmp = array($v, self::PARAM_UNKNOWN); } - if (!is_array ($tmp[0]) && substr ($tmp[0], 0, 1) == '!') - { + // Parse comparators + if (!is_array($tmp[0]) && substr($tmp[0], 0, 1) === '!') { $query .= $k . ' != ? AND '; - $tmp[0] = substr ($tmp[0], 1); - } - - else if (isset ($tmp[2]) && strtoupper ($tmp[2]) == 'LIKE') - { + $tmp[0] = substr($tmp[0], 1); + } elseif (isset($tmp[2]) && strtoupper($tmp[2]) === 'LIKE') { $query .= $k . ' LIKE ? AND '; - $tmp = array ($tmp[0], $tmp[1]); - } - - else if (isset ($tmp[2]) && strtoupper ($tmp[2]) == 'NOT') - { + $tmp = array($tmp[0], $tmp[1]); + } elseif (isset ($tmp[2]) && strtoupper($tmp[2]) === 'NOT') { $query .= $k . ' != ? AND '; - $tmp = array ($tmp[0], $tmp[1]); - } - - else if (isset ($tmp[2]) + $tmp = array($tmp[0], $tmp[1]); + } elseif ( + isset ($tmp[2]) && ( - strtoupper ($tmp[2]) == '>' - || strtoupper ($tmp[2]) == '<' - || strtoupper ($tmp[2]) == '>=' - || strtoupper ($tmp[2]) == '<=' - || strtoupper ($tmp[2]) == '!=' + strtoupper ($tmp[2]) === '>' + || strtoupper ($tmp[2]) === '<' + || strtoupper ($tmp[2]) === '>=' + || strtoupper ($tmp[2]) === '<=' + || strtoupper ($tmp[2]) === '!=' ) - ) - { + ) { $query .= $k . ' ' . $tmp[2] . ' ? AND '; - $tmp = array ($tmp[0], $tmp[1]); - } - - else if (isset ($tmp[2]) && strtoupper ($tmp[2]) == 'IN') - { + $tmp = array($tmp[0], $tmp[1]); + } elseif (isset($tmp[2]) && strtoupper($tmp[2]) == 'IN') { $query .= $k . ' ' . $tmp[2] . ' ? AND '; $tmp = array ($tmp[0], $tmp[1]); - } - - else if (is_array ($tmp[0])) - { + } elseif (is_array($tmp[0])) { $query .= $k . ' IN ? AND '; - } - - else - { + } elseif ($tmp[0] === null) { + $query .= $k . ' IS NULL AND '; + } else { $query .= $k . ' = ? AND '; } $values[] = $tmp; } - $query = substr ($query, 0, -5); + $query = substr($query, 0, -5); } return $query; @@ -211,46 +188,44 @@ private static function processWhere (array $where, &$values) * @param null $limit * @return Query */ - public static function select ($table, array $data = array (), array $where = array (), $order = array (), $limit = null) - { + public static function select ( + $table, + array $data = array(), + array $where = array(), + $order = array(), + $limit = null + ) { $query = 'SELECT '; $values = array (); - if (count ($data) > 0) - { - foreach ($data as $v) - { + if (count ($data) > 0) { + foreach ($data as $v) { $query .= $v . ', '; } $query = substr ($query, 0, -2) . ' '; - } - else - { + } else { $query .= '* '; } - $query .= 'FROM `' . $table . '` '; + $query .= 'FROM ' . self::escapeTableName($table) . ' '; $query .= self::processWhere ($where, $values); // Order - if (count ($order) > 0) - { + if (count ($order) > 0) { $query .= " ORDER BY "; - foreach ($order as $v) - { + foreach ($order as $v) { $query .= $v . ", "; } $query = substr ($query, 0, -2); } // Limit - if ($limit) - { + if ($limit) { $query .= " LIMIT " . $limit; } - $query = new self ($query); - $query->bindValues ($values); + $query = new self($query); + $query->bindValues($values); return $query; } @@ -260,15 +235,15 @@ public static function select ($table, array $data = array (), array $where = ar * @param array $where * @return Query|string */ - public static function delete ($table, array $where) + public static function delete($table, array $where) { - $query = 'DELETE FROM `' . $table . '`'; + $query = 'DELETE FROM ' . self::escapeTableName($table) . ''; - $values = array (); - $query .= self::processWhere ($where, $values); + $values = array(); + $query .= self::processWhere($where, $values); - $query = new self ($query); - $query->bindValues ($values); + $query = new self($query); + $query->bindValues($values); return $query; } @@ -281,55 +256,66 @@ public function __construct ($query) $this->query = $query; } + /** + * @param $values + * @return Query + */ public function bindValues ($values) { $this->values = $values; + return $this; } - public function bindValue ($index, $value, $type = self::PARAM_STR, $canBeNull = false) - { + /** + * @param string $index + * @param mixed $value + * @param int $type + * @param bool $canBeNull + * @return Query + */ + public function bindValue( + $index, + $value, + $type = self::PARAM_UNKNOWN, + $canBeNull = false + ) { $this->values[$index] = array ($value, $type, $canBeNull); // Chaining return $this; } + /** + * @return string + */ public function getParsedQuery () { - $keys = array (); - $values = array (); + $keys = array(); + $values = array(); - foreach ($this->values as $k => $v) - { + foreach ($this->values as $k => $v) { // Column type? - if (!isset ($v[1])) - { + if (!isset ($v[1])) { // Check for known "special types" if ($v[0] instanceof Point) { $v[1] = self::PARAM_POINT; - } - - else if ($v[0] instanceof DateTime) { + } elseif ($v[0] instanceof DateTime) { $v[1] = self::PARAM_DATE; - } - - else { - $v[1] = self::PARAM_STR; + } else { + $v[1] = self::PARAM_UNKNOWN; } } // NULL on empty? - if (!isset ($v[2])) - { - $v[2] = false; + if (!isset($v[2])) { + $v[2] = true; } // Empty and should set NULL? if ($v[2] && empty ($v[0])) { $value = "NULL"; - } - else { - $value = $this->getValues ($k, $v); + } else { + $value = $this->getValues($k, $v); } $values[$k] = $value; @@ -337,16 +323,14 @@ public function getParsedQuery () // Replace question marks or tokens? if (is_string ($k)) { $keys[] = '/:'.$k.'/'; - } - else { + } else { $keys[] = '/[?]/'; } } // First we make a list with placeholders which we will later repalce with values $fakeValues = array (); - foreach ($values as $k => $v) - { + foreach ($values as $k => $v) { $fakeValues[$k] = '{{{ctlb-custom-placeholder-' . $k . '}}}'; } @@ -354,25 +338,30 @@ public function getParsedQuery () $query = preg_replace ($keys, $fakeValues, $this->query, 1); // And now replace the tokens with the actual values - foreach ($values as $k => $v) - { + foreach ($values as $k => $v) { $query = str_replace ($fakeValues[$k], $v, $query); } return $query; } - private function getValue ($value, $type, $parameterName) { + /** + * @param mixed $value + * @param string $type + * @param string $parameterName + * @return int|string + * @throws InvalidParameter + */ + private function getValue ($value, $type, $parameterName) + { $db = Database::getInstance (); - switch ($type) - { + switch ($type) { case self::PARAM_NUMBER: if (!is_numeric ($value)) { throw new InvalidParameter ("Parameter " . $parameterName . " should be numeric in query " . $this->query); } return (string)str_replace (',', '.', $value); - break; case self::PARAM_DATE: @@ -387,49 +376,68 @@ private function getValue ($value, $type, $parameterName) { throw new InvalidParameter ("Parameter " . $parameterName . " should be a valid timestamp in query " . $this->query); } - break; - case self::PARAM_POINT: if (! ($value instanceof Point)) { throw new InvalidParameter ("Parameter " . $parameterName . " should be a valid \\Neuron\\Models\\Point " . $this->query); } return $value = "POINT(" . $value->getLongtitude() . "," . $value->getLatitude() .")"; - break; case self::PARAM_STR: - default: - - if (is_numeric ($value)) { + if (is_numeric ($value)) { $value = (string)str_replace (',', '.', $value); } - $value = "'" . $db->escape (strval ($value)) . "'"; - return $value; - break; - } - } - - private function getValues ($k, $v) { + return "'" . $db->escape (strval ($value)) . "'"; - if (is_array ($v[0])) { - $tmp = array (); + case self::PARAM_UNKNOWN: + if (is_int($value)) { + return intval($value); + } elseif (is_numeric ($value)) { + $value = (string)str_replace (',', '.', $value); + } + return "'" . $db->escape (strval ($value)) . "'"; - foreach ($v[0] as $kk => $vv) { - $tmp[] = $this->getValue ($vv, $v[1], $k . '[' . $kk . ']'); - } - - return '(' . implode (',', $tmp) . ')'; - } - else { - return $this->getValue ($v[0], $v[1], $k); } } + /** + * @return Result|int + */ public function execute () { - $db = Database::getInstance (); - $query = $this->getParsedQuery (); - return $db->query ($query); + $db = Database::getInstance(); + $query = $this->getParsedQuery(); + return $db->query($query); } + + /** + * @param $k + * @param $v + * @return string + * @throws InvalidParameter + */ + private function getValues ($k, $v) + { + if (is_array ($v[0])) { + $tmp = array (); + + foreach ($v[0] as $kk => $vv) { + $tmp[] = $this->getValue($vv, $v[1], $k . '[' . $kk . ']'); + } + + return '(' . implode (',', $tmp) . ')'; + } else { + return $this->getValue($v[0], $v[1], $k); + } + } + + /** + * @param string $table + * @return string + */ + private static function escapeTableName($table) + { + return "`$table`"; + } } \ No newline at end of file diff --git a/src/Neuron/DB/Result.php b/src/Neuron/DB/Result.php index 9e1893b..84eb85a 100755 --- a/src/Neuron/DB/Result.php +++ b/src/Neuron/DB/Result.php @@ -1,13 +1,15 @@ assertEquals ($expected, $sql); } + /** + * @test + */ public function testQueryBuilderSelect () { $expected1 = "SELECT column1, column2, column3 FROM `table` WHERE m_id = 1 AND m_date = FROM_UNIXTIME(1379289600) AND m_string = 'Value 1'"; @@ -59,6 +66,9 @@ public function testQueryBuilderSelect () $this->assertEquals ($expected2, $selectsql); } + /** + * @test + */ public function testQueryBuilderInsert () { // Insert query with only strings @@ -96,6 +106,9 @@ public function testQueryBuilderInsert () $this->assertEquals ($expected, $sql); } + /** + * @test + */ public function testQueryBuilderUpdate () { // And do the same with update @@ -141,6 +154,9 @@ public function testQueryBuilderUpdate () $this->assertEquals ($expected, $sql); } + /** + * @test + */ public function testQueryOrder () { $expected1 = "SELECT column1, column2, column3 FROM `table` WHERE m_id = 1 AND m_date = FROM_UNIXTIME(1379289600) AND m_string = 'Value 1' ORDER BY m_id ASC"; @@ -160,6 +176,9 @@ public function testQueryOrder () $this->assertEquals ($expected1, $selectsql); } + /** + * @test + */ public function testQueryLimit () { $expected1 = "SELECT column1, column2, column3 FROM `table` WHERE m_id = 1 AND m_date = FROM_UNIXTIME(1379289600) AND m_string = 'Value 1' LIMIT 0, 10"; @@ -179,6 +198,9 @@ public function testQueryLimit () $this->assertEquals ($expected1, $selectsql); } + /** + * @test + */ public function testQueryOrderAndLimit () { $expected1 = "SELECT column1, column2, column3 FROM `table` WHERE m_id = 1 AND m_date = FROM_UNIXTIME(1379289600) AND m_string = 'Value 1' ORDER BY m_id ASC LIMIT 0, 10"; @@ -199,6 +221,9 @@ public function testQueryOrderAndLimit () $this->assertEquals ($expected1, $selectsql); } + /** + * @test + */ public function testStupidQuestionmarkReplace () { $values = array @@ -211,11 +236,14 @@ public function testStupidQuestionmarkReplace () // Insert $query = Query::insert ('table', $values); - $expected = "INSERT INTO `table` SET m_id = '1', m_test = 'test string with a random ? in it.', m_next = 'another parameter'"; + $expected = "INSERT INTO `table` SET m_id = 1, m_test = 'test string with a random ? in it.', m_next = 'another parameter'"; $this->assertEquals ($expected, $query->getParsedQuery ()); } + /** + * @test + */ public function testStupidNamedParameterReplace () { // Insert @@ -225,11 +253,14 @@ public function testStupidNamedParameterReplace () $query->bindValue ('m_next', 'another parameter'); $query->bindValue ('m_id', 1); - $expected = "INSERT INTO `table` SET m_id = '1', m_test = 'test string with a random :m_next parameter in it.', m_next = 'another parameter'"; + $expected = "INSERT INTO `table` SET m_id = 1, m_test = 'test string with a random :m_next parameter in it.', m_next = 'another parameter'"; $this->assertEquals ($expected, $query->getParsedQuery ()); } + /** + * @test + */ public function testStupidMixedNameAndQuestionmarks () { // Insert @@ -239,7 +270,7 @@ public function testStupidMixedNameAndQuestionmarks () $query->bindValue (2, 'another parameter'); $query->bindValue ('m_id', 1); - $expected = "INSERT INTO `table` SET m_id = '1', m_test = 'test string with a random :m_next parameter in it.', m_next = 'another parameter'"; + $expected = "INSERT INTO `table` SET m_id = 1, m_test = 'test string with a random :m_next parameter in it.', m_next = 'another parameter'"; $this->assertEquals ($expected, $query->getParsedQuery ()); } @@ -253,11 +284,14 @@ public function testStupidMixedNameAndQuestionmarksReversed () $query->bindValue ('m_test', 'test string with a random :m_next parameter in it.'); $query->bindValue (2, 'another parameter'); - $expected = "INSERT INTO `table` SET m_id = '1', m_test = 'test string with a random :m_next parameter in it.', m_next = 'another parameter'"; + $expected = "INSERT INTO `table` SET m_id = 1, m_test = 'test string with a random :m_next parameter in it.', m_next = 'another parameter'"; $this->assertEquals ($expected, $query->getParsedQuery ()); } + /** + * @test + */ public function testStupidZeroBasedQuestionmarks () { // Insert @@ -267,8 +301,47 @@ public function testStupidZeroBasedQuestionmarks () $query->bindValue (1, 'test string with a random :m_next parameter in it.'); $query->bindValue (2, 'another parameter'); - $expected = "INSERT INTO `table` SET m_id = '1', m_test = 'test string with a random :m_next parameter in it.', m_next = 'another parameter'"; + $expected = "INSERT INTO `table` SET m_id = 1, m_test = 'test string with a random :m_next parameter in it.', m_next = 'another parameter'"; $this->assertEquals ($expected, $query->getParsedQuery ()); } + + /** + * @test + */ + public function testNullValues() + { + $query = Query::select( + 'tableName', + array('id'), + array( + 'id' => 1, + 'deleted_at' => null + ) + )->getParsedQuery(); + + $this->assertEquals( + 'SELECT id FROM `tableName` WHERE id = 1 AND deleted_at IS NULL', + $query + ); + } + + /** + * @test + */ + public function testNullInsert() + { + $query = Query::insert( + 'tableName', + array( + 'id' => 1, + 'name' => null + ) + )->getParsedQuery(); + + $this->assertEquals( + 'INSERT INTO `tableName` SET id = 1, name = NULL', + $query + ); + } } \ No newline at end of file From 9ede57d0253e4c1604a5c57a7eb850ea1e7a23fc Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 20 Jan 2016 00:14:13 +0100 Subject: [PATCH 177/231] Accepting x-http-form data. --- src/Neuron/Net/Entity.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index ff771dc..88badb3 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -1,24 +1,23 @@ setData($_POST); } } } From 54b028a53ecc5309128f367b5524ade2d2622807 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 20 Jan 2016 14:49:53 +0100 Subject: [PATCH 178/231] Bug. --- src/Neuron/DB/Query.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/DB/Query.php b/src/Neuron/DB/Query.php index f674d93..cd19d4d 100644 --- a/src/Neuron/DB/Query.php +++ b/src/Neuron/DB/Query.php @@ -312,7 +312,7 @@ public function getParsedQuery () } // Empty and should set NULL? - if ($v[2] && empty ($v[0])) { + if ($v[2] && $v[0] === null) { $value = "NULL"; } else { $value = $this->getValues($k, $v); From 3a2532d2650a52da16602aa1c791adcdb57c6c19 Mon Sep 17 00:00:00 2001 From: daedeloth Date: Wed, 12 Oct 2016 14:05:46 +0200 Subject: [PATCH 179/231] FIxing old bugs. --- src/Neuron/DB/Query.php | 12 ++++---- src/Neuron/SessionHandlers/SessionHandler.php | 30 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Neuron/DB/Query.php b/src/Neuron/DB/Query.php index cd19d4d..5c9693e 100644 --- a/src/Neuron/DB/Query.php +++ b/src/Neuron/DB/Query.php @@ -311,12 +311,12 @@ public function getParsedQuery () $v[2] = true; } - // Empty and should set NULL? - if ($v[2] && $v[0] === null) { - $value = "NULL"; - } else { - $value = $this->getValues($k, $v); - } + // Empty and should set NULL? + if ($v[2] && $v[0] === null) { + $value = "NULL"; + } else { + $value = $this->getValues($k, $v); + } $values[$k] = $value; diff --git a/src/Neuron/SessionHandlers/SessionHandler.php b/src/Neuron/SessionHandlers/SessionHandler.php index daa3130..d87e690 100644 --- a/src/Neuron/SessionHandlers/SessionHandler.php +++ b/src/Neuron/SessionHandlers/SessionHandler.php @@ -22,21 +22,21 @@ public final function start ($sessionId = null) { $this->register (); - if (isset($sessionId)) { - session_id ($sessionId); - - ini_set ("session.use_cookies", 0); - ini_set ("session.use_only_cookies", 0); - ini_set ("session.use_trans_sid", 0); # Forgot this one! - - Logger::getInstance ()->log ("Starting session with provided id " . $sessionId, false, 'cyan'); - } else if ($defaultSession = Tools::getInput ($_COOKIE, 'PHPSESSID', 'varchar')) { - Logger::getInstance ()->log ("Starting session with default cookie " . $defaultSession, false, 'cyan'); - session_id ($defaultSession); - } else { - session_regenerate_id (); - Logger::getInstance ()->log ("Starting brand new session with id " . session_id (), false, 'cyan'); - } + if (isset($sessionId)) { + session_id ($sessionId); + + ini_set ("session.use_cookies", 0); + ini_set ("session.use_only_cookies", 0); + ini_set ("session.use_trans_sid", 0); # Forgot this one! + + Logger::getInstance ()->log ("Starting session with provided id " . $sessionId, false, 'cyan'); + } elseif ($defaultSession = Tools::getInput ($_COOKIE, 'PHPSESSID', 'varchar')) { + Logger::getInstance ()->log ("Starting session with default cookie " . $defaultSession, false, 'cyan'); + session_id ($defaultSession); + } elseif (session_status() == PHP_SESSION_ACTIVE) { + session_regenerate_id (); + Logger::getInstance ()->log ("Starting brand new session with id " . session_id (), false, 'cyan'); + } session_start (); From 7af0920752d590853aeb8cd888d4ffa696451a2f Mon Sep 17 00:00:00 2001 From: daedeloth Date: Mon, 2 Jan 2017 09:49:13 +0100 Subject: [PATCH 180/231] Allow null values in model collection. --- src/Neuron/Collections/ModelCollection.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Collections/ModelCollection.php b/src/Neuron/Collections/ModelCollection.php index 898969f..72e879b 100644 --- a/src/Neuron/Collections/ModelCollection.php +++ b/src/Neuron/Collections/ModelCollection.php @@ -26,11 +26,19 @@ public function __construct () $this->on ('unset', array ($this, 'onUnset')); } - protected function onAdd (Model $model, $offset) + /** + * @param Model|null $model + * @param null $offset + */ + protected function onAdd (Model $model = null, $offset = null) { $this->map[$model->getId ()] = $model; } + /** + * @param Model|null $model + * @param null $offset + */ protected function onUnset (Model $model = null, $offset = null) { if ($model) @@ -41,10 +49,15 @@ protected function onUnset (Model $model = null, $offset = null) * Return all ids. * @return array */ - public function getIds () { + public function getIds () + { return array_keys ($this->map); } + /** + * @param $id + * @return mixed|null + */ public function getFromId ($id) { if (isset ($this->map[$id])) From b1346a4ef06c4f9f6c4db0cda25baef949c883f8 Mon Sep 17 00:00:00 2001 From: daedeloth Date: Mon, 2 Jan 2017 10:04:21 +0100 Subject: [PATCH 181/231] Allow null values in model collection. --- src/Neuron/Collections/ModelCollection.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Neuron/Collections/ModelCollection.php b/src/Neuron/Collections/ModelCollection.php index 72e879b..40b91f4 100644 --- a/src/Neuron/Collections/ModelCollection.php +++ b/src/Neuron/Collections/ModelCollection.php @@ -32,7 +32,9 @@ public function __construct () */ protected function onAdd (Model $model = null, $offset = null) { - $this->map[$model->getId ()] = $model; + if ($model) { + $this->map[$model->getId ()] = $model; + } } /** @@ -41,8 +43,9 @@ protected function onAdd (Model $model = null, $offset = null) */ protected function onUnset (Model $model = null, $offset = null) { - if ($model) - unset ($this->map[$model->getId ()]); + if ($model) { + unset ($this->map[$model->getId()]); + } } /** @@ -60,8 +63,7 @@ public function getIds () */ public function getFromId ($id) { - if (isset ($this->map[$id])) - { + if (isset ($this->map[$id])) { return $this->map[$id]; } return null; From 6e9f001e911dd4ccd27a844d68225f0f0424a11c Mon Sep 17 00:00:00 2001 From: daedeloth Date: Fri, 20 Jan 2017 11:48:55 +0100 Subject: [PATCH 182/231] Disable warnings. --- src/Neuron/Net/Request.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 41aa38f..5cbb319 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -75,17 +75,15 @@ private static function getHeadersFromInput () if (function_exists('getallheaders')) return getallheaders(); // getallheaders not available: manually extract 'm - $headers = ''; + $headers = []; foreach ($_SERVER as $name => $value) { - if (substr($name, 0, 5) == 'HTTP_') - { - $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; - } - - else if (strtolower (substr ($name, 0, 7)) == 'content') - { - $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $name))))] = $value; + if (substr($name, 0, 5) == 'HTTP_') { + $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))); + $headers[$key] = $value; + } else if (strtolower (substr ($name, 0, 7)) == 'content') { + $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $name)))); + $headers[$key] = $value; } } return $headers; From 4eea2335a7ef861956332cd7dc1a2020a115ea23 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 26 Nov 2017 15:00:45 +0100 Subject: [PATCH 183/231] DbSessionHandler should return empty strong on trying to read unavailable session data. (php7.1 complaints about that) --- src/Neuron/SessionHandlers/DbSessionHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/SessionHandlers/DbSessionHandler.php b/src/Neuron/SessionHandlers/DbSessionHandler.php index dc4d44e..5d49f50 100644 --- a/src/Neuron/SessionHandlers/DbSessionHandler.php +++ b/src/Neuron/SessionHandlers/DbSessionHandler.php @@ -57,7 +57,7 @@ public function read ( $session_id ) } else { - $this->sessions[$session_id] = null; + $this->sessions[$session_id] = ''; } } return $this->sessions[$session_id]; From 67dca5349891e23b31a96dcdead893b9491a1b8b Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 27 Feb 2018 11:35:17 +0100 Subject: [PATCH 184/231] Introduce ResponseException which is caught by the Router. --- src/Neuron/Exceptions/ResponseException.php | 35 +++++++++++++++ src/Neuron/Router.php | 48 +++++++++++---------- src/Neuron/URLBuilder.php | 21 +++++++-- 3 files changed, 79 insertions(+), 25 deletions(-) create mode 100644 src/Neuron/Exceptions/ResponseException.php diff --git a/src/Neuron/Exceptions/ResponseException.php b/src/Neuron/Exceptions/ResponseException.php new file mode 100644 index 0000000..bf915ea --- /dev/null +++ b/src/Neuron/Exceptions/ResponseException.php @@ -0,0 +1,35 @@ +response = $response; + parent::__construct('Response exception', $response->getStatus()); + } + + /** + * @return Response + */ + public function getResponse() + { + return $this->response; + } +} \ No newline at end of file diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index c737b39..6c85e39 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -9,6 +9,7 @@ namespace Neuron; use Neuron\Exceptions\InvalidParameter; +use Neuron\Exceptions\ResponseException; use Neuron\Interfaces\Controller; use Neuron\Interfaces\Module; use Neuron\Models\Router\Route; @@ -173,37 +174,40 @@ public function module ($prefix, Module $module) * Execute the router: Loop all defined before middlewares and routes, and execute the handling function if a mactch was found * * @param Request $request - * @return Response */ public function run (Request $request) { - // Define which method we need to handle - $this->method = $request->getMethod (); + try { - // Set request - $this->request = $request; + // Define which method we need to handle + $this->method = $request->getMethod(); - // Handle all routes - $numHandled = 0; - if (isset($this->routes[$this->method])) - $numHandled = $this->handle($this->routes[$this->method], true); - - // If no route was handled, trigger the 404 (if any) - if ($numHandled == 0) { - if ($this->notFound) { - //call_user_func($this->notFound); - $this->handleMatch ($this->notFound, array ()); - } - else { + // Set request + $this->request = $request; + + // Handle all routes + $numHandled = 0; + if (isset($this->routes[$this->method])) + $numHandled = $this->handle($this->routes[$this->method], true); - $request = Response::error ('Page not found.', Response::STATUS_NOTFOUND); - $request->output (); + // If no route was handled, trigger the 404 (if any) + if ($numHandled == 0) { + if ($this->notFound) { + //call_user_func($this->notFound); + $this->handleMatch($this->notFound, array()); + } else { + + $request = Response::error('Page not found.', Response::STATUS_NOTFOUND); + $request->output(); + } } - } - // If it originally was a HEAD request, clean up after ourselves by emptying the output buffer - if ($_SERVER['REQUEST_METHOD'] == 'HEAD') ob_end_clean(); + // If it originally was a HEAD request, clean up after ourselves by emptying the output buffer + if ($_SERVER['REQUEST_METHOD'] == 'HEAD') ob_end_clean(); + } catch (ResponseException $e) { + $e->getResponse()->output(); + } } /** diff --git a/src/Neuron/URLBuilder.php b/src/Neuron/URLBuilder.php index 07c9c0f..d2f84a0 100644 --- a/src/Neuron/URLBuilder.php +++ b/src/Neuron/URLBuilder.php @@ -65,9 +65,24 @@ public static function getAbsoluteURL ($module = '', $data = array ()) { } } - private static function guessAbsoluteURL () { - return $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . '/'; - } + /** + * Guest absolute url from server variables. + * @return string + */ + private static function guessAbsoluteURL () { + $scheme = 'http'; + $host = 'localhost'; + + if (isset($_SERVER['REQUEST_SCHEME'])) { + $scheme = $_SERVER['REQUEST_SCHEME']; + } + + if (isset($_SERVER['HTTP_HOST'])) { + $host = $_SERVER['HTTP_HOST']; + } + + return $scheme . '://' . $host . '/'; + } private static function isAbsolute ($url) { if (substr (strtolower ($url), 0, 4) == 'http') { From 626aa36fff8521b72bf25f6c3ab9ce8a2a583f5b Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 31 May 2019 12:28:55 +0200 Subject: [PATCH 185/231] Implement usable getHeader method. --- src/Neuron/Net/Entity.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index 88badb3..d009b6e 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -360,6 +360,36 @@ public function getHeaders () return $this->headers; } + /** + * @param $name + * @return string|null + */ + public function getHeader($name) + { + $name = $this->getSafeHeaderName($name); + foreach ($this->getHeaders() as $k => $v) { + if ($this->getSafeHeaderName($k) === $name) { + return $v; + } + } + return null; + } + + /** + * @param $name + * @return string + */ + protected function getSafeHeaderName($name) + { + $name = str_replace('-', '_', $name); + $name = str_replace('_', ' ', $name); + $name = strtolower($name); + $name = ucwords($name); + $name = str_replace(' ', '-', $name); + + return $name; + } + public function setCookies ($cookies) { $this->cookies = $cookies; From f03f3dfa10d2240f96d4fe27b825835f2aad60d5 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 17 Nov 2019 18:46:35 +0100 Subject: [PATCH 186/231] Expore response http code to the response status & change the way we set the user agent string. --- src/Neuron/Net/Client.php | 104 +++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 46 deletions(-) diff --git a/src/Neuron/Net/Client.php b/src/Neuron/Net/Client.php index f4601ff..f3f9c18 100644 --- a/src/Neuron/Net/Client.php +++ b/src/Neuron/Net/Client.php @@ -11,117 +11,126 @@ use Neuron\Exceptions\NotImplemented; -class Client { +class Client +{ - public static function getInstance () + public static function getInstance() { static $in; - if (!isset ($in)) - { + if (!isset ($in)) { $in = new self (); } return $in; } - public static function http_parse_headers ($raw_headers) { + public static function http_parse_headers($raw_headers) + { $headers = array(); $key = ''; // [+] - foreach(explode("\n", $raw_headers) as $i => $h) - { + foreach (explode("\n", $raw_headers) as $i => $h) { $h = explode(':', $h, 2); - if (isset($h[1])) - { + if (isset($h[1])) { if (!isset($headers[$h[0]])) $headers[$h[0]] = trim($h[1]); - elseif (is_array($headers[$h[0]])) - { + elseif (is_array($headers[$h[0]])) { // $tmp = array_merge($headers[$h[0]], array(trim($h[1]))); // [-] // $headers[$h[0]] = $tmp; // [-] $headers[$h[0]] = array_merge($headers[$h[0]], array(trim($h[1]))); // [+] - } - else - { + } else { // $tmp = array_merge(array($headers[$h[0]]), array(trim($h[1]))); // [-] // $headers[$h[0]] = $tmp; // [-] $headers[$h[0]] = array_merge(array($headers[$h[0]]), array(trim($h[1]))); // [+] } $key = $h[0]; // [+] - } - else // [+] + } else // [+] { // [+] if (substr($h[0], 0, 1) == "\t") // [+] - $headers[$key] .= "\r\n\t".trim($h[0]); // [+] + $headers[$key] .= "\r\n\t" . trim($h[0]); // [+] elseif (!$key) // [+] - $headers[0] = trim($h[0]);trim($h[0]); // [+] + $headers[0] = trim($h[0]); + trim($h[0]); // [+] } // [+] } return $headers; } - private function __construct () + private function __construct() { } - public function get (Request $request) + public function get(Request $request) { - return $this->api ($request, 'GET'); + return $this->api($request, 'GET'); } - public function post (Request $request) + public function post(Request $request) { - return $this->api ($request, 'POST'); + return $this->api($request, 'POST'); } - public function put (Request $request) + public function put(Request $request) { - return $this->api ($request, 'PUT'); + return $this->api($request, 'PUT'); } - public function delete (Request $request) + public function delete(Request $request) { - return $this->api ($request, 'DELETE'); + return $this->api($request, 'DELETE'); } - public function process (Request $request) { - return $this->api ($request, $request->getMethod ()); + public function process(Request $request) + { + return $this->api($request, $request->getMethod()); } - private function api (Request $request, $method) + private function api(Request $request, $method) { $ch = curl_init(); - $post = $request->getBody (); + $post = $request->getBody(); - $parsedUrl = $request->getUrl (); + $parsedUrl = $request->getUrl(); - if ($request->getParameters ()) { + if ($request->getParameters()) { - if (strpos ($parsedUrl, '?')) { + if (strpos($parsedUrl, '?')) { $parsedUrl .= '&'; - } - else { + } else { $parsedUrl .= '?'; } - $parsedUrl .= http_build_query ($request->getParameters ()); + $parsedUrl .= http_build_query($request->getParameters()); }; curl_setopt($ch, CURLOPT_URL, $parsedUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 1); - if ($request->getHeaders ()) { - $headers = $request->getHeaders (); - curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers); + if ($request->getHeaders()) { + $headers = []; + foreach ($request->getHeaders() as $k => $v) { + switch ($k) { + case 'User-Agent': + curl_setopt($ch, CURLOPT_USERAGENT, $v); + break; + + default: + $headers[$k] = $v; + break; + } + } + + if (count($headers) > 0) { + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + } } - switch ($method) - { + switch ($method) { case 'GET': break; @@ -154,10 +163,13 @@ private function api (Request $request, $method) $header = substr($output, 0, $header_size); $body = substr($output, $header_size); - $response = Response::fromRaw ($body, self::http_parse_headers ($header)); - curl_close ($ch); + $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + $response = Response::fromRaw($body, self::http_parse_headers($header)); + curl_close($ch); + + $response->setStatus($status); return $response; } - -} \ No newline at end of file +} \ No newline at end of file From d51e3f7bf796badc4f1783524258c3432b02904f Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 4 Apr 2020 20:00:25 +0200 Subject: [PATCH 187/231] Fix very silly curl request issue with headers. --- src/Neuron/Net/Client.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Net/Client.php b/src/Neuron/Net/Client.php index f3f9c18..0dd9861 100644 --- a/src/Neuron/Net/Client.php +++ b/src/Neuron/Net/Client.php @@ -120,7 +120,7 @@ private function api(Request $request, $method) break; default: - $headers[$k] = $v; + $headers[] = $k . ': ' . $v; break; } } @@ -172,4 +172,4 @@ private function api(Request $request, $method) return $response; } -} \ No newline at end of file +} From 77221c3889ff6ff49aaa8c2982bdcbeb7c0b4d8d Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 5 Apr 2020 11:31:11 +0200 Subject: [PATCH 188/231] Add ability to create specific loggers (instead of one global one) --- src/Neuron/Models/Logger.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Models/Logger.php b/src/Neuron/Models/Logger.php index 9ca4024..6292ce5 100644 --- a/src/Neuron/Models/Logger.php +++ b/src/Neuron/Models/Logger.php @@ -35,7 +35,7 @@ public static function start ($string, $replace = false, $color = null) return self::getInstance ()->log ($string, $replace, $color); } - private function __construct () + public function __construct () { $this->start = microtime(true); } @@ -173,4 +173,4 @@ public function flushTemporaryLog () return $out; } -} \ No newline at end of file +} From 868a6d02a895b41026594f426c047236fa3a8a76 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 21 Nov 2020 13:26:27 +0100 Subject: [PATCH 189/231] Add ability to set user to null (and add method clearUser) in Request. --- src/Neuron/Net/Request.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index 5cbb319..e25b7c3 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -428,7 +428,7 @@ public function input ($field, $type = 'string', $default = null, $separator = ' * @param User $user * @return $this */ - public function setUser (User $user) + public function setUser (User $user = null) { $this->user = $user; return $this; @@ -502,6 +502,14 @@ public function getUser ($callbackName = null) return $this->user; } + /** + * + */ + public function clearUser() + { + $this->setUser(null); + } + /** * Evaluate a route and return the parameters. * @param Route $route @@ -539,4 +547,4 @@ public function parseRoute (Route $route) { return false; } -} \ No newline at end of file +} From 30b9d9318a4fdedabd6a5210125a5ed3b9965690 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 25 Nov 2020 23:22:42 +0100 Subject: [PATCH 190/231] Add ability to set php session from query string. Old code is old. --- src/Neuron/SessionHandlers/SessionHandler.php | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Neuron/SessionHandlers/SessionHandler.php b/src/Neuron/SessionHandlers/SessionHandler.php index d87e690..86896a5 100644 --- a/src/Neuron/SessionHandlers/SessionHandler.php +++ b/src/Neuron/SessionHandlers/SessionHandler.php @@ -1,21 +1,21 @@ started) @@ -31,8 +31,11 @@ public final function start ($sessionId = null) Logger::getInstance ()->log ("Starting session with provided id " . $sessionId, false, 'cyan'); } elseif ($defaultSession = Tools::getInput ($_COOKIE, 'PHPSESSID', 'varchar')) { - Logger::getInstance ()->log ("Starting session with default cookie " . $defaultSession, false, 'cyan'); - session_id ($defaultSession); + Logger::getInstance()->log("Starting session with default cookie " . $defaultSession, false, 'cyan'); + session_id($defaultSession); + } elseif ($queryParamSession = Tools::getInput ($_GET, self::SESSION_QUERY_PARAMETER, 'varchar')) { + Logger::getInstance()->log("Starting session with query parameter " . $queryParamSession, false, 'cyan'); + session_id($queryParamSession); } elseif (session_status() == PHP_SESSION_ACTIVE) { session_regenerate_id (); Logger::getInstance ()->log ("Starting brand new session with id " . session_id (), false, 'cyan'); @@ -52,6 +55,14 @@ public final function stop () $this->started = false; } + /** + * @return string + */ + public function getSessionQueryString() + { + return self::SESSION_QUERY_PARAMETER . '=' . session_id(); + } + /* Methods */ public function close () { @@ -96,4 +107,4 @@ public function register () array($this, 'gc') ); } -} \ No newline at end of file +} From df8f6ebabe10bac3fa583e93dfddc925a0b01eed Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 25 Nov 2020 23:27:32 +0100 Subject: [PATCH 191/231] Add ability to set php session from query string. Old code is old. --- src/Neuron/Net/Session.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Net/Session.php b/src/Neuron/Net/Session.php index 6552d0b..3d7d843 100644 --- a/src/Neuron/Net/Session.php +++ b/src/Neuron/Net/Session.php @@ -80,4 +80,12 @@ public function get ($key) } return null; } -} \ No newline at end of file + + /** + * @return string + */ + public function getSessionQueryString() + { + return $this->handler->getSessionQueryString(); + } +} From a72bc06880c3630404f0c5d5c173c2bfb6acc2a1 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 29 Nov 2020 15:21:54 +0100 Subject: [PATCH 192/231] Make setDomain chainable. --- src/Neuron/Tools/Text.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Tools/Text.php b/src/Neuron/Tools/Text.php index afeb89f..d0156e0 100644 --- a/src/Neuron/Tools/Text.php +++ b/src/Neuron/Tools/Text.php @@ -37,11 +37,13 @@ public function addPath ($domain, $path) } /** - * @param string $domain + * @param $domain + * @return $this */ public function setDomain ($domain) { $this->domain = $domain; + return $this; } /** @@ -72,4 +74,4 @@ public static function get ($message1, $message2 = null, $n = null) $in = self::getInstance (); return $in->getText ($message1, $message2, $n); } -} \ No newline at end of file +} From 68d4e42fc2cec2ba3f2e85bcc83f2eff443c7f9c Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 19 Jan 2021 23:29:59 +0100 Subject: [PATCH 193/231] Add ability to add parameters to Template::combine(). --- src/Neuron/Core/Template.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index e1bac7f..0f7fded 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -334,8 +334,11 @@ private function layout ($layout) /** * Go trough all set template directories and search for * a specific template. Concat all of them. + * @param $template + * @param array $parameters + * @return false|string */ - private function combine ($template) + private function combine ($template, $parameters = []) { ob_start(); @@ -347,6 +350,10 @@ private function combine ($template) ${$k} = $v; } + foreach ($parameters as $k => $v) { + ${$k} = $v; + } + if ($ctlbtmpltfiles = $this->getFilenames($template, true)) { foreach ($ctlbtmpltfiles as $ctlbtmpltfile) { include $ctlbtmpltfile; @@ -459,4 +466,4 @@ private function getURL ($path, array $params = null, $normalize = true, $appurl public function __toString () { return $this->parse (); } -} \ No newline at end of file +} From e8f99e0f66155be705dde5e38053de8225cdaaf3 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 28 Jan 2021 12:05:36 +0100 Subject: [PATCH 194/231] Passwords should have a minimum length of 8 characters. --- src/Neuron/Core/Tools.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index 8fe7d24..56e98e3 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -82,7 +82,8 @@ public static function checkInput ($value, $type) elseif ($type == 'password') { - return self::isValidUTF8 ($value) && strlen ($value) > 2; + // Minimum 8 characters + return self::isValidUTF8 ($value) && strlen ($value) > 7; } elseif ($type == 'email') From cebaab82a9c51de90ac2145058b46e59387ff150 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 28 Jan 2021 22:06:40 +0100 Subject: [PATCH 195/231] Change the user interface (i can do that since nobody is using this project) --- src/Neuron/Interfaces/Models/User.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Interfaces/Models/User.php b/src/Neuron/Interfaces/Models/User.php index f2d406a..915046f 100644 --- a/src/Neuron/Interfaces/Models/User.php +++ b/src/Neuron/Interfaces/Models/User.php @@ -5,13 +5,14 @@ interface User extends \Neuron\Interfaces\Model { /** + * @param bool $formal * @return string */ - public function getUsername (); + public function getDisplayName ($formal = false); /** * @return string */ public function getEmail (); -} \ No newline at end of file +} From 99238138dd77872e7db825ea0d9a46cd187b0711 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 17 Feb 2021 08:59:51 +0100 Subject: [PATCH 196/231] Absolutely no idea why I need to set the LANGUAGE environment variable instead of the LANGUAGE one... but hey this works on my working station. --- src/Neuron/Application.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index ce1452c..86943f3 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -81,6 +81,7 @@ public function setLocale ($locale) // Also let php know putenv ("LANG=" . $this->locale); + putenv ("LANGUAGE=" . $this->locale); $result = setlocale (LC_ALL, $this->locale); if (!$result) @@ -179,4 +180,4 @@ public function dispatch (Request $request = null) // End $this->trigger ('dispatch:terminate'); } -} \ No newline at end of file +} From de1bdd69a71267f01e595e8108f552d816a4ca98 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 17 Feb 2021 22:22:26 +0100 Subject: [PATCH 197/231] Add getLanguage method to Application. --- src/Neuron/Application.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index 86943f3..77990e1 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -99,13 +99,20 @@ public function getLocale () return $this->locale; } + /** + * @return string + */ + public function getLanguage() + { + return substr($this->locale, 0, 2); + } + /** * Check if locale is set, and if not, set it to english. */ private function checkLocale () { - if (!isset ($this->locale)) - { + if (!isset ($this->locale)) { $this->setLocale ('en_GB.utf8'); } } From ffed5b56d9a51dfe6db6ff4facc57589a4760954 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 19 Feb 2021 14:20:27 +0100 Subject: [PATCH 198/231] Fix clearUser so that it will call the user callback again. --- src/Neuron/Net/Request.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index e25b7c3..daf2ce4 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -508,6 +508,7 @@ public function getUser ($callbackName = null) public function clearUser() { $this->setUser(null); + $this->usercallbackcalled = false; } /** From 68f604687e2b10f3a8c403e6600e9d5d82dc045d Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 28 Feb 2021 01:36:14 +0100 Subject: [PATCH 199/231] Add array of tracking parameters. --- src/Neuron/Net/QueryTrackingParameters.php | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/Neuron/Net/QueryTrackingParameters.php diff --git a/src/Neuron/Net/QueryTrackingParameters.php b/src/Neuron/Net/QueryTrackingParameters.php new file mode 100644 index 0000000..d84312f --- /dev/null +++ b/src/Neuron/Net/QueryTrackingParameters.php @@ -0,0 +1,33 @@ + Date: Sun, 28 Feb 2021 02:11:20 +0100 Subject: [PATCH 200/231] Add piwik visitor tracking to tracking parameters. --- src/Neuron/Net/QueryTrackingParameters.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Net/QueryTrackingParameters.php b/src/Neuron/Net/QueryTrackingParameters.php index d84312f..e8bbc5f 100644 --- a/src/Neuron/Net/QueryTrackingParameters.php +++ b/src/Neuron/Net/QueryTrackingParameters.php @@ -28,6 +28,7 @@ public function instance() 'utm_campaign', 'utm_term', 'utm_content', - '_ga' + '_ga', + 'pk_vid' ]; } From 359c08ebed98f50d9a26b480d2d8890fb0a34f31 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 28 Feb 2021 02:15:20 +0100 Subject: [PATCH 201/231] Add piwik visitor tracking to tracking parameters. --- src/Neuron/Net/QueryTrackingParameters.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Neuron/Net/QueryTrackingParameters.php b/src/Neuron/Net/QueryTrackingParameters.php index e8bbc5f..09e50f7 100644 --- a/src/Neuron/Net/QueryTrackingParameters.php +++ b/src/Neuron/Net/QueryTrackingParameters.php @@ -29,6 +29,7 @@ public function instance() 'utm_term', 'utm_content', '_ga', + '_gac', 'pk_vid' ]; } From 47931811840b1e749dfdcb152324114291610266 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 28 Feb 2021 02:45:33 +0100 Subject: [PATCH 202/231] Make QueryTrackingParameters::instance static. --- src/Neuron/Net/QueryTrackingParameters.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Net/QueryTrackingParameters.php b/src/Neuron/Net/QueryTrackingParameters.php index 09e50f7..1f65749 100644 --- a/src/Neuron/Net/QueryTrackingParameters.php +++ b/src/Neuron/Net/QueryTrackingParameters.php @@ -11,7 +11,7 @@ class QueryTrackingParameters /** * @return QueryTrackingParameters */ - public function instance() + public static function instance() { static $in; if (!isset($in)) { From a2528fa893512e538616ef82cbc5c77f11e89cdc Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 5 Mar 2021 12:39:55 +0100 Subject: [PATCH 203/231] Change the way mysql error are handled. --- src/Neuron/DB/MySQL.php | 17 ++++------------- src/Neuron/Exceptions/DbException.php | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/Neuron/DB/MySQL.php b/src/Neuron/DB/MySQL.php index c9c7d8e..60723e9 100755 --- a/src/Neuron/DB/MySQL.php +++ b/src/Neuron/DB/MySQL.php @@ -148,19 +148,10 @@ public function query ($sSQL, $log = true) $this->addQueryLog($sSQL, $duration); } - if (!$result) - { - //var_dump (debug_backtrace ()); - //$data = debug_backtrace (); - //print_r ($data); - - - echo $sSQL; - throw new DbException ('MySQL Error: '.$this->connection->error); - } - - elseif ($result instanceof MySQLi_Result) - { + if (!$result) { + throw (new DbException ('MySQL Error: '.$this->connection->error)) + ->setErrorCode($this->connection->errno); + } elseif ($result instanceof MySQLi_Result) { return new Result ($result); } diff --git a/src/Neuron/Exceptions/DbException.php b/src/Neuron/Exceptions/DbException.php index ea804c5..f819fa9 100644 --- a/src/Neuron/Exceptions/DbException.php +++ b/src/Neuron/Exceptions/DbException.php @@ -9,6 +9,8 @@ class DbException { private $query; + private $mysqlErrorCode; + /** * @param string $query */ @@ -16,5 +18,22 @@ public function setQuery ($query) { $this->query = $query; } + + /** + * @param $status + * @return $this + */ + public function setErrorCode($status) + { + $this->mysqlErrorCode = $status; + return $this; + } + + /** + * @return mixed + */ + public function getErrorCode() + { + return $this->mysqlErrorCode; + } } -?> From 05b0b66bab000b275758b3a1c13bcc4ed7886382 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 7 Mar 2021 16:52:12 +0100 Subject: [PATCH 204/231] Make query tracking parameters configurable. --- src/Neuron/Net/QueryTrackingParameters.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Net/QueryTrackingParameters.php b/src/Neuron/Net/QueryTrackingParameters.php index 1f65749..dc3441c 100644 --- a/src/Neuron/Net/QueryTrackingParameters.php +++ b/src/Neuron/Net/QueryTrackingParameters.php @@ -2,6 +2,8 @@ namespace Neuron\Net; +use Neuron\Config; + /** * Class QueryTrackingParameters * @package Neuron\Net @@ -16,6 +18,11 @@ public static function instance() static $in; if (!isset($in)) { $in = new self(); + + // Can we set these from config? + if (Config::get('tracking.queryParameters')) { + $in->queryParameters = Config::get('tracking.queryParameters'); + } } return $in; } @@ -30,6 +37,7 @@ public static function instance() 'utm_content', '_ga', '_gac', - 'pk_vid' + 'pk_vid', + '_gl' ]; } From 3e612c369439837e0a74574eeb329912e4a36a60 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Thu, 29 Apr 2021 15:20:21 +0200 Subject: [PATCH 205/231] Add additional parameter to template folder. --- src/Neuron/Core/Template.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 0f7fded..057483d 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -368,8 +368,11 @@ private function combine ($template, $parameters = []) /** * Include a single template inside another template. + * @param $template + * @param array $parameters + * @return false|string */ - private function template ($template) + private function template ($template, $parameters = []) { ob_start(); @@ -381,6 +384,10 @@ private function template ($template) ${$k} = $v; } + foreach ($parameters as $k => $v) { + ${$k} = $v; + } + if ($ctlbtmpltfiles = $this->getFilenames($template)) { foreach ($ctlbtmpltfiles as $ctlbtmpltfile) { include $ctlbtmpltfile; From 4a0e0cccb4fe810fea923fc8a3f661571cb74bbf Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Tue, 11 May 2021 10:44:01 +0200 Subject: [PATCH 206/231] Fix content parsing when headers are sent lowercase. --- src/Neuron/Net/Entity.php | 262 ++++++++++++++++++-------------------- 1 file changed, 122 insertions(+), 140 deletions(-) diff --git a/src/Neuron/Net/Entity.php b/src/Neuron/Net/Entity.php index d009b6e..a48cc0b 100644 --- a/src/Neuron/Net/Entity.php +++ b/src/Neuron/Net/Entity.php @@ -11,13 +11,14 @@ * Class Entity * @package Neuron\Net */ -abstract class Entity { +abstract class Entity +{ const CHECK_SIGNATURE = false; /** - * @var Session $session - */ + * @var Session $session + */ private $session; private $body; @@ -47,74 +48,64 @@ abstract class Entity { * @return \Neuron\Net\Request * @throws \Neuron\Exceptions\InvalidParameter */ - public function setFromData ($data) + public function setFromData($data) { // Check signature $model = $this; $chk = self::CHECK_SIGNATURE; - if ($chk && !isset ($data['signature'])) - { + if ($chk && !isset ($data['signature'])) { throw new InvalidParameter ("All decoded requests must have a signature."); } - if ($chk && $data['signature'] != self::calculateSignature ($data)) - { + if ($chk && $data['signature'] != self::calculateSignature($data)) { throw new InvalidParameter ("Leave now, and Never come Back! *gollem, gollem* (Decoded request signature mismatch)."); } // The body. If data is found, body is not used. - if (isset ($data['data']) && !empty ($data['data'])) - { - $model->setData ($data['data']); - } - - else if (isset ($data['body'])) - { - $model->setBody ($data['body']); + if (isset ($data['data']) && !empty ($data['data'])) { + $model->setData($data['data']); + } else if (isset ($data['body'])) { + $model->setBody($data['body']); } - if (isset ($data['headers'])) - { - $model->setHeaders ($data['headers']); + if (isset ($data['headers'])) { + $model->setHeaders($data['headers']); } - if (isset ($data['cookies'])) - { - $model->setCookies ($data['cookies']); + if (isset ($data['cookies'])) { + $model->setCookies($data['cookies']); } - if (isset ($data['post'])) - { - $model->setPost ($data['post']); + if (isset ($data['post'])) { + $model->setPost($data['post']); } - if (isset ($data['status'])) - { - $model->setStatus ($data['status']); + if (isset ($data['status'])) { + $model->setStatus($data['status']); } return $model; } - protected function parseData () { - - $headers = $this->getHeaders (); - if (isset ($headers['Content-Type'])) - { - switch (strtolower ($headers['Content-Type'])) - { + /** + * Parse data based on content type. + */ + protected function parseData() + { + $contentType = $this->getHeader('content-type'); + if ($contentType) { + switch (strtolower($contentType)) { case 'application/json': case 'text/json': - $data = json_decode ($this->getBody (), true); + $data = json_decode($this->getBody(), true); if (!$data) { - $this->setError ('JSON decode error: ' . json_last_error_msg ()); - } - else { - $this->setData ($data); + $this->setError('JSON decode error: ' . json_last_error_msg()); + } else { + $this->setData($data); } break; @@ -128,25 +119,23 @@ protected function parseData () { /** * @return array */ - public function getJSONData () + public function getJSONData() { - $data = array (); + $data = array(); - if ($this->getData ()) - { - $plaindata = $this->getData (); - if (!empty ($plaindata)) - { - $data['data'] = $this->getData (); + if ($this->getData()) { + $plaindata = $this->getData(); + if (!empty ($plaindata)) { + $data['data'] = $this->getData(); } } - $data['body'] = $this->getBody (); + $data['body'] = $this->getBody(); - $data['headers'] = $this->getHeaders (); - $data['cookies'] = $this->getCookies (); - $data['post'] = $this->getPost (); - $data['status'] = $this->getStatus (); + $data['headers'] = $this->getHeaders(); + $data['cookies'] = $this->getCookies(); + $data['post'] = $this->getPost(); + $data['status'] = $this->getStatus(); return $data; } @@ -155,23 +144,22 @@ public function getJSONData () * @param array $data * @return string */ - private static function calculateSignature (array $data) + private static function calculateSignature(array $data) { - $txt = self::calculateBaseString ($data); - return md5 ($txt); + $txt = self::calculateBaseString($data); + return md5($txt); } - private static function calculateBaseString (array $data) + private static function calculateBaseString(array $data) { unset ($data['signature']); $txt = '\(^-^)/ !Stupid Rainbow Tables! \(^-^)/ '; - foreach ($data as $k => $v) - { - $txt .= $k . ":" . json_encode ($v) . "|"; + foreach ($data as $k => $v) { + $txt .= $k . ":" . json_encode($v) . "|"; } - $txt .= Config::get ('app.secret'); + $txt .= Config::get('app.secret'); return $txt; } @@ -179,31 +167,29 @@ private static function calculateBaseString (array $data) /** * @return string json */ - public function toJSON () + public function toJSON() { - $data = $this->getJSONData (); - $data['random'] = mt_rand (); - $data['time'] = gmdate ('c'); - $data['signature'] = $this->calculateSignature ($data); - return json_encode ($data); + $data = $this->getJSONData(); + $data['random'] = mt_rand(); + $data['time'] = gmdate('c'); + $data['signature'] = $this->calculateSignature($data); + return json_encode($data); } /** - * @throws DataNotSet * @return \Neuron\Net\Session + * @throws DataNotSet */ - public function getSession () + public function getSession() { - if (!isset ($this->session)) - { + if (!isset ($this->session)) { // First check the router if ($this instanceof Response) { - $router = Application::getInstance ()->getRouter (); + $router = Application::getInstance()->getRouter(); if ($router) { - $this->session = $router->getRequest ()->getSession (); + $this->session = $router->getRequest()->getSession(); } - } - else { + } else { throw new DataNotSet ("No session is set in the request."); } } @@ -214,7 +200,7 @@ public function getSession () * @param Session $session * @return $this */ - public function setSession (Session $session) + public function setSession(Session $session) { $this->session = $session; return $this; @@ -224,7 +210,7 @@ public function setSession (Session $session) * @param $body * @return $this */ - public function setBody ($body) + public function setBody($body) { $this->body = $body; return $this; @@ -233,7 +219,7 @@ public function setBody ($body) /** * @return mixed */ - public function getBody () + public function getBody() { return $this->body; } @@ -242,16 +228,16 @@ public function getBody () * @param $id * @return $this */ - public function setApplication ($id) + public function setApplication($id) { - $this->setSession ('application', $id); + $this->setSession('application', $id); return $this; } /** * @return mixed */ - public function getApplication () + public function getApplication() { return $this->application; } @@ -260,7 +246,7 @@ public function getApplication () * @param $path * @return $this */ - public function setPath ($path) + public function setPath($path) { $this->path = $path; return $this; @@ -269,7 +255,7 @@ public function setPath ($path) /** * @return mixed */ - public function getPath () + public function getPath() { return $this->path; } @@ -278,7 +264,7 @@ public function getPath () * @param array $post * @return $this */ - public function setPost ($post) + public function setPost($post) { $this->post = $post; return $this; @@ -287,7 +273,7 @@ public function setPost ($post) /** * @return array */ - public function getPost () + public function getPost() { return $this->post; } @@ -296,7 +282,7 @@ public function getPost () * @param mixed $data * @return $this */ - public function setData ($data) + public function setData($data) { $this->data = $data; return $this; @@ -305,7 +291,7 @@ public function setData ($data) /** * @return mixed */ - public function getData () + public function getData() { return $this->data; } @@ -313,16 +299,14 @@ public function getData () /** * Check if request has data */ - public function hasData () + public function hasData() { - if (!isset ($this->data)) - { + if (!isset ($this->data)) { if (!isset ($this->error)) - $this->setError ('No input data set'); + $this->setError('No input data set'); return false; - } - else { + } else { return true; } } @@ -332,11 +316,10 @@ public function hasData () * @param string $value * @return $this */ - public function setHeader ($name, $value = null) + public function setHeader($name, $value = null) { - if (!isset ($this->headers)) - { - $this->headers = array (); + if (!isset ($this->headers)) { + $this->headers = array(); } $this->headers[$name] = $value; return $this; @@ -346,7 +329,7 @@ public function setHeader ($name, $value = null) * @param array $headers * @return $this */ - public function setHeaders ($headers) + public function setHeaders($headers) { $this->headers = $headers; return $this; @@ -355,67 +338,66 @@ public function setHeaders ($headers) /** * @return array */ - public function getHeaders () + public function getHeaders() { return $this->headers; } - /** - * @param $name - * @return string|null - */ + /** + * @param $name + * @return string|null + */ public function getHeader($name) - { - $name = $this->getSafeHeaderName($name); - foreach ($this->getHeaders() as $k => $v) { - if ($this->getSafeHeaderName($k) === $name) { - return $v; - } - } - return null; - } - - /** - * @param $name - * @return string - */ - protected function getSafeHeaderName($name) - { - $name = str_replace('-', '_', $name); - $name = str_replace('_', ' ', $name); - $name = strtolower($name); - $name = ucwords($name); - $name = str_replace(' ', '-', $name); - - return $name; - } - - public function setCookies ($cookies) + { + $name = $this->getSafeHeaderName($name); + foreach ($this->getHeaders() as $k => $v) { + if ($this->getSafeHeaderName($k) === $name) { + return $v; + } + } + return null; + } + + /** + * @param $name + * @return string + */ + protected function getSafeHeaderName($name) + { + $name = str_replace('-', '_', $name); + $name = str_replace('_', ' ', $name); + $name = strtolower($name); + $name = ucwords($name); + $name = str_replace(' ', '-', $name); + + return $name; + } + + public function setCookies($cookies) { $this->cookies = $cookies; return $this; } - public function getCookies () + public function getCookies() { return $this->cookies; } - public function setStatus ($status) + public function setStatus($status) { $this->status = $status; return $this; } - public function isStatusSet () + public function isStatusSet() { return isset ($this->status); } - public function getStatus () + public function getStatus() { - if (isset ($this->status)) - { + if (isset ($this->status)) { return $this->status; } return 200; @@ -425,7 +407,7 @@ public function getStatus () * @param $error * @return $this */ - public function setError ($error) + public function setError($error) { $this->error = $error; return $this; @@ -434,7 +416,7 @@ public function setError ($error) /** * @return string */ - public function getError () + public function getError() { return $this->error; } @@ -443,8 +425,8 @@ public function getError () * Return an error response. * @return Response */ - public function getErrorResponse () + public function getErrorResponse() { - return Response::error ($this->getError (), self::STATUS_INVALID_INPUT); + return Response::error($this->getError(), self::STATUS_INVALID_INPUT); } -} \ No newline at end of file +} From 9ee32eeb6df67fbfb5118c99513011b9f2b213b3 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 21 May 2021 11:40:15 +0200 Subject: [PATCH 207/231] Make some changes to the error collection to be able to return localized errors. --- src/Neuron/Collections/ErrorCollection.php | 55 +++++++++- src/Neuron/Models/Error.php | 87 +++++++++++++++ src/Neuron/Models/Helpers/Errorable.php | 122 ++++++++++++--------- 3 files changed, 205 insertions(+), 59 deletions(-) create mode 100644 src/Neuron/Models/Error.php diff --git a/src/Neuron/Collections/ErrorCollection.php b/src/Neuron/Collections/ErrorCollection.php index bb19fdd..16e608d 100644 --- a/src/Neuron/Collections/ErrorCollection.php +++ b/src/Neuron/Collections/ErrorCollection.php @@ -8,18 +8,63 @@ namespace Neuron\Collections; +use Neuron\Models\Error; -class ErrorCollection - extends Collection { +/** + * Class ErrorCollection + * @package Neuron\Collections + */ +class ErrorCollection extends Collection { + + /** + * Add an error message in vsprintf syntax + * @param $errorMessage + * @param array $arguments + * @return Error + */ + public function addError($errorMessage, $arguments = []) + { + $error = new Error($errorMessage, $arguments); + $this->add($error); + + return $error; + } + /** + * @return array + */ + public function getLocalisableData() + { + $out = array (); + foreach ($this as $v) { + if ($v instanceof Error) { + $out[] = [ + 'message' => $v->getMessage(), + 'template' => $v->getTemplate(), + 'arguments' => $v->getArguments(), + 'subject' => $v->getSubject() + ]; + } else { + $out[] = [ + 'message' => $v->getMessage(), + 'template' => $v->getMessage(), + 'arguments' => [], + 'subject' => null + ]; + } + } + return $out; + } + + /** + * @return string[] + */ public function getData () { $out = array (); - foreach ($this as $v) $out[] = (string) $v; return $out; } - -} \ No newline at end of file +} diff --git a/src/Neuron/Models/Error.php b/src/Neuron/Models/Error.php new file mode 100644 index 0000000..21b3711 --- /dev/null +++ b/src/Neuron/Models/Error.php @@ -0,0 +1,87 @@ +template = $message; + $this->arguments = $arguments; + } + + /** + * @param string $subject + * @return $this + */ + public function setSubject($subject) + { + $this->subject = $subject; + return $this; + } + + /** + * @return string + */ + public function getSubject() + { + return $this->subject; + } + + /** + * @return string + */ + public function getTemplate() + { + return $this->template; + } + + /** + * @return mixed[] + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * @return string + */ + public function getMessage() + { + return vsprintf($this->getTemplate(), $this->getArguments()); + } + + /** + * @return string + */ + public function __toString() + { + return $this->getMessage(); + } +} diff --git a/src/Neuron/Models/Helpers/Errorable.php b/src/Neuron/Models/Helpers/Errorable.php index c59e318..20b2ee3 100644 --- a/src/Neuron/Models/Helpers/Errorable.php +++ b/src/Neuron/Models/Helpers/Errorable.php @@ -7,7 +7,9 @@ */ namespace Neuron\Models\Helpers; + use Neuron\Collections\ErrorCollection; +use Neuron\Models\Error; /** * Class Errorable @@ -19,65 +21,77 @@ abstract class Errorable { - /** - * @var string array - */ - private $errors = null; + /** + * @var ErrorCollection array + */ + private $errors = null; + + /** + * + */ + private function touchErrors() + { + if (!isset ($this->errors)) { + $this->setErrors($this->createErrorCollection()); + } + } - private function touchErrors () - { - if (!isset ($this->errors)) { - $this->setErrors (new ErrorCollection ()); - } - } + /** + * @return ErrorCollection + */ + protected function createErrorCollection() + { + return new ErrorCollection (); + } - /** - * @param string $error - */ - public function setError ($error) - { - call_user_func_array (array ($this, 'addError'), func_get_args ()); - } + /** + * @param string $error + */ + public function setError($error) + { + return call_user_func_array(array($this, 'addError'), func_get_args()); + } - /** - * Set the error array. By reference! - */ - public function setErrors (ErrorCollection $errors){ - $this->errors = $errors; - } + /** + * Set the error array. By reference! + */ + public function setErrors(ErrorCollection $errors) + { + $this->errors = $errors; + } - /** - * @return string|null - */ - public function getError () - { - $this->touchErrors (); - if (count ($this->errors) > 0) - { - return end ($this->errors); - } - return null; - } + /** + * @return string|null + */ + public function getError() + { + $this->touchErrors(); + if (count($this->errors) > 0) { + return end($this->errors); + } + return null; + } - /** - * @param $error - */ - public function addError ($error) - { - $args = func_get_args (); - array_shift ($args); + /** + * @param $error + * @return Error + */ + public function addError($error) + { + $args = func_get_args(); + array_shift($args); - $this->touchErrors (); - $this->errors[] = vsprintf ($error, $args); - } + $this->touchErrors(); + return $this->errors->addError($error, $args); + } - /** - * @return ErrorCollection - */ - public function getErrors () - { - $this->touchErrors (); - return $this->errors; - } + /** + * @return ErrorCollection + */ + public function getErrors() + { + $this->touchErrors(); + return $this->errors; + } -} \ No newline at end of file +} From f37af7bc0281fb6a82eb14a2b7a9e6a5c5dcd83c Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 21 May 2021 11:46:07 +0200 Subject: [PATCH 208/231] Rename getLocalisableData to getDetailedData and add code property. --- src/Neuron/Collections/ErrorCollection.php | 8 +++++--- src/Neuron/Models/Error.php | 23 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Neuron/Collections/ErrorCollection.php b/src/Neuron/Collections/ErrorCollection.php index 16e608d..721fe0e 100644 --- a/src/Neuron/Collections/ErrorCollection.php +++ b/src/Neuron/Collections/ErrorCollection.php @@ -33,7 +33,7 @@ public function addError($errorMessage, $arguments = []) /** * @return array */ - public function getLocalisableData() + public function getDetailedData() { $out = array (); foreach ($this as $v) { @@ -42,14 +42,16 @@ public function getLocalisableData() 'message' => $v->getMessage(), 'template' => $v->getTemplate(), 'arguments' => $v->getArguments(), - 'subject' => $v->getSubject() + 'subject' => $v->getSubject(), + 'code' => $v->getCode() ]; } else { $out[] = [ 'message' => $v->getMessage(), 'template' => $v->getMessage(), 'arguments' => [], - 'subject' => null + 'subject' => null, + 'code' => null ]; } } diff --git a/src/Neuron/Models/Error.php b/src/Neuron/Models/Error.php index 21b3711..d31aa7f 100644 --- a/src/Neuron/Models/Error.php +++ b/src/Neuron/Models/Error.php @@ -24,6 +24,11 @@ class Error */ private $subject; + /** + * @var string + */ + private $code; + /** * Error constructor. * @param $message @@ -45,6 +50,16 @@ public function setSubject($subject) return $this; } + /** + * @param $code + * @return $this + */ + public function setCode($code) + { + $this->code = $code; + return $this; + } + /** * @return string */ @@ -69,6 +84,14 @@ public function getArguments() return $this->arguments; } + /** + * @return string + */ + public function getCode() + { + return $this->code; + } + /** * @return string */ From 81b56dac9646fe86f9aee088da06f79641fe4522 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sat, 26 Jun 2021 16:15:31 +0200 Subject: [PATCH 209/231] Only initiate a session if a route requests the 'session' filter. --- src/Neuron/Application.php | 35 +++++++++++++++++------ src/Neuron/Router.php | 58 +++++++++++++++++++++++++++++--------- 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index 77990e1..c91981a 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -11,9 +11,9 @@ use Neuron\Core\Template; use Neuron\Exceptions\DataNotSet; use Neuron\Models\Observable; +use Neuron\Models\Router\Filter; use Neuron\Net\Request; use Neuron\Net\Session; -use Neuron\SessionHandlers\DefaultSessionHandler; use Neuron\SessionHandlers\SessionHandler; class Application @@ -32,6 +32,11 @@ class Application /** @var bool */ private $isFirstDispatch = true; + /** + * @var Session|null + */ + private $session = null; + private static $in; /** @@ -60,6 +65,23 @@ private function __construct () public function setRouter (Router $router) { $this->router = $router; + + // Here we will make a special filter called 'session' that initiates the session handler if it is requested + // by the router. We will also make sure that the session filter is the first one to be loaded. + // Yes, this isn't perfect design, but this framework is 10-ish years old and only used for a few self made projects. + $this->router->addFilter('session', function(Filter $filter) { + + // Set session from the session handler + $this->session = new Session ($this->getSessionHandler()); + $this->session->connect(); + + // Set session in request + $filter->getRequest()->setSession($this->session); + + return true; + + }, 100); + $this->trigger ('router:set'); } @@ -165,13 +187,6 @@ public function dispatch (Request $request = null) $request = Request::fromInput (); } - // Set session from the session handler - $session = new Session ($this->getSessionHandler ()); - $session->connect (); - - // Set session in request - $request->setSession ($session); - // Trigger before $this->trigger ('dispatch:before', $request); @@ -182,7 +197,9 @@ public function dispatch (Request $request = null) $this->trigger ('dispatch:after', $request); // Disconnect the session - $session->disconnect (); + if ($this->session) { + $this->session->disconnect(); + } // End $this->trigger ('dispatch:terminate'); diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 6c85e39..cc9c9ad 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -50,7 +50,7 @@ class Router { /** @var Module|null */ private $module = null; - /** @var callable[] */ + /** @var [callable[],int] */ private $filters = array (); /** @@ -275,10 +275,14 @@ private function handle ($routes) { * Add a filter that can be added. * @param string $filtername * @param callable $method + * @param int $priority */ - public function addFilter ($filtername, callable $method = null) + public function addFilter ($filtername, callable $method = null, $priority = 0) { - $this->filters[$filtername] = $method; + $this->filters[$filtername] = [ + 'callback' => $method, + 'priority' => $priority + ]; } /** @@ -296,23 +300,49 @@ private function handleMatch (Route $route, $params) } // First handle the filters + + // Find all filters that need to be execued + $filtersToExecute = []; + foreach ($route->getFilters () as $filter) { // Check if exist - if (!isset ($this->filters[$filter->getName ()])) - throw new InvalidParameter ("Filter " . $filter->getName () . " is not registered in the router."); + if (!isset ($this->filters[$filter->getName ()])) { + throw new InvalidParameter ("Filter " . $filter->getName() . " is not registered in the router."); + } - $filter->setRequest ($this->request); - $response = $filter->check ($this->filters[$filter->getName ()]); - $filter->clearRequest (); + $filterCallback = $this->filters[$filter->getName()]; - // If output was not TRUE, handle the filter return value as output. - if ($response !== true) { - $this->output ($response); - return; - } + $filtersToExecute[] = [ + 'callback' => $filterCallback['callback'], + 'priority' => $filterCallback['priority'], + 'filter' => $filter + ]; } + // order filters on priority + usort($filtersToExecute, function($a, $b) { + if ($a['priority'] == $b['priority']) { + return 0; + } + return $a['priority'] < $b['priority'] ? 1 : -1; + }); + + foreach ($filtersToExecute as $v) { + + $filter = $v['filter']; + + $filter->setRequest ($this->request); + $response = $filter->check ($v['callback']); + $filter->clearRequest (); + + // If output was not TRUE, handle the filter return value as output. + if ($response !== true) { + $this->output ($response); + return; + } + } + if (is_callable ($function)) { $response = call_user_func_array($function, $params); @@ -378,4 +408,4 @@ private function handleController ($controller, $method, $params, $module = null } } -} \ No newline at end of file +} From a7c5cbcf7d0138dfa31ffc09e44553b9cb4f3bf5 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 28 Jun 2021 11:04:28 +0200 Subject: [PATCH 210/231] Add 'dispatch:post-filters' event to router. --- src/Neuron/Application.php | 10 ++++++++++ src/Neuron/Router.php | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index c91981a..c02cd2f 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -65,6 +65,7 @@ private function __construct () public function setRouter (Router $router) { $this->router = $router; + $router->setApplication($this); // Here we will make a special filter called 'session' that initiates the session handler if it is requested // by the router. We will also make sure that the session filter is the first one to be loaded. @@ -83,6 +84,7 @@ public function setRouter (Router $router) }, 100); $this->trigger ('router:set'); + } /** @@ -204,4 +206,12 @@ public function dispatch (Request $request = null) // End $this->trigger ('dispatch:terminate'); } + + /** + * @param Request $request + */ + public function postFilters(Request $request) + { + $this->trigger ('dispatch:post-filters', $request); + } } diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index cc9c9ad..69e38d2 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -53,6 +53,19 @@ class Router { /** @var [callable[],int] */ private $filters = array (); + /** + * @var Application + */ + private $app; + + /** + * @param Application $app + */ + public function setApplication(Application $app) + { + $this->app = $app; + } + /** * Store a route and a handling function to be executed when accessed using one of the specified methods * @@ -343,6 +356,9 @@ private function handleMatch (Route $route, $params) } } + // trigger post filter events + $this->app->postFilters($this->request); + if (is_callable ($function)) { $response = call_user_func_array($function, $params); From f3c73a4dd600a2165ad42f9ab4ce50f3e8c2b2f8 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 28 Jun 2021 11:29:06 +0200 Subject: [PATCH 211/231] Add 'dispatch:session' event. --- src/Neuron/Application.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Neuron/Application.php b/src/Neuron/Application.php index c02cd2f..569d2a9 100644 --- a/src/Neuron/Application.php +++ b/src/Neuron/Application.php @@ -79,6 +79,7 @@ public function setRouter (Router $router) // Set session in request $filter->getRequest()->setSession($this->session); + $this->trigger('dispatch:session', $filter->getRequest()); return true; }, 100); From 8b32f23d9fb96bc7de35d1c06e2efd2275f03917 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 28 Jun 2021 12:03:56 +0200 Subject: [PATCH 212/231] Make 404 callback return the route. --- src/Neuron/Router.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index 69e38d2..f88b5f1 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -209,7 +209,6 @@ public function run (Request $request) //call_user_func($this->notFound); $this->handleMatch($this->notFound, array()); } else { - $request = Response::error('Page not found.', Response::STATUS_NOTFOUND); $request->output(); } @@ -234,13 +233,15 @@ public function getRequest () /** * Set the 404 handling function - * @param object $fn The function to be executed + * @param $fn + * @return Route|object */ public function set404($fn) { $this->notFound = new Route ("404"); $this->notFound->setFunction ($fn); - } + return $this->notFound; + } /** * Handle a a set of routes: if a match is found, execute the relating handling function From 9773f58989a0e7426d60f194e79e986edf392584 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Fri, 1 Oct 2021 17:59:08 +0200 Subject: [PATCH 213/231] Add _cc parameter to tracking codes. --- src/Neuron/Net/QueryTrackingParameters.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Net/QueryTrackingParameters.php b/src/Neuron/Net/QueryTrackingParameters.php index dc3441c..5a44141 100644 --- a/src/Neuron/Net/QueryTrackingParameters.php +++ b/src/Neuron/Net/QueryTrackingParameters.php @@ -38,6 +38,7 @@ public static function instance() '_ga', '_gac', 'pk_vid', - '_gl' + '_gl', + '_cc' ]; } From 4fa456beae39a8727e0a05f3cdc0fc785a6ceea7 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 21 Nov 2021 11:28:11 +0100 Subject: [PATCH 214/231] Fix routing issue with optional parameters. --- src/Neuron/Net/Request.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Neuron/Net/Request.php b/src/Neuron/Net/Request.php index daf2ce4..035531d 100644 --- a/src/Neuron/Net/Request.php +++ b/src/Neuron/Net/Request.php @@ -527,12 +527,15 @@ public function parseRoute (Route $route) { $params = array_map(function($match, $index) use ($matches) { // We have a following parameter: take the substring from the current param position until the next one's position (thank you PREG_OFFSET_CAPTURE) - if (isset($matches[$index+1]) && isset($matches[$index+1][0]) && is_array($matches[$index+1][0])) { + if ( + isset($matches[$index+1]) && + isset($matches[$index+1][0]) && + is_array($matches[$index+1][0]) && + $matches[$index+1][0][1] >= 0 + ) { return trim(substr($match[0][0], 0, $matches[$index+1][0][1] - $match[0][1]), '/'); - } - - // We have no following paramete: return the whole lot - else { + } else { + // We have no following paramete: return the whole lot return (isset($match[0][0]) ? trim($match[0][0], '/') : null); } From 4b2d6f7ac889f7d4498059c2d00720e2ad8fd905 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Sun, 6 Feb 2022 14:12:52 +0100 Subject: [PATCH 215/231] Add 'clear' method to collection. --- src/Neuron/Collections/Collection.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Neuron/Collections/Collection.php b/src/Neuron/Collections/Collection.php index 1e744d8..75734f2 100644 --- a/src/Neuron/Collections/Collection.php +++ b/src/Neuron/Collections/Collection.php @@ -249,4 +249,13 @@ public function last () end($this->data); return $this->data[key($this->data)]; } -} \ No newline at end of file + + /** + * Clear array + */ + public function clear () + { + $this->data = array (); + $this->rewind (); + } +} From 1ad53875118c2d84d2b9ae81c76ba214a055f774 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 6 Feb 2023 17:55:43 +0100 Subject: [PATCH 216/231] Add parameters to filters. --- src/Neuron/Models/Router/Filter.php | 7 ++++--- src/Neuron/Router.php | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Neuron/Models/Router/Filter.php b/src/Neuron/Models/Router/Filter.php index 63f30e3..430430d 100644 --- a/src/Neuron/Models/Router/Filter.php +++ b/src/Neuron/Models/Router/Filter.php @@ -85,10 +85,11 @@ public function getRequest () /** * @param $callback + * @param array $parameters * @return mixed */ - public function check ($callback) + public function check ($callback, $parameters = []) { - return call_user_func_array ($callback, array ($this)); + return call_user_func_array ($callback, array ($this, $parameters)); } -} \ No newline at end of file +} diff --git a/src/Neuron/Router.php b/src/Neuron/Router.php index f88b5f1..ec5f18e 100644 --- a/src/Neuron/Router.php +++ b/src/Neuron/Router.php @@ -347,7 +347,7 @@ private function handleMatch (Route $route, $params) $filter = $v['filter']; $filter->setRequest ($this->request); - $response = $filter->check ($v['callback']); + $response = $filter->check ($v['callback'], $params); $filter->clearRequest (); // If output was not TRUE, handle the filter return value as output. From 782329bd6c111275ee6888b9132fc9b7b5fdc369 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Mon, 31 Jul 2023 13:45:23 +0200 Subject: [PATCH 217/231] Set a max length to passwords. --- src/Neuron/Core/Tools.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index 56e98e3..f3c2111 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -82,8 +82,10 @@ public static function checkInput ($value, $type) elseif ($type == 'password') { - // Minimum 8 characters - return self::isValidUTF8 ($value) && strlen ($value) > 7; + // Minimum 8 characters, maximum 256 characters. + return self::isValidUTF8 ($value) + && strlen ($value) > 7 + && strlen ($value) <= 256; } elseif ($type == 'email') From add23f21601dd8f92f5ea8d4dd0b267bda15ee41 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 4 Oct 2023 23:11:39 +0200 Subject: [PATCH 218/231] Apply strip_tags to all input that is not raw or html. (Breaking change but nobody uses this anyway) --- src/Neuron/Core/Tools.php | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index f3c2111..ed82b39 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -35,19 +35,19 @@ public static function getInput ($dat, $key, $type, $default = null) case 'date': $time = explode ('-', $dat[$key]); return mktime (0, 0, 1, $time[1], $time[2], $time[0]); - break; case 'datetime': return new DateTime ($dat[$key]); - break; case 'base64': return base64_decode ($dat[$key]); - break; - default: + case 'html': + case 'raw': return $dat[$key]; - break; + + default: + return strip_tags($dat[$key]); } } @@ -70,12 +70,17 @@ public static function checkInput ($value, $type) return true; } - else if ($type == 'bool') + elseif ($type == 'bool') { return $value == 1 || $value == 'true'; } - elseif ($type == 'varchar' || $type == 'string') + elseif ($type == 'varchar' || $type == 'string' || $type == 'html') + { + return self::isValidUTF8 ($value); + } + + elseif ($type === 'name') { return self::isValidUTF8 ($value); } @@ -151,6 +156,11 @@ public static function checkInput ($value, $type) { return is_numeric ($value) && (int)$value == $value; } + + elseif ($type == 'raw') + { + return true; + } else { From bd4aed7bc90454744066398b0ab80dcbccf0e074 Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 4 Oct 2023 23:15:57 +0200 Subject: [PATCH 219/231] Make name field more strict. --- src/Neuron/Core/Tools.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index ed82b39..4c88481 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -82,7 +82,7 @@ public static function checkInput ($value, $type) elseif ($type === 'name') { - return self::isValidUTF8 ($value); + return self::isValidUTF8 ($value) && strip_tags($value) === $value; } elseif ($type == 'password') From 58a8c581e6130cd62c2662b9217ac5370bf27fdf Mon Sep 17 00:00:00 2001 From: Thijs Van der Schaeghe Date: Wed, 4 Oct 2023 23:40:24 +0200 Subject: [PATCH 220/231] htmlentity() all template input before it goes out by default, unless it is set raw. --- src/Neuron/Core/Template.php | 70 +++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/src/Neuron/Core/Template.php b/src/Neuron/Core/Template.php index 057483d..b469e7e 100755 --- a/src/Neuron/Core/Template.php +++ b/src/Neuron/Core/Template.php @@ -10,10 +10,11 @@ class Template { private $values = array (); - + private $rawValues = array (); + private $sTextFile = null; private $sTextSection = null; - + private $objText = null; private $layoutRender = null; @@ -32,10 +33,10 @@ class Template /** @var array $helpers */ static $helpers = array (); - + public static function load () { - + } /** @@ -80,8 +81,8 @@ public static function addHelper ($name, $helper) } /** - * I believe this is a nicer way to do the directory setting. - */ + * I believe this is a nicer way to do the directory setting. + */ public static function setPath ($path) { self::$paths = array (); @@ -95,7 +96,7 @@ public static function setPath ($path) * @param $path: path to add * @param $prefix: only templates starting with given prefix will be loaded from this path. * @param $priority - */ + */ public static function addPath ($path, $prefix = '', $priority = 0) { if (substr ($path, -1) !== '/') @@ -141,7 +142,7 @@ public static function getPaths () private function setTextSection ($sTextSection, $sTextFile = null) { $this->sTextSection = $sTextSection; - + if (isset ($sTextFile)) { $this->sTextFile = $sTextFile; @@ -169,7 +170,13 @@ private function setTextFile ($sTextFile) */ public function set ($var, $value, $overwrite = false, $first = false) { - $this->setVariable ($var, $value, $overwrite, $first); + $this->setVariable ($var, $value, $overwrite, $first, false); + return $this; + } + + public function setRaw($var, $value, $overwrite = false, $first = false) + { + $this->setVariable ($var, $value, $overwrite, $first, true); return $this; } @@ -179,23 +186,27 @@ public function set ($var, $value, $overwrite = false, $first = false) * @param bool $overwrite * @param bool $first */ - private function setVariable ($var, $value, $overwrite = false, $first = false) + private function setVariable ($var, $value, $overwrite = false, $first = false, $raw = false) { + if ($raw) { + $this->rawValues[$var] = true; + } + if ($overwrite) { $this->values[$var] = $value; } - + else { if (isset ($this->values[$var])) { if ($first) { $this->values[$var] = $value.$this->values[$var]; } - + else { $this->values[$var].= $value; } } - + else { $this->values[$var] = $value; } @@ -251,9 +262,9 @@ private static function getFilenames ($template, $all = false) { return $out; } - return false; + return false; } - + public static function hasTemplate ($template) { return self::getFilenames ($template) ? true : false; @@ -283,15 +294,25 @@ public function parse ($template = null, $text = null) foreach (self::$shares as $k => $v) { - ${$k} = $v; + if (is_string($v) && !$this->isRaw($k)) { + ${$k} = htmlentities($v); + ${'_' . $k . '_'} = $v; + } else { + ${$k} = $v; + } } foreach ($this->values as $k => $v) { - ${$k} = $v; + if (is_string($v) && !$this->isRaw($k)) { + ${$k} = htmlentities($v); + ${'_' . $k . '_'} = $v; + } else { + ${$k} = $v; + } } include $ctlbtmpltfiles[0]; - + $val = ob_get_contents(); ob_end_clean(); @@ -299,6 +320,11 @@ public function parse ($template = null, $text = null) return $this->processRenderQueue (array ('content' => $val)); } + private function isRaw($var) + { + return isset($this->rawValues[$var]); + } + private function processRenderQueue ($contents = array ()) { if (isset ($this->layoutRender)) { @@ -306,13 +332,17 @@ private function processRenderQueue ($contents = array ()) // Set the variables that have been set here. foreach ($this->values as $k => $v) { - $template->set ($k, $v); + if ($this->isRaw($k)) { + $template->setRaw($k, $v); + } else { + $template->set($k, $v); + } } // And now set the content blocks. // This might overwrite other sets. foreach ($contents as $k => $v) { - $template->set ($k, $v, true); + $template->setRaw ($k, $v, true); } return $template->parse ($this->layoutRender); From a97e38dc9222beeb929d403207a0552efbcc858e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:50:13 +0000 Subject: [PATCH 221/231] Initial plan From 7d17108d62c04f2f56367d5e0c0b82903999a0d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 10:06:16 +0000 Subject: [PATCH 222/231] Fix date input validation bugs and add comprehensive tests - Fix checkInput for 'date' type to validate parts are integers using ctype_digit() and checkdate() - Fix getInput for 'date' type to cast parts to (int) before mktime() - Update composer.json dependencies for PHP 8.3 compatibility (PHPUnit 10/11, Carbon 2/3) - Update phpunit.xml to modern PHPUnit format - Update all existing tests to use PHPUnit\Framework\TestCase - Add comprehensive tests for date validation, SQL injection patterns, all input types - Add tests for Collection, ErrorCollection, SimpleCrypt, URLBuilder, TokenGenerator Co-authored-by: daedeloth <1168599+daedeloth@users.noreply.github.com> --- .gitignore | 3 +- composer.json | 6 +- phpunit.xml | 12 +- src/Neuron/Core/Tools.php | 13 +- tests/CollectionTest.php | 195 ++++++++++++++ tests/DbQueryTest.php | 4 +- tests/ErrorCollectionTest.php | 55 ++++ tests/FilterTest.php | 4 +- tests/SimpleCryptTest.php | 81 ++++++ tests/TokenGeneratorTest.php | 4 +- tests/ToolsTest.php | 487 +++++++++++++++++++++++++++++++++- tests/URLBuilderTest.php | 59 ++++ 12 files changed, 903 insertions(+), 20 deletions(-) create mode 100644 tests/CollectionTest.php create mode 100644 tests/ErrorCollectionTest.php create mode 100644 tests/SimpleCryptTest.php create mode 100644 tests/URLBuilderTest.php diff --git a/.gitignore b/.gitignore index cdb3d20..9df1b6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea/ vendor/ -composer.lock \ No newline at end of file +composer.lock +.phpunit.cache \ No newline at end of file diff --git a/composer.json b/composer.json index 0afb7da..65eed88 100644 --- a/composer.json +++ b/composer.json @@ -15,13 +15,13 @@ ], "require" : { - "php": ">=5.5.0", + "php": ">=8.1.0", "ext-gettext" : "*", - "nesbot/carbon": "~1.18" + "nesbot/carbon": "^2.0||^3.0" }, "require-dev": { - "phpunit/phpunit": "5.1.*" + "phpunit/phpunit": "^10.0||^11.0" }, "autoload": { diff --git a/phpunit.xml b/phpunit.xml index 7362ee9..216c033 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,11 +1,13 @@ - + - - + + src/Neuron - - + + diff --git a/src/Neuron/Core/Tools.php b/src/Neuron/Core/Tools.php index 4c88481..740af75 100755 --- a/src/Neuron/Core/Tools.php +++ b/src/Neuron/Core/Tools.php @@ -34,7 +34,7 @@ public static function getInput ($dat, $key, $type, $default = null) // For date's return timestamp. case 'date': $time = explode ('-', $dat[$key]); - return mktime (0, 0, 1, $time[1], $time[2], $time[0]); + return mktime (0, 0, 1, (int)$time[1], (int)$time[2], (int)$time[0]); case 'datetime': return new DateTime ($dat[$key]); @@ -106,8 +106,15 @@ public static function checkInput ($value, $type) elseif ($type == 'date') { - $time = explode ('-', $value); - return self::isValidUTF8 ($value) && (count ($time) == 3); + if (!self::isValidUTF8($value)) { + return false; + } + $time = explode('-', $value); + return count($time) === 3 + && ctype_digit($time[0]) + && ctype_digit($time[1]) + && ctype_digit($time[2]) + && checkdate((int)$time[1], (int)$time[2], (int)$time[0]); } elseif ($type == 'datetime') { diff --git a/tests/CollectionTest.php b/tests/CollectionTest.php new file mode 100644 index 0000000..b13d453 --- /dev/null +++ b/tests/CollectionTest.php @@ -0,0 +1,195 @@ +assertCount (0, $collection); + + $collection->add ('a'); + $collection->add ('b'); + $collection->add ('c'); + $this->assertCount (3, $collection); + } + + public function testFirstAndLast () + { + $collection = new Collection (); + $collection->add ('first'); + $collection->add ('middle'); + $collection->add ('last'); + + $this->assertEquals ('first', $collection->first ()); + $this->assertEquals ('last', $collection->last ()); + } + + public function testFirstAndLastEmpty () + { + $collection = new Collection (); + $this->assertNull ($collection->first ()); + $this->assertNull ($collection->last ()); + } + + public function testIterator () + { + $collection = new Collection (); + $collection->add ('a'); + $collection->add ('b'); + $collection->add ('c'); + + $values = []; + foreach ($collection as $key => $value) { + $values[$key] = $value; + } + + $this->assertEquals ([0 => 'a', 1 => 'b', 2 => 'c'], $values); + } + + public function testRewind () + { + $collection = new Collection (); + $collection->add ('a'); + $collection->add ('b'); + + // Iterate to end + foreach ($collection as $v) {} + + // Rewind and verify + $collection->rewind (); + $this->assertEquals ('a', $collection->current ()); + } + + public function testArrayAccess () + { + $collection = new Collection (); + $collection[] = 'value1'; + $collection[] = 'value2'; + + $this->assertTrue (isset ($collection[0])); + $this->assertTrue (isset ($collection[1])); + $this->assertFalse (isset ($collection[2])); + + $this->assertEquals ('value1', $collection[0]); + $this->assertEquals ('value2', $collection[1]); + } + + public function testOffsetSet () + { + $collection = new Collection (); + $collection[5] = 'value5'; + + $this->assertTrue (isset ($collection[5])); + $this->assertEquals ('value5', $collection[5]); + } + + public function testOffsetUnset () + { + $collection = new Collection (); + $collection->add ('a'); + $collection->add ('b'); + + unset ($collection[0]); + $this->assertFalse (isset ($collection[0])); + } + + public function testRemove () + { + $collection = new Collection (); + $collection->add ('a'); + $collection->add ('b'); + $collection->add ('c'); + + $result = $collection->remove ('b'); + $this->assertTrue ($result); + $this->assertCount (2, $collection); + } + + public function testRemoveNonExistent () + { + $collection = new Collection (); + $collection->add ('a'); + + $result = $collection->remove ('nonexistent'); + $this->assertFalse ($result); + } + + public function testClear () + { + $collection = new Collection (); + $collection->add ('a'); + $collection->add ('b'); + + $collection->clear (); + $this->assertCount (0, $collection); + } + + public function testPeek () + { + $collection = new Collection (); + $collection->add ('a'); + $collection->add ('b'); + $collection->add ('c'); + + $collection->rewind (); + $this->assertEquals ('a', $collection->current ()); + $this->assertEquals ('b', $collection->peek ()); + // Position should not have changed + $this->assertEquals ('a', $collection->current ()); + } + + public function testPeekAtEnd () + { + $collection = new Collection (); + $collection->add ('a'); + + $collection->rewind (); + $this->assertNull ($collection->peek ()); + } + + public function testReverse () + { + $collection = new Collection (); + $collection->add ('a'); + $collection->add ('b'); + $collection->add ('c'); + + $collection->reverse (); + $this->assertEquals ('c', $collection->first ()); + $this->assertEquals ('a', $collection->last ()); + } + + public function testCurrentAtInvalidPosition () + { + $collection = new Collection (); + $this->assertNull ($collection->current ()); + } + + public function testValid () + { + $collection = new Collection (); + $collection->add ('a'); + + $collection->rewind (); + $this->assertTrue ($collection->valid ()); + $collection->next (); + $this->assertFalse ($collection->valid ()); + } + + public function testKey () + { + $collection = new Collection (); + $collection->add ('a'); + $collection->add ('b'); + + $collection->rewind (); + $this->assertEquals (0, $collection->key ()); + $collection->next (); + $this->assertEquals (1, $collection->key ()); + } +} diff --git a/tests/DbQueryTest.php b/tests/DbQueryTest.php index f145e6c..7c4035c 100644 --- a/tests/DbQueryTest.php +++ b/tests/DbQueryTest.php @@ -2,14 +2,14 @@ namespace Neuron\Tests; -use PHPUnit_Framework_TestCase; +use PHPUnit\Framework\TestCase; use Neuron\DB\Query; /** * Class DbQueryTest * @package Neuron\Tests */ -class DbQueryTest extends PHPUnit_Framework_TestCase +class DbQueryTest extends TestCase { /** * @test diff --git a/tests/ErrorCollectionTest.php b/tests/ErrorCollectionTest.php new file mode 100644 index 0000000..5b8786e --- /dev/null +++ b/tests/ErrorCollectionTest.php @@ -0,0 +1,55 @@ +addError ('Something went wrong'); + + $this->assertCount (1, $collection); + $this->assertInstanceOf (\Neuron\Models\Error::class, $error); + } + + public function testGetData () + { + $collection = new ErrorCollection (); + $collection->addError ('Error %s', ['one']); + $collection->addError ('Error %s', ['two']); + + $data = $collection->getData (); + $this->assertCount (2, $data); + $this->assertEquals ('Error one', $data[0]); + $this->assertEquals ('Error two', $data[1]); + } + + public function testGetDetailedData () + { + $collection = new ErrorCollection (); + $error = $collection->addError ('Error %s in %s', ['field', 'form']); + $error->setSubject ('test_subject'); + $error->setCode ('ERR001'); + + $detailed = $collection->getDetailedData (); + $this->assertCount (1, $detailed); + $this->assertEquals ('Error field in form', $detailed[0]['message']); + $this->assertEquals ('Error %s in %s', $detailed[0]['template']); + $this->assertEquals (['field', 'form'], $detailed[0]['arguments']); + $this->assertEquals ('test_subject', $detailed[0]['subject']); + $this->assertEquals ('ERR001', $detailed[0]['code']); + } + + public function testAddErrorWithNoArguments () + { + $collection = new ErrorCollection (); + $collection->addError ('Simple error message'); + + $data = $collection->getData (); + $this->assertEquals ('Simple error message', $data[0]); + } +} diff --git a/tests/FilterTest.php b/tests/FilterTest.php index e79f8f6..6fd1993 100644 --- a/tests/FilterTest.php +++ b/tests/FilterTest.php @@ -10,13 +10,13 @@ use Neuron\Filter\Context; use Neuron\Filter\Field; -use PHPUnit_Framework_TestCase; +use PHPUnit\Framework\TestCase; use Neuron\Filter\Parser; use Neuron\Filter\Scanner; class FilterTest - extends PHPUnit_Framework_TestCase + extends TestCase { public function testFilter () diff --git a/tests/SimpleCryptTest.php b/tests/SimpleCryptTest.php new file mode 100644 index 0000000..34851bc --- /dev/null +++ b/tests/SimpleCryptTest.php @@ -0,0 +1,81 @@ +encrypt ($original); + $this->assertNotEquals ($original, $encrypted); + + $decrypted = $crypt->decrypt ($encrypted); + $this->assertEquals ($original, $decrypted); + } + + public function testDifferentPasswordsFail () + { + $crypt1 = new SimpleCrypt ('password1'); + $crypt2 = new SimpleCrypt ('password2'); + + $encrypted = $crypt1->encrypt ('secret'); + $decrypted = $crypt2->decrypt ($encrypted); + + $this->assertNotEquals ('secret', $decrypted); + } + + public function testEncryptProducesDifferentOutput () + { + $crypt = new SimpleCrypt ('password'); + + $encrypted1 = $crypt->encrypt ('same text'); + $encrypted2 = $crypt->encrypt ('same text'); + + // Due to random salt, encrypted values should differ + $this->assertNotEquals ($encrypted1, $encrypted2); + } + + public function testEncryptDecryptEmptyString () + { + $crypt = new SimpleCrypt ('password'); + $encrypted = $crypt->encrypt (''); + $decrypted = $crypt->decrypt ($encrypted); + $this->assertEquals ('', $decrypted); + } + + public function testEncryptDecryptSpecialCharacters () + { + $crypt = new SimpleCrypt ('password'); + $original = "Special chars: !@#\$%^&*()_+-=[]{}|;':\",./<>?"; + + $encrypted = $crypt->encrypt ($original); + $decrypted = $crypt->decrypt ($encrypted); + $this->assertEquals ($original, $decrypted); + } + + public function testEncryptDecryptUTF8 () + { + $crypt = new SimpleCrypt ('password'); + $original = 'Héllo Wörld 日本語'; + + $encrypted = $crypt->encrypt ($original); + $decrypted = $crypt->decrypt ($encrypted); + $this->assertEquals ($original, $decrypted); + } + + public function testEncryptDecryptWithSaltMarkerInContent () + { + $crypt = new SimpleCrypt ('password'); + $original = 'Text with |||CWSALT inside it'; + + $encrypted = $crypt->encrypt ($original); + $decrypted = $crypt->decrypt ($encrypted); + $this->assertEquals ($original, $decrypted); + } +} diff --git a/tests/TokenGeneratorTest.php b/tests/TokenGeneratorTest.php index 2f301e9..a2f1693 100644 --- a/tests/TokenGeneratorTest.php +++ b/tests/TokenGeneratorTest.php @@ -3,11 +3,11 @@ namespace Neuron\Tests; -use PHPUnit_Framework_TestCase; +use PHPUnit\Framework\TestCase; class TokenGeneratorTest - extends PHPUnit_Framework_TestCase + extends TestCase { public function testLengthSimplified () { diff --git a/tests/ToolsTest.php b/tests/ToolsTest.php index 26cae51..6c92292 100644 --- a/tests/ToolsTest.php +++ b/tests/ToolsTest.php @@ -3,12 +3,12 @@ namespace Neuron\Tests; -use PHPUnit_Framework_TestCase; +use PHPUnit\Framework\TestCase; use Neuron\Core\Tools; class ToolsTest - extends PHPUnit_Framework_TestCase + extends TestCase { public function testEmailInputCheck () { @@ -102,4 +102,487 @@ public function testDateInput () { $this->assertTrue (Tools::checkInput ('2015-06-01T10:00', 'datetime')); $this->assertFalse (Tools::checkInput ('06-01-2015T10:00', 'datetime')); } + + // --------------------------------------------------------------- + // Date validation tests (the bug fix) + // --------------------------------------------------------------- + + public function testDateCheckInputValidDates () + { + $this->assertTrue (Tools::checkInput ('2015-06-01', 'date')); + $this->assertTrue (Tools::checkInput ('2000-01-01', 'date')); + $this->assertTrue (Tools::checkInput ('1999-12-31', 'date')); + $this->assertTrue (Tools::checkInput ('2024-02-29', 'date')); // leap year + } + + public function testDateCheckInputInvalidNonIntegerParts () + { + // The original bug: "a-b-c" would pass + $this->assertFalse (Tools::checkInput ('a-b-c', 'date')); + $this->assertFalse (Tools::checkInput ('foo-bar-baz', 'date')); + $this->assertFalse (Tools::checkInput ('20xx-01-01', 'date')); + $this->assertFalse (Tools::checkInput ('2015-ab-01', 'date')); + $this->assertFalse (Tools::checkInput ('2015-01-cd', 'date')); + } + + public function testDateCheckInputInvalidDateValues () + { + $this->assertFalse (Tools::checkInput ('2015-13-01', 'date')); // month 13 + $this->assertFalse (Tools::checkInput ('2015-00-01', 'date')); // month 0 + $this->assertFalse (Tools::checkInput ('2015-02-30', 'date')); // Feb 30 + $this->assertFalse (Tools::checkInput ('2023-02-29', 'date')); // non-leap year + $this->assertFalse (Tools::checkInput ('2015-06-32', 'date')); // day 32 + $this->assertFalse (Tools::checkInput ('0000-01-01', 'date')); // year 0 + } + + public function testDateCheckInputInvalidFormats () + { + $this->assertFalse (Tools::checkInput ('', 'date')); + $this->assertFalse (Tools::checkInput ('2015', 'date')); + $this->assertFalse (Tools::checkInput ('2015-06', 'date')); + $this->assertFalse (Tools::checkInput ('2015/06/01', 'date')); + $this->assertFalse (Tools::checkInput ('01-06-2015', 'date')); // wrong order but valid checkdate would pass + $this->assertFalse (Tools::checkInput ('2015-06-01-extra', 'date')); + } + + public function testDateGetInputValidDate () + { + $dat = array ('date' => '2015-06-01'); + $result = Tools::getInput ($dat, 'date', 'date'); + $this->assertIsInt ($result); + $this->assertEquals ('2015-06-01', date ('Y-m-d', $result)); + } + + public function testDateGetInputInvalidDate () + { + $dat = array ('date' => 'a-b-c'); + $result = Tools::getInput ($dat, 'date', 'date'); + $this->assertNull ($result); + } + + public function testDateGetInputMissing () + { + $dat = array (); + $result = Tools::getInput ($dat, 'date', 'date'); + $this->assertNull ($result); + } + + public function testDateGetInputDefault () + { + $dat = array ('date' => 'invalid'); + $result = Tools::getInput ($dat, 'date', 'date', 'default_value'); + $this->assertEquals ('default_value', $result); + } + + // --------------------------------------------------------------- + // Datetime validation tests + // --------------------------------------------------------------- + + public function testDatetimeCheckInputValid () + { + $this->assertTrue (Tools::checkInput ('2015-06-01T10:00', 'datetime')); + $this->assertTrue (Tools::checkInput ('2024-12-31T23:59', 'datetime')); + } + + public function testDatetimeCheckInputInvalid () + { + $this->assertFalse (Tools::checkInput ('06-01-2015T10:00', 'datetime')); + $this->assertFalse (Tools::checkInput ('not-a-datetime', 'datetime')); + $this->assertFalse (Tools::checkInput ('2015-06-01 10:00', 'datetime')); + $this->assertFalse (Tools::checkInput ('', 'datetime')); + } + + public function testDatetimeGetInputValid () + { + $dat = array ('dt' => '2015-06-01T10:00'); + $result = Tools::getInput ($dat, 'dt', 'datetime'); + $this->assertInstanceOf (\DateTime::class, $result); + } + + // --------------------------------------------------------------- + // Text and varchar type tests + // --------------------------------------------------------------- + + public function testTextCheckInput () + { + $this->assertTrue (Tools::checkInput ('anything', 'text')); + $this->assertTrue (Tools::checkInput ('', 'text')); + $this->assertTrue (Tools::checkInput ('', 'text')); + } + + public function testVarcharCheckInput () + { + $this->assertTrue (Tools::checkInput ('valid text', 'varchar')); + $this->assertTrue (Tools::checkInput ('valid text', 'string')); + $this->assertTrue (Tools::checkInput ('valid html', 'html')); + } + + public function testNameCheckInput () + { + $this->assertTrue (Tools::checkInput ('John Doe', 'name')); + $this->assertFalse (Tools::checkInput ('John', 'name')); + $this->assertFalse (Tools::checkInput ('', 'name')); + } + + // --------------------------------------------------------------- + // Bool type tests + // --------------------------------------------------------------- + + public function testBoolCheckInput () + { + $this->assertTrue (Tools::checkInput (1, 'bool')); + $this->assertTrue (Tools::checkInput ('true', 'bool')); + $this->assertFalse (Tools::checkInput (0, 'bool')); + $this->assertFalse (Tools::checkInput ('false', 'bool')); + $this->assertFalse (Tools::checkInput ('', 'bool')); + } + + public function testBoolGetInput () + { + // When checkInput passes (value is 1 or 'true'), getInput returns strip_tags(value) + $dat = array ('flag' => 1); + $this->assertEquals ('1', Tools::getInput ($dat, 'flag', 'bool')); + + $dat = array ('flag' => 'true'); + $this->assertEquals ('true', Tools::getInput ($dat, 'flag', 'bool')); + + // When bool validation fails, getInput returns false (special case) + $dat = array ('flag' => 0); + $this->assertFalse (Tools::getInput ($dat, 'flag', 'bool')); + + $dat = array ('flag' => 'no'); + $this->assertFalse (Tools::getInput ($dat, 'flag', 'bool')); + } + + // --------------------------------------------------------------- + // Password type tests + // --------------------------------------------------------------- + + public function testPasswordCheckInput () + { + $this->assertTrue (Tools::checkInput ('password123', 'password')); + $this->assertTrue (Tools::checkInput ('12345678', 'password')); + $this->assertFalse (Tools::checkInput ('short', 'password')); + $this->assertFalse (Tools::checkInput ('1234567', 'password')); // 7 chars + $this->assertFalse (Tools::checkInput (str_repeat ('a', 257), 'password')); // too long + $this->assertTrue (Tools::checkInput (str_repeat ('a', 256), 'password')); // max allowed + } + + // --------------------------------------------------------------- + // Username type tests + // --------------------------------------------------------------- + + public function testUsernameCheckInput () + { + $this->assertTrue (Tools::checkInput ('john_doe', 'username')); + $this->assertTrue (Tools::checkInput ('User123', 'username')); + $this->assertTrue (Tools::checkInput ('abc', 'username')); // min 3 chars + $this->assertFalse (Tools::checkInput ('ab', 'username')); // too short + $this->assertFalse (Tools::checkInput ('', 'username')); + $this->assertFalse (Tools::checkInput ('user name', 'username')); // space + $this->assertFalse (Tools::checkInput ('user@name', 'username')); // special chars + $this->assertFalse (Tools::checkInput (str_repeat ('a', 21), 'username')); // too long + } + + // --------------------------------------------------------------- + // MD5 type tests + // --------------------------------------------------------------- + + public function testMd5CheckInput () + { + $this->assertTrue (Tools::checkInput (md5 ('test'), 'md5')); + $this->assertTrue (Tools::checkInput ('d41d8cd98f00b204e9800998ecf8427e', 'md5')); + $this->assertFalse (Tools::checkInput ('tooshort', 'md5')); + $this->assertFalse (Tools::checkInput ('', 'md5')); + $this->assertFalse (Tools::checkInput (str_repeat ('a', 33), 'md5')); + } + + // --------------------------------------------------------------- + // Base64 type tests + // --------------------------------------------------------------- + + public function testBase64CheckInput () + { + $this->assertTrue (Tools::checkInput (base64_encode ('test'), 'base64')); + $this->assertTrue (Tools::checkInput (base64_encode ('hello world'), 'base64')); + $this->assertFalse (Tools::checkInput ('not valid base64!!!', 'base64')); + } + + public function testBase64GetInput () + { + $dat = array ('data' => base64_encode ('hello world')); + $result = Tools::getInput ($dat, 'data', 'base64'); + $this->assertEquals ('hello world', $result); + } + + // --------------------------------------------------------------- + // Raw type tests + // --------------------------------------------------------------- + + public function testRawCheckInput () + { + $this->assertTrue (Tools::checkInput ('anything', 'raw')); + $this->assertTrue (Tools::checkInput ('', 'raw')); + } + + public function testRawGetInput () + { + $dat = array ('data' => ''); + $result = Tools::getInput ($dat, 'data', 'raw'); + $this->assertEquals ('', $result); + } + + public function testHtmlGetInput () + { + $dat = array ('data' => 'bold'); + $result = Tools::getInput ($dat, 'data', 'html'); + $this->assertEquals ('bold', $result); + } + + // --------------------------------------------------------------- + // Unknown type tests + // --------------------------------------------------------------- + + public function testUnknownTypeReturnsFalse () + { + $this->assertFalse (Tools::checkInput ('value', 'nonexistent_type')); + } + + // --------------------------------------------------------------- + // getInput default behavior tests + // --------------------------------------------------------------- + + public function testGetInputMissingKey () + { + $dat = array (); + $this->assertNull (Tools::getInput ($dat, 'missing', 'text')); + } + + public function testGetInputMissingKeyWithDefault () + { + $dat = array (); + $this->assertEquals ('fallback', Tools::getInput ($dat, 'missing', 'text', 'fallback')); + } + + public function testGetInputStripsTagsByDefault () + { + $dat = array ('name' => 'John Doe'); + $result = Tools::getInput ($dat, 'name', 'varchar'); + $this->assertEquals ('John Doe', $result); + } + + // --------------------------------------------------------------- + // SQL injection patterns via checkInput + // --------------------------------------------------------------- + + public function testSqlInjectionInEmailField () + { + $this->assertFalse (Tools::checkInput ("' OR '1'='1", 'email')); + $this->assertFalse (Tools::checkInput ("admin@example.com' OR 1=1--", 'email')); + $this->assertFalse (Tools::checkInput ("admin@example.com'; DROP TABLE users;--", 'email')); + $this->assertFalse (Tools::checkInput ("' UNION SELECT * FROM users--", 'email')); + } + + public function testSqlInjectionInUsernameField () + { + $this->assertFalse (Tools::checkInput ("' OR '1'='1", 'username')); + $this->assertFalse (Tools::checkInput ("admin'; DROP TABLE users;--", 'username')); + $this->assertFalse (Tools::checkInput ("admin' UNION SELECT * FROM users--", 'username')); + $this->assertFalse (Tools::checkInput ("1; DROP TABLE users", 'username')); + } + + public function testSqlInjectionInDateField () + { + $this->assertFalse (Tools::checkInput ("'; DROP TABLE users;--", 'date')); + $this->assertFalse (Tools::checkInput ("2015-01-01' OR '1'='1", 'date')); + $this->assertFalse (Tools::checkInput ("2015-01-01; DROP TABLE users;--", 'date')); + $this->assertFalse (Tools::checkInput ("1 OR 1=1", 'date')); + $this->assertFalse (Tools::checkInput ("' UNION SELECT * FROM users--", 'date')); + } + + public function testSqlInjectionInDatetimeField () + { + $this->assertFalse (Tools::checkInput ("'; DROP TABLE users;--", 'datetime')); + $this->assertFalse (Tools::checkInput ("not-a-datetime", 'datetime')); + } + + public function testSqlInjectionInIntField () + { + $this->assertFalse (Tools::checkInput ("1; DROP TABLE users", 'int')); + $this->assertFalse (Tools::checkInput ("1 OR 1=1", 'int')); + $this->assertFalse (Tools::checkInput ("' OR '1'='1", 'int')); + $this->assertFalse (Tools::checkInput ("1 UNION SELECT * FROM users", 'int')); + } + + public function testSqlInjectionInNumberField () + { + $this->assertFalse (Tools::checkInput ("1; DROP TABLE users", 'number')); + $this->assertFalse (Tools::checkInput ("1 OR 1=1", 'number')); + $this->assertFalse (Tools::checkInput ("' OR '1'='1", 'number')); + } + + public function testSqlInjectionInMd5Field () + { + $this->assertFalse (Tools::checkInput ("' OR '1'='1' --", 'md5')); + $this->assertFalse (Tools::checkInput ("'; DROP TABLE users;--", 'md5')); + } + + public function testSqlInjectionInPasswordField () + { + // These pass checkInput because password only checks length/UTF-8 + // But they should still be properly escaped before use in queries + $this->assertTrue (Tools::checkInput ("password' OR '1'='1", 'password')); + } + + public function testSqlInjectionInUrlField () + { + $this->assertFalse (Tools::checkInput ("'; DROP TABLE users;--", 'url')); + $this->assertFalse (Tools::checkInput ("' OR '1'='1", 'url')); + } + + // --------------------------------------------------------------- + // XSS injection patterns via getInput + // --------------------------------------------------------------- + + public function testXssStrippedByGetInputDefault () + { + $dat = array ('name' => ''); + $result = Tools::getInput ($dat, 'name', 'varchar'); + $this->assertStringNotContainsString (''); + $this->assertStringNotContainsString ('