From c454fd63ee229cb73856ee00bd9b170d529f07c8 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Sat, 10 Jul 2010 04:35:19 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20Piwik=20=E5=88=B0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=BA=93=E4=B8=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +YUCHENG HU+ git-svn-id: https://svn.code.sf.net/p/hawebs/svn@478 a2543c7e-f6e9-4f8a-8bff-1ffc34733512 --- .../trunk/plugins/Installation/Controller.php | 889 ++++++++++++++++++ .../Installation/FormDatabaseSetup.php | 54 ++ .../Installation/FormFirstWebsiteSetup.php | 68 ++ .../plugins/Installation/FormGeneralSetup.php | 87 ++ .../plugins/Installation/Installation.php | 81 ++ oss/piwik/trunk/plugins/Installation/View.php | 59 ++ .../Installation/templates/allSteps.tpl | 11 + .../Installation/templates/databaseCheck.tpl | 34 + .../Installation/templates/databaseSetup.tpl | 14 + .../templates/displayJavascriptCode.tpl | 45 + .../Installation/templates/finished.tpl | 8 + .../templates/firstWebsiteSetup.tpl | 23 + .../Installation/templates/generalSetup.tpl | 5 + .../templates/integrityDetails.tpl | 43 + .../Installation/templates/structure.tpl | 241 +++++ .../Installation/templates/systemCheck.tpl | 256 +++++ .../Installation/templates/tablesCreation.tpl | 63 ++ .../Installation/templates/welcome.tpl | 29 + .../trunk/plugins/LanguagesManager/API.php | 197 ++++ .../plugins/LanguagesManager/Controller.php | 36 + .../LanguagesManager/LanguagesManager.php | 154 +++ .../LanguagesManager/templates/languages.tpl | 22 + 22 files changed, 2419 insertions(+) create mode 100644 oss/piwik/trunk/plugins/Installation/Controller.php create mode 100644 oss/piwik/trunk/plugins/Installation/FormDatabaseSetup.php create mode 100644 oss/piwik/trunk/plugins/Installation/FormFirstWebsiteSetup.php create mode 100644 oss/piwik/trunk/plugins/Installation/FormGeneralSetup.php create mode 100644 oss/piwik/trunk/plugins/Installation/Installation.php create mode 100644 oss/piwik/trunk/plugins/Installation/View.php create mode 100644 oss/piwik/trunk/plugins/Installation/templates/allSteps.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/databaseCheck.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/databaseSetup.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/displayJavascriptCode.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/finished.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/firstWebsiteSetup.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/generalSetup.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/integrityDetails.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/structure.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/systemCheck.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/tablesCreation.tpl create mode 100644 oss/piwik/trunk/plugins/Installation/templates/welcome.tpl create mode 100644 oss/piwik/trunk/plugins/LanguagesManager/API.php create mode 100644 oss/piwik/trunk/plugins/LanguagesManager/Controller.php create mode 100644 oss/piwik/trunk/plugins/LanguagesManager/LanguagesManager.php create mode 100644 oss/piwik/trunk/plugins/LanguagesManager/templates/languages.tpl diff --git a/oss/piwik/trunk/plugins/Installation/Controller.php b/oss/piwik/trunk/plugins/Installation/Controller.php new file mode 100644 index 00000000..e2f4e4ec --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/Controller.php @@ -0,0 +1,889 @@ + 'Installation_Welcome', + 'systemCheck' => 'Installation_SystemCheck', + 'databaseSetup' => 'Installation_DatabaseSetup', + 'databaseCheck' => 'Installation_DatabaseCheck', + 'tablesCreation' => 'Installation_Tables', + 'generalSetup' => 'Installation_GeneralSetup', + 'firstWebsiteSetup' => 'Installation_SetupWebsite', + 'displayJavascriptCode' => 'Installation_JsTag', + 'finished' => 'Installation_Congratulations', + ); + + protected $pathView = 'Installation/templates/'; + + protected $session; + + public function __construct() + { + $this->session = new Zend_Session_Namespace('Piwik_Installation'); + if(!isset($this->session->currentStepDone)) + { + $this->session->currentStepDone = ''; + $this->session->skipThisStep = array(); + } + + Piwik_PostEvent('InstallationController.construct', $this); + } + + /** + * Get installation steps + * + * @return array installation steps + */ + public function getInstallationSteps() + { + return $this->steps; + } + + /** + * Get default action (first installation step) + * + * @return string function name + */ + function getDefaultAction() + { + $steps = array_keys($this->steps); + return $steps[0]; + } + + /** + * Installation Step 1: Welcome + */ + function welcome($message) + { + $view = new Piwik_Installation_View( + $this->pathView . 'welcome.tpl', + $this->getInstallationSteps(), + __FUNCTION__ + ); + $view->newInstall = !file_exists(Piwik_Config::getDefaultUserConfigPath()); + $view->errorMessage = $message; + $this->skipThisStep( __FUNCTION__ ); + $view->showNextStep = $view->newInstall; + $this->session->currentStepDone = __FUNCTION__; + echo $view->render(); + } + + /** + * Installation Step 2: System Check + */ + function systemCheck() + { + $this->checkPreviousStepIsValid( __FUNCTION__ ); + + $view = new Piwik_Installation_View( + $this->pathView . 'systemCheck.tpl', + $this->getInstallationSteps(), + __FUNCTION__ + ); + $this->skipThisStep( __FUNCTION__ ); + + $view->infos = self::getSystemInformation(); + $view->helpMessages = array( + 'zlib' => 'Installation_SystemCheckZlibHelp', + 'SPL' => 'Installation_SystemCheckSplHelp', + 'iconv' => 'Installation_SystemCheckIconvHelp', + 'dom' => 'Installation_SystemCheckDomHelp', + 'set_time_limit' => 'Installation_SystemCheckTimeLimitHelp', + 'mail' => 'Installation_SystemCheckMailHelp', + 'parse_ini_file' => 'Installation_SystemCheckParseIniFileHelp', + 'debug_backtrace' => 'Installation_SystemCheckDebugBacktraceHelp', + 'create_function' => 'Installation_SystemCheckCreateFunctionHelp', + 'eval' => 'Installation_SystemCheckEvalHelp', + ); + + $view->problemWithSomeDirectories = (false !== array_search(false, $view->infos['directories'])); + + $view->showNextStep = !$view->problemWithSomeDirectories + && $view->infos['phpVersion_ok'] + && count($view->infos['adapters']) + && !count($view->infos['missing_extensions']) + && !count($view->infos['missing_functions']) + ; + + $this->session->currentStepDone = __FUNCTION__; + + echo $view->render(); + } + + /** + * Installation Step 3: Database Set-up + */ + function databaseSetup() + { + $this->checkPreviousStepIsValid( __FUNCTION__ ); + + // case the user hits the back button + $this->session->skipThisStep = array( + 'firstWebsiteSetup' => false, + 'displayJavascriptCode' => false, + ); + + $view = new Piwik_Installation_View( + $this->pathView . 'databaseSetup.tpl', + $this->getInstallationSteps(), + __FUNCTION__ + ); + $this->skipThisStep( __FUNCTION__ ); + + $view->showNextStep = false; + + $form = new Piwik_Installation_FormDatabaseSetup(); + + if($form->validate()) + { + $adapter = $form->getSubmitValue('adapter'); + $port = Piwik_Db_Adapter::getDefaultPortForAdapter($adapter); + + $dbInfos = array( + 'host' => $form->getSubmitValue('host'), + 'username' => $form->getSubmitValue('username'), + 'password' => $form->getSubmitValue('password'), + 'dbname' => $form->getSubmitValue('dbname'), + 'tables_prefix' => $form->getSubmitValue('tables_prefix'), + 'adapter' => $adapter, + 'port' => $port, + ); + + if(($portIndex = strpos($dbInfos['host'], '/')) !== false) + { + // unix_socket=/path/sock.n + $dbInfos['port'] = substr($dbInfos['host'], $portIndex); + $dbInfos['host'] = ''; + } + else if(($portIndex = strpos($dbInfos['host'], ':')) !== false) + { + // host:port + $dbInfos['port'] = substr($dbInfos['host'], $portIndex + 1 ); + $dbInfos['host'] = substr($dbInfos['host'], 0, $portIndex); + } + + try{ + try { + Piwik::createDatabaseObject($dbInfos); + $this->session->databaseCreated = true; + } catch (Zend_Db_Adapter_Exception $e) { + $db = Piwik_Db_Adapter::factory($adapter, $dbInfos); + + // database not found, we try to create it + if($db->isErrNo($e, '1049')) + { + $dbInfosConnectOnly = $dbInfos; + $dbInfosConnectOnly['dbname'] = null; + Piwik::createDatabaseObject($dbInfosConnectOnly); + Piwik::createDatabase($dbInfos['dbname']); + $this->session->databaseCreated = true; + } + else + { + throw $e; + } + } + + Piwik::checkDatabaseVersion(); + $this->session->databaseVersionOk = true; + + $this->session->db_infos = $dbInfos; + $this->redirectToNextStep( __FUNCTION__ ); + } catch(Exception $e) { + $view->errorMessage = $e->getMessage(); + } + } + $view->addForm($form); + + echo $view->render(); + } + + /** + * Installation Step 4: Database Check + */ + function databaseCheck() + { + $this->checkPreviousStepIsValid( __FUNCTION__ ); + $view = new Piwik_Installation_View( + $this->pathView . 'databaseCheck.tpl', + $this->getInstallationSteps(), + __FUNCTION__ + ); + + $error = false; + $this->skipThisStep( __FUNCTION__ ); + + if(isset($this->session->databaseVersionOk) + && $this->session->databaseVersionOk === true) + { + $view->databaseVersionOk = true; + } + else + { + $error = true; + } + + if(isset($this->session->databaseCreated) + && $this->session->databaseCreated === true) + { + $dbInfos = $this->session->db_infos; + $view->databaseName = $dbInfos['dbname']; + $view->databaseCreated = true; + } + else + { + $error = true; + } + + $this->createDbFromSessionInformation(); + $db = Zend_Registry::get('db'); + + try { + $db->checkClientVersion(); + } catch(Exception $e) { + $view->clientVersionWarning = $e->getMessage(); + $error = true; + } + + if(!Piwik::isDatabaseConnectionUTF8()) + { + $dbInfos = $this->session->db_infos; + $dbInfos['charset'] = 'utf8'; + $this->session->db_infos = $dbInfos; + } + + $view->showNextStep = true; + $this->session->currentStepDone = __FUNCTION__; + + if($error === false) + { + $this->redirectToNextStep(__FUNCTION__); + } + echo $view->render(); + } + + /** + * Installation Step 5: Table Creation + */ + function tablesCreation() + { + $this->checkPreviousStepIsValid( __FUNCTION__ ); + + $view = new Piwik_Installation_View( + $this->pathView . 'tablesCreation.tpl', + $this->getInstallationSteps(), + __FUNCTION__ + ); + $this->skipThisStep( __FUNCTION__ ); + $this->createDbFromSessionInformation(); + + if(Piwik_Common::getRequestVar('deleteTables', 0, 'int') == 1) + { + Piwik::dropTables(); + $view->existingTablesDeleted = true; + + // when the user decides to drop the tables then we dont skip the next steps anymore + // workaround ZF-1743 + $tmp = $this->session->skipThisStep; + $tmp['firstWebsiteSetup'] = false; + $tmp['displayJavascriptCode'] = false; + $this->session->skipThisStep = $tmp; + } + + $tablesInstalled = Piwik::getTablesInstalled(); + $tablesToInstall = Piwik::getTablesNames(); + $view->tablesInstalled = ''; + if(count($tablesInstalled) > 0) + { + // we have existing tables + $view->tablesInstalled = implode(', ', $tablesInstalled); + $view->someTablesInstalled = true; + + $minimumCountPiwikTables = 12; + $baseTablesInstalled = preg_grep('/archive_numeric|archive_blob/', $tablesInstalled, PREG_GREP_INVERT); + + Piwik::createAccessObject(); + Piwik::setUserIsSuperUser(); + + if(count($baseTablesInstalled) >= $minimumCountPiwikTables && + count(Piwik_SitesManager_API::getInstance()->getAllSitesId()) > 0 && + count(Piwik_UsersManager_API::getInstance()->getUsers()) > 0) + { + $view->showReuseExistingTables = true; + // when the user reuses the same tables we skip the website creation step + // workaround ZF-1743 + $tmp = $this->session->skipThisStep; + $tmp['firstWebsiteSetup'] = true; + $tmp['displayJavascriptCode'] = true; + $this->session->skipThisStep = $tmp; + } + } + else + { + Piwik::createTables(); + Piwik::createAnonymousUser(); + + $updater = new Piwik_Updater(); + $updater->recordComponentSuccessfullyUpdated('core', Piwik_Version::VERSION); + $view->tablesCreated = true; + $view->showNextStep = true; + } + + $this->session->currentStepDone = __FUNCTION__; + echo $view->render(); + } + + /** + * Installation Step 6: General Set-up (superuser login/password/email and subscriptions) + */ + function generalSetup() + { + $this->checkPreviousStepIsValid( __FUNCTION__ ); + + $view = new Piwik_Installation_View( + $this->pathView . 'generalSetup.tpl', + $this->getInstallationSteps(), + __FUNCTION__ + ); + $this->skipThisStep( __FUNCTION__ ); + + $form = new Piwik_Installation_FormGeneralSetup(); + + if($form->validate()) + { + $superUserInfos = array( + 'login' => $form->getSubmitValue('login'), + 'password' => md5( $form->getSubmitValue('password') ), + 'email' => $form->getSubmitValue('email'), + 'salt' => Piwik_Common::generateUniqId(), + ); + + $this->session->superuser_infos = $superUserInfos; + + $host = 'http://api.piwik.org/1.0/'; + $host .= 'subscribeNewsletter/'; + $params = array( + 'email' => $form->getSubmitValue('email'), + 'security' => $form->getSubmitValue('subscribe_newsletter_security'), + 'community' => $form->getSubmitValue('subscribe_newsletter_community'), + 'url' => Piwik_Url::getCurrentUrlWithoutQueryString(), + ); + if($params['security'] == '1' + || $params['community'] == '1') + { + if( !isset($params['security'])) { $params['security'] = '0'; } + if( !isset($params['community'])) { $params['community'] = '0'; } + $url = $host . '?' . http_build_query($params, '', '&'); + try { + Piwik_Http::sendHttpRequest($url, $timeout = 2); + } catch(Exception $e) { + // e.g., disable_functions = fsockopen; allow_url_open = Off + } + } + $this->redirectToNextStep( __FUNCTION__ ); + } + $view->addForm($form); + + echo $view->render(); + } + + /** + * Installation Step 7: Configure first web-site + */ + public function firstWebsiteSetup() + { + $this->checkPreviousStepIsValid( __FUNCTION__ ); + + $view = new Piwik_Installation_View( + $this->pathView . 'firstWebsiteSetup.tpl', + $this->getInstallationSteps(), + __FUNCTION__ + ); + $this->skipThisStep( __FUNCTION__ ); + + $form = new Piwik_Installation_FormFirstWebsiteSetup(); + if( !isset($this->session->generalSetupSuccessMessage)) + { + $view->displayGeneralSetupSuccess = true; + $this->session->generalSetupSuccessMessage = true; + } + + $this->initObjectsToCallAPI(); + if($form->validate()) + { + $name = urlencode($form->getSubmitValue('siteName')); + $url = urlencode($form->getSubmitValue('url')); + + + $request = new Piwik_API_Request(" + method=SitesManager.addSite + &siteName=$name + &urls=$url + &format=original + "); + + try { + $result = $request->process(); + $this->session->site_idSite = $result; + $this->session->site_name = $name; + $this->session->site_url = $url; + + $this->redirectToNextStep( __FUNCTION__ ); + } catch(Exception $e) { + $view->errorMessage = $e->getMessage(); + } + + } + $view->addForm($form); + echo $view->render(); + } + + /** + * Installation Step 8: Display JavaScript tracking code + */ + public function displayJavascriptCode() + { + $this->checkPreviousStepIsValid( __FUNCTION__ ); + + $view = new Piwik_Installation_View( + $this->pathView . 'displayJavascriptCode.tpl', + $this->getInstallationSteps(), + __FUNCTION__ + ); + $this->skipThisStep( __FUNCTION__ ); + + if( !isset($this->session->firstWebsiteSetupSuccessMessage)) + { + $view->displayfirstWebsiteSetupSuccess = true; + $this->session->firstWebsiteSetupSuccessMessage = true; + } + + $view->websiteName = urldecode($this->session->site_name); + + $jsTag = Piwik::getJavascriptCode($this->session->site_idSite, Piwik_Url::getCurrentUrlWithoutFileName()); + + $view->javascriptTag = $jsTag; + $view->showNextStep = true; + + $this->session->currentStepDone = __FUNCTION__; + echo $view->render(); + } + + /** + * Installation Step 9: Finished! + */ + public function finished() + { + $this->checkPreviousStepIsValid( __FUNCTION__ ); + + $view = new Piwik_Installation_View( + $this->pathView . 'finished.tpl', + $this->getInstallationSteps(), + __FUNCTION__ + ); + $this->skipThisStep( __FUNCTION__ ); + + if(!file_exists(Piwik_Config::getDefaultUserConfigPath())) + { + $this->writeConfigFileFromSession(); + } + + $view->showNextStep = false; + + $this->session->currentStepDone = __FUNCTION__; + echo $view->render(); + } + + /** + * Instantiate access and log objects + */ + protected function initObjectsToCallAPI() + { + // connect to the database using the DB infos currently in the session + $this->createDbFromSessionInformation(); + + Piwik::createAccessObject(); + Piwik::setUserIsSuperUser(); + Piwik::createLogObject(); + } + + /** + * Create database connection from session-store + */ + protected function createDbFromSessionInformation() + { + $dbInfos = $this->session->db_infos; + Zend_Registry::get('config')->disableSavingConfigurationFileUpdates(); + Zend_Registry::get('config')->database = $dbInfos; + Piwik::createDatabaseObject($dbInfos); + } + + /** + * Write configuration file from session-store + */ + protected function writeConfigFileFromSession() + { + if(!isset($this->session->superuser_infos) + || !isset($this->session->db_infos)) + { + return; + } + $config = Zend_Registry::get('config'); + $config->superuser = $this->session->superuser_infos; + $dbInfos = $this->session->db_infos; + $config->database = $dbInfos; + + unset($this->session->superuser_infos); + unset($this->session->db_infos); + } + + /** + * Save language selection in session-store + */ + public function saveLanguage() + { + $language = Piwik_Common::getRequestVar('language'); + Piwik_LanguagesManager_API::getInstance()->setLanguageForSession($language); + Piwik_Url::redirectToReferer(); + } + + /** + * The previous step is valid if it is either + * - any step before (OK to go back) + * - the current step (case when validating a form) + * If step is invalid, then exit. + * + * @param string $currentStep Current step + */ + protected function checkPreviousStepIsValid( $currentStep ) + { + $error = false; + + if(empty($this->session->currentStepDone)) + { + $error = true; + } + else if($currentStep == 'finished' && $this->session->currentStepDone == 'finished') + { + // ok to refresh this page or use language selector + } + else + { + if(file_exists(Piwik_Config::getDefaultUserConfigPath())) + { + $error = true; + } + + $steps = array_keys($this->steps); + + // the currentStep + $currentStepId = array_search($currentStep, $steps); + + // the step before + $previousStepId = array_search($this->session->currentStepDone, $steps); + + // not OK if currentStepId > previous+1 + if( $currentStepId > $previousStepId + 1 ) + { + $error = true; + } + } + if($error) + { + Piwik_Login_Controller::clearSession(); + $message = Piwik_Translate('Installation_ErrorInvalidState', + array( '
', + '', + '', + '') + ); + Piwik::exitWithErrorMessage( $message ); + } + } + + /** + * Redirect to next step + * + * @param string Current step + * @return none + */ + protected function redirectToNextStep($currentStep) + { + $steps = array_keys($this->steps); + $this->session->currentStepDone = $currentStep; + $nextStep = $steps[1 + array_search($currentStep, $steps)]; + Piwik::redirectToModule('Installation' , $nextStep); + } + + /** + * Skip this step (typically to mark the current function as completed) + * + * @param string function name + */ + protected function skipThisStep( $step ) + { + $skipThisStep = $this->session->skipThisStep; + if(isset($skipThisStep[$step]) && $skipThisStep[$step]) + { + $this->redirectToNextStep($step); + } + } + + /** + * Get system information + */ + public static function getSystemInformation() + { + $minimumPhpVersion = Zend_Registry::get('config')->General->minimum_php_version; + $minimumMemoryLimit = Zend_Registry::get('config')->General->minimum_memory_limit; + + $infos = array(); + + $infos['directories'] = Piwik::checkDirectoriesWritable(); + + $serverSoftware = $_SERVER['SERVER_SOFTWARE']; + if(preg_match('/^Microsoft-IIS\/(.+)/', $serverSoftware, $matches) && version_compare($matches[1], '7') >= 0) + { + Piwik::createWebConfigFiles(); + } + else if(strpos($serverSoftware, 'Apache/') === 0) + { + Piwik::createHtAccessFiles(); + } + + $infos['phpVersion_minimum'] = $minimumPhpVersion; + $infos['phpVersion'] = phpversion(); + $infos['phpVersion_ok'] = version_compare( $minimumPhpVersion, $infos['phpVersion']) === -1; + + // critical errors + $extensions = @get_loaded_extensions(); + $needed_extensions = array( + 'zlib', + 'SPL', + 'iconv', + 'Reflection', + ); + $infos['needed_extensions'] = $needed_extensions; + $infos['missing_extensions'] = array(); + foreach($needed_extensions as $needed_extension) + { + if(!in_array($needed_extension, $extensions)) + { + $infos['missing_extensions'][] = $needed_extension; + } + } + + $infos['pdo_ok'] = false; + if(in_array('PDO', $extensions)) + { + $infos['pdo_ok'] = true; + } + + $infos['adapters'] = Piwik_Db_Adapter::getAdapters(); + + $infos['json'] = false; + if(in_array('json', $extensions)) + { + $infos['json'] = true; + } + + $infos['xml'] = false; + if(in_array('xml', $extensions)) + { + $infos['xml'] = true; + } + + $needed_functions = array( + 'debug_backtrace', + 'create_function', + 'eval', + ); + $infos['needed_functions'] = $needed_functions; + $infos['missing_functions'] = array(); + foreach($needed_functions as $needed_function) + { + if(!self::functionExists($needed_function)) + { + $infos['missing_functions'][] = $needed_function; + } + } + + // warnings + $desired_functions = array( + 'set_time_limit', + 'mail', + 'parse_ini_file', + ); + $infos['desired_functions'] = $desired_functions; + $infos['missing_desired_functions'] = array(); + foreach($desired_functions as $desired_function) + { + if(!self::functionExists($desired_function)) + { + $infos['missing_desired_functions'][] = $desired_function; + } + } + + $infos['openurl'] = Piwik_Http::getTransportMethod(); + + $infos['gd_ok'] = false; + if (in_array('gd', $extensions)) + { + $gdInfo = gd_info(); + $infos['gd_version'] = $gdInfo['GD Version']; + preg_match('/([0-9]{1})/', $gdInfo['GD Version'], $gdVersion); + if($gdVersion[0] >= 2) + { + $infos['gd_ok'] = true; + } + } + + $infos['hasMbstring'] = false; + $infos['multibyte_ok'] = true; + if(function_exists('mb_internal_encoding')) + { + $infos['hasMbstring'] = true; + if (((int) ini_get('mbstring.func_overload')) != 0) + { + $infos['multibyte_ok'] = false; + } + } + + /** + * @see http://php.net/ip2long + */ + $infos['isIpv4'] = true; + if(strpos($_SERVER['REMOTE_ADDR'], ':') !== false) + { + $infos['isIpv4'] = false; + } + + $infos['serverVersion'] = addslashes($serverSoftware); + $infos['serverOs'] = @php_uname(); + $infos['serverTime'] = date('H:i:s'); + + $infos['registerGlobals_ok'] = ini_get('register_globals') == 0; + $infos['memoryMinimum'] = $minimumMemoryLimit; + + $infos['memory_ok'] = true; + $infos['memoryCurrent'] = '-1'; + + $raised = Piwik::raiseMemoryLimitIfNecessary(); + if( $memoryValue = Piwik::getMemoryLimitValue() ) + { + $infos['memoryCurrent'] = $memoryValue.'M'; + $infos['memory_ok'] = $memoryValue >= $minimumMemoryLimit; + } + + $infos['isWindows'] = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'; + + $infos['protocol_ok'] = true; + $infos['protocol'] = self::getProtocolInformation(); + if(Piwik_Url::getCurrentScheme() == 'http' && + $infos['protocol'] !== null) + { + $infos['protocol_ok'] = false; + } + + $integrityInfo = Piwik::getFileIntegrityInformation(); + $infos['integrity'] = $integrityInfo[0]; + + $infos['integrityErrorMessages'] = array(); + if(isset($integrityInfo[1])) + { + if($infos['integrity'] == false) + { + $infos['integrityErrorMessages'][] = ''.Piwik_Translate('General_FileIntegrityWarningExplanation').''; + } + $infos['integrityErrorMessages'] = array_merge($infos['integrityErrorMessages'], array_slice($integrityInfo, 1)); + } + + $infos['timezone'] = Piwik::isTimezoneSupportEnabled(); + return $infos; + } + + /** + * Get protocol information, with the exception of HTTPS + * + * @return string protocol information + */ + public static function getProtocolInformation() + { + if(Piwik_Common::getRequestVar('clientProtocol', 'http', 'string') == 'https') + { + return 'https'; + } + + if(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) + { + return 'SERVER_PORT=443'; + } + + if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') + { + return 'X-Forwarded-Proto'; + } + + if(isset($_SERVER['HTTP_X_FORWARDED_SCHEME']) && strtolower($_SERVER['HTTP_X_FORWARDED_SCHEME']) == 'https') + { + return 'X-Forwarded-Scheme'; + } + + if(isset($_SERVER['HTTP_X_URL_SCHEME']) && strtolower($_SERVER['HTTP_X_URL_SCHEME']) == 'https') + { + return 'X-Url-Scheme'; + } + + return null; + } + + /** + * Test if function exists. Also handles case where function is disabled via Suhosin. + * + * @param string $functionName Function name + * @return bool True if function exists (not disabled); False otherwise. + */ + public static function functionExists($functionName) + { + // eval() is a language construct + if($functionName == 'eval') + { + // does not check suhosin.executor.eval.whitelist (or blacklist) + if(extension_loaded('suhosin')) + { + return @ini_get("suhosin.executor.disable_eval") != "1"; + } + return true; + } + + $exists = function_exists($functionName); + if(extension_loaded('suhosin')) + { + $blacklist = @ini_get("suhosin.executor.func.blacklist"); + if(!empty($blacklist)) + { + $blacklistFunctions = array_map('strtolower', array_map('trim', explode(',', $blacklist))); + return $exists && !in_array($functionName, $blacklistFunctions); + } + + } + return $exists; + } +} diff --git a/oss/piwik/trunk/plugins/Installation/FormDatabaseSetup.php b/oss/piwik/trunk/plugins/Installation/FormDatabaseSetup.php new file mode 100644 index 00000000..687883d0 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/FormDatabaseSetup.php @@ -0,0 +1,54 @@ + $port) + { + $adapters[$adapter] = $adapter; + } + + $formElements = array( + array('text', 'host', Piwik_Translate('Installation_DatabaseSetupServer'), 'value='.'localhost'), + array('text', 'username', Piwik_Translate('Installation_DatabaseSetupLogin')), + array('password', 'password', Piwik_Translate('Installation_DatabaseSetupPassword')), + array('text', 'dbname', Piwik_Translate('Installation_DatabaseSetupDatabaseName')), + array('text', 'tables_prefix', Piwik_Translate('Installation_DatabaseSetupTablePrefix'), 'value='.'piwik_'), + array('select', 'adapter', Piwik_Translate('Installation_DatabaseSetupAdapter'), $adapters), + ); + $this->addElements( $formElements ); + + $formRules = array(); + foreach($formElements as $row) + { + if($row[1] != 'password' && $row[1] != 'tables_prefix') + { + $formRules[] = array($row[1], Piwik_Translate('General_Required', $row[2]), 'required'); + } + } + $this->addRules( $formRules ); + + $this->addElement('submit', 'submit', Piwik_Translate('Installation_SubmitGo')); + } +} diff --git a/oss/piwik/trunk/plugins/Installation/FormFirstWebsiteSetup.php b/oss/piwik/trunk/plugins/Installation/FormFirstWebsiteSetup.php new file mode 100644 index 00000000..efda7c7a --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/FormFirstWebsiteSetup.php @@ -0,0 +1,68 @@ +getSubmitValue('timezone'); + if(!empty($timezone)) + { + Piwik_SitesManager_API::getInstance()->setDefaultTimezone($timezone); + } + } catch(Exception $e) { + $this->_errors['timezone'] = Piwik_Translate('General_NotValid', Piwik_Translate('Installation_Timezone')); + } + return parent::validate(); + } + + function init() + { + $urlToGoAfter = 'index.php' . Piwik_Url::getCurrentQueryString(); + + $urlExample = 'http://example.org'; + $javascriptOnClickUrlExample = "\"javascript:if(this.value=='$urlExample'){this.value='http://';} this.style.color='black';\""; + + $timezones = Piwik_SitesManager_API::getInstance()->getTimezonesList(); + $timezones = array_merge(array('No timezone' => Piwik_Translate('SitesManager_SelectACity')), $timezones); + + $formElements = array( + array('text', 'siteName', Piwik_Translate('Installation_SetupWebSiteName')), + array('text', 'url', Piwik_Translate('Installation_SetupWebSiteURL'), "style='color:rgb(153, 153, 153);' value=$urlExample onfocus=".$javascriptOnClickUrlExample." onclick=".$javascriptOnClickUrlExample), + array('select', 'timezone', Piwik_Translate('Installation_Timezone'), $timezones), + + ); + $this->addElements( $formElements ); + + $formRules = array(); + foreach($formElements as $row) + { + $formRules[] = array($row[1], Piwik_Translate('General_Required', $row[2]), 'required'); + } + + + $submitTimezone = $this->getSubmitValue('timezone'); + if(!$this->isSubmitted() + || !empty($submitTimezone)) + { + $this->setSelected('timezone', $submitTimezone); + } + $this->addRules( $formRules ); + + $this->addElement('submit', 'submit', Piwik_Translate('Installation_SubmitGo')); + } +} diff --git a/oss/piwik/trunk/plugins/Installation/FormGeneralSetup.php b/oss/piwik/trunk/plugins/Installation/FormGeneralSetup.php new file mode 100644 index 00000000..08892db2 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/FormGeneralSetup.php @@ -0,0 +1,87 @@ +getSubmitValue('login'); + if(!empty($login)) + { + Piwik::checkValidLoginString($login); + } + } catch(Exception $e) { + $this->_errors['login'] = $e->getMessage(); + } + return parent::validate(); + } + + function init() + { + $urlToGoAfter = 'index.php' . Piwik_Url::getCurrentQueryString(); + + $formElements = array( + array('text', 'login', Piwik_Translate('Installation_SuperUserLogin')), + array('password', 'password', Piwik_Translate('Installation_Password')), + array('password', 'password_bis', Piwik_Translate('Installation_PasswordRepeat')), + array('text', 'email', Piwik_Translate('Installation_Email')), + array('checkbox', 'subscribe_newsletter_security', '', '  ' . Piwik_Translate('Installation_SecurityNewsletter')), + array('checkbox', 'subscribe_newsletter_community', '', '  '. Piwik_Translate('Installation_CommunityNewsletter')), + ); + $this->addElements( $formElements ); + + if(!$this->isSubmitted() + || $this->getSubmitValue('subscribe_newsletter_community') == '1') + { + $this->setChecked('subscribe_newsletter_community'); + } + if(!$this->isSubmitted() + || $this->getSubmitValue('subscribe_newsletter_security') == '1') + { + $this->setChecked('subscribe_newsletter_security'); + } + + $formRules = array(); + foreach($formElements as $row) + { + // checkboxes are not required (form should validate when unchecked) + if(in_array($row[1],array('subscribe_newsletter_security','subscribe_newsletter_community'))) + { + continue; + } + $formRules[] = array($row[1], Piwik_Translate('General_Required', $row[2]), 'required'); + } + + $formRules[] = array( 'email', + Piwik_Translate( 'UsersManager_ExceptionInvalidEmail'), + 'checkEmail' + ); + $formRules[] = array( 'password', + Piwik_Translate( 'Installation_PasswordDoNotMatch'), + 'fieldHaveSameValue', + 'password_bis' + ); + + $this->addRules( $formRules ); + $this->addElement('submit', 'submit', Piwik_Translate('Installation_SubmitGo')); + } +} diff --git a/oss/piwik/trunk/plugins/Installation/Installation.php b/oss/piwik/trunk/plugins/Installation/Installation.php new file mode 100644 index 00000000..d4a41caf --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/Installation.php @@ -0,0 +1,81 @@ + Piwik_Translate('Installation_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + + return $info; + } + + function getListHooksRegistered() + { + $hooks = array( + 'FrontController.NoConfigurationFile' => 'dispatch', + 'FrontController.badConfigurationFile' => 'dispatch', + ); + return $hooks; + } + + public function setControllerToLoad( $newControllerName ) + { + $this->installationControllerName = $newControllerName; + } + + protected function getInstallationController() + { + return new $this->installationControllerName(); + } + + function dispatch($notification = null) + { + if($notification) + { + $exception = $notification->getNotificationObject(); + $message = $exception->getMessage(); + } + else + { + $message = ''; + } + + Piwik_Translate::getInstance()->loadUserTranslation(); + + Piwik_PostEvent('Installation.startInstallation', $this); + + $step = Piwik_Common::getRequestVar('action', 'welcome', 'string'); + $controller = $this->getInstallationController(); + if(in_array($step, array_keys($controller->getInstallationSteps())) || $step == 'saveLanguage') + { + $controller->$step($message); + } + else + { + Piwik::exitWithErrorMessage(Piwik_Translate('Installation_NoConfigFound')); + } + + exit; + } +} diff --git a/oss/piwik/trunk/plugins/Installation/View.php b/oss/piwik/trunk/plugins/Installation/View.php new file mode 100644 index 00000000..10cddf51 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/View.php @@ -0,0 +1,59 @@ +mainTemplate); + + $this->subTemplateToLoad = $subtemplatePath; + $this->steps = array_keys($installationSteps); + $this->allStepsTitle = array_values($installationSteps); + $this->currentStepName = $currentStepName; + $this->showNextStep = false; + } + + function render() + { + // prepare the all steps templates + $this->currentStepId = array_search($this->currentStepName, $this->steps); + $this->totalNumberOfSteps = count($this->steps); + + $this->percentDone = round(($this->currentStepId) * 100 / ($this->totalNumberOfSteps-1)); + $this->percentToDo = 100 - $this->percentDone; + + $this->nextModuleName = ''; + if(isset($this->steps[$this->currentStepId + 1])) + { + $this->nextModuleName = $this->steps[$this->currentStepId + 1]; + } + $this->previousModuleName = ''; + if(isset($this->steps[$this->currentStepId - 1])) + { + $this->previousModuleName = $this->steps[$this->currentStepId - 1]; + } + $this->previousPreviousModuleName = ''; + if(isset($this->steps[$this->currentStepId - 2])) + { + $this->previousPreviousModuleName = $this->steps[$this->currentStepId - 2]; + } + + return parent::render(); + } +} diff --git a/oss/piwik/trunk/plugins/Installation/templates/allSteps.tpl b/oss/piwik/trunk/plugins/Installation/templates/allSteps.tpl new file mode 100644 index 00000000..5cba61e4 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/allSteps.tpl @@ -0,0 +1,11 @@ + diff --git a/oss/piwik/trunk/plugins/Installation/templates/databaseCheck.tpl b/oss/piwik/trunk/plugins/Installation/templates/databaseCheck.tpl new file mode 100644 index 00000000..3374582f --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/databaseCheck.tpl @@ -0,0 +1,34 @@ +{assign var=ok value=""} +{assign var=error value=""} +{assign var=warning value=""} +{assign var=link value=""} + +

{'Installation_DatabaseCheck'|translate}

+ + + + + + + + + + +{if isset($clientVersionWarning)} + + + +{/if} + + + + +
{'Installation_DatabaseServerVersion'|translate}{if isset($databaseVersionOk)}{$ok}{else}{$error}{/if}
{'Installation_DatabaseClientVersion'|translate}{if isset($clientVersionWarning)}{$warning}{else}{$ok}{/if}
+ + {$clientVersionWarning} + +
{'Installation_DatabaseCreation'|translate}{if isset($databaseCreated)}{$ok}{else}{$error}{/if}
+ +

+{$link} {'Installation_Requirements'|translate} +

diff --git a/oss/piwik/trunk/plugins/Installation/templates/databaseSetup.tpl b/oss/piwik/trunk/plugins/Installation/templates/databaseSetup.tpl new file mode 100644 index 00000000..ff60befc --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/databaseSetup.tpl @@ -0,0 +1,14 @@ +

{'Installation_DatabaseSetup'|translate}

+ +{if isset($errorMessage)} +
+ + {'Installation_DatabaseErrorConnect'|translate}: +
{$errorMessage} + +
+{/if} + +{if isset($form_data)} + {include file=default/genericForm.tpl} +{/if} diff --git a/oss/piwik/trunk/plugins/Installation/templates/displayJavascriptCode.tpl b/oss/piwik/trunk/plugins/Installation/templates/displayJavascriptCode.tpl new file mode 100644 index 00000000..4cdd03c0 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/displayJavascriptCode.tpl @@ -0,0 +1,45 @@ + +{literal} + + + + +{/literal} + +{if isset($displayfirstWebsiteSetupSuccess)} + + + {'Installation_SetupWebsiteSetupSuccess'|translate:$websiteName} + + +{/if} +

{'Installation_JsTag'|translate}

+{'Installation_JsTagHelp'|translate} + +{$javascriptTag} + + +

{'Installation_JsTagHelpTitle'|translate}

+{include file=SitesManager/templates/JavascriptTagHelp.tpl} + +
+

{'Installation_LargePiwikInstances'|translate}

+{'Installation_JsTagArchivingHelp'|translate} + diff --git a/oss/piwik/trunk/plugins/Installation/templates/finished.tpl b/oss/piwik/trunk/plugins/Installation/templates/finished.tpl new file mode 100644 index 00000000..ee96dfe9 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/finished.tpl @@ -0,0 +1,8 @@ +

{'Installation_Congratulations'|translate}

+ +{'Installation_CongratulationsHelp'|translate} + + +

+ {'Installation_ContinueToPiwik'|translate} » +

diff --git a/oss/piwik/trunk/plugins/Installation/templates/firstWebsiteSetup.tpl b/oss/piwik/trunk/plugins/Installation/templates/firstWebsiteSetup.tpl new file mode 100644 index 00000000..f8d19f70 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/firstWebsiteSetup.tpl @@ -0,0 +1,23 @@ + + +{if isset($displayGeneralSetupSuccess)} + + {'Installation_GeneralSetupSuccess'|translate} + + +{/if} + +

{'Installation_SetupWebsite'|translate}

+ +{if isset($errorMessage)} +
+ + {'Installation_SetupWebsiteError'|translate}: +
- {$errorMessage} + +
+{/if} + +{if isset($form_data)} + {include file=default/genericForm.tpl} +{/if} diff --git a/oss/piwik/trunk/plugins/Installation/templates/generalSetup.tpl b/oss/piwik/trunk/plugins/Installation/templates/generalSetup.tpl new file mode 100644 index 00000000..869addbf --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/generalSetup.tpl @@ -0,0 +1,5 @@ +

{'Installation_GeneralSetup'|translate}

+ +{if isset($form_data)} + {include file=default/genericForm.tpl} +{/if} diff --git a/oss/piwik/trunk/plugins/Installation/templates/integrityDetails.tpl b/oss/piwik/trunk/plugins/Installation/templates/integrityDetails.tpl new file mode 100644 index 00000000..edac9418 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/integrityDetails.tpl @@ -0,0 +1,43 @@ +{if !isset($warningMessages)} +{assign var=warningMessages value=$infos.integrityErrorMessages} +{/if} + + diff --git a/oss/piwik/trunk/plugins/Installation/templates/structure.tpl b/oss/piwik/trunk/plugins/Installation/templates/structure.tpl new file mode 100644 index 00000000..b98ca8e0 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/structure.tpl @@ -0,0 +1,241 @@ + + + +Piwik › {'Installation_Installation'|translate} + + + + + + + + + + +{literal} + +{/literal} + +{literal} + +{/literal} + + + +
+
+ +
+
+ {postEvent name="template_topBar"} +
+
+ +
+ {include file="Installation/templates/allSteps.tpl"} +
+ +
+ {include file="$subTemplateToLoad"} + {if $showNextStep} +

+ {'General_Next'|translate} » +

+ {/if} +
+ +
+ +
+
+

{'Installation_InstallationStatus'|translate}

+ +
+ {'Installation_PercentDone'|translate:$percentDone} +
+
+ + diff --git a/oss/piwik/trunk/plugins/Installation/templates/systemCheck.tpl b/oss/piwik/trunk/plugins/Installation/templates/systemCheck.tpl new file mode 100644 index 00000000..b0433c96 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/systemCheck.tpl @@ -0,0 +1,256 @@ +{assign var=ok value=""} +{assign var=error value=""} +{assign var=warning value=""} +{assign var=link value=""} + +

{'Installation_SystemCheck'|translate}

+ + + + + + + + + + + {foreach from=$infos.adapters key=adapter item=port} + + + + + {/foreach} + {if !count($infos.adapters)} + + + + {/if} + + + + + {if !$infos.json && !$infos.xml} + + + + {/if} + + + + + {if count($infos.missing_extensions) gt 0} + + + + {/if} + + + + + + + + +
{'Installation_SystemCheckPhp'|translate} > {$infos.phpVersion_minimum}{if $infos.phpVersion_ok}{$ok}{else}{$error}{/if}
PDO {'Installation_Extension'|translate}{if $infos.pdo_ok}{$ok} + {else}-{/if} +
{$adapter} {'Installation_Extension'|translate}{$ok}
+ + {'Installation_SystemCheckDatabaseHelp'|translate} +

+ {if $infos.isWindows} + {'Installation_SystemCheckWinPdoAndMysqliHelp'|translate:"

extension=php_mysqli.dll
extension=php_pdo.dll
extension=php_pdo_mysql.dll
"|nl2br} + {else} + {'Installation_SystemCheckPdoAndMysqliHelp'|translate:"

--with-mysqli
--with-pdo-mysql
":"

extension=mysqli.so
extension=pdo.so
extension=pdo_mysql.so
"|nl2br} + {/if} +
+ {'Installation_SystemCheckPhpPdoAndMysqliSite'|translate} +

+
+
+ {'Installation_SystemCheckJson'|translate} + {if $infos.json || $infos.xml}{$ok} + {else}{$error}{/if} +
+ + {'Installation_SystemCheckJsonHelp'|translate} +
+ {if version_compare($infos.phpVersion, '5.2.0') >= 0} + {'Installation_SystemCheckJsonSite'|translate} + {else} + {'Installation_SystemCheckXmlSite'|translate} + {/if} +
+
{'Installation_SystemCheckExtensions'|translate}{foreach from=$infos.needed_extensions item=needed_extension} + {$needed_extension} + {if in_array($needed_extension, $infos.missing_extensions)} + {$error} + {else} + {$ok} + {/if} +
+ {/foreach} +
+ + {foreach from=$infos.missing_extensions item=missing_extension} +

+ {$helpMessages[$missing_extension]|translate} +

+ {/foreach} +
+
{'Installation_SystemCheckFunctions'|translate}{foreach from=$infos.needed_functions item=needed_function} + {$needed_function} + {if in_array($needed_function, $infos.missing_functions)} + {$error} +

+ {$helpMessages[$needed_function]|translate} +

+ {else} + {$ok}
+ {/if} + {/foreach} +
+ {'Installation_SystemCheckWriteDirs'|translate} + + + {foreach from=$infos.directories key=dir item=bool} + {if $bool}{$ok}{else} + {$error}{/if} + {$dir} +
+ {/foreach} +
+
+{if $problemWithSomeDirectories} +
+
+ {'Installation_SystemCheckWriteDirsHelp'|translate}: + {foreach from=$infos.directories key=dir item=bool} + + {/foreach} +
+
+{/if} +

{'Optional'|translate}

+ + + + + + + + + + + + + + + + + + {if $infos.json} + + + + + {/if} + + + + + {if $infos.hasMbstring} + + + + + {/if} + + + + + + + + + + + + +
{'Installation_SystemCheckFileIntegrity'|translate} + {if empty($infos.integrityErrorMessages)} + {$ok} + {else} + {if $infos.integrity} + {$warning} {$infos.integrityErrorMessages[0]} + {else} + {$error} {$infos.integrityErrorMessages[0]} + {/if} + {if count($infos.integrityErrorMessages) > 1} + + {/if} + {/if} +
{'Installation_SystemCheckMemoryLimit'|translate} + {$infos.memoryCurrent} + {if $infos.memory_ok}{$ok}{else}{$warning} +
{'Installation_SystemCheckMemoryLimitHelp'|translate}{/if} +
{'SitesManager_Timezone'|translate} + {if $infos.timezone}{$ok}{else}{$warning} +
{'SitesManager_AdvancedTimezoneSupportNotFound'|translate}{/if} +
{'Installation_SystemCheckOpenURL'|translate} + {if $infos.openurl}{$infos.openurl} {$ok}{else}{$warning}
{'Installation_SystemCheckOpenURLHelp'|translate}{/if} +
{'Installation_SystemCheckXml'|translate} + {if $infos.xml}{$ok}{else}{$warning}
{'Installation_SystemCheckXmlHelp'|translate}{/if} +
{'Installation_SystemCheckGD'|translate} + {if $infos.gd_ok}{$ok}{else}{$warning}
{'Installation_SystemCheckGDHelp'|translate}{/if} +
{'Installation_SystemCheckMbstring'|translate} + {if $infos.multibyte_ok}{$ok}{else}{$warning}
{'Installation_SystemCheckMbstringHelp'|translate}{/if} +
{'Installation_SystemCheckFunctions'|translate}{foreach from=$infos.desired_functions item=desired_function} + {$desired_function} + {if in_array($desired_function, $infos.missing_desired_functions)} + {$warning} +

+ {$helpMessages[$desired_function]|translate} +

+ {else} + {$ok}
+ {/if} + {/foreach} +
{'Installation_SystemCheckProtocol'|translate} + {if $infos.protocol_ok}{$ok}{else}{$warning} {$infos.protocol}
{'Installation_SystemCheckProtocolHelp'|translate}

[General]
reverse_proxy = 1
{/if} +
{'Installation_SystemCheckIpv4'|translate} + {if $infos.isIpv4}{$ok}{else}{$warning}
{'Installation_SystemCheckIpv4Help'|translate}{/if} +
+ +{include file="Installation/templates/integrityDetails.tpl"} + +

+{$link} {'Installation_Requirements'|translate} +

+ +{if !$showNextStep} +{literal} + +{/literal} +
+{'Installation_Legend'|translate} +
+{$ok} {'General_Ok'|translate}
+{$error} {'General_Error'|translate}: {'Installation_SystemCheckError'|translate}
+{$warning} {'General_Warning'|translate}: {'Installation_SystemCheckWarning'|translate}
+
+ + +

+ {'General_Refresh'|translate} » +

+{/if} diff --git a/oss/piwik/trunk/plugins/Installation/templates/tablesCreation.tpl b/oss/piwik/trunk/plugins/Installation/templates/tablesCreation.tpl new file mode 100644 index 00000000..028799e9 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/tablesCreation.tpl @@ -0,0 +1,63 @@ +

{'Installation_Tables'|translate}

+ +{if isset($someTablesInstalled)} +
{'Installation_TablesWithSameNamesFound'|translate:"":""} + +
+ + + {if isset($showReuseExistingTables)} +

{'Installation_TablesWarningHelp'|translate}

+

{'Installation_TablesReuse'|translate} »

+ {else} +

« {'Installation_GoBackAndDefinePrefix'|translate}

+ {/if} + +

{'Installation_TablesDelete'|translate} »

+{/if} + +{if isset($existingTablesDeleted)} +
{'Installation_TablesDeletedSuccess'|translate} +
+{/if} + +{if isset($tablesCreated)} +
{'Installation_TablesCreatedSuccess'|translate} +
+{/if} + +{literal} + +{/literal} diff --git a/oss/piwik/trunk/plugins/Installation/templates/welcome.tpl b/oss/piwik/trunk/plugins/Installation/templates/welcome.tpl new file mode 100644 index 00000000..2de55967 --- /dev/null +++ b/oss/piwik/trunk/plugins/Installation/templates/welcome.tpl @@ -0,0 +1,29 @@ +

{'Installation_Welcome'|translate}

+ +{if $newInstall} +{'Installation_WelcomeHelp'|translate:$totalNumberOfSteps} +{else} +

{'Installation_ConfigurationHelp'|translate}

+
+
+{$errorMessage} +
+{/if} + +{literal} + +{/literal} + +{if !$showNextStep} +

+ {'General_Refresh'|translate} » +

+{/if} diff --git a/oss/piwik/trunk/plugins/LanguagesManager/API.php b/oss/piwik/trunk/plugins/LanguagesManager/API.php new file mode 100644 index 00000000..05910ede --- /dev/null +++ b/oss/piwik/trunk/plugins/LanguagesManager/API.php @@ -0,0 +1,197 @@ +getAvailableLanguages()); + } + + /** + * Return array of available languages + * + * @return array Arry of strings, each containing its ISO language code + */ + public function getAvailableLanguages() + { + if(!is_null($this->languageNames)) + { + return $this->languageNames; + } + $path = PIWIK_INCLUDE_PATH . "/lang/"; + $languages = glob($path . "*.php"); + $pathLength = strlen($path); + $languageNames = array(); + foreach($languages as $language) + { + $languageNames[] = substr($language, $pathLength, -strlen('.php')); + } + $this->languageNames = $languageNames; + return $languageNames; + } + + /** + * Return information on translations (code, language, % translated, etc) + * + * @return array Array of arrays + */ + public function getAvailableLanguagesInfo() + { + require PIWIK_INCLUDE_PATH . '/lang/en.php'; + $englishTranslation = $translations; + $filenames = $this->getAvailableLanguages(); + $languagesInfo = array(); + foreach($filenames as $filename) + { + require PIWIK_INCLUDE_PATH . "/lang/$filename.php"; + $translationStringsDone = array_intersect_key($englishTranslation, array_filter($translations, 'strlen')); + $percentageComplete = count($translationStringsDone) / count($englishTranslation); + $percentageComplete = round(100 * $percentageComplete, 0); + $languageInfo = array( 'code' => $filename, + 'name' => $translations['General_OriginalLanguageName'], + 'english_name' => $translations['General_EnglishLanguageName'], + 'translators' => $translations['General_TranslatorName'], + 'translators_email' => $translations['General_TranslatorEmail'], + 'percentage_complete' => $percentageComplete . '%', + ); + $languagesInfo[] = $languageInfo; + } + return $languagesInfo; + } + + /** + * Return array of available languages + * + * @return array Arry of array, each containing its ISO language code and name of the language + */ + public function getAvailableLanguageNames() + { + if(!is_null($this->availableLanguageNames)) + { + return $this->availableLanguageNames; + } + + $filenames = $this->getAvailableLanguages(); + $languagesInfo = array(); + foreach($filenames as $filename) + { + require PIWIK_INCLUDE_PATH . "/lang/$filename.php"; + $languagesInfo[] = array( 'code' => $filename, 'name' => $translations['General_OriginalLanguageName']); + } + $this->availableLanguageNames = $languagesInfo; + return $this->availableLanguageNames; + } + + /** + * Returns translation strings by language + * + * @param string $languageCode ISO language code + * @return array|false Array of arrays, each containing 'label' (translation index) and 'value' (translated string); false if language unavailable + */ + public function getTranslationsForLanguage($languageCode) + { + if(!$this->isLanguageAvailable($languageCode)) + { + return false; + } + require PIWIK_INCLUDE_PATH . "/lang/$languageCode.php"; + $languageInfo = array(); + foreach($translations as $key => $value) + { + $languageInfo[] = array('label' => $key, 'value' => $value); + } + return $languageInfo; + } + + /** + * Returns the language for the user + * + * @param string $login + * @param string|false $layout + */ + public function getLanguageForUser( $login ) + { + Piwik::checkUserIsSuperUserOrTheUser($login); + return Piwik_FetchOne('SELECT language FROM '.Piwik_Common::prefixTable('user_language') . + ' WHERE login = ? ', array($login )); + } + + /** + * Sets the language for the user + * + * @param string $login + * @param string $languageCode + */ + public function setLanguageForUser($login, $languageCode) + { + Piwik::checkUserIsSuperUserOrTheUser($login); + $paramsBind = array($login, $languageCode, $languageCode); + Piwik_Query('INSERT INTO '.Piwik_Common::prefixTable('user_language') . + ' (login, language) + VALUES (?,?) + ON DUPLICATE KEY UPDATE language=?', + $paramsBind); + } + + /** + * Returns the langage for the session + * + * @return string|null + */ + public function getLanguageForSession() + { + $session = new Zend_Session_Namespace("Piwik_LanguagesManager"); + if(isset($session->language)) + { + return $session->language; + } + return null; + } + + /** + * Set the language for the session + * + * @param string $languageCode ISO language code + */ + public function setLanguageForSession($languageCode) + { + $session = new Zend_Session_Namespace("Piwik_LanguagesManager"); + $session->language = $languageCode; + } +} diff --git a/oss/piwik/trunk/plugins/LanguagesManager/Controller.php b/oss/piwik/trunk/plugins/LanguagesManager/Controller.php new file mode 100644 index 00000000..b7cb43c8 --- /dev/null +++ b/oss/piwik/trunk/plugins/LanguagesManager/Controller.php @@ -0,0 +1,36 @@ +setLanguageForSession($language); + if(Zend_Registry::isRegistered('access')) { + $currentUser = Piwik::getCurrentUserLogin(); + if($currentUser && $currentUser !== 'anonymous') + { + Piwik_LanguagesManager_API::getInstance()->setLanguageForUser($currentUser, $language); + } + } + Piwik_Url::redirectToReferer(); + } +} diff --git a/oss/piwik/trunk/plugins/LanguagesManager/LanguagesManager.php b/oss/piwik/trunk/plugins/LanguagesManager/LanguagesManager.php new file mode 100644 index 00000000..39fe26ab --- /dev/null +++ b/oss/piwik/trunk/plugins/LanguagesManager/LanguagesManager.php @@ -0,0 +1,154 @@ + Piwik_Translate('LanguagesManager_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + } + + public function getListHooksRegistered() + { + return array( + 'template_css_import' => 'css', + 'template_topBar' => 'showLanguagesSelector', + 'Translate.getLanguageToLoad' => 'getLanguageToLoad', + 'UsersManager.deleteUser' => 'deleteUserLanguage', + ); + } + + function css() + { + echo "\n"; + } + + /** + * Show styled language selection drop-down list + * + * @param string $url The form action. Default is to save language. + */ + function showLanguagesSelector() + { + // don't use Piwik_View::factory() here + $view = new Piwik_View("LanguagesManager/templates/languages.tpl"); + $view->languages = Piwik_LanguagesManager_API::getInstance()->getAvailableLanguageNames(); + $view->currentLanguageCode = self::getLanguageCodeForCurrentUser(); + $view->currentLanguageName = self::getLanguageNameForCurrentUser(); + echo $view->render(); + } + + function getLanguageToLoad($notification) + { + $language =& $notification->getNotificationObject(); + $language = self::getLanguageCodeForCurrentUser(); + } + + function deleteUserLanguage($notification) + { + $userLogin = $notification->getNotificationObject(); + Piwik_Query('DELETE FROM ' . Piwik_Common::prefixTable('user_language') . ' WHERE login = ?', $userLogin); + } + + /** + * @throws Exception if non-recoverable error + */ + public function install() + { + // we catch the exception + try{ + $sql = "CREATE TABLE ". Piwik_Common::prefixTable('user_language')." ( + login VARCHAR( 100 ) NOT NULL , + language VARCHAR( 10 ) NOT NULL , + PRIMARY KEY ( login ) + ) DEFAULT CHARSET=utf8 " ; + Piwik_Exec($sql); + } catch(Exception $e){ + // mysql code error 1050:table already exists + // see bug #153 http://dev.piwik.org/trac/ticket/153 + if(!Zend_Registry::get('db')->isErrNo($e, '1050')) + { + throw $e; + } + } + } + + /** + * @throws Exception if non-recoverable error + */ + public function uninstall() + { + $sql = "DROP TABLE ". Piwik_Common::prefixTable('user_language') ; + Piwik_Exec($sql); + } + + /** + * @return string Two letters language code, eg. "fr" + */ + static public function getLanguageCodeForCurrentUser() + { + $languageCode = self::getLanguageFromPreferences(); + if(!Piwik_LanguagesManager_API::getInstance()->isLanguageAvailable($languageCode)) + { + $languageCode = Piwik_Common::extractLanguageCodeFromBrowserLanguage(Piwik_Common::getBrowserLanguage(), Piwik_LanguagesManager_API::getInstance()->getAvailableLanguages()); + } + if(!Piwik_LanguagesManager_API::getInstance()->isLanguageAvailable($languageCode)) + { + $languageCode = 'en'; + } + return $languageCode; + } + + /** + * @return string Full english language string, eg. "French" + */ + static public function getLanguageNameForCurrentUser() + { + $languageCode = self::getLanguageCodeForCurrentUser(); + $languages = Piwik_LanguagesManager_API::getInstance()->getAvailableLanguageNames(); + foreach($languages as $language) + { + if($language['code'] === $languageCode) + { + return $language['name']; + } + } + } + + /** + * @return string|false if language preference could not be loaded + */ + static protected function getLanguageFromPreferences() + { + if ($language = Piwik_LanguagesManager_API::getInstance()->getLanguageForSession()) + { + return $language; + } + + try { + $currentUser = Piwik::getCurrentUserLogin(); + return Piwik_LanguagesManager_API::getInstance()->getLanguageForUser($currentUser); + } catch(Exception $e) { + return false; + } + } +} diff --git a/oss/piwik/trunk/plugins/LanguagesManager/templates/languages.tpl b/oss/piwik/trunk/plugins/LanguagesManager/templates/languages.tpl new file mode 100644 index 00000000..444caf72 --- /dev/null +++ b/oss/piwik/trunk/plugins/LanguagesManager/templates/languages.tpl @@ -0,0 +1,22 @@ + + + + {literal} + {/literal} +