mabslabs/Mabs

View on GitHub
src/Application.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
/**
 * Mabs framework
 *
 * @author      Mohamed Aymen Ben Slimane <aymen.kernel@gmail.com>
 * @copyright   2015 Mohamed Aymen Ben Slimane
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Mohamed Aymen Ben Slimane
 *
 * 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.
 */

namespace Mabs;

use Mabs\Container\Container;
use Mabs\Dispatcher\EventDispatcher;
use Mabs\Router\Route;
use Mabs\Router\RouteCollection;
use Mabs\Router\Router;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class Application
{
    const VERSION = '2.1.1';

    protected $container;

    protected $adapters;

    protected $debug;

    protected $loaded = false;

    protected $booted = false;

    public function __construct($debug = false)
    {
        if ($debug) {
            ini_set('display_errors', 'on');
            error_reporting(E_ALL);
        } else {
            error_reporting(0);
        }
        $this->debug = $debug;
        $this->adapters = new \SplObjectStorage();
        $this->container = new Container();

        $this->load();

        $this->lock();
    }

    /**
     * check if debug mode is active
     * @return bool
     */
    public function isDebugMode()
    {
        return $this->debug === true;
    }

    /**
     * attach an action for an event
     * @param string $eventName
     * @param callable $callback
     * @param int $priority
     * @return \Mabs\EventDispatcher
     */
    public function on($eventName, \Closure $callback, $priority = 0)
    {
        return $this->container['event_dispatcher']->register($eventName, $callback, $priority);
    }

    /**
     * detach registered actions for an event
     * @param string $eventName
     * @return \Mabs\EventDispatcher
     */
    public function detach($eventName)
    {
        return $this->container['event_dispatcher']->detach($eventName);
    }

    /**
     * @param string $eventName
     * @param mixed $data
     * @return mixed
     */
    public function dispatch($eventName, $data = null)
    {
        return $this->container['event_dispatcher']->dispatch($eventName, $data);
    }

    /**
     * check if all component are loaded
     * @return bool
     */
    public function isLoaded()
    {
        return $this->loaded === true;
    }

    /**
     * check if all component are booted
     * @return bool
     */
    public function isBooted()
    {
        return $this->booted === true;
    }

    /**
     * run applicaton : handle the request and send response
     */
    public function run()
    {
        try {

            if (!$this->isLoaded()) {
                $this->load();
            }

            if (!$this->isBooted()) {
                $this->boot();
            }

            $response = $this->handleRequest();
            $this->dispatch(Events::MABS_ON_TERMINATE, $response);

        } catch (\Exception $e) {
            $this->dispatch(Events::MABS_HANDLE_EXCEPTION, $e);
            $response = new Response('500 internal server error', 500);
        }

        $response->send();
        $this->dispatch(Events::MABS_ON_FINISH);
    }

    /**
     * handle a Request
     * @param Request $request
     * @return Response
     */
    public function handleRequest(Request $request = null)
    {
        if (!$request) {
            $request = $this->container['request'];
        }

        $this->dispatch(Events::MABS_HANDLE_REQUEST, $request);

        $response = $this->container['router']->handleRequest($request);
        if (! $response instanceof Response) {
            $response = new Response($response, 200);
        }

        return $response;
    }

    /**
     * add GET route
     * @param string $pattern
     * @param \Closure|string $callback
     * @param null|string $routeName
     * @return Application
     */
    public function get($pattern, $callback, $routeName = null)
    {
        return $this->mount($pattern, $callback, $routeName, array(Request::METHOD_GET));
    }

    /**
     * add POST route
     * @param string $pattern
     * @param \Closure|string $callback
     * @param null|string $routeName
     * @return Application
     */
    public function post($pattern, $callback, $routeName = null)
    {
        return $this->mount($pattern, $callback, $routeName, array(Request::METHOD_POST));
    }

    /**
     * add PUT route
     * @param string $pattern
     * @param \Closure|string $callback
     * @param null|string $routeName
     * @return Application
     */
    public function put($pattern, $callback, $routeName = null)
    {
        return $this->mount($pattern, $callback, $routeName, array(Request::METHOD_PUT));
    }

    /**
     * add DELETE route
     * @param string $pattern
     * @param \Closure|string $callback
     * @param null|string $routeName
     * @return Application
     */
    public function delete($pattern, $callback, $routeName = null)
    {
        return $this->mount($pattern, $callback, $routeName, array(Request::METHOD_DELETE));
    }

    /**
     * add a route
     * @param string $pattern
     * @param \Closure|string $callback
     * @param null|string $routeName
     * @param array HTTP Methode
     * @return Application
     */
    public function mount($pattern, $callback, $routeName = null, $methodes = array())
    {
        $route = new Route();
        $route->setPath($pattern)
            ->setName($routeName)
            ->setCallback($callback);

        $this->container['router']->mount($route, $methodes);

        return $this;
    }

    /**
     * get the DI container
     * @return Container
     */
    public function getContainer()
    {
        return $this->container;
    }

    /**
     * lock the container
     */
    public function lock()
    {
        $this->container->lock(true);
        $this->dispatch(Events::MABS_ON_LOCKED);
    }

    /**
     * list of active components
     * @return array
     */
    public function getAdapters()
    {
        return array(
            new \Mabs\Adapter\SessionServiceAdapter(),
        );
    }

    /**
     * load all component in the DI Container
     */
    protected function load()
    {
        $this->container['event_dispatcher'] = function (Container $container) {
            return new EventDispatcher($container);
        };

        $this->container['request'] = function () {
            return Request::createFromGlobals();
        };

        $this->container['router'] = function (Container $container) {
            return new Router();
        };

        foreach ($this->getAdapters() as $adapter) {
            $adapter->load($this->container);
            $this->adapters->attach($adapter);
        }

        $this->loaded = true;
    }

    /**
     * initialize all components
     */
    protected function boot()
    {
        foreach ($this->adapters as $adapter) {
            $adapter->boot($this->container);
        }
        $this->dispatch(Events::MABS_ON_BOOT);
        $this->booted = true;
    }
}