Newer
Older
mattpiwik
a validé
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
mattpiwik
a validé
*
mattpiwik
a validé
* @package Piwik
*/
/**
* @see core/PluginsManager.php
* @see core/Translate.php
* @see core/Option.php
*/
require_once PIWIK_INCLUDE_PATH . '/core/PluginsManager.php';
require_once PIWIK_INCLUDE_PATH . '/core/Translate.php';
require_once PIWIK_INCLUDE_PATH . '/core/Option.php';
mattpiwik
a validé
/**
* Front controller.
* This is the class hit in the first place.
* It dispatches the request to the right controller.
*
* For a detailed explanation, see the documentation on http://piwik.org/docs/plugins/framework-overview
mattpiwik
a validé
*
* @package Piwik
mattpiwik
a validé
*/
class Piwik_FrontController
{
/**
* Set to false and the Front Controller will not dispatch the request
*
* @var bool
*/
static public $enableDispatch = true;
static private $instance = null;
/**
* returns singleton
*
* @return Piwik_FrontController
*/
static public function getInstance()
{
if (self::$instance == null)
{
self::$instance = new self;
mattpiwik
a validé
}
return self::$instance;
}
mattpiwik
a validé
/**
* Dispatches the request to the right plugin and executes the requested action on the plugin controller.
*
* @throws Exception|Piwik_FrontController_PluginDeactivatedException in case the plugin doesn't exist, the action doesn't exist, there is not enough permission, etc.
mattpiwik
a validé
*
* @param string $module
* @param string $action
* @param array $parameters
* @return mixed The returned value of the calls, often nothing as the module print but don't return data
mattpiwik
a validé
*/
function dispatch( $module = null, $action = null, $parameters = null)
{
if( self::$enableDispatch === false)
{
return;
}
mattpiwik
a validé
if(is_null($module))
{
$defaultModule = 'CoreHome';
$module = Piwik_Common::getRequestVar('module', $defaultModule, 'string');
}
mattpiwik
a validé
if(is_null($action))
{
$action = Piwik_Common::getRequestVar('action', false);
}
if(!Piwik_Session::isFileBasedSessions()
&& ($module !== 'API' || ($action && $action !== 'index')))
mattpiwik
a validé
if(is_null($parameters))
{
$parameters = array();
}
if(!ctype_alnum($module))
{
throw new Exception("Invalid module name '$module'");
}
if( ! Piwik_PluginsManager::getInstance()->isPluginActivated( $module ))
{
throw new Piwik_FrontController_PluginDeactivatedException($module);
mattpiwik
a validé
}
$controllerClassName = 'Piwik_'.$module.'_Controller';
// FrontController's autoloader
if(!class_exists($controllerClassName, false))
mattpiwik
a validé
{
$moduleController = PIWIK_INCLUDE_PATH . '/plugins/' . $module . '/Controller.php';
if(!is_readable($moduleController))
mattpiwik
a validé
{
throw new Exception("Module controller $moduleController not found!");
}
require_once $moduleController; // prefixed by PIWIK_INCLUDE_PATH
mattpiwik
a validé
}
$controller = new $controllerClassName();
mattpiwik
a validé
if($action === false)
{
$action = $controller->getDefaultAction();
}
// Piwik::log("Dispatching $module / $action, parameters: ".var_export($parameters, $return = true));
mattpiwik
a validé
if( !is_callable(array($controller, $action)))
{
throw new Exception("Action $action not found in the controller $controllerClassName.");
}
mattpiwik
a validé
// Generic hook that plugins can use to modify any input to the function,
// or even change the plugin being called
$params = array($controller, $action, $parameters);
Piwik_PostEvent('FrontController.dispatch', $params);
mattpiwik
a validé
try {
mattpiwik
a validé
return call_user_func_array( array($params[0], $params[1] ), $params[2]);
mattpiwik
a validé
} catch(Piwik_Access_NoAccessException $e) {
Piwik_PostEvent('FrontController.NoAccessException', $e);
$debugTrace = $e->getTraceAsString();
Piwik_ExitWithMessage($e->getMessage(), Piwik::shouldLoggerLog() ? $debugTrace : '', true);
mattpiwik
a validé
}
}
/**
* Often plugins controller display stuff using echo/print.
* Using this function instead of dispatch() returns the output string form the actions calls.
mattpiwik
a validé
*
* @param string $controllerName
* @param string $actionName
* @param array $parameters
* @return string
*/
function fetchDispatch( $controllerName = null, $actionName = null, $parameters = null)
{
ob_start();
$output = $this->dispatch( $controllerName, $actionName, $parameters);
// if nothing returned we try to load something that was printed on the screen
if(empty($output))
{
$output = ob_get_contents();
}
ob_end_clean();
return $output;
mattpiwik
a validé
}
/**
* Called at the end of the page generation
*
*/
function __destruct()
{
try {
Piwik::printSqlProfilingReportZend();
Piwik::printQueryCount();
mattpiwik
a validé
} catch(Exception $e) {}
}
// Should we show exceptions messages directly rather than display an html error page?
public static function shouldRethrowException()
{
// If we are in no dispatch mode, eg. a script reusing Piwik libs,
// then we should return the exception directly, rather than trigger the event "bad config file"
// which load the HTML page of the installer with the error.
// This is at least required for misc/cron/archive.php and useful to all other scripts
return (defined('PIWIK_ENABLE_DISPATCH') && !PIWIK_ENABLE_DISPATCH)
|| Piwik_Common::isPhpCliMode()
|| Piwik_Common::isArchivePhpTriggered()
;
}
mattpiwik
a validé
/**
* Must be called before dispatch()
* - checks that directories are writable,
* - loads the configuration file,
mattpiwik
a validé
* - inits the DB connection,
* - etc.
* @throws Exception
* @throws Exception
* @throws bool|Exception
* @return
mattpiwik
a validé
*/
function init()
{
robocoder
a validé
static $initialized = false;
if($initialized)
{
return;
}
$initialized = true;
mattpiwik
a validé
try {
Zend_Registry::set('timer', new Piwik_Timer);
$directoriesToCheck = array(
'/tmp/',
'/tmp/templates_c/',
'/tmp/cache/',
'/tmp/assets/',
'/tmp/tcpdf/'
mattpiwik
a validé
);
Piwik::checkDirectoriesWritableOrDie($directoriesToCheck);
Piwik_Common::assignCliParametersToRequest();
robocoder
a validé
Piwik_Translate::getInstance()->loadEnglishTranslation();
mattpiwik
a validé
$exceptionToThrow = false;
robocoder
a validé
mattpiwik
a validé
try {
Piwik::createConfigObject();
} catch(Exception $e) {
Piwik_PostEvent('FrontController.NoConfigurationFile', $e, $info = array(), $pending = true);
mattpiwik
a validé
$exceptionToThrow = $e;
}
robocoder
a validé
if(Piwik_Session::isFileBasedSessions())
{
Piwik_Session::start();
}
if(Piwik_Config::getInstance()->General['maintenance_mode'] == 1
&& !Piwik_Common::isPhpCliMode())
{
$format = Piwik_Common::getRequestVar('format', '');
$exception = new Exception("Piwik is in scheduled maintenance. Please come back later.");
if(empty($format))
{
throw $exception;
}
$response = new Piwik_API_ResponseBuilder( $format );
echo $response->getResponseException( $exception );
exit;
}
&& Piwik_Config::getInstance()->General['force_ssl'] == 1
&& !Piwik::isHttps()
// Specifically disable for the opt out iframe
&& !(Piwik_Common::getRequestVar('module', '') == 'CoreAdminHome'
&& Piwik_Common::getRequestVar('action', '') == 'optOut')
)
{
$url = Piwik_Url::getCurrentUrl();
$url = str_replace("http://", "https://", $url);
Piwik_Url::redirectToUrl($url);
}
$pluginsToLoad = Piwik_Config::getInstance()->Plugins['Plugins'];
mattpiwik
a validé
$pluginsManager->loadPlugins( $pluginsToLoad );
robocoder
a validé
mattpiwik
a validé
if($exceptionToThrow)
{
throw $exceptionToThrow;
}
robocoder
a validé
try {
Piwik::createDatabaseObject();
} catch(Exception $e) {
Piwik_PostEvent('FrontController.badConfigurationFile', $e, $info = array(), $pending = true);
throw $e;
}
mattpiwik
a validé
Piwik::createLogObject();
// creating the access object, so that core/Updates/* can enforce Super User and use some APIs
Piwik::createAccessObject();
Piwik_PostEvent('FrontController.dispatchCoreAndPluginUpdatesScreen');
robocoder
a validé
mattpiwik
a validé
Piwik::install();
// ensure the current Piwik URL is known for later use
mattpiwik
a validé
if(method_exists('Piwik', 'getPiwikUrl'))
{
$host = Piwik::getPiwikUrl();
}
mattpiwik
a validé
Piwik_PostEvent('FrontController.initAuthenticationObject');
try {
$authAdapter = Zend_Registry::get('auth');
} catch(Exception $e){
throw new Exception("Authentication object cannot be found in the Registry. Maybe the Login plugin is not activated?
<br />You can activate the plugin by adding:<br />
<code>Plugins[] = Login</code><br />
under the <code>[Plugins]</code> section in your config/config.ini.php");
mattpiwik
a validé
}
Zend_Registry::get('access')->reloadAccess($authAdapter);
// Force the auth to use the token_auth if specified, so that embed dashboard
// and all other non widgetized controller methods works fine
if(($token_auth = Piwik_Common::getRequestVar('token_auth', false, 'string')) !== false)
{
Piwik_API_Request::reloadAuthUsingTokenAuth();
}
mattpiwik
a validé
$pluginsManager->postLoadPlugins();
Piwik_PostEvent('FrontController.checkForUpdates');
mattpiwik
a validé
} catch(Exception $e) {
Piwik_ExitWithMessage($e->getMessage(), false, true);
// Piwik::log('End FrontController->init() - Request: '. var_export($_REQUEST, true));
mattpiwik
a validé
}
/**
* Exception thrown when the requested plugin is not activated in the config file
*
* @package Piwik
mattpiwik
a validé
*/
class Piwik_FrontController_PluginDeactivatedException extends Exception
mattpiwik
a validé
{
function __construct($module)
{
parent::__construct("The plugin $module is not enabled. You can activate the plugin on Settings > Plugins page in Piwik.");
mattpiwik
a validé
}
}