From f8a26075e9ee566a933125f76e73208fffd775a2 Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Thu, 29 Sep 2011 20:18:37 -0700 Subject: [PATCH] Initial skeleton in place with ZF2 submodule pointed at current master --- .gitmodules | 3 + configs/application.config.php | 13 ++ library/ZendFramework | 1 + modules/Application/Module.php | 60 ++++++ modules/Application/autoload_classmap.php | 9 + modules/Application/autoload_function.php | 12 ++ modules/Application/autoload_register.php | 2 + modules/Application/configs/module.config.php | 68 ++++++ modules/Application/src/Application/Bootstrap.php | 86 ++++++++ .../src/Application/Controller/ErrorController.php | 33 +++ .../src/Application/Controller/IndexController.php | 13 ++ .../src/Application/View/Helper/Url.php | 30 +++ .../Application/src/Application/View/Listener.php | 218 ++++++++++++++++++++ modules/Application/views/error/index.phtml | 14 ++ modules/Application/views/index/index.phtml | 1 + modules/Application/views/layouts/layout.phtml | 12 ++ public/.htaccess | 8 + public/index.php | 32 +++ 18 files changed, 615 insertions(+) create mode 100644 .gitmodules create mode 100644 configs/application.config.php create mode 160000 library/ZendFramework create mode 100644 modules/Application/Module.php create mode 100644 modules/Application/autoload_classmap.php create mode 100644 modules/Application/autoload_function.php create mode 100644 modules/Application/autoload_register.php create mode 100644 modules/Application/configs/module.config.php create mode 100644 modules/Application/src/Application/Bootstrap.php create mode 100644 modules/Application/src/Application/Controller/ErrorController.php create mode 100644 modules/Application/src/Application/Controller/IndexController.php create mode 100644 modules/Application/src/Application/View/Helper/Url.php create mode 100644 modules/Application/src/Application/View/Listener.php create mode 100644 modules/Application/views/error/index.phtml create mode 100644 modules/Application/views/index/index.phtml create mode 100644 modules/Application/views/layouts/layout.phtml create mode 100644 public/.htaccess create mode 100644 public/index.php diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..80fc458 --- /dev/null +++ b/.gitmodules @@ -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 index 0000000..b093106 --- /dev/null +++ b/configs/application.config.php @@ -0,0 +1,13 @@ + 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 index 0000000..795d6ae --- /dev/null +++ b/library/ZendFramework @@ -0,0 +1 @@ +Subproject commit 795d6aeeb3694d17cf151ad0c7a9b9af8382144f diff --git a/modules/Application/Module.php b/modules/Application/Module.php new file mode 100644 index 0000000..cfcc333 --- /dev/null +++ b/modules/Application/Module.php @@ -0,0 +1,60 @@ +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 index 0000000..890cf29 --- /dev/null +++ b/modules/Application/autoload_classmap.php @@ -0,0 +1,9 @@ + __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 index 0000000..3ea81c4 --- /dev/null +++ b/modules/Application/autoload_function.php @@ -0,0 +1,12 @@ + '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[^/]+)(/(?P[^/]+)?)?', + '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 index 0000000..fed8b36 --- /dev/null +++ b/modules/Application/src/Application/Bootstrap.php @@ -0,0 +1,86 @@ +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 index 0000000..17f002e --- /dev/null +++ b/modules/Application/src/Application/Controller/ErrorController.php @@ -0,0 +1,33 @@ +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 index 0000000..8c1f5e1 --- /dev/null +++ b/modules/Application/src/Application/Controller/IndexController.php @@ -0,0 +1,13 @@ +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 index 0000000..a6054c8 --- /dev/null +++ b/modules/Application/src/Application/View/Listener.php @@ -0,0 +1,218 @@ +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 index 0000000..696917d --- /dev/null +++ b/modules/Application/views/error/index.phtml @@ -0,0 +1,14 @@ +

An error occurred

+

vars('message') ?>

+ +vars()->exception)): ?> + +

Exception information:

+

+ Message: vars('exception')->getMessage() ?> +

+ +

Stack trace:

+
vars('exception')->getTraceAsString() ?>
+ + diff --git a/modules/Application/views/index/index.phtml b/modules/Application/views/index/index.phtml new file mode 100644 index 0000000..debe855 --- /dev/null +++ b/modules/Application/views/index/index.phtml @@ -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 index 0000000..6e80807 --- /dev/null +++ b/modules/Application/views/layouts/layout.phtml @@ -0,0 +1,12 @@ +plugin('doctype') ?> + + + + + plugin('headTitle') ?> + + + +vars()->getRawValue('content'); ?> + + diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..361e2e3 --- /dev/null +++ b/public/.htaccess @@ -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 index 0000000..f4bf164 --- /dev/null +++ b/public/index.php @@ -0,0 +1,32 @@ + 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(); -- 1.7.10.4