PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

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

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