Application.php
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2020 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of the MIT License.
7  *
8  * See the LICENSE file distributed with this work for
9  * additional information.
10  */
11 namespace wcmf\lib\presentation;
12 
16 
17 /**
18  * Application is the main application class, that does all the initialization.
19  *
20  * @author ingo herwig <ingo@wemove.com>
21  */
22 class Application {
23 
24  private $startTime = null;
25  private $request = null;
26  private $response = null;
27 
28  private $debug = false;
29 
30  private static $logger = null;
31  private static $errorHandler = null;
32 
33  /**
34  * Constructor
35  */
36  public function __construct() {
37  $this->startTime = microtime(true);
38  if (self::$logger == null) {
39  self::$logger = LogManager::getLogger(__CLASS__);
40  }
41  ob_start([$this, "outputHandler"]);
42  self::$errorHandler = new ErrorHandler();
43  }
44 
45  /**
46  * Destructor
47  */
48  public function __destruct() {
49  // log resource usage
50  if (self::$logger->isDebugEnabled()) {
51  $timeDiff = microtime(true)-$this->startTime;
52  $memory = number_format(memory_get_peak_usage()/(1024*1024), 2);
53  $msg = "Time[".round($timeDiff, 2)."s] Memory[".$memory."mb]";
54  if ($this->request != null) {
55  $msg .= " Request[".$this->request->getSender()."?".
56  $this->request->getContext()."?".$this->request->getAction()."]";
57  }
58  $msg .= " URI[".$_SERVER['REQUEST_URI']."]";
59  self::$logger->debug($msg);
60  }
61  ob_end_flush();
62  }
63 
64  /**
65  * Initialize the request.
66  *
67  * @param $defaultController The controller to call if none is given in request parameters (optional, default: '')
68  * @param $defaultContext The context to set if none is given in request parameters (optional, default: '')
69  * @param $defaultAction The action to perform if none is given in request parameters (optional, default: 'login')
70  * @return Request instance representing the current HTTP request
71  */
72  public function initialize($defaultController='', $defaultContext='', $defaultAction='login') {
73  $config = ObjectFactory::getInstance('configuration');
74  $this->debug = $config->getBooleanValue('debug', 'Application');
75 
76  // configure php
77  if ($config->hasSection('phpconfig')) {
78  $phpSettings = $config->getSection('phpconfig');
79  foreach ($phpSettings as $option => $value) {
80  ini_set($option, $value);
81  }
82  }
83 
84  // create the Request and Response instances
85  $this->request = ObjectFactory::getInstance('request');
86  $this->response = ObjectFactory::getInstance('response');
87  $this->request->setResponse($this->response);
88 
89  $this->request->initialize($defaultController, $defaultContext, $defaultAction);
90 
91  // initialize session
92  $session = ObjectFactory::getInstance('session');
93 
94  // load user configuration
95  $principalFactory = ObjectFactory::getInstance('principalFactory');
96  $authUser = $principalFactory->getUser($session->getAuthUser(), true);
97  if ($authUser && strlen($authUser->getConfig()) > 0) {
98  $config->addConfiguration($authUser->getConfig(), true);
99  }
100 
101  // load event listeners
102  $listeners = $config->getValue('listeners', 'application');
103  foreach ($listeners as $key) {
105  }
106 
107  // set timezone
108  date_default_timezone_set($config->getValue('timezone', 'application'));
109 
110  // return the request
111  return $this->request;
112  }
113 
114  /**
115  * Run the application with the given request
116  * @param $request
117  * @return Response instance
118  */
119  public function run(Request $request) {
120  // process the requested action
121  ObjectFactory::getInstance('actionMapper')->processAction($request, $this->response);
122  return $this->response;
123  }
124 
125  /**
126  * Default exception handling method. Rolls back the transaction and
127  * executes 'failure' action.
128  * @param $exception The Exception instance
129  */
130  public function handleException(\Exception $exception) {
131  // get error level
132  $logFunction = 'error';
133  if ($exception instanceof ApplicationException) {
134  $logFunction = $exception->getError()->getLevel() == ApplicationError::LEVEL_WARNING ?
135  'warn' : 'error';
136  }
137  self::$logger->$logFunction($exception);
138 
139  try {
140  if (ObjectFactory::getInstance('configuration') != null) {
141  // rollback current transaction
142  $persistenceFacade = ObjectFactory::getInstance('persistenceFacade');
143  $persistenceFacade->getTransaction()->rollback();
144 
145  // redirect to failure action
146  if ($this->request) {
147  $error = ApplicationError::fromException($exception);
148  $this->request->addError($error);
149  $this->response->addError($error);
150  $this->request->setAction('failure');
151  $this->response->setAction('failure');
152  $this->response->setStatus($error->getStatusCode());
153  ObjectFactory::getInstance('actionMapper')->processAction($this->request, $this->response);
154  return;
155  }
156  }
157  throw $exception;
158  }
159  catch (\Exception $ex) {
160  self::$logger->error($ex->getMessage()."\n".$ex->getTraceAsString());
161  }
162  }
163 
164  /**
165  * This method is run as ob_start callback
166  * @note must be public
167  * @param $buffer The content to be returned to the client
168  * @return String
169  */
170  public function outputHandler($buffer) {
171  // log last error, if it's level is enabled
172  $error = error_get_last();
173  if ($error !== null && (in_array($error['type'], [E_ERROR, E_PARSE, E_COMPILE_ERROR]))) {
174  $errorStr = $error['file']."::".$error['line'].": ".$error['type'].": ".$error['message'];
175  self::$logger->error($errorStr);
176  // suppress error message in browser
177  if (!$this->debug) {
178  header('HTTP/1.1 500 Internal Server Error');
179  $buffer = '';
180  }
181  else {
182  $buffer = "<pre>\n".$errorStr."\n</pre>";
183  }
184  }
185  return trim($buffer);
186  }
187 }
188 ?>
Request holds the request values that are used as input to Controller instances.
Definition: Request.php:18
static fromException(\Exception $ex)
Factory method for transforming an exception into an ApplicationError instance.
outputHandler($buffer)
This method is run as ob_start callback.
handleException(\Exception $exception)
Default exception handling method.
ApplicationException signals a general application exception.
run(Request $request)
Run the application with the given request.
static getLogger($name)
Get the logger with the given name.
Definition: LogManager.php:37
static getInstance($name, $dynamicConfiguration=[])
initialize($defaultController='', $defaultContext='', $defaultAction='login')
Initialize the request.
Definition: Application.php:72
LogManager is used to retrieve Logger instances.
Definition: LogManager.php:20
ObjectFactory implements the service locator pattern by wrapping a Factory instance and providing sta...
Application is the main application class, that does all the initialization.
Definition: Application.php:22
ErrorHandler catches all php errors and transforms fatal errors into ErrorExceptions and non-fatal in...
Presentation related interfaces and classes.
Definition: namespaces.php:59