Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

o Initial pass at Halo core for new Substrate.

  • Loading branch information...
commit 1f3c41c97800fdf7efc19fed48173a77074b1460 0 parents
@simensen simensen authored
4 .gitignore
@@ -0,0 +1,4 @@
+.buildpath
+.project
+.settings
+._*
26 LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2010, Dragonfly Development Inc
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Dragonfly Development Inc nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
9 README
@@ -0,0 +1,9 @@
+Halo Web Application Framework for PHP
+http://halo-php.org/
+
+
+Halo is a web application framework for PHP. Halo is built on top of
+Substrate, an Inversion of Control/Dependency Injection Container
+(IoC/DI) for PHP.
+
+Halo was inspired by aspects of Spring MVC.
177 lib/halo_AbstractHandlerMapping.php
@@ -0,0 +1,177 @@
+<?php
+
+require_once('halo_IHandlerMapping.php');
+
+require_once('substrate_Context.php');
+require_once('substrate_stones_IContextAware.php');
+require_once('substrate_stones_IOrderedStone.php');
+
+abstract class halo_AbstractHandlerMapping implements halo_IHandlerMapping, substrate_stones_IContextAware, substrate_stones_IOrderedStone {
+
+ /**
+ * Substrate context
+ * @var substrate_Context
+ */
+ protected $context;
+
+ /**
+ * Default handler
+ * @var mixed
+ */
+ protected $defaultHandler;
+
+ /**
+ * List of interceptors
+ * @var Array
+ */
+ protected $interceptors = array();
+
+ /**
+ * List of adapted interceptors
+ * @var Array
+ */
+ protected $adaptedInterceptors = array();
+
+ /**
+ * Stone order
+ * @var number
+ */
+ protected $stoneOrder = null;
+
+ /**
+ * Get a handler
+ * @param halo_HttpRequest $httpRequest
+ */
+ final public function getHandler(halo_HttpRequest $httpRequest) {
+ $handler = $this->getHandlerInternal($httpRequest);
+ if ( $handler === null ) {
+ $handler = $this->defaultHandler;
+ }
+ if ( $handler === null ) {
+ return null;
+ }
+ if ( is_string($handler) ) {
+ //
+ }
+ return $handler;
+ }
+
+ /**
+ * We are Substrate context aware
+ * @param $context
+ */
+ public function informAboutContext(substrate_Context $context) {
+ $this->context = $context;
+ $this->initContext();
+ }
+
+ /**
+ * Initialize context
+ */
+ protected function initContext() {
+ $this->extendInterceptors($this->interceptors);
+ $this->initInterceptors();
+ }
+
+ /**
+ * Get the adapted interceptors.
+ */
+ protected function getAdaptedInterceptors() {
+ return $this->adaptedInterceptors;
+ }
+
+ /**
+ * Get the handler execution chain
+ * @param mixed $handler
+ * @return halo_HandlerExecutionChain
+ */
+ public function getHandlerExecutionChain(halo_HttpRequest $httpRequest) {
+ $handler = $this->getHandler($httpRequest);
+ if ( $handler !== null ) {
+ // We must have found a handler, wrap it!
+ return $this->getHandlerExecutionChainInternal($handler);
+ }
+ return null;
+ }
+
+ /**
+ * Get the handler execution chain (internal)
+ * @param mixed $handler
+ * @return halo_HandlerExecutionChain
+ */
+ protected function getHandlerExecutionChainInternal($handler) {
+ if ( $handler instanceof halo_HandlerExecutionChain ) {
+ $handler->addInterceptors($this->getAdaptedInterceptors());
+ return $handler;
+ } else {
+ return new halo_HandlerExecutionChain($handler, $this->getAdaptedInterceptors());
+ }
+ }
+
+ /**
+ * Set interceptors
+ * @param $interceptors
+ */
+ public function setInterceptors($interceptors) {
+ if ( ! is_array($interceptors) ) { $interceptors = array($interceptors); }
+ foreach ( $interceptors as $interceptor ) {
+ $this->interceptors[] = $interceptor;
+ }
+ }
+
+ /**
+ * Hook to allow for additional interceptors to be registred.
+ * @param Array
+ */
+ public function extendInterceptors($interceptors) {
+ // noop
+ }
+
+ /**
+ * Initialize interceptors
+ */
+ public function initInterceptors() {
+ foreach ( $this->interceptors as $interceptor ) {
+ if ( is_string($interceptor) ) {
+ $interceptor = $this->context->get($interceptor);
+ }
+ $this->adaptedInterceptors[] = $this->adaptInterceptor($interceptor);
+ }
+ }
+
+ /**
+ * Make certain that this interceptor is something we can use
+ * @param $interceptor
+ */
+ public function adaptInterceptor($interceptor) {
+ if ( $interceptor instanceof halo_IHandlerInterceptor ) {
+ return $interceptor;
+ //} elseif ( $interceptor instanceof halo_ISomethingElse ) {
+ //return new halo_HandlerInterceptorInterfaceAdapter($interceptor);
+ } else {
+ throw new Exception('Interceptor of type "' . get_class($interceptor) . '" not supported.');
+ }
+ }
+
+ /**
+ * Get the order of this stone
+ */
+ public function getStoneOrder() {
+ return $this->stoneOrder;
+ }
+
+ /**
+ * Set the order of this stone
+ * @param $stoneOrder
+ */
+ public function setStoneOrder($stoneOrder) {
+ $this->stoneOrder = $stoneOrder;
+ }
+
+ /**
+ * Get a handler
+ * @param $httpRequest
+ */
+ abstract protected function getHandlerInternal(halo_HttpRequest $httpRequest);
+
+}
37 lib/halo_AbstractUriHandlerMapping.php
@@ -0,0 +1,37 @@
+<?php
+require_once('halo_AbstractHandlerMapping.php');
+abstract class halo_AbstractUriHandlerMapping extends halo_AbstractHandlerMapping {
+
+ /**
+ * Registered handlers
+ * @var Array
+ */
+ protected $registeredHandlers;
+
+ /**
+ * (non-PHPdoc)
+ * @see halo_AbstractHandlerMapping::initContext()
+ */
+ protected function initContext() {
+ parent::initContext();
+ $this->registerHandlers();
+ }
+
+ /**
+ * Register a handler
+ * @param $uriPaths
+ * @param $handlerName
+ */
+ protected function registerHandler($uriPaths, $handlerName) {
+ if ( ! is_array($uriPaths) ) $uriPaths = array($uriPaths);
+ foreach ( $uriPaths as $uriPath ) {
+ $this->registeredHandlers[$uriPath] = $handlerName;
+ }
+ }
+
+ /**
+ * Register handlers
+ */
+ abstract protected function registerHandlers();
+
+}
26 lib/halo_ControllerHandlerAdapter.php
@@ -0,0 +1,26 @@
+<?php
+
+require_once('halo_IHandlerAdapter.php');
+require_once('halo_IController.php');
+require_once('halo_HttpRequest.php');
+require_once('halo_HttpResponse.php');
+
+class halo_ControllerHandlerAdapter implements halo_IHandlerAdapter {
+
+ /**
+ * (non-PHPdoc)
+ * @see halo_IHandlerAdapter::supports()
+ */
+ public function supports($object) {
+ return $object instanceof halo_IController;
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see halo_IHandlerAdapter::handle()
+ */
+ public function handle(halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse, $handler) {
+ return $handler->handleRequest($httpRequest, $httpResponse);
+ }
+
+}
254 lib/halo_Dispatcher.php
@@ -0,0 +1,254 @@
+<?php
+
+require_once('dd_logging_LogFactory.php');
+require_once('dd_logging_ILogger.php');
+
+require_once('substrate_stones_IContextStartupAware.php');
+require_once('substrate_Context.php');
+
+require_once('substrate_stones_OrderedUtil.php');
+
+require_once('halo_HttpRequest.php');
+require_once('halo_HttpResponse.php');
+require_once('halo_ModelAndView.php');
+
+require_once('halo_HandlerExecutionChain.php');
+
+class halo_Dispatcher implements substrate_stones_IContextStartupAware {
+
+ /**
+ * @var dd_logging_ILogger
+ */
+ static public $LOGGER;
+
+ /**
+ * We will be told about our context
+ * @var substrate_Context
+ */
+ protected $context;
+
+ /**
+ * Called once the context has started
+ * @param $context
+ */
+ public function informAboutContextStartup(substrate_Context $context) {
+
+ // Remember this.
+ $this->context = $context;
+
+ // Find all handler mappings.
+ $this->handlerMappings = substrate_stones_OrderedUtil::SORT(
+ $context->findStonesByImplementation('halo_IHandlerMapping')
+ );
+
+ // Find all handler adapters.
+ $this->handlerAdapters = substrate_stones_OrderedUtil::SORT(
+ $context->findStonesByImplementation('halo_IHandlerAdapter')
+ );
+
+ // Find all view resolvers.
+ $this->viewResolvers = $context->findStonesByImplementation(
+ 'halo_IViewResolver'
+ );
+
+ }
+
+ /**
+ * Catch fatal errors
+ * @param $buffer
+ * @return buffer
+ */
+ public function doServiceErrorHandler($buffer) {
+ $error = error_get_last();
+ if ( $error !== null and $error['type'] == 1 ) {
+ if ( self::$LOGGER->isFatalEnabled() ) {
+ self::$LOGGER->fatal('SOMETHING MAJOR HAPPENED');
+ self::$LOGGER->fatal($error['message'] . ' in ' . $error['file'] . ' on line ' . $error['line']);
+ }
+ }
+ return $buffer;
+ }
+
+ /**
+ * Handle internal server error
+ */
+ protected function handleInternalServerError() {
+ // TODO: Can we find a way to customize 500 error?
+ header('HTTP/1.1 500 Internal Server Error');
+ echo '<strong>500 Internal Server Error</strong><br />';
+ echo 'An internal error has occurred.';
+ }
+
+ /**
+ * Main entry point.
+ * @param halo_HttpRequest $httpRequest
+ * @param halo_HttpResponse $httpResponse
+ */
+ public function doService(halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse) {
+
+ $didCatchException = false;
+ $exception = null;
+
+ ob_start(array($this, 'doServiceErrorHandler'));;
+
+ try {
+ $this->doServiceInternal($httpRequest, $httpResponse);
+ } catch (Exception $e) {
+ $didCatchException = true;
+ $exception = $e;
+ }
+
+ if ( $didCatchException ) {
+ if ( self::$LOGGER->isErrorEnabled() ) {
+ self::$LOGGER->error('Something pretty bad happened.');
+ self::$LOGGER->error('Caught exception: ' . get_class($exception) . ' [code:' . $exception->getCode() . ']');
+ self::$LOGGER->error($exception->getMessage());
+ }
+ while (ob_get_level()) {
+ ob_end_clean();
+ }
+ $this->handleInternalServerError();
+ } else {
+ // Everything is all good here.
+ ob_flush();
+ }
+ }
+
+ /**
+ * This is a safe internal method for handling the service
+ * @param halo_HttpRequest $httpRequest
+ * @param halo_HttpResponse $httpResponse
+ */
+ protected function doServiceInternal(halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse) {
+
+ // Let's get this party started!
+ halo_DispatcherUtil::SET_CONTEXT($httpRequest, $this->context);
+
+ $handlerExecutionChain = $this->getHandlerExecutionChain($httpRequest);
+
+ if ( $handlerExecutionChain === null or $handlerExecutionChain->getHandler() == null ) {
+ throw new Exception('Unable to find a handler for request.');
+ }
+
+ $handler = $handlerExecutionChain->getHandler();
+ $interceptorIdx = -1;
+ foreach ( $handlerExecutionChain->getInterceptors() as $interceptor ) {
+ $interceptorIdx++;
+ if ( ! $interceptor->preHandle($httpRequest, $httpResponse, $handler) ) {
+ $this->triggerAfterCompletion($handlerExecutionChain, $interceptorIdx, $httpRequest, $httpResponse);
+ return;
+ }
+ }
+
+ $handlerAdapter = $this->getHandlerAdapter($handler);
+
+ if ( $handlerAdapter === null ) {
+ throw new Exception('Unable to find a handler adapter for handler.');
+ }
+
+ $modelAndView = $handlerAdapter->handle($httpRequest, $httpResponse, $handler);
+
+ foreach ( $handlerExecutionChain->getInterceptors() as $interceptor ) {
+ $interceptor->postHandle($httpRequest, $httpResponse, $handler, $modelAndView);
+ }
+
+ $this->render($modelAndView, $httpRequest, $httpResponse);
+
+ $this->triggerAfterCompletion($handlerExecutionChain, $interceptorIdx, $httpRequest, $httpResponse);
+
+ }
+
+ /**
+ * Get handler execution change for the request
+ *
+ * Checks all handler mappings to see if at least one can handle the
+ * request (likely by way of examining the request URI).
+ *
+ * @param halo_HttpRequest $httpRequest
+ * @return halo_HandlerExecutionChain
+ */
+ public function getHandlerExecutionChain(halo_HttpRequest $httpRequest) {
+ foreach ( $this->handlerMappings as $handlerMapping ) {
+ $handler = $handlerMapping->getHandlerExecutionChain($httpRequest);
+ if ( $handler !== null ) {
+ return $handler;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find something that can handle this handler
+ * @param $handler
+ */
+ public function getHandlerAdapter($handler) {
+ foreach ( $this->handlerAdapters as $handlerAdapter ) {
+ if ( $handlerAdapter->supports($handler) ) {
+ return $handlerAdapter;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Render
+ * @param halo_ModelAndView $modelAndView
+ * @param halo_HttpRequest $httpRequest
+ * @param halo_HttpResponse $httpResponse
+ */
+ public function render(halo_ModelAndView $modelAndView = null, halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse) {
+ if ( $modelAndView === null ) return;
+ $view = null;
+ if ( $modelAndView->isReferenced() ) {
+ $view = $this->resolveViewName($modelAndView->getViewName(), $httpRequest, $httpResponse);
+ } else {
+ $view = $modelAndView->getView();
+ }
+ if ( $view === null ) {
+ // What to do here? Technically this is not really an error... but how would
+ // we raise this to the user without being obnoxious?
+ } else {
+ $viewContent = $view->render($modelAndView->getModel(), $httpRequest, $httpResponse);
+ print $viewContent;
+ }
+ }
+
+ /**
+ * Resolve a view name
+ * @param $viewName
+ * @param $httpRequest
+ * @param $httpResponse
+ */
+ public function resolveViewName($viewName, halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse) {
+ foreach ( $this->viewResolvers as $viewResolver ) {
+ $view = $viewResolver->resolve($viewName, $httpRequest, $httpResponse);
+ if ( $view !== null ) return $view;
+ }
+ return $view;
+ }
+
+ /**
+ * Trigger after completion (FINALLY)
+ * @param $handlerExecutionChain
+ * @param $interceptorIdx
+ * @param $httpRequest
+ * @param $httpResponse
+ * @param $exception
+ */
+ public function triggerAfterCompletion(halo_HandlerExecutionChain $handlerExecutionChain, $interceptorIdx, halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse, $exception = null) {
+ if ( $handlerExecutionChain !== null ) {
+ $interceptors = $handlerExecutionChain->getInterceptors();
+ for ( $i = $interceptorIdx; $i >= 0; $i-- ) {
+ $interceptor = $interceptors[$i];
+ try {
+ $interceptor->afterCompletion($httpRequest, $httpResponse, $handlerExecutionChain->getHandler(), $exception);
+ } catch (Exception $e) {
+ $this->logger->info('IHandlerInterceptor.afterCompletion() threw exception.');
+ }
+ }
+ }
+ }
+
+}
+
+halo_Dispatcher::$LOGGER = dd_logging_LogFactory::get('halo_Dispatcher');
52 lib/halo_DispatcherUtil.php
@@ -0,0 +1,52 @@
+<?php
+require_once('halo_HttpRequest.php');
+require_once('halo_HttpResponse.php');
+class halo_DispatcherUtil {
+
+ /**
+ * Key by which we can set and get our context for a given request
+ * @var string
+ */
+ protected static $CONTEXT_KEY = '__halo_context';
+
+ /**
+ * Make an HTTP Request.
+ * @return halo_HttpRequest
+ */
+ public static function MAKE_HTTP_REQUEST() {
+ return new halo_HttpRequest(
+ $_SERVER['REQUEST_METHOD'],
+ $_GET,
+ $_POST,
+ $_FILES,
+ $_SERVER
+ );
+ }
+
+ /**
+ * Make an HTTP Response.
+ * @return halo_HttpResponse
+ */
+ public static function MAKE_HTTP_RESPONSE() {
+ return new halo_HttpResponse();
+ }
+
+ /**
+ * Get the Substrate context from an HTTP Request.
+ * @param halo_HttpRequest $httpRequest
+ * @return substrate_Context
+ */
+ public static function GET_CONTEXT(halo_HttpRequest $httpRequest) {
+ return $httpRequest->attribute(self::$CONTEXT_KEY);
+ }
+
+ /**
+ * Set the Substrate context for an HTTP Request.
+ * @param halo_HttpRequest $httpRequest
+ * @param substrate_Context $context
+ */
+ public static function SET_CONTEXT(halo_HttpRequest $httpRequest, substrate_Context $context) {
+ return $httpRequest->setAttribute(self::$CONTEXT_KEY, $context);
+ }
+
+}
48 lib/halo_HandlerExecutionChain.php
@@ -0,0 +1,48 @@
+<?php
+
+class halo_HandlerExecutionChain {
+
+ /**
+ * Actual handler
+ * @var mixed
+ */
+ protected $handler;
+
+ /**
+ * Interceptors
+ * @var Array
+ */
+ protected $interceptors;
+
+ /**
+ * Constructor
+ * @param $handler
+ * @param $interceptors
+ */
+ public function __construct($handler, $interceptors = null) {
+ if ( $interceptors == null ) { $interceptors = array(); }
+ if ( ! is_array($interceptors) ) { $interceptors = array($interceptors); }
+ if ( $handler instanceof halo_HandlerExecutionChain ) {
+ $this->handler = $handler->getHandler();
+ $this->interceptors = array_merge($handler->getInterceptors(), $interceptors);
+ } else {
+ $this->handler = $handler;
+ $this->interceptors = $interceptors;
+ }
+ }
+
+ /**
+ * Get the handler
+ */
+ public function getHandler() {
+ return $this->handler;
+ }
+
+ /**
+ * Get the interceptors
+ */
+ public function getInterceptors() {
+ return $this->interceptors;
+ }
+
+}
204 lib/halo_HttpRequest.php
@@ -0,0 +1,204 @@
+<?php
+
+require_once('dd_logging_ILogger.php');
+require_once('dd_logging_LogFactory.php');
+
+class halo_HttpRequest {
+
+ /**
+ * Logger
+ * @var dd_logging_ILogger
+ */
+ static public $LOGGER;
+
+ /**
+ * Request method.
+ * @var string
+ */
+ protected $method;
+
+ /**
+ * Query params.
+ *
+ * Think $_GET.
+ * @var array
+ */
+ protected $queryParams;
+
+ /**
+ * Post params.
+ *
+ * Think $_POST.
+ * @var array
+ */
+ protected $postParams;
+
+ /**
+ * File data
+ *
+ * Think $_FILES.
+ * @var array
+ */
+ protected $fileData;
+
+ /**
+ * Environment
+ *
+ * Think $_ENV.
+ * @var Array
+ */
+ protected $env;
+
+ /**
+ * Attributes
+ *
+ * Customized attributes added by the application. Can be used to
+ * add additional context to the request but are not required.
+ * @var Array
+ */
+ protected $attributes = array();
+
+ /**
+ * URI Params.
+ *
+ * Experimental. The URI may be parsed for params depending on the
+ * handler mapping.
+ * @var array
+ */
+ protected $uriParams = array();
+
+ /**
+ * Script path root.
+ * @var string
+ */
+ protected $scriptPathRoot;
+
+ /**
+ * Original requested URI.
+ * @var string
+ */
+ protected $requestedUri;
+
+ /**
+ * Body of request
+ * @var mixed
+ */
+ protected $body;
+
+ /**
+ * Constructor
+ * @param $method
+ * @param $queryParams
+ * @param $postParams
+ * @param $fileData
+ * @param $env
+ * @param $body
+ */
+ public function __construct($method, array $queryParams = null, array $postParams = null, array $fileData = null, array $env = null, $body = null) {
+
+ if ( $env === null ) $env = array();
+
+ foreach ( array('PATH_INFO', 'SCRIPT_PATH_INFO') as $envKey ) {
+ if ( ! isset($env[$envKey]) ) $env[$envKey] = null;
+ }
+
+ $this->method = $method;
+ $this->queryParams = $queryParams;
+ $this->postParams = $postParams;
+ $this->fileData = $fileData;
+ $this->env = $env;
+ $this->body = $body;
+
+ // Trim any leading slashes.
+ $this->requestedUri = preg_replace('/^\/*/', '', $env['PATH_INFO']);
+
+ if ( isset($env['REQUEST_URI']) ) {
+ $requestUri = $env['REQUEST_URI'];
+ $this->scriptPathRoot = $env['SCRIPT_PATH_ROOT'] =
+ preg_replace('/\/+/', '/', $this->requestedUri ?
+ substr($requestUri, 0, strpos($requestUri, $this->requestedUri)) :
+ $requestUri);
+ } else {
+ $this->scriptPathRoot = $env['SCRIPT_PATH_ROOT'] = '/';
+ }
+
+ // TODO: Does this actually make sense?
+ $_SERVER = $this->env;
+
+ }
+
+ public function method() { return $this->method; }
+ public function requestedUri() { return $this->requestedUri; }
+ public function getRequestedUri() { return $this->deprecated()->requestedUri(); }
+ public function getRequestedUrl() { return $this->deprecated()->requestedUri(); }
+
+ public function queryParamExists($key) { return array_key_exists($key, $this->queryParams); }
+ public function queryParam($key) { return isset($this->queryParams[$key]) ? $this->queryParams[$key] : null; }
+ public function setQueryParam($key, $value = null) { $this->queryParams[$key] = $value; }
+ public function unsetQueryParam($key) { unset($this->queryParams[$key]); }
+ public function queryParams() { return $this->queryParams; }
+ public function getQueryParams() { return $this->deprecated()->queryParams(); }
+
+ public function postParamExists($key) { return array_key_exists($key, $this->postParams); }
+ public function postParam($key) { return isset($this->postParam[$key]) ? $this->postParam[$key] : null; }
+ public function setPostParam($key, $value = null) { $this->postParams[$key] = $value; }
+ public function unsetPostParam($key) { unset($this->postParams[$key]); }
+ public function postParams() { return $this->postParams; }
+ public function getPostParams() { return $this->deprecated()->postParams(); }
+
+ public function attributeExists($key) { return array_key_exists($key, $this->attributes); }
+ public function attribute($key) { return isset($this->attributes[$key]) ? $this->attributes[$key] : null; }
+ public function setAttribute($key, $value = null) { $this->attributes[$key] = $value; }
+ public function unsetAttribute($key) { unset($this->attributes[$key]); }
+ public function attributes() { return $this->attributes; }
+ public function attributeKeys() { return array_keys($this->attributes); }
+ public function getAttributes() { return $this->deprecated()->attributes(); }
+ public function getAttributeKeys() { return $this->deprecated()->attributeKeys(); }
+
+ public function uriParamExists($key) { return array_key_exists($key, $this->uriParams); }
+ public function uriParam($key) { return isset($this->uriParams[$key]) ? $this->uriParams[$key] : null; }
+ public function setUriParam($key, $value = null) { $this->uriParams[$key] = $value; }
+ public function unsetUriParam($key) { unset($this->uriParams[$key]); }
+ public function uriParams() { return $this->uriParams; }
+ public function uriParamNames() { return array_keys($this->uriParams); }
+
+ public function urlParamExists($key) { return $this->deprecated()->uriParamExists($key); }
+ public function urlParam($key) { $this->deprecated()->uriParam($key); }
+ public function setUrlParam($key, $value = null) { $this->deprecated()->setUriParam($key, $value); }
+ public function unsetUrlParam($key) { $this->deprecated()->unsetUriParam($key); }
+ public function urlParams() { $this->deprecated()->uriParams(); }
+ public function getUrlParams() { $this->deprecated()->uriParams(); }
+ public function urlParamNames() { $this->deprecated()->uriParamNames($key); }
+ public function getUrlParamNames() { $this->deprecated()->uriParamNames($key); }
+
+ public function fileParams() { return $this->fileParams; }
+ public function fileParam($key, $secondKey = null) {
+ if ( array_key_exists($key, $this->fileData) ) {
+ $value = $this->fileData[$key];
+ if ( $secondKey === null ) { return $value; }
+ elseif ( array_key_exists($secondKey, $value) ) { return $value[$secondKey]; }
+ }
+ return null;
+ }
+
+ public function envExists($key) { return array_key_exists($key, $this->env); }
+ public function envKeys() { return array_keys($this->env); }
+ public function env($key) { return isset($this->env[$key]) ? $this->env[$key] : null; }
+
+ public function body() { return $this->body; }
+
+ public function getFileParams() { return $this->deprecated()->fileParams(); }
+ public function getFileParam($key, $secondKey = null) { return $this->deprecated()->fileParam($key, $secondKey); }
+
+ protected function deprecated() {
+ if ( self::$LOGGER->isWarnEnabled() ) {
+ $back = debug_backtrace();
+ self::$LOGGER->warn('Deprecated call to ' . $back[1]['class'] . '::' . $back[1]['function'] . ', ' . $back[1]['file'] . ':' . $back[1]['line']);
+ }
+ return $this;
+ }
+
+}
+
+halo_HttpRequest::$LOGGER = dd_logging_LogFactory::get('halo_HttpRequest');
+
5 lib/halo_HttpResponse.php
@@ -0,0 +1,5 @@
+<?php
+
+class halo_HttpResponse {
+ //
+}
31 lib/halo_IController.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * Halo Controller Interface.
+ * @package halo
+ */
+
+require_once('halo_HttpRequest.php');
+require_once('halo_HttpResponse.php');
+
+/**
+ * Halo Controller Interface.
+ * @package halo
+ */
+interface halo_IController {
+
+ /**
+ * Handle request.
+ *
+ * Expected to handle the request and return a {@link halo_ModelAndView} object or
+ * NULL if the output has already been handled.
+ *
+ * Implementing this interface is the only requirement of a Halo controller.
+ *
+ * @param halo_HttpRequest $httpRequest The request.
+ * @param halo_HttpResponse $httpResponse The response.
+ * @return halo_ModelAndView Model and View or NULL if output has already been taken care of.
+ */
+ public function handleRequest(halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse);
+
+}
22 lib/halo_IHandlerAdapter.php
@@ -0,0 +1,22 @@
+<?php
+
+require_once('halo_HttpRequest.php');
+require_once('halo_HttpResponse.php');
+
+interface halo_IHandlerAdapter {
+
+ /**
+ * Determine whether this handler adapter supports a given handler
+ * @param $object
+ */
+ public function supports($object);
+
+ /**
+ * Handle a request
+ * @param $httpRequest
+ * @param $httpResponse
+ * @param $handler
+ */
+ public function handle(halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse, $handler);
+
+}
35 lib/halo_IHandlerInterceptor.php
@@ -0,0 +1,35 @@
+<?php
+
+require_once('halo_HttpRequest.php');
+require_once('halo_HttpResponse.php');
+require_once('halo_ModelAndView.php');
+
+interface halo_IHandlerInterceptor {
+
+ /**
+ * Execute before handler is called
+ * @param $httpRequest
+ * @param $httpResponse
+ * @param $handler
+ */
+ public function preHandle(halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse, $handler);
+
+ /**
+ * Execute after handler is called
+ * @param $httpRequest
+ * @param $httpResponse
+ * @param $handler
+ * @param $modelAndView
+ */
+ public function postHandle(halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse, $handler, halo_ModelAndView $modelAndView);
+
+ /**
+ * Execute after execution is completed (read: FINALLY)
+ * @param $httpRequest
+ * @param $httpResponse
+ * @param $handler
+ * @param $e
+ */
+ public function afterCompletion(halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse, $handler, Exception $e);
+
+}
11 lib/halo_IHandlerMapping.php
@@ -0,0 +1,11 @@
+<?php
+
+interface halo_IHandlerMapping {
+
+ /**
+ * Get the handler execution chain
+ * @param $httpRequest
+ */
+ public function getHandlerExecutionChain(halo_HttpRequest $httpRequest);
+
+}
41 lib/halo_ModelAndView.php
@@ -0,0 +1,41 @@
+<?php
+class halo_ModelAndView {
+ protected $view;
+ protected $viewName;
+ protected $model;
+ protected $isReferenced;
+ public function __construct($viewMixed, $model = null) {
+ if ( is_object($viewMixed) ) {
+ $this->view = $viewMixed;
+ $this->isReferenced = false;
+ } else {
+ $this->viewName = $viewMixed;
+ $this->isReferenced = true;
+ }
+ $this->model = $model === null ? array() : $model;
+ }
+ public function isReferenced() {
+ return $this->isReferenced;
+ }
+ public function getView() {
+ return $this->view;
+ }
+ public function getViewName() {
+ return $this->viewName;
+ }
+ public function getModel() {
+ return $this->model;
+ }
+ public function keys() {
+ return array_keys($this->model);
+ }
+ public function exists($key) {
+ return array_key_exists($key, $this->model);
+ }
+ public function get($key) {
+ return $this->model[$key];
+ }
+ public function set($key, $value = null) {
+ $this->model[$key] = $value;
+ }
+}
73 lib/halo_SimpleUriHandlerMapping.php
@@ -0,0 +1,73 @@
+<?php
+
+require_once('halo_AbstractUriHandlerMapping.php');
+require_once('halo_HttpRequest.php');
+
+require_once('dd_logging_LogFactory.php');
+require_once('dd_logging_ILogger.php');
+
+class halo_SimpleUriHandlerMapping extends halo_AbstractUriHandlerMapping {
+
+ /**
+ * Logger
+ * @var dd_logging_ILogger
+ */
+ public static $LOGGER;
+
+ /**
+ * URI to handler mappings
+ * @var Array
+ */
+ protected $mappings;
+
+ /**
+ * Should we use a default handler?
+ * @var Bool
+ */
+ protected $useDefault;
+
+ /**
+ * Constructor
+ * @param $mappings
+ * @param $default
+ */
+ public function __construct(array $mappings, $default = null) {
+ $this->mappings = $mappings;
+ $this->default = $default;
+ if ( $default !== null ) {
+ $this->useDefault = true;
+ } else {
+ $this->useDefault = false;
+ }
+ }
+
+ /**
+ * Get the actual handler
+ * @param $httpRequest
+ */
+ protected function getHandlerInternal(halo_HttpRequest $httpRequest) {
+ $uri = $httpRequest->requestedUri();
+ if ( $this->useDefault and ( $uri === null or $uri === '' ) and $this->default !== null ) {
+ return $this->context->get($this->default);
+ }
+ if ( isset($this->registeredHandlers[$uri]) ) {
+ return $this->context->get($this->registeredHandlers[$uri]);
+ }
+ if ( self::$LOGGER->isInfoEnabled() ) {
+ self::$LOGGER->info('Unable to handle request for URI: [' . $uri . ']');
+ }
+ return null;
+ }
+
+ /**
+ * Register the handlers
+ */
+ protected function registerHandlers() {
+ foreach ( $this->mappings as $uri => $objectName ) {
+ $this->registerHandler($uri, $objectName);
+ }
+ }
+
+}
+
+halo_SimpleUriHandlerMapping::$LOGGER = dd_logging_LogFactory::get('halo_SimpleUriHandlerMapping');
9 lib/halo_base.context.php
@@ -0,0 +1,9 @@
+<?php
+
+$context->add('halo.dispatcher', array(
+ 'className' => 'halo_Dispatcher',
+));
+
+$context->add('halo.controllerHandlerAdapter', array(
+ 'className' => 'halo_ControllerHandlerAdapter',
+));
40 lib/halo_examples_SimpleEchoController.php
@@ -0,0 +1,40 @@
+<?php
+
+require_once('halo_IController.php');
+
+require_once('dd_logging_LogFactory.php');
+require_once('dd_logging_ILogger.php');
+
+class halo_examples_SimpleEchoController implements halo_IController {
+
+ /**
+ * Logger
+ * @var dd_logging_ILogger
+ */
+ public static $LOGGER;
+
+ /**
+ * Content to render
+ * @var unknown_type
+ */
+ protected $content;
+
+ /**
+ * Constructor
+ * @param $content
+ */
+ public function __construct($content = null) {
+ $this->content = $content;
+ }
+
+ /**
+ * (non-PHPdoc)
+ * @see halo_IController::handleRequest()
+ */
+ public function handleRequest(halo_HttpRequest $httpRequest, halo_HttpResponse $httpResponse) {
+ echo $this->content;
+ }
+
+}
+
+halo_examples_SimpleEchoController::$LOGGER = dd_logging_LogFactory::get('halo_examples_SimpleEchoController');
Please sign in to comment.
Something went wrong with that request. Please try again.