Page MenuHomePhabricator

No OneTemporary

diff --git a/core/Context.php b/core/Context.php
index 6adc571..613d2bb 100644
--- a/core/Context.php
+++ b/core/Context.php
@@ -1,129 +1,133 @@
<?php namespace spitfire\core;
use \spitfire\App;
use Controller;
use publicException;
use spitfire\cache\MemcachedAdapter;
use spitfire\core\annotations\ActionReflector;
use spitfire\core\Request;
use spitfire\core\Response;
use spitfire\exceptions\PrivateException;
use spitfire\InputSanitizer;
use spitfire\io\session\Session;
use spitfire\mvc\View;
/**
* The context is a wrapper for an Intent. Basically it describes a full request
* for a page inside Spitfire. Usually you would have a single Context in any
* execution.
*
* Several contexts will usually only be found in Unit Tests that mock the context,
* when using nested controllers or in a CLI application.
*
* @link http://www.spitfirephp.com/wiki/index.php/Class:Context
* @author César de la Cal <cesar@magic3w.com>
* @last-revision 2013-10-25
*/
class Context
{
/**
* This is a reference to the context itself. This is a little helper for the
* View and Controller objects that do expose the Context's elements via Magic
* methods, this way we do not need any extra cases for the context.
*
* @var Context
*/
public $context;
public $middleware;
/**
* The application running the current context. The app will provide the controller
* to handle the request / context provided.
*
* @var App
*/
public $app;
/**
* The controller is in charge of preparig a proper response to the request.
* This is the first logical level that is user-defined.
*
* @var Controller
*/
public $controller;
public $action;
public $object;
public $extension;
+ public $annotations;
/**
* Holds the view the app uses to handle the current request. This view is in
* charge of rendering the page once the controller has finished processing
* it.
*
* @var View
*/
public $view;
public $parameters;
public $get;
public $post;
public $cache;
/**
*
* @var Request
*/
public $request;
public $response;
public $session;
function __construct() {
$this->context = $this;
}
public static function create() {
$context = new Context;
$context->get = new InputSanitizer($_GET);
$context->post = new InputSanitizer($_POST);
$context->session = Session::getInstance();
$context->cache = MemcachedAdapter::getInstance();
$context->request = Request::get();
$context->parameters = new InputSanitizer($context->request->getPath()->getParameters());
$context->response = new Response($context);
$context->middleware = new \spitfire\mvc\middleware\MiddlewareStack($context);
$context->app = spitfire()->getApp($context->request->getPath()->getApp());
$context->controller = $context->app->getController($context->request->getPath()->getController(), $context);
$context->action = $context->request->getPath()->getAction();
$context->object = $context->request->getPath()->getObject();
$context->view = $context->app->getView($context->controller);
return $context;
}
public function run() {
#Run the onload
if (method_exists($this->controller, '_onload') ) {
call_user_func_array(Array($this->controller, '_onload'), Array($this->action));
}
- $this->middleware->before();
-
$reflector = new ActionReflector($this->controller, $this->action);
+
+ $annotationParser = new annotations\AnnotationParser();
+ $this->annotations = $annotationParser->parse($reflector->getDocBlock());
+
+ $this->middleware->before();
$reflector->execute();
#Check if the controller can handle the request
$request = Array($this->controller, $this->action);
if (is_callable($request)) { $_return = call_user_func_array($request, $this->object); }
else { throw new publicException('Page not found', 404, new PrivateException('Action not found', 0)); }
$this->middleware->after();
if ($_return instanceof Context) { return $_return; }
else { return $this; }
}
public function __clone() {
$this->context = $this;
}
}
diff --git a/core/annotations/AnnotationParser.php b/core/annotations/AnnotationParser.php
index 6b5e9aa..8288f5b 100644
--- a/core/annotations/AnnotationParser.php
+++ b/core/annotations/AnnotationParser.php
@@ -1,105 +1,105 @@
<?php namespace spitfire\core\annotations;
use BadMethodCallException;
use Reflector;
use Strings;
/**
* Reads a docblock and parses the information that it provides to extract the
* annotations that a programmer may use to modify an application's behavior.
*
* To keep these as flexible as possible, the parser will just return an array
* of information that it extracted from the docblock.
*
* @author César de la Cal Bretschneider <cesar@magic3w.com>
*/
class AnnotationParser
{
/**
* Filters the data from a docblock, extracting the lines that do contain
* annotations and the information these provide.
*
* The return for this will look like this:
* <code>Array('annotationA paramA paramB', 'annotationB paramA paramB')</code>
*
* With this information, the parse function will be able to organize the data
* so it's easily accessible to the programmer using it.
*
* Notice that this function will trim off asterisks and forward slashes of your
* annotation, so if you wish to use those you need to make sure to ask the user
* to quote them for the application to properly use them.
*
* Annotations for this function may as well be numeric or contain special
* characters. You're though encouraged to use simple alphanumeric characters,
* since we're not testing for the operation with Unicode.
*
* @param Reflector|string $doc
* @return string[]
*/
protected function filter($doc) {
#Raw contains the complete docblock comment, which will contain extra data
#that may be uninteresting, we will filter it and return.
#This is an interesting case of a _pain in the ass_, you would expect to be
#able to somehow decently test if the thing is a reflection. But you can't...
$raw = is_object($doc) && method_exists($doc, 'getDocComment') ? $doc->getDocComment() : $doc;
#Check if raw is a string or if whatever we got passed was bogus
if (!is_string($raw)) { throw new BadMethodCallException('Invalid argument', 1607131552); }
#Individual lines make it easier to parse the data
$pieces = explode("\n", $raw);
#Remove unrelated data
$clean = array_filter(array_map(function ($e) {
$trimmed = trim($e, "\r\t */");
return Strings::startsWith($trimmed, '@')? ltrim($trimmed, '@') : null;
}, $pieces));
return $clean;
}
/**
* The parser will retrieve a DocComment, or any similar structure and read
* the annotations, providing you with an array that is structured like this
*
* <code>Array('annotation' => Array(Array('paramA'))</code>
*
* Please note that there are three levels to the array:
* * Annotation type
* * Annotation disambiguation (you can have several &at;param for example)
* * Parameters
*
* With the data structured, although inside a multi-layer array, it should be
* fairly simple to access the data that you need to make use of the annotation.
*
* @todo The return of this parser is weird enough to justify a wiki page or
* a special return type
*
* @param Reflector|string $doc
* @return string[][][]
*/
public function parse($doc) {
#Prepare the variables we need.
$annotations = Array();
$clean = $this->filter($doc);
#Sort the data
foreach ($clean as $line) {
$segments = array_filter(explode(' ', $line));
$name = array_shift($segments);
#If uninitialized, initialize the array for the docblock
if (!isset($annotations[$name])) { $annotations[$name] = Array(); }
#Add the value we parsed
- $annotations[$name][] = $segments;
+ $annotations[$name][] = implode(' ', $segments);
}
return $annotations;
}
}
diff --git a/mvc/middleware/standard/ValidationMiddleware.php b/mvc/middleware/standard/ValidationMiddleware.php
new file mode 100644
index 0000000..a80e1d2
--- /dev/null
+++ b/mvc/middleware/standard/ValidationMiddleware.php
@@ -0,0 +1,62 @@
+<?php namespace spitfire\mvc\middleware\standard;
+
+use spitfire\core\Context;
+use spitfire\core\Response;
+use spitfire\mvc\middleware\MiddlewareInterface;
+use spitfire\validation\parser\Parser;
+
+/*
+ * The MIT License
+ *
+ * Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+class ValidationMiddleware implements MiddlewareInterface
+{
+
+ public function before(Context $context) {
+ $expressions = $context->annotations['validate'];
+ $parser = new Parser();
+
+ $context->validation = collect();
+
+ foreach ($expressions as $expression) {
+ $throw = true;
+
+ if(substr($expression, 0, 2) === '>>') {
+ $expression = substr($expression, 2);
+ $throw = false;
+ }
+
+ $validator = $parser->parse($expression)->setValue(['GET' => $_GET->getRaw(), 'POST' => $_POST, 'OBJ' => $context->object]);
+
+ if (!$validator->isOk()) {
+ if ($throw) { throw new \spitfire\exceptions\PublicException('Validation failed', 400); }
+ $context->validation->add($validator->getMessages());
+ }
+ }
+ }
+
+ public function after(Context $context, Response $response) {
+
+ }
+
+}

File Metadata

Mime Type
text/x-diff
Expires
Apr 12 2021, 10:22 PM (9 w, 22 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1764
Default Alt Text
(10 KB)

Event Timeline