<?php
// define constants required by the application.
defined('BASE_PATH')
or define('BASE_PATH', realpath(dirname(__DIR__)));
defined('DATA_PATH')
or define('DATA_PATH', BASE_PATH . '/data');
defined('APPLICATION_PATH')
or define('APPLICATION_PATH', BASE_PATH . '/application');
defined('LIBRARY_PATH')
or define('LIBRARY_PATH', BASE_PATH . '/library');
defined('SITES_PATH')
or define('SITES_PATH', BASE_PATH . '/sites');
/**
* Initialize the application and environment.
* Note: the init functions are called in the order that they are defined.
*
* @copyright 2011 Perforce Software. All rights reserved.
* @license Please see LICENSE.txt in top-level folder of this distribution.
* @version <release>/<patch>
*/
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
/**
* Provide default application settings to ensure proper operation.
*
* @param string $environment the application environment to get defaults for.
* @return array the default application options.
*/
public static function getDefaultOptions($environment = null)
{
$options = array(
"phpSettings" => array(
"display_startup_errors" => 0,
"display_errors" => 0,
"error_reporting" => (E_ALL & ~(E_STRICT|E_NOTICE))
),
"resources" => array(
"log" => array(
"file" => DATA_PATH . '/log',
"priority" => Zend_Log::ERR,
"format" => "%timestamp% PID (%pid%) %priorityName% (%priority%): %message%\n"
),
"frontController" => array(
"env" => APPLICATION_ENV,
"moduleDirectory" => APPLICATION_PATH,
"defaultModule" => "content",
"prefixDefaultModule" => true,
"actionHelperPaths" => array(
"P4Cms_Controller_Action_Helper" =>
LIBRARY_PATH . "/P4Cms/Controller/Action/Helper"
)
),
"layout" => array(
"layout" => "default-layout"
),
"view" => array(
"encoding" => "UTF-8",
"useStreamWrapper" => true,
"helperPath" => array(
"Zend_Dojo_View_Helper" =>
LIBRARY_PATH . "/Zend/Dojo/View/Helper",
"Zend_View_Helper_Navigation" =>
LIBRARY_PATH . "/Zend/View/Helper/Navigation",
"P4Cms_View_Helper" =>
LIBRARY_PATH . "/P4Cms/View/Helper"
)
),
"cachemanager" => array(
"enabled" => true,
"default" => array(
"frontend" => array(
"name" => "Core",
"options" => array("automatic_serialization" => true)
),
"backend" => array(
"name" => "P4Cms_Cache_Backend_File",
"customBackendNaming" => true,
"options" => array("cache_dir" => DATA_PATH . '/cache/default')
),
),
"page" => array(
"frontend" => array(
"name" => "P4Cms_Cache_Frontend_Action",
"customFrontendNaming" => true,
"options" => array(
'default_options' => array(
'specific_lifetime' => 43200 // 12h
),
'actions' => array(
'content/list-widget/rss' => array(),
'content/index/index' => array(),
'content/index/view' => array(),
'content/index/image' => array(
'compress' => false,
'cache_with_username' => true,
'make_id_with_locale' => false,
'cache_with_session' => true,
'make_id_with_session' => false,
'cache_with_get' => true
),
'content/index/download' => array(
'compress' => false,
'cache_with_username' => true,
'make_id_with_locale' => false,
'cache_with_session' => true,
'make_id_with_session' => false,
'cache_with_get' => true
),
'widget/image-widget/image' => array(
'compress' => false,
'cache_with_username' => true,
'make_id_with_rolename' => false,
'make_id_with_locale' => false,
'cache_with_session' => true,
'make_id_with_session' => false
),
'content/type/icon' => array(
'compress' => false,
'cache_with_username' => true,
'make_id_with_locale' => false,
'cache_with_session' => true,
'make_id_with_session' => false,
'specific_lifetime' => null // forever
)
)
)
),
"backend" => array(
"name" => "P4Cms_Cache_Backend_File",
"customBackendNaming" => true,
"options" => array("cache_dir" => DATA_PATH . '/cache/page')
),
),
"global" => array(
"frontend" => array(
"name" => "Core",
"options" => array("automatic_serialization" => true)
),
"backend" => array(
"name" => "P4Cms_Cache_Backend_File",
"customBackendNaming" => true,
"options" => array(
"cache_dir" => DATA_PATH . '/cache/global',
"namespace" => false
)
)
)
),
'assethandler' => array(
'class' => 'P4Cms_AssetHandler_File',
'options' => array(
'outputPath' => DATA_PATH . '/resources'
)
),
'session' => array(
'save_path' => DATA_PATH . '/sessions',
'gc_maxlifetime' => 43200 // 12h
)
),
"performance" => array(
"aggregateCss" => true,
"aggregateJs" => true,
"autoBuildDojo" => true,
),
"reportVersion" => false
);
// tweak defaults for development environments
// - increase error/log verbosity
// - disable resource aggregation
// - disable caching
if ($environment == "development" || $environment == "testing") {
$options['phpSettings']['display_startup_errors'] = 1;
$options['phpSettings']['display_errors'] = 1;
$options['phpSettings']['error_reporting'] = (E_ALL & ~E_STRICT);
$options['resources']['log']['priority'] = Zend_Log::DEBUG;
$options['resources']['cachemanager']['enabled'] = false;
$options['performance']['aggregateCss'] = false;
$options['performance']['aggregateJs'] = false;
$options['performance']['autoBuildDojo'] = false;
$options["reportVersion"] = true;
}
return $options;
}
/**
* Initialize PATH to include bundled p4 binaries.
* Used primarily by _initPath() - made public static so it can used by tests.
*/
public static function initPath()
{
$system = php_uname('s');
$release = php_uname('r');
$machine = php_uname('m');
// normalize uname info according to p4-bin conventions.
$system = strtolower($system);
$machine = preg_replace("/i.86/", "x86", $machine);
// treat all versions of windows the same
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
$system = 'nt';
}
switch ($system) {
case 'darwin':
if (floatval($release) >= 9.0) {
$release = '90';
}
// there is no easy way to detect 32 vs 64 bit on mac
// we hard-code to 64 as only the core-duos were 32 bit.
$machine = 'x86_64';
break;
case 'linux':
$release = substr(str_replace('.', '', $release), 0, 2);
if (intval($release) > 26) {
$release = '26';
}
break;
case 'nt':
$release = '';
$machine = 'x86';
break;
}
// if a matching p4-bin path exists, add to PATH.
$path = BASE_PATH . '/p4-bin/bin.' . $system . $release . $machine;
if (is_dir($path) && strpos(getenv('PATH'), $path . PATH_SEPARATOR) !== 0) {
putenv('PATH=' . $path . PATH_SEPARATOR . getenv('PATH'));
}
}
/**
* Determine if setup needs to be run. Setup must be run if
* we have no connection to Perforce or no sites are defined.
*
* @return boolean true if setup needs to be run.
*/
public function isSetupNeeded()
{
return !$this->hasResource('perforce') || !$this->hasResource('site');
}
/**
* Register a new resource plugin. Extended to ignore any resources
* that are already known class resources. The plugin version won't
* be used if there is a class resource of the same name, however,
* we could get an exception if the plugin does not exist.
*
* @param string|Zend_Application_Resource_Resource $resource the resource to register
* @param mixed $options options for the resource
* @return Zend_Application_Bootstrap_BootstrapAbstract provides fluent interface
* @throws Zend_Application_Bootstrap_Exception when invalid resource is provided
*/
public function registerPluginResource($resource, $options = null)
{
$classResources = $this->getClassResourceNames();
if (is_string($resource) && in_array(strtolower($resource), $classResources)) {
return $this;
}
return parent::registerPluginResource($resource, $options);
}
/**
* Set default timezone to suppress PHP warnings.
*/
protected function _initTimezone()
{
date_default_timezone_set(@date_default_timezone_get());
}
/**
* Register known libraries with our loader.
*/
protected function _initLibraries()
{
$libraries = array('P4', 'P4Cms', 'Phly', 'Zend');
foreach ($libraries as $library) {
P4Cms_Loader::addPackagePath($library, LIBRARY_PATH . '/' . $library);
}
}
/**
* Initialize the logger.
*
* @return Zend_Log the initialized logger.
*/
protected function _initLog()
{
// don't setup logger if we can't write log file.
$options = $this->getOption('resources');
$options = isset($options['log']) ? (array) $options['log'] : array();
$logFile = isset($options['file']) ? $options['file'] : null;
if (!$logFile || !@touch($logFile)) {
return;
}
// if we don't already have a logger; set one up.
if (!P4Cms_Log::hasLogger()) {
P4Cms_Log::setLogger(new Zend_Log);
}
// attach our writer to the logger
$logger = P4Cms_Log::getLogger();
$logger->setEventItem('pid', getmypid());
$writer = new Zend_Log_Writer_Stream($logFile);
$logger->addWriter($writer);
// configure log format.
$format = new Zend_Log_Formatter_Simple(
isset($options['format']) ? $options['format'] : null
);
$writer->setFormatter($format);
// filter by priority.
$filter = new Zend_Log_Filter_Priority((int)$options['priority']);
$writer->addFilter($filter);
// log uncaught exceptions.
set_exception_handler(
function(Exception $e)
{
// abort page caching on unhandled exceptions
// as we want users to get the real content
// if the issue is later fixed.
if (P4Cms_Cache::canCache('page')) {
P4Cms_Cache::getCache('page')->cancel();
}
P4Cms_Log::logException("Uncaught ", $e);
trigger_error($e);
}
);
return $logger;
}
/**
* Create the request object (normally doesn't happen until dispatch).
*
* @return Zend_Controller_Request_Http the initialized request object.
*/
protected function _initRequest()
{
return new P4Cms_Controller_Request_Http;
}
/**
* Configure the cache manager.
*
* Registers the cache manager with P4Cms_Cache for easy/static
* access to caching facilities (e.g. save(), load()).
*
* @return void|P4Cms_Cache_Manager the configured cache manager or void if none.
*/
protected function _initCacheManager()
{
// don't initialize cache manager if its not configured or enabled.
$options = $this->getOptions();
if (!isset($options['resources']['cachemanager']['enabled'])
|| !$options['resources']['cachemanager']['enabled']
) {
P4Cms_Cache::setLoggingEnabled(false);
return;
}
// create the cache manager.
$manager = new P4Cms_Cache_Manager;
// provide convenient static access via P4Cms_Cache
P4Cms_Cache::setManager($manager);
return $manager;
}
/**
* Register any global cache templates.
*
* Any template that specifies a fixed namespace option is considered
* to be 'global' and will be initialized here. All other templates
* are automatically assumed to be site specific and will be configured
* after we initialize the site so that we can set the site namespace.
*/
protected function _initGlobalCache()
{
$this->bootstrap('cacheManager');
$manager = $this->getResource('cacheManager');
$options = $this->getOptions();
// if no cache manager, can't configure global caches.
if (!$manager) {
return;
}
// add global cache templates (explicit namespaces only)
$templates = $options['resources']['cachemanager'];
foreach ($templates as $name => $template) {
if (!is_array($template) || !isset($template['backend']['options']['namespace'])) {
continue;
}
// skip any backend which specifies a non-writable cache_dir
if (isset($template['backend']['options']['cache_dir'])) {
$cachePath = $template['backend']['options']['cache_dir'];
@mkdir($cachePath, 0755, true);
if (!is_writable($cachePath)) {
continue;
}
}
$manager->setCacheTemplate($name, $template);
}
}
/**
* Figure out the current site.
*
* @return P4Cms_Site the active site model.
*/
protected function _initSite()
{
$this->bootstrap('request');
$request = $this->getResource('request');
// tell site model where sites are stored.
P4Cms_Site::setSitesPackagesPath(SITES_PATH);
P4Cms_Site::setSitesDataPath(DATA_PATH . '/sites');
// try to fetch sites without initializing perforce.
// this will only work if we have previously cached
// sites - if it fails, init perforce and try again.
$perforce = null;
try {
$sites = P4Cms_Site::fetchAll();
} catch (Exception $e) {
$this->bootstrap('perforce');
$perforce = $this->getResource('perforce');
if (!$perforce) {
return;
}
// cold cache case, need to fetch against perforce.
$sites = P4Cms_Site::fetchAll(null, $perforce);
}
// can't init site if there are no sites.
if (!$sites->count()) {
return;
}
// application config may limit (whitelist) the
// branches that can be safely exposed.
$limit = null;
$options = $this->getOption('resources');
if (isset($options['site']['whitelist'])) {
$limit = (array) $options['site']['whitelist'];
}
// find the best site/branch for this request (honor limit).
$site = P4Cms_Site::fetchByRequest($request, $limit, $perforce);
return $site;
}
/**
* Register any site specific cache templates.
*
* Cache templates that do not specify a namespace are automatically
* assumed to be site specific and are configured here (post site init).
*/
protected function _initSiteCache()
{
$this->bootstrap('site');
$this->bootstrap('cacheManager');
$site = $this->getResource('site');
$manager = $this->getResource('cacheManager');
$options = $this->getOptions();
// if no cache manager or no site, can't configure site caches.
if (!$manager || !$site) {
return;
}
// add site specific cache templates (no explicit namespace)
$templates = $options['resources']['cachemanager'];
foreach ($templates as $name => $template) {
if (!is_array($template) || isset($template['backend']['options']['namespace'])) {
continue;
}
// skip any backend which specify a non-writable cache_dir
if (isset($template['backend']['options']['cache_dir'])) {
$cachePath = $template['backend']['options']['cache_dir'];
@mkdir($cachePath, 0755, true);
if (!is_writable($cachePath)) {
continue;
}
}
// make cache site specific by passing the site id as a
// 'namespace' option to the backend (the backend will
// simply ignore this option if it doesn't support it).
$template['backend']['options']['namespace'] = $site->getId();
$manager->setCacheTemplate($name, $template);
}
}
/**
* If the page cache has been configured by the cacheManager bootstrap;
* this task will 'start' it causing a cached page to be served if possible
* and attempting to capture the current page otherwise.
*
* @return void|Zend_Cache_Core The page cache instance or void if none.
*/
protected function _initPageCache()
{
$this->bootstrap('cacheManager');
$this->bootstrap('request');
$cacheManager = $this->getResource('cacheManager');
$request = $this->getResource('request');
// early exit if no page cache is configured
if (!$cacheManager instanceof Zend_Cache_Manager || !$cacheManager->hasCache('page')) {
return;
}
$cache = $cacheManager->getCache('page');
// setting the baseUrl allows the page cache to munge regex's to still
// match with sub-folder installs
$cache->setBaseUrl($request->getBaseUrl());
// Provide default values for username/rolenames aimed at anonymous users.
$cache->setUsername('')
->setRolenames(array());
// If cookies are present attempt to pull out the user name and role names.
// We avoid this when there are no cookies to prevent needlessly starting
// a new session for anonymous users.
if (count($_COOKIE)) {
// verify the session is configured if we are taking this branch.
$this->bootstrap('sessionHandler');
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$identity = $auth->getIdentity();
if (is_array($identity) && isset($identity['id'])) {
$username = (string)$identity['id'];
// the roles are cached for us by initUser, attempt to access them here.
$rolenames = P4Cms_Cache::load('p4cms_user_roles_' . md5($username));
// if we weren't able to find a list of roles for this user, then
// we have no way of making a suitable cache id, early exit.
// presumably we will put the roles into cache for the next request.
if ($rolenames === false) {
return $cacheManager->getCache('page');
} else {
$cache->setUsername($username);
$cache->setRolenames($rolenames);
}
}
}
}
// Start the page cache. If a cached copy is present it
// will be output at this point and the script will die
// to stop further execution.
$cache->start();
return $cacheManager->getCache('page');
}
/**
* If session options were declared, intialize the session handler
* at this point. By default initialization would happen much later
* and we could end up accessing session data prior to the handler
* being initialized.
*/
protected function _initSessionHandler()
{
$options = $this->getOption('resources');
// attempt to make writable session save path if one is set.
if (isset($options['session']['save_path'])) {
$path = $options['session']['save_path'];
@mkdir($path, 0700, true);
if (!is_writable($path)) {
@chmod($path, 0700);
}
// if still not writable, clear unusable save path.
if (!is_writable($path)) {
P4Cms_Log::log(
"Session save path '$path' is not writable. Using default instead.",
P4Cms_Log::WARN
);
$this->setOptions(
array('resources' => array('session' => array('save_path' => null)))
);
}
}
if (isset($options['session'])) {
$this->bootstrap('session');
}
}
/**
* Setup view with our (theme-aware) view renderer and automatic context switching.
*
* @return Zend_View the configured view instance.
*/
protected function _initView()
{
// grab view options.
$options = $this->getOptions();
if (isset($options['resources']['view'])) {
$options = $options['resources']['view'];
} else {
$options = array();
}
// setup view.
$view = new Zend_View($options);
// use our renderer.
$renderer = new P4Cms_Controller_Action_Helper_ViewRenderer;
$renderer->setView($view);
Zend_Controller_Action_HelperBroker::addHelper($renderer);
return $view;
}
/**
* Define application version constants.
*/
protected function _initVersion()
{
$versionFile = BASE_PATH . '/Version';
$versionData = is_readable($versionFile)
? file_get_contents($versionFile)
: '';
// extract key/value constants from version file
preg_match_all('/^([A-Z]+)\s*=\s*(.+[^\s])\s*;/m', $versionData, $matches);
// preset release, patchlevel and suppdate to guard against their absence
$constants = array(
'NAME' => 'P4CHRONICLE',
'RELEASE' => 'unknown-release',
'PATCHLEVEL' => 'unknown-patchlevel',
'SUPPDATE' => 'unknown-date'
);
// merge in constants from the file
if (is_array($matches[1]) && is_array($matches[2])) {
foreach ($matches[1] as $key => $constant) {
if (isset($matches[2][$key])) {
$constants[$constant] = $matches[2][$key];
}
}
}
// properly format our constants
$constants['RELEASE'] = str_replace(' ', '.', $constants['RELEASE']);
$constants['SUPPDATE'] = str_replace(' ', '/', $constants['SUPPDATE']);
// define our constants
foreach ($constants as $name => $value) {
$constantName = 'P4CMS_VERSION_' . $name;
if (!defined($constantName)) {
define($constantName, $value);
}
}
// produce a version string
if (!defined('P4CMS_VERSION')) {
$version = P4CMS_VERSION_NAME
. '/' . P4CMS_VERSION_RELEASE
. '/' . P4CMS_VERSION_PATCHLEVEL
. ' (' . P4CMS_VERSION_SUPPDATE . ')';
define('P4CMS_VERSION', $version);
}
$options = $this->getOptions();
if (isset($options['reportVersion']) && $options['reportVersion'] === true) {
$this->getResource('view')->headMeta()->appendName('chronicle-version', P4CMS_VERSION);
}
}
/**
* Setup action helpers.
*/
protected function _initActionHelpers()
{
$options = $this->getOptions();
// use our automatic context switch helper to adjust
// view script suffix (no need to call init context).
Zend_Controller_Action_HelperBroker::addHelper(
new P4Cms_Controller_Action_Helper_ContextSwitch
);
// use the WidgetContext helper to provide contextual data to widgets
Zend_Controller_Action_HelperBroker::addHelper(
new P4Cms_Controller_Action_Helper_WidgetContext
);
// use the extended Redirector helper to provide option
// to redirect to one of the previously visited pages
Zend_Controller_Action_HelperBroker::addHelper(
new P4Cms_Controller_Action_Helper_Redirector
);
// add acl helper to provide convenient access checks
Zend_Controller_Action_HelperBroker::addHelper(
new P4Cms_Controller_Action_Helper_Acl
);
// add audit helper to record dispatched actions
Zend_Controller_Action_HelperBroker::addHelper(
new P4Cms_Controller_Action_Helper_Audit
);
}
/**
* Ensure our existing request object is set on the front controller
* so that we don't have two of them in-flight.
*/
protected function _initFrontRequest()
{
$this->bootstrap('request');
$this->bootstrap('frontController');
$request = $this->getResource('request');
$front = $this->getResource('frontController');
$front->setRequest($request);
}
/**
* Setup the router to use a custom version of the default route.
* The custom version provides support for shorter urls (e.g. the
* controller can be omitted if it is the default ('index')
* controller.
*
* @return Zend_Controller_Router_Interface the initialized router.
*/
protected function _initRouter()
{
$this->bootstrap('frontController');
$this->bootstrap('request');
$front = $this->getResource('frontController');
$request = $this->getResource('request');
$router = new P4Cms_Controller_Router_Rewrite;
$front->setRouter($router);
$router->addRoute(
'default',
new P4Cms_Controller_Router_Route_Module(
array(),
$front->getDispatcher(),
$request
)
);
return $router;
}
/**
* Initialize pub-sub component to use our provider.
*/
protected function _initPubSub()
{
P4Cms_PubSub::setInstance(new P4Cms_PubSub_Provider);
}
/**
* Initialize PATH to include bundled p4 binaries.
*/
protected function _initPath()
{
static::initPath();
}
/**
* Establish our connection with Perforce.
*/
protected function _initPerforce()
{
// place the p4trust file under the data path.
// the trust file has to be in a writable
// location to support ssl enabled servers
putenv('P4TRUST=' . DATA_PATH . '/p4trust');
// set the app name to use for all connections created
// via the connection factory (needed for license).
P4_Connection::setAppName('chronicle');
$options = $this->getOption('resources');
if (!isset($options['perforce']) || !is_array($options['perforce'])) {
return null;
}
// if we are using perforce we need to ensure we select
// the proper p4/p4d by initing the PATH first.
$this->bootstrap('path');
// extract perforce options into local scope.
extract($options['perforce']);
// create a perforce connection object.
$connection = P4_Connection::factory(
isset($port) ? $port : null,
isset($user) ? $user : null,
isset($client) ? $client : null,
isset($password) ? $password : null,
isset($ticket) ? $ticket : null,
isset($type) ? $type : null
);
// login and set as default connection.
$connection->login();
P4_Connection::setDefaultConnection($connection);
return $connection;
}
/**
* Load the current site.
*
* @return P4Cms_Site the active site model.
*/
protected function _initLoadSite()
{
$this->bootstrap('site');
$this->bootstrap('perforce');
$site = $this->getResource('site');
$perforce = $this->getResource('perforce');
// if we have a site and a connection, load the site.
if ($site && $perforce) {
$site->setConnection($perforce)
->load();
}
return $site;
}
/**
* Initialize the current active user.
*
* @return P4Cms_User the active user model.
*/
protected function _initUser()
{
$this->bootstrap('loadSite');
$this->bootstrap('cacheManager');
// if auth has a valid identity and we have a default adapter,
// fetch the authenticated user (can't fetch w.out adapter).
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity() && P4Cms_Record::hasDefaultAdapter()) {
$identity = $auth->getIdentity();
if (is_array($identity) && isset($identity['id'])) {
try {
$user = P4Cms_User::fetch($identity['id']);
// deny access if user has no roles
$roles = $user->getRoles();
if (!count($roles)) {
throw new Exception(
'Any authenticated user must have at least one role.'
);
}
// make the active user's personal adapter the default
// so that we communicate with Perforce as the user.
$ticket = isset($identity['ticket']) ? $identity['ticket'] : null;
$adapter = $user->createPersonalAdapter($ticket);
$connection = $adapter->getConnection();
// test user's ticket.
$connection->run('login', '-s');
$user->setPersonalAdapter($adapter);
P4Cms_Record::setDefaultAdapter($adapter);
P4_Connection::setDefaultConnection($connection);
// Cache out the roles so initPageCache will have access to them
// on subsequent requests without having to talk to perforce.
if (P4Cms_Cache::canCache()) {
P4Cms_Cache::save(
$roles->invoke('getId'),
'p4cms_user_roles_' . md5($user->getId()),
array('p4cms_user_' . md5($user->getId))
);
}
} catch (Exception $e) {
P4Cms_Log::logException(
"Failed to initialize authenticated user",
$e
);
unset($user);
$auth->clearIdentity();
P4Cms_Notifications::add(
"You have been logged out.",
P4Cms_Notifications::SEVERITY_WARNING
);
}
}
}
// if no authenticated user, create anonymous user instance.
if (!isset($user)) {
$user = new P4Cms_User;
}
// set the active user for this request.
P4Cms_User::setActive($user);
return $user;
}
/**
* Initialize the ACL for the application.
*
* @return P4Cms_Acl the active acl.
*/
protected function _initAcl()
{
$this->bootstrap('view');
$this->bootstrap('loadSite');
$this->bootstrap('user');
// if there is an active site, load it's acl
// otherwise, create a blank one.
if (P4Cms_Site::hasActive()) {
$acl = P4Cms_Site::fetchActive()->getAcl();
} else {
$acl = new P4Cms_Acl;
}
// if the active user has a personal adapter, use it.
$user = P4Cms_User::fetchActive();
if ($user->hasPersonalAdapter()) {
$acl->getRecord()->setAdapter($user->getPersonalAdapter());
}
// set acl on acl action helper.
if (Zend_Controller_Action_HelperBroker::hasHelper('acl')) {
$helper = Zend_Controller_Action_HelperBroker::getExistingHelper('acl');
$helper->setAcl($acl);
}
// set acl on navigation view helper.
$view = $this->getResource('view');
$role = $user->getAggregateRole($acl);
$view->getHelper('navigation')
->setRole($role)
->setAcl($acl);
return $acl->makeActive();
}
/**
* Initialize all of the enabled modules.
*/
protected function _initModules()
{
$this->bootstrap('loadSite');
// tell package system where the application's public folder is.
P4Cms_PackageAbstract::setDocumentRoot(BASE_PATH);
// tell p4cms module where to find core modules.
P4Cms_Module::setCoreModulesPath(APPLICATION_PATH);
// if setup must be run or if setup is already running,
// restrict module bootstrap to just an init of core modules
if ($this->isSetupNeeded() || self::_isSetupRunning()) {
// init all of the core modules and any optional modules that
// are enabled by default so they can participate in setup.
$modules = P4Cms_Module::fetchAll();
foreach ($modules as $module) {
if ($module->isCoreModule() || $module->getPackageInfo('enableByDefault')) {
$module->init();
}
}
// load modules we require for proper operation during setup.
$required = array('Error', 'Setup', 'Ui', 'Dojo');
foreach ($required as $module) {
P4Cms_Module::fetch($module)->load();
}
return;
}
// initialize then load the enabled modules.
$modules = P4Cms_Module::fetchAllEnabled();
$modules->invoke('init');
$modules->invoke('load');
return $modules;
}
/**
* Initialize the theme.
*
* @return P4Cms_Theme the current theme.
*/
protected function _initTheme()
{
// if a theme is already active, return it.
if (P4Cms_Theme::hasActive()) {
return P4Cms_Theme::fetchActive();
}
// if there is an active site, load it's theme.
if (P4Cms_Site::hasActive()) {
try {
$config = P4Cms_Site::fetchActive()->getConfig();
$theme = P4Cms_Theme::fetch($config->getTheme());
$theme->load();
return $theme;
} catch (Exception $e) {
P4Cms_Log::logException(
"Failed to load theme.",
$e
);
}
}
// load default theme.
P4Cms_Theme::addPackagesPath(SITES_PATH . '/all/themes');
$theme = P4Cms_Theme::fetchDefault();
$theme->load();
return $theme;
}
/**
* Setup the asset handler. This is primarly intended for storing generated
* assets. In single server configurations, default, this just directs assets
* to the local filesystem. When running multiple servers you can use a shared
* asset store to ensure all web servers have access.
*
* @return P4Cms_AssetHandlerInterface|null asset handler or null
*/
protected function _initAssetHandler()
{
// return if we don't have any settings
$options = $this->getOption('resources');
if (!isset($options['assethandler']) || !isset($options['assethandler']['class'])) {
return null;
}
// return if class is invalid
$class = $options['assethandler']['class'];
if (!class_exists($class)) {
return null;
}
// pull out options defaulting to empty array
$options = isset($options['assethandler']['options'])
? $options['assethandler']['options']
: array();
$handler = new $class($options);
// returm null if the required interface isn't implemented
if (!is_a($handler, 'P4Cms_AssetHandlerInterface')) {
return null;
}
return $handler;
}
/**
* Setup view helpers (enable dojo, css aggregation, ...)
*
* @todo move dojo specific parts into dojo modules init method
*/
protected function _initViewHelpers()
{
$this->bootstrap('view');
$this->bootstrap('request');
$this->bootstrap('assetHandler');
$view = $this->getResource('view');
$request = $this->getResource('request');
$assetHandler = $this->getResource('assetHandler');
$options = $this->getOption('performance');
// enable dojo.
Zend_Dojo::enableView($view);
Zend_Dojo_View_Helper_Dojo::setUseDeclarative();
$dojo = $view->getHelper('dojo');
$dojo->setLocalPath(
$request->getBaseUrl() . '/application/dojo/resources/dojo/dojo.js'
);
// setup automatic dojo builds if enabled and we have a site.
if ($options['autoBuildDojo']) {
$dojo->setAutoBuild(true)
->setDocumentRoot(BASE_PATH)
->setAssetHandler($assetHandler);
}
// setup head script with JS aggregation.
$headScript = $view->getHelper('headScript');
$headScript->appendScript(
"if (typeof(p4cms) == 'undefined') p4cms = {};\n" .
"p4cms.baseUrl='" . $request->getBaseUrl() . "';\n" .
"p4cms.branchBaseUrl='" . $request->getBranchBaseUrl() . "';\n"
);
if ($options['aggregateJs']) {
$headScript->setAggregateJs(true)
->setDocumentRoot(BASE_PATH)
->setAssetHandler($assetHandler);
}
// setup css aggregation if so enabled.
if ($options['aggregateCss']) {
$headLink = $view->getHelper('headLink');
$headLink->setAggregateCss(true)
->setDocumentRoot(BASE_PATH)
->setAssetHandler($assetHandler);
}
// set the page title to the app name or site name (if active).
$title = $view->getHelper('headTitle');
$title->setSeparator(' - ');
if (P4Cms_Site::hasActive()) {
$site = P4Cms_Site::fetchActive();
$title->setPostfix($site->getConfig()->getTitle());
} else {
$title->setPostfix('Chronicle');
}
}
/**
* Initialize setup program if necessary.
*/
protected function _initSetup()
{
$this->bootstrap('request');
$this->bootstrap('loadSite');
$this->bootstrap('modules');
// if setup is needed, make it run (unless it is already running).
if ($this->isSetupNeeded() && !self::_isSetupRunning()) {
$this->getResource('request')->setPathInfo('/setup');
}
// if setup isn't going to run, nothing more to do.
if (!self::_isSetupRunning()) {
return;
}
// we want errors to show during setup regardless of app config.
$this->getApplication()->setPhpSettings(
array(
'display_errors' => 1,
'phpSettings' => (E_ALL & ~(E_STRICT|E_NOTICE))
)
);
}
/**
* Determine if setup is currently set to run.
*
* @return boolean true if setup has been requested to run.
*/
protected function _isSetupRunning()
{
$this->bootstrap('request');
$request = $this->getResource('request');
$paths = explode('/', substr($request->getPathInfo(), 1));
if (isset($paths[0]) && $paths[0] == 'setup') {
return true;
} else {
return false;
}
}
}