Initial skeleton in place with ZF2 submodule pointed at current master
authorEvan Coury <me@evancoury.com>
Fri, 30 Sep 2011 03:18:37 +0000 (20:18 -0700)
committerEvan Coury <me@evancoury.com>
Fri, 30 Sep 2011 03:18:37 +0000 (20:18 -0700)
18 files changed:
.gitmodules [new file with mode: 0644]
configs/application.config.php [new file with mode: 0644]
library/ZendFramework [new submodule]
modules/Application/Module.php [new file with mode: 0644]
modules/Application/autoload_classmap.php [new file with mode: 0644]
modules/Application/autoload_function.php [new file with mode: 0644]
modules/Application/autoload_register.php [new file with mode: 0644]
modules/Application/configs/module.config.php [new file with mode: 0644]
modules/Application/src/Application/Bootstrap.php [new file with mode: 0644]
modules/Application/src/Application/Controller/ErrorController.php [new file with mode: 0644]
modules/Application/src/Application/Controller/IndexController.php [new file with mode: 0644]
modules/Application/src/Application/View/Helper/Url.php [new file with mode: 0644]
modules/Application/src/Application/View/Listener.php [new file with mode: 0644]
modules/Application/views/error/index.phtml [new file with mode: 0644]
modules/Application/views/index/index.phtml [new file with mode: 0644]
modules/Application/views/layouts/layout.phtml [new file with mode: 0644]
public/.htaccess [new file with mode: 0644]
public/index.php [new file with mode: 0644]

diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..80fc458
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "library/ZendFramework"]
+       path = library/ZendFramework
+       url = git://github.com/zendframework/zf2.git
diff --git a/configs/application.config.php b/configs/application.config.php
new file mode 100644 (file)
index 0000000..b093106
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+return new Zend\Config\Config(array(
+    'module_paths' => array(
+        realpath(__DIR__ . '/../modules'),
+    ),
+    'modules' => array(
+        'Application',
+    ),
+    'module_config' => array( 
+        'cache_config'  => false,
+        'cache_dir'     => realpath(__DIR__ . '/../data/cache'),
+    ),
+));
diff --git a/library/ZendFramework b/library/ZendFramework
new file mode 160000 (submodule)
index 0000000..795d6ae
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 795d6aeeb3694d17cf151ad0c7a9b9af8382144f
diff --git a/modules/Application/Module.php b/modules/Application/Module.php
new file mode 100644 (file)
index 0000000..cfcc333
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+
+namespace Application;
+
+use InvalidArgumentException,
+    Zend\Module\Manager,
+    Zend\Config\Config,
+    Zend\Di\Locator,
+    Zend\EventManager\EventCollection,
+    Zend\EventManager\StaticEventCollection;
+
+class Module
+{
+    protected $appListeners    = array();
+    protected $staticListeners = array();
+    protected $viewListener;
+
+    public function init(Manager $moduleManager)
+    {
+        $this->initAutoloader($moduleManager->getOptions()->getApplicationEnv());
+    }
+
+    protected function initAutoloader($env = null)
+    {
+        require __DIR__ . '/autoload_register.php';
+    }
+
+    public static function getConfig()
+    {
+        return new Config(include __DIR__ . '/configs/module.config.php');
+    }
+    
+    public function registerApplicationListeners(EventCollection $events, Locator $locator, Config $config)
+    {
+        $view          = $locator->get('view');
+        $viewListener  = $this->getViewListener($view, $config);
+        $events->attachAggregate($viewListener);
+    }
+
+    public function registerStaticListeners(StaticEventCollection $events, Locator $locator, Config $config)
+    {
+        $view         = $locator->get('view');
+        $viewListener = $this->getViewListener($view, $config);
+
+        $viewListener->registerStaticListeners($events, $locator);
+    }
+
+    protected function getViewListener($view, $config)
+    {
+        if ($this->viewListener instanceof View\Listener) {
+            return $this->viewListener;
+        }
+
+        $viewListener       = new View\Listener($view, $config->layout);
+        $viewListener->setDisplayExceptionsFlag($config->display_exceptions);
+
+        $this->viewListener = $viewListener;
+        return $viewListener;
+    }
+}
diff --git a/modules/Application/autoload_classmap.php b/modules/Application/autoload_classmap.php
new file mode 100644 (file)
index 0000000..890cf29
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+return array (
+  'Application\\View\\Listener' => __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Application' . DIRECTORY_SEPARATOR . 'View' . DIRECTORY_SEPARATOR . 'Listener.php',
+  'Application\\View\\Helper\\Url' => __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Application' . DIRECTORY_SEPARATOR . 'View' . DIRECTORY_SEPARATOR . 'Helper' . DIRECTORY_SEPARATOR . 'Url.php',
+  'Application\\Bootstrap' => __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Application' . DIRECTORY_SEPARATOR . 'Bootstrap.php',
+  'Application\\Controller\\IndexController' => __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Application' . DIRECTORY_SEPARATOR . 'Controller' . DIRECTORY_SEPARATOR . 'IndexController.php',
+  'Application\\Controller\\ErrorController' => __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Application' . DIRECTORY_SEPARATOR . 'Controller' . DIRECTORY_SEPARATOR . 'ErrorController.php',
+  'Application\\Module' => __DIR__ . DIRECTORY_SEPARATOR . 'Module.php',
+);
\ No newline at end of file
diff --git a/modules/Application/autoload_function.php b/modules/Application/autoload_function.php
new file mode 100644 (file)
index 0000000..3ea81c4
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+return function ($class) {
+    static $map;
+    if (!$map) {
+        $map = include __DIR__ . '/autoload_classmap.php';
+    }
+
+    if (!isset($map[$class])) {
+        return false;
+    }
+    return include $map[$class];
+};
diff --git a/modules/Application/autoload_register.php b/modules/Application/autoload_register.php
new file mode 100644 (file)
index 0000000..a8dcbb4
--- /dev/null
@@ -0,0 +1,2 @@
+<?php
+spl_autoload_register(include __DIR__ . '/autoload_function.php');
diff --git a/modules/Application/configs/module.config.php b/modules/Application/configs/module.config.php
new file mode 100644 (file)
index 0000000..3b5caf2
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+return array(
+    'bootstrap_class' => 'Application\Bootstrap',
+    'layout'          => 'layouts/layout.phtml',
+    'di'              => array(
+        'instance' => array(
+            'alias' => array(
+                'index' => 'Application\Controller\IndexController',
+                'error' => 'Application\Controller\ErrorController',
+                'view'  => 'Zend\View\PhpRenderer',
+            ),
+
+            'Zend\View\HelperLoader' => array(
+                'parameters' => array(
+                    'map' => array(
+                        'url' => 'Application\View\Helper\Url',
+                    ),
+                ),
+            ),
+
+            'Zend\View\HelperBroker' => array(
+                'parameters' => array(
+                    'loader' => 'Zend\View\HelperLoader',
+                ),
+            ),
+
+            'Zend\View\PhpRenderer' => array(
+                'methods' => array(
+                    'setResolver' => array(
+                        'resolver' => 'Zend\View\TemplatePathStack',
+                        'options'  => array(
+                            'script_paths' => array(
+                                'application' => __DIR__ . '/../views',
+                            ),
+                        ),
+                    ),
+                ),
+                'parameters' => array(
+                    'broker' => 'Zend\View\HelperBroker',
+                ),
+            ),
+        ),
+    ),
+
+    'routes' => array(
+        'default' => array(
+            'type'    => 'Zend\Mvc\Router\Http\Regex',
+            'options' => array(
+                'regex'    => '/(?P<controller>[^/]+)(/(?P<action>[^/]+)?)?',
+                'spec'     => '/%controller%/%action%',
+                'defaults' => array(
+                    'controller' => 'error',
+                    'action'     => 'index',
+                ),
+            ),
+        ),
+        'home' => array(
+            'type' => 'Zend\Mvc\Router\Http\Literal',
+            'options' => array(
+                'route'    => '/',
+                'defaults' => array(
+                    'controller' => 'index',
+                    'action'     => 'index',
+                ),
+            ),
+        ),
+    ),
+);
diff --git a/modules/Application/src/Application/Bootstrap.php b/modules/Application/src/Application/Bootstrap.php
new file mode 100644 (file)
index 0000000..fed8b36
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+namespace Application;
+
+use Zend\Config\Config,
+    Zend\Di\Configuration,
+    Zend\Di\Definition,
+    Zend\Di\DependencyInjector,
+    Zend\EventManager\StaticEventManager,
+    Zend\Module\Manager as ModuleManager,
+    Zend\Mvc\Application;
+
+class Bootstrap
+{
+    protected $config;
+    protected $modules;
+
+    public function __construct(Config $config, ModuleManager $modules)
+    {
+        $this->config  = $config;
+        $this->modules = $modules; 
+    }
+
+    public function bootstrap(Application $app)
+    {
+        $this->setupLocator($app);
+        $this->setupRoutes($app);
+        $this->setupEvents($app);
+    }
+
+    protected function setupLocator(Application $app)
+    {
+        $definition = new Definition\AggregateDefinition;
+        $definition->addDefinition(new Definition\RuntimeDefinition);
+
+        $di = new DependencyInjector;
+        $di->setDefinition($definition);
+
+        $config = new Configuration($this->config->di);
+        $config->configure($di);
+
+        $app->setLocator($di);
+    }
+
+    protected function setupRoutes(Application $app)
+    {
+        $router = $app->getLocator()->get('Zend\Mvc\Router\SimpleRouteStack');
+        foreach ($this->config->routes as $name => $config) {
+            $class   = $config->type;
+            $options = $config->options;
+            $route   = new $class($options);
+            $router->addRoute($name, $route);
+        }
+        $app->setRouter($router);
+    }
+
+    protected function setupEvents(Application $app)
+    {
+        $view         = $this->getView($app);
+        $locator      = $app->getLocator();
+        $events       = $app->events();
+        $staticEvents = StaticEventManager::getInstance();
+
+        foreach ($this->modules->getLoadedModules() as $name => $module) {
+            if (method_exists($module, 'registerApplicationListeners')) {
+                $module->registerApplicationListeners($events, $locator, $this->config);
+            }
+
+            if (method_exists($module, 'registerStaticListeners')) {
+                $module->registerStaticListeners($staticEvents, $locator, $this->config);
+            }
+        }
+    }
+
+    protected function getView($app)
+    {
+        $di     = $app->getLocator();
+        $view   = $di->get('view');
+        $url    = $view->plugin('url');
+        $url->setRouter($app->getRouter());
+
+        $view->plugin('headTitle')->setSeparator(' - ')
+                                  ->setAutoEscape(false)
+                                  ->append('Application');
+        return $view;
+    }
+}
diff --git a/modules/Application/src/Application/Controller/ErrorController.php b/modules/Application/src/Application/Controller/ErrorController.php
new file mode 100644 (file)
index 0000000..17f002e
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+
+namespace Application\Controller;
+
+use Zend\Mvc\Controller\ActionController;
+
+class ErrorController extends ActionController
+{
+    const ERROR_NO_ROUTE = 404;
+    const ERROR_NO_CONTROLLER = 404;
+
+    public function indexAction()
+    {
+        $error = $this->request->getMetadata('error', false);
+        if (!$error) {
+            $error = array(
+                'type'    => 404,
+                'message' => 'Page not found',
+            );
+        }
+        
+        switch ($error['type']) {
+            case self::ERROR_NO_ROUTE:
+            case self::ERROR_NO_CONTROLLER:
+            default:
+                // 404 error -- controller or action not found
+                $this->response->setStatusCode(404);
+                break;
+        }
+        
+        return array('message' => $error['message']);
+    }
+}
diff --git a/modules/Application/src/Application/Controller/IndexController.php b/modules/Application/src/Application/Controller/IndexController.php
new file mode 100644 (file)
index 0000000..8c1f5e1
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+
+namespace Application\Controller;
+
+use Zend\Mvc\Controller\ActionController;
+
+class IndexController extends ActionController
+{
+    public function indexAction()
+    {
+        return array();
+    }
+}
diff --git a/modules/Application/src/Application/View/Helper/Url.php b/modules/Application/src/Application/View/Helper/Url.php
new file mode 100644 (file)
index 0000000..ccea1fe
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+namespace Application\View\Helper;
+
+use Zend\View\Helper\AbstractHelper,
+    Zend\Mvc\Router\RouteStack;
+
+class Url extends AbstractHelper
+{
+    protected $router;
+
+    public function setRouter(RouteStack $router)
+    {
+        $this->router = $router;
+    }
+
+    public function direct($params = array(), $options = array())
+    {
+        if (null === $this->router) {
+            return '';
+        }
+
+        // Remove trailing '/index' from generated URLs.
+        $url = $this->router->assemble($params, $options);
+        if ((6 <= strlen($url)) && '/index' == substr($url, -6)) {
+            $url = substr($url, 0, strlen($url) - 6);
+        }
+
+        return $url;
+    }
+}
diff --git a/modules/Application/src/Application/View/Listener.php b/modules/Application/src/Application/View/Listener.php
new file mode 100644 (file)
index 0000000..a6054c8
--- /dev/null
@@ -0,0 +1,218 @@
+<?php
+
+namespace Application\View;
+
+use ArrayAccess,
+    Zend\Di\Locator,
+    Zend\EventManager\EventCollection,
+    Zend\EventManager\ListenerAggregate,
+    Zend\EventManager\StaticEventCollection,
+    Zend\Http\Response,
+    Zend\Mvc\Application,
+    Zend\Mvc\MvcEvent,
+    Zend\View\Renderer;
+
+class Listener implements ListenerAggregate
+{
+    protected $layout;
+    protected $listeners = array();
+    protected $staticListeners = array();
+    protected $view;
+    protected $displayExceptions = false;
+
+    public function __construct(Renderer $renderer, $layout = 'layout.phtml')
+    {
+        $this->view   = $renderer;
+        $this->layout = $layout;
+    }
+
+    public function setDisplayExceptionsFlag($flag)
+    {
+        $this->displayExceptions = (bool) $flag;
+        return $this;
+    }
+
+    public function displayExceptions()
+    {
+        return $this->displayExceptions;
+    }
+
+    public function attach(EventCollection $events)
+    {
+        $this->listeners[] = $events->attach('dispatch.error', array($this, 'renderError'));
+        $this->listeners[] = $events->attach('dispatch', array($this, 'render404'), -80);
+        $this->listeners[] = $events->attach('dispatch', array($this, 'renderLayout'), -1000);
+    }
+
+    public function detach(EventCollection $events)
+    {
+        foreach ($this->listeners as $key => $listener) {
+            $events->detach($listener);
+            unset($this->listeners[$key]);
+            unset($listener);
+        }
+    }
+
+    public function registerStaticListeners(StaticEventCollection $events, $locator)
+    {
+        $ident   = 'Application\Controller\PageController';
+        $handler = $events->attach($ident, 'dispatch', array($this, 'renderPageController'), -50);
+        $this->staticListeners[] = array($ident, $handler);
+
+        $ident   = 'Zend\Mvc\Controller\ActionController';
+        $handler = $events->attach($ident, 'dispatch', array($this, 'renderView'), -50);
+        $this->staticListeners[] = array($ident, $handler);
+    }
+
+    public function detachStaticListeners(StaticEventCollection $events)
+    {
+        foreach ($this->staticListeners as $i => $info) {
+            list($id, $handler) = $info;
+            $events->detach($id, $handler);
+            unset($this->staticListeners[$i]);
+        }
+    }
+
+    public function renderPageController(MvcEvent $e)
+    {
+        $page = $e->getResult();
+        if ($page instanceof Response) {
+            return;
+        }
+
+        $response = $e->getResponse();
+        if ($response->isNotFound()) {
+            return;
+        } 
+
+        $routeMatch = $e->getRouteMatch();
+
+        if (!$routeMatch) {
+            $page = '404';
+        } else {
+            $page = $routeMatch->getParam('action', '404');
+        }
+
+        if ($page == '404') {
+            $response->setStatusCode(404);
+        }
+
+        $script     = 'pages/' . $page . '.phtml';
+
+        // Action content
+        $content    = $this->view->render($script);
+        $e->setResult($content);
+
+        return $this->renderLayout($e);
+    }
+
+    public function renderView(MvcEvent $e)
+    {
+        $response = $e->getResponse();
+        if (!$response->isSuccess()) {
+            return;
+        }
+
+        $routeMatch = $e->getRouteMatch();
+        $controller = $routeMatch->getParam('controller', 'index');
+        $action     = $routeMatch->getParam('action', 'index');
+        $script     = $controller . '/' . $action . '.phtml';
+
+        $vars       = $e->getResult();
+        if (is_scalar($vars)) {
+            $vars = array('content' => $vars);
+        } elseif (is_object($vars) && !$vars instanceof ArrayAccess) {
+            $vars = (array) $vars;
+        }
+
+        $content    = $this->view->render($script, $vars);
+
+        $e->setResult($content);
+        return $content;
+    }
+
+    public function renderLayout(MvcEvent $e)
+    {
+        $response = $e->getResponse();
+        if (!$response) {
+            $response = new Response();
+            $e->setResponse($response);
+        }
+        if ($response->isRedirect()) {
+            return $response;
+        }
+
+        $footer   = $e->getParam('footer', false);
+        $vars     = array('footer' => $footer);
+
+        if (false !== ($contentParam = $e->getParam('content', false))) {
+            $vars['content'] = $contentParam;
+        } else {
+            $vars['content'] = $e->getResult();
+        }
+
+        $layout   = $this->view->render($this->layout, $vars);
+        $response->setContent($layout);
+        return $response;
+    }
+
+    public function render404(MvcEvent $e)
+    {
+        $vars = $e->getResult();
+        if ($vars instanceof Response) {
+            return;
+        }
+
+        $response = $e->getResponse();
+        if ($response->getStatusCode() != 404) {
+            // Only handle 404's
+            return;
+        }
+
+        $vars = array('message' => 'Page not found.');
+
+        $content = $this->view->render('pages/404.phtml', $vars);
+
+        $e->setResult($content);
+
+        return $this->renderLayout($e);
+    }
+
+    public function renderError(MvcEvent $e)
+    {
+        $error    = $e->getError();
+        $app      = $e->getTarget();
+        $response = $e->getResponse();
+        if (!$response) {
+            $response = new Response();
+            $e->setResponse($response);
+        }
+
+        switch ($error) {
+            case Application::ERROR_CONTROLLER_NOT_FOUND:
+            case Application::ERROR_CONTROLLER_INVALID:
+                $vars = array(
+                    'message' => 'Page not found.',
+                );
+                $response->setStatusCode(404);
+                break;
+
+            case Application::ERROR_EXCEPTION:
+            default:
+                $exception = $e->getParam('exception');
+                $vars = array(
+                    'message'            => 'An error occurred during execution; please try again later.',
+                    'exception'          => $e->getParam('exception'),
+                    'display_exceptions' => $this->displayExceptions(),
+                );
+                $response->setStatusCode(500);
+                break;
+        }
+
+        $content = $this->view->render('error.phtml', $vars);
+
+        $e->setResult($content);
+
+        return $this->renderLayout($e);
+    }
+}
diff --git a/modules/Application/views/error/index.phtml b/modules/Application/views/error/index.phtml
new file mode 100644 (file)
index 0000000..696917d
--- /dev/null
@@ -0,0 +1,14 @@
+<h1>An error occurred</h1>
+<h2><?php echo $this->vars('message') ?></h2>
+
+<?php if (isset($this->vars()->exception)): ?>
+
+<h3>Exception information:</h3>
+<p>
+    <b>Message:</b> <?php echo $this->vars('exception')->getMessage() ?>
+</p>
+
+<h3>Stack trace:</h3>
+<pre><?php echo $this->vars('exception')->getTraceAsString() ?></pre>
+
+<?php endif ?>
diff --git a/modules/Application/views/index/index.phtml b/modules/Application/views/index/index.phtml
new file mode 100644 (file)
index 0000000..debe855
--- /dev/null
@@ -0,0 +1 @@
+application module -> index controller -> index action
diff --git a/modules/Application/views/layouts/layout.phtml b/modules/Application/views/layouts/layout.phtml
new file mode 100644 (file)
index 0000000..6e80807
--- /dev/null
@@ -0,0 +1,12 @@
+<?php echo $this->plugin('doctype') ?>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <?php echo $this->plugin('headTitle') ?>
+
+</head>
+<body>
+<?php echo $this->vars()->getRawValue('content'); ?>
+</body>
+</html>
diff --git a/public/.htaccess b/public/.htaccess
new file mode 100644 (file)
index 0000000..361e2e3
--- /dev/null
@@ -0,0 +1,8 @@
+SetEnv APPLICATION_ENV development
+
+RewriteEngine On
+RewriteCond %{REQUEST_FILENAME} -s [OR]
+RewriteCond %{REQUEST_FILENAME} -l [OR]
+RewriteCond %{REQUEST_FILENAME} -d
+RewriteRule ^.*$ - [NC,L]
+RewriteRule ^.*$ index.php [NC,L]
diff --git a/public/index.php b/public/index.php
new file mode 100644 (file)
index 0000000..f4bf164
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+// Define application environment
+defined('APPLICATION_ENV')
+    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
+
+// Ensure ZF is on the include path
+set_include_path(implode(PATH_SEPARATOR, array(
+    realpath(__DIR__ . '/../library/ZendFramework/library'),
+    get_include_path(),
+)));
+
+require_once 'Zend/Loader/AutoloaderFactory.php';
+Zend\Loader\AutoloaderFactory::factory(array('Zend\Loader\StandardAutoloader' => array()));
+
+$appConfig = include __DIR__ . '/../configs/application.config.php';
+
+$moduleLoader = new Zend\Loader\ModuleAutoloader($appConfig->module_paths);
+$moduleLoader->register();
+
+$moduleManager = new Zend\Module\Manager(
+    $appConfig->modules,
+    new Zend\Module\ManagerOptions($appConfig->module_config)
+);
+
+// Get the merged config object
+$config = $moduleManager->getMergedConfig();
+
+// Create application, bootstrap, and run
+$bootstrap = new $config->bootstrap_class($config, $moduleManager);
+$application = new Zend\Mvc\Application;
+$bootstrap->bootstrap($application);
+$application->run()->send();