PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/pkp/classes/core/PKPApplication.inc.php

https://gitlab.com/si77/RCS
PHP | 493 lines | 275 code | 70 blank | 148 comment | 30 complexity | dc30b946027ac7fa6850a94765aa2a60 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @file classes/core/PKPApplication.inc.php
  4. *
  5. * Copyright (c) 2000-2011 John Willinsky
  6. * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
  7. *
  8. * @class PKPApplication
  9. * @ingroup core
  10. *
  11. * @brief Class describing this application.
  12. *
  13. */
  14. define('REALLY_BIG_NUMBER', 10000);
  15. define('ROUTE_COMPONENT', 'component');
  16. define('ROUTE_PAGE', 'page');
  17. define('ASSOC_TYPE_USER', 0x00001000); // This value used because of bug #6068
  18. define('ASSOC_TYPE_USER_GROUP', 0x0100002);
  19. define('ASSOC_TYPE_CITATION', 0x0100003);
  20. define('ASSOC_TYPE_AUTHOR', 0x0100004);
  21. define('ASSOC_TYPE_EDITOR', 0x0100005);
  22. class PKPApplication {
  23. var $enabledProducts;
  24. var $allProducts;
  25. function PKPApplication() {
  26. // Configure error reporting
  27. // FIXME: Error logging needs to be suppressed for strict
  28. // and deprecation errors in PHP5 as long as we support PHP 4.
  29. // This is primarily for static method warnings and warnings
  30. // about use of ... =& new ... Static class members cannot be
  31. // declared in PHP4 and ... =& new ... is deprecated since PHP 5.
  32. $errorReportingLevel = E_ALL;
  33. if (defined('E_STRICT')) $errorReportingLevel &= ~E_STRICT;
  34. if (defined('E_DEPRECATED')) $errorReportingLevel &= ~E_DEPRECATED;
  35. @error_reporting($errorReportingLevel);
  36. // Instantiate the profiler
  37. import('lib.pkp.classes.core.PKPProfiler');
  38. $pkpProfiler = new PKPProfiler();
  39. // Begin debug logging
  40. Console::logMemory('', 'PKPApplication::construct');
  41. Console::logSpeed('PKPApplication::construct');
  42. // Seed random number generator
  43. mt_srand(((double) microtime()) * 1000000);
  44. import('lib.pkp.classes.core.Core');
  45. import('lib.pkp.classes.core.String');
  46. import('lib.pkp.classes.core.Registry');
  47. import('lib.pkp.classes.config.Config');
  48. if (Config::getVar('debug', 'display_errors')) {
  49. // Try to switch off normal error display when error display
  50. // is being managed by OJS.
  51. @ini_set('display_errors', false);
  52. }
  53. if (Config::getVar('debug', 'deprecation_warnings')) {
  54. // Switch deprecation warnings back on. This can only be done
  55. // after declaring the Config class as we need access to the
  56. // configuration and we cannot declare the Config class before
  57. // we've switched of deprecation warnings as its declaration
  58. // causes warnings itself.
  59. // FIXME: When we drop PHP4 support and can declare static methods
  60. // as such then we can also include E_STRICT/E_DEPRECATED here as
  61. // nearly all strict/deprecated warnings concern PHP4 support.
  62. @error_reporting($errorReportingLevel);
  63. }
  64. Registry::set('application', $this);
  65. import('lib.pkp.classes.db.DAORegistry');
  66. import('lib.pkp.classes.db.XMLDAO');
  67. import('lib.pkp.classes.cache.CacheManager');
  68. import('classes.security.Validation');
  69. import('lib.pkp.classes.session.SessionManager');
  70. import('classes.template.TemplateManager');
  71. import('lib.pkp.classes.plugins.PluginRegistry');
  72. import('lib.pkp.classes.plugins.HookRegistry');
  73. import('classes.i18n.Locale');
  74. String::init();
  75. set_error_handler(array($this, 'errorHandler'));
  76. $microTime = Core::microtime();
  77. Registry::set('system.debug.startTime', $microTime);
  78. $notes = array();
  79. Registry::set('system.debug.notes', $notes);
  80. Registry::set('system.debug.profiler', $pkpProfiler);
  81. if (Config::getVar('general', 'installed')) {
  82. // Initialize database connection
  83. $conn =& DBConnection::getInstance();
  84. if (!$conn->isConnected()) {
  85. if (Config::getVar('database', 'debug')) {
  86. $dbconn =& $conn->getDBConn();
  87. fatalError('Database connection failed: ' . $dbconn->errorMsg());
  88. } else {
  89. fatalError('Database connection failed!');
  90. }
  91. }
  92. }
  93. }
  94. /**
  95. * Get the current application object
  96. * @return Application
  97. */
  98. function &getApplication() {
  99. $application =& Registry::get('application');
  100. return $application;
  101. }
  102. /**
  103. * Get the request implementation singleton
  104. * @return Request
  105. */
  106. function &getRequest() {
  107. $request =& Registry::get('request', true, null);
  108. if (is_null($request)) {
  109. import('classes.core.Request');
  110. // Implicitly set request by ref in the registry
  111. $request = new Request();
  112. }
  113. return $request;
  114. }
  115. /**
  116. * Get the dispatcher implementation singleton
  117. * @return Dispatcher
  118. */
  119. function &getDispatcher() {
  120. $dispatcher =& Registry::get('dispatcher', true, null);
  121. if (is_null($dispatcher)) {
  122. import('lib.pkp.classes.core.Dispatcher');
  123. // Implicitly set dispatcher by ref in the registry
  124. $dispatcher = new Dispatcher();
  125. // Inject dependency
  126. $dispatcher->setApplication($this->getApplication());
  127. // Inject router configuration
  128. $dispatcher->addRouterName('lib.pkp.classes.core.PKPComponentRouter', ROUTE_COMPONENT);
  129. $dispatcher->addRouterName('classes.core.PageRouter', ROUTE_PAGE);
  130. }
  131. return $dispatcher;
  132. }
  133. /**
  134. * This executes the application by delegating the
  135. * request to the dispatcher.
  136. */
  137. function execute() {
  138. // Dispatch the request to the correct handler
  139. $dispatcher =& $this->getDispatcher();
  140. $dispatcher->dispatch($this->getRequest());
  141. }
  142. /**
  143. * Get the symbolic name of this application
  144. * @return string
  145. */
  146. function getName() {
  147. return 'pkp-lib';
  148. }
  149. /**
  150. * Get the locale key for the name of this application.
  151. * @return string
  152. */
  153. function getNameKey() {
  154. // must be implemented by sub-classes
  155. assert(false);
  156. }
  157. /**
  158. * Get the "context depth" of this application, i.e. the number of
  159. * parts of the URL after index.php that represent the context of
  160. * the current request (e.g. Journal [1], or Conference and
  161. * Scheduled Conference [2]).
  162. * @return int
  163. */
  164. function getContextDepth() {
  165. // must be implemented by sub-classes
  166. assert(false);
  167. }
  168. /**
  169. * Get the list of the contexts available for this application
  170. * i.e. the various parameters that are needed to represent the
  171. * (e.g. array('journal') or array('conference', 'schedConf'))
  172. * @return Array
  173. */
  174. function getContextList() {
  175. // must be implemented by sub-classes
  176. assert(false);
  177. }
  178. /**
  179. * Get the URL to the XML descriptor for the current version of this
  180. * application.
  181. * @return string
  182. */
  183. function getVersionDescriptorUrl() {
  184. // must be implemented by sub-classes
  185. assert(false);
  186. }
  187. /**
  188. * This function retrieves all enabled product versions once
  189. * from the database and caches the result for further
  190. * access.
  191. *
  192. * @param $category string
  193. * @return array
  194. */
  195. function &getEnabledProducts($category = null) {
  196. if (is_null($this->enabledProducts)) {
  197. $contextDepth = $this->getContextDepth();
  198. $settingContext = array();
  199. if ($contextDepth > 0) {
  200. $request =& $this->getRequest();
  201. $router =& $request->getRouter();
  202. // Try to identify the main context (e.g. journal, conference, press),
  203. // will be null if none found.
  204. $mainContext =& $router->getContext($request, 1);
  205. // Create the context for the setting if found
  206. if ($mainContext) $settingContext[] = $mainContext->getId();
  207. $settingContext = array_pad($settingContext, $contextDepth, 0);
  208. $settingContext = array_combine($this->getContextList(), $settingContext);
  209. }
  210. $versionDAO =& DAORegistry::getDAO('VersionDAO');
  211. $this->enabledProducts =& $versionDAO->getCurrentProducts($settingContext);
  212. }
  213. if (is_null($category)) {
  214. return $this->enabledProducts;
  215. } elseif (isset($this->enabledProducts[$category])) {
  216. return $this->enabledProducts[$category];
  217. } else {
  218. $returner = array();
  219. return $returner;
  220. }
  221. }
  222. /**
  223. * Get the list of plugin categories for this application.
  224. */
  225. function getPluginCategories() {
  226. // To be implemented by sub-classes
  227. assert(false);
  228. }
  229. /**
  230. * Return the current version of the application.
  231. * @return Version
  232. */
  233. function &getCurrentVersion() {
  234. $currentVersion =& $this->getEnabledProducts('core');
  235. assert(count($currentVersion)) == 1;
  236. return $currentVersion[$this->getName()];
  237. }
  238. /**
  239. * Get the map of DAOName => full.class.Path for this application.
  240. * @return array
  241. */
  242. function getDAOMap() {
  243. return array(
  244. 'AccessKeyDAO' => 'lib.pkp.classes.security.AccessKeyDAO',
  245. 'AuthSourceDAO' => 'lib.pkp.classes.security.AuthSourceDAO',
  246. 'CaptchaDAO' => 'lib.pkp.classes.captcha.CaptchaDAO',
  247. 'ControlledVocabDAO' => 'lib.pkp.classes.controlledVocab.ControlledVocabDAO',
  248. 'ControlledVocabEntryDAO' => 'lib.pkp.classes.controlledVocab.ControlledVocabEntryDAO',
  249. 'CountryDAO' => 'lib.pkp.classes.i18n.CountryDAO',
  250. 'CurrencyDAO' => 'lib.pkp.classes.currency.CurrencyDAO',
  251. 'GroupDAO' => 'lib.pkp.classes.group.GroupDAO',
  252. 'GroupMembershipDAO' => 'lib.pkp.classes.group.GroupMembershipDAO',
  253. 'HelpTocDAO' => 'lib.pkp.classes.help.HelpTocDAO',
  254. 'HelpTopicDAO' => 'lib.pkp.classes.help.HelpTopicDAO',
  255. 'InterestDAO' => 'lib.pkp.classes.user.InterestDAO',
  256. 'InterestEntryDAO' => 'lib.pkp.classes.user.InterestEntryDAO',
  257. 'LanguageDAO' => 'lib.pkp.classes.language.LanguageDAO',
  258. 'NotificationDAO' => 'lib.pkp.classes.notification.NotificationDAO',
  259. 'NotificationSettingsDAO' => 'lib.pkp.classes.notification.NotificationSettingsDAO',
  260. 'ProcessDAO' => 'lib.pkp.classes.process.ProcessDAO',
  261. 'ScheduledTaskDAO' => 'lib.pkp.classes.scheduledTask.ScheduledTaskDAO',
  262. 'SessionDAO' => 'lib.pkp.classes.session.SessionDAO',
  263. 'SignoffDAO' => 'lib.pkp.classes.signoff.SignoffDAO',
  264. 'SiteDAO' => 'lib.pkp.classes.site.SiteDAO',
  265. 'SiteSettingsDAO' => 'lib.pkp.classes.site.SiteSettingsDAO',
  266. 'TimeZoneDAO' => 'lib.pkp.classes.i18n.TimeZoneDAO',
  267. 'TemporaryFileDAO' => 'lib.pkp.classes.file.TemporaryFileDAO',
  268. 'VersionDAO' => 'lib.pkp.classes.site.VersionDAO',
  269. 'XMLDAO' => 'lib.pkp.classes.db.XMLDAO'
  270. );
  271. }
  272. /**
  273. * Return the fully-qualified (e.g. page.name.ClassNameDAO) name of the
  274. * given DAO.
  275. * @param $name string
  276. * @return string
  277. */
  278. function getQualifiedDAOName($name) {
  279. $map =& Registry::get('daoMap', true, $this->getDAOMap());
  280. if (isset($map[$name])) return $map[$name];
  281. return null;
  282. }
  283. /**
  284. * Instantiate the help object for this application.
  285. * @return object
  286. */
  287. function &instantiateHelp() {
  288. // must be implemented by sub-classes
  289. assert(false);
  290. }
  291. /**
  292. * Custom error handler
  293. *
  294. * NB: Custom error handlers are called for all error levels
  295. * independent of the error_reporting parameter.
  296. * @param $errorno string
  297. * @param $errstr string
  298. * @param $errfile string
  299. * @param $errline string
  300. */
  301. function errorHandler($errorno, $errstr, $errfile, $errline) {
  302. // We only report/log errors if their corresponding
  303. // error level bit is set in error_reporting.
  304. // We have to check error_reporting() each time as
  305. // some application parts change the setting (e.g.
  306. // smarty, adodb, certain plugins).
  307. if(error_reporting() & $errorno) {
  308. if ($errorno == E_ERROR) {
  309. echo 'An error has occurred. Please check your PHP log file.';
  310. } elseif (Config::getVar('debug', 'display_errors')) {
  311. echo $this->buildErrorMessage($errorno, $errstr, $errfile, $errline) . "<br/>\n";
  312. }
  313. error_log($this->buildErrorMessage($errorno, $errstr, $errfile, $errline), 0);
  314. }
  315. }
  316. /**
  317. * Auxiliary function to errorHandler that returns a formatted error message.
  318. * Error type formatting code adapted from ash, http://ca3.php.net/manual/en/function.set-error-handler.php
  319. * @param $errorno string
  320. * @param $errstr string
  321. * @param $errfile string
  322. * @param $errline string
  323. * @return $message string
  324. */
  325. function buildErrorMessage($errorno, $errstr, $errfile, $errline) {
  326. $message = array();
  327. $errorType = array (
  328. E_ERROR => 'ERROR',
  329. E_WARNING => 'WARNING',
  330. E_PARSE => 'PARSING ERROR',
  331. E_NOTICE => 'NOTICE',
  332. E_CORE_ERROR => 'CORE ERROR',
  333. E_CORE_WARNING => 'CORE WARNING',
  334. E_COMPILE_ERROR => 'COMPILE ERROR',
  335. E_COMPILE_WARNING => 'COMPILE WARNING',
  336. E_USER_ERROR => 'USER ERROR',
  337. E_USER_WARNING => 'USER WARNING',
  338. E_USER_NOTICE => 'USER NOTICE',
  339. );
  340. if (array_key_exists($errorno, $errorType)) {
  341. $type = $errorType[$errorno];
  342. } else {
  343. $type = 'CAUGHT EXCEPTION';
  344. }
  345. // Return abridged message if strict error or notice (since they are more common)
  346. // This also avoids infinite loops when E_STRICT (=deprecation level) error
  347. // reporting is switched on.
  348. $shortErrors = E_NOTICE;
  349. if (defined('E_STRICT')) $shortErrors |= E_STRICT;
  350. if (defined('E_DEPRECATED')) $shortErrors |= E_DEPRECATED;
  351. if ($errorno & $shortErrors) {
  352. return $type . ': ' . $errstr . ' (' . $errfile . ':' . $errline . ')';
  353. }
  354. $message[] = $this->getName() . ' has produced an error';
  355. $message[] = ' Message: ' . $type . ': ' . $errstr;
  356. $message[] = ' In file: ' . $errfile;
  357. $message[] = ' At line: ' . $errline;
  358. $message[] = ' Stacktrace: ';
  359. if(Config::getVar('debug', 'show_stacktrace')) {
  360. $trace = debug_backtrace();
  361. // Remove the call to fatalError from the call trace.
  362. array_shift($trace);
  363. // Back-trace pretty-printer adapted from the following URL:
  364. // http://ca3.php.net/manual/en/function.debug-backtrace.php
  365. // Thanks to diz at ysagoon dot com
  366. foreach ($trace as $bt) {
  367. $args = '';
  368. if (isset($bt['args'])) foreach ($bt['args'] as $a) {
  369. if (!empty($args)) {
  370. $args .= ', ';
  371. }
  372. switch (gettype($a)) {
  373. case 'integer':
  374. case 'double':
  375. $args .= $a;
  376. break;
  377. case 'string':
  378. $a = htmlspecialchars($a);
  379. $args .= "\"$a\"";
  380. break;
  381. case 'array':
  382. $args .= 'Array('.count($a).')';
  383. break;
  384. case 'object':
  385. $args .= 'Object('.get_class($a).')';
  386. break;
  387. case 'resource':
  388. $args .= 'Resource('.strstr($a, '#').')';
  389. break;
  390. case 'boolean':
  391. $args .= $a ? 'True' : 'False';
  392. break;
  393. case 'NULL':
  394. $args .= 'Null';
  395. break;
  396. default:
  397. $args .= 'Unknown';
  398. }
  399. }
  400. $class = isset($bt['class'])?$bt['class']:'';
  401. $type = isset($bt['type'])?$bt['type']:'';
  402. $function = isset($bt['function'])?$bt['function']:'';
  403. $file = isset($bt['file'])?$bt['file']:'(unknown)';
  404. $line = isset($bt['line'])?$bt['line']:'(unknown)';
  405. $message[] = " File: {$file} line {$line}";
  406. $message[] = " Function: {$class}{$type}{$function}($args)";
  407. }
  408. }
  409. static $dbServerInfo;
  410. if (!isset($dbServerInfo)) {
  411. $dbconn =& DBConnection::getConn();
  412. $dbServerInfo = $dbconn->ServerInfo();
  413. }
  414. $message[] = " Server info:";
  415. $message[] = " OS: " . Core::serverPHPOS();
  416. $message[] = " PHP Version: " . Core::serverPHPVersion();
  417. $message[] = " Apache Version: " . (function_exists('apache_get_version') ? apache_get_version() : 'N/A');
  418. $message[] = " DB Driver: " . Config::getVar('database', 'driver');
  419. $message[] = " DB server version: " . (empty($dbServerInfo['description']) ? $dbServerInfo['version'] : $dbServerInfo['description']);
  420. return implode("\n", $message);
  421. }
  422. }
  423. ?>