PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/wind/web/WindWebApplication.php

http://github.com/phpwind/windframework
PHP | 314 lines | 173 code | 17 blank | 124 comment | 32 complexity | 81680c3e639d3f3148b7802f2b751481 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * 应用控制器,协调处理用户请求,处理,跳转分发等工作
  4. *
  5. * @author Qiong Wu <papa0924@gmail.com>
  6. * @copyright ©2003-2103 phpwind.com
  7. * @license http://www.windframework.com
  8. * @version $Id$
  9. * @package web
  10. */
  11. class WindWebApplication extends WindModule implements IWindApplication {
  12. /**
  13. * @var WindHttpRequest
  14. */
  15. protected $request;
  16. /**
  17. * @var WindHttpResponse
  18. */
  19. protected $response;
  20. /**
  21. * @var WindFactory
  22. */
  23. protected $windFactory = null;
  24. /**
  25. * @var WindDispatcher
  26. */
  27. protected $dispatcher = null;
  28. /**
  29. * @var WindRouter
  30. */
  31. protected $handlerAdapter = null;
  32. protected $defaultModule = array(
  33. 'controller-path' => 'controller',
  34. 'controller-suffix' => 'Controller',
  35. 'error-handler' => 'WIND:web.WindErrorHandler');
  36. /**
  37. * 应用初始化操作
  38. *
  39. * @param WindHttpRequest $request
  40. * @param WindHttpResponse $response
  41. * @param WindFactory $factory
  42. */
  43. public function __construct($request, $factory) {
  44. $this->response = $request->getResponse();
  45. $this->request = $request;
  46. $this->windFactory = $factory;
  47. }
  48. /**
  49. * 请求处理完毕后,进一步分发
  50. *
  51. * @param WindForward $forward
  52. * @param boolean $display
  53. */
  54. public function doDispatch($forward, $display = false) {
  55. if ($forward === null) return;
  56. $this->_getDispatcher()->dispatch($forward, $this->handlerAdapter, $display);
  57. }
  58. /* (non-PHPdoc)
  59. * @see IWindApplication::run()
  60. */
  61. public function run($filters = false) {
  62. $module = $this->getModules($this->_getHandlerAdapter()->getModule());
  63. $handlerPath = $module['controller-path'] . '.' . ucfirst($this->handlerAdapter->getController()) . $module['controller-suffix'];
  64. $className = Wind::import($handlerPath);
  65. if (!class_exists($className)) throw new WindException(
  66. 'Your requested \'' . $handlerPath . '\' was not found on this server.', 404);
  67. $handler = new $className();
  68. $handler->setDelayAttributes(
  69. array('errorMessage' => array('ref' => 'errorMessage'), 'forward' => array('ref' => 'forward')));
  70. $filters && $this->resolveActionFilters($handler);
  71. try {
  72. $forward = $handler->doAction($this->handlerAdapter);
  73. $this->doDispatch($forward);
  74. } catch (WindForwardException $e) {
  75. $this->doDispatch($e->getForward());
  76. } catch (WindActionException $e) {
  77. $this->sendErrorMessage(($e->getError() ? $e->getError() : $e->getMessage()), $e->getCode());
  78. } catch (WindException $e) {
  79. $this->sendErrorMessage($e->getMessage(), $e->getCode());
  80. }
  81. }
  82. /* (non-PHPdoc)
  83. * @see WindModule::setConfig()
  84. */
  85. public function setConfig($config) {
  86. parent::setConfig($config);
  87. if ($default = $this->getConfig('modules', 'default', array())) {
  88. $this->defaultModule = WindUtility::mergeArray($this->defaultModule, $default);
  89. }
  90. $charset = $this->getConfig('charset', '', 'utf-8');
  91. $this->getResponse()->setHeader('Content-type', 'text/html;charset=' . $charset);
  92. $this->getResponse()->setCharset($charset);
  93. }
  94. /**
  95. * 设置全局变量
  96. *
  97. * @param array|object|string $data
  98. * @param string $key
  99. * @return void
  100. */
  101. public function setGlobal($data, $key = '') {
  102. if ($key)
  103. $_G[$key] = $data;
  104. else {
  105. if (is_object($data)) $data = get_object_vars($data);
  106. $_G = $data;
  107. }
  108. $this->response->setData($_G, 'G', true);
  109. }
  110. /**
  111. * 获取全局变量
  112. *
  113. * @return mixed
  114. */
  115. public function getGlobal() {
  116. $_args = func_get_args();
  117. array_unshift($_args, 'G');
  118. return call_user_func_array(array($this->response, 'getData'), $_args);
  119. }
  120. /**
  121. * 添加module配置
  122. * <code>
  123. * <controller-path>controller</controller-path>
  124. * <!-- 指定该模块下的controller的后缀格式 -->
  125. * <controller-suffix>Controller</controller-suffix>
  126. * <!-- 配置该模块的error处理的action controller类 -->
  127. * <error-handler>WIND:web.WindErrorHandler</error-handler>
  128. * <!-- 试图相关配置,config中配置可以根据自己的需要进行配置或是使用缺省 -->
  129. * <!-- 可以在这里进行view的配置,该配置只会影响该module下的view行为,该配置可以设置也可以不设置 -->
  130. * <!-- 指定模板路径 -->
  131. * <template-dir>template</template-dir>
  132. * <!-- 指定模板后缀 -->
  133. * <template-ext>htm</template-ext></code>
  134. *
  135. * @param string $name module名称
  136. * @param array $config 配置数组
  137. * @param boolean $replace 如果module已经存在是否覆盖他 默认值为false不进行覆盖
  138. * @return array
  139. */
  140. public function setModules($name, $config, $replace = false) {
  141. if ($replace || !isset($this->_config['modules'][$name])) {
  142. $this->_config['modules'][$name] = (array) $config;
  143. }
  144. return $this->_config['modules'][$name];
  145. }
  146. /**
  147. * 获得module配置,$name为空时返回当前module配置
  148. *
  149. * @param string $name module名称 默认为空
  150. * @param boolean $merge 合并默认值
  151. * @return array
  152. * @throws WindActionException
  153. * @throws WindException
  154. */
  155. public function getModules($name = '') {
  156. if ($name === '') $name = $this->handlerAdapter->getModule();
  157. $_module = $this->getConfig('modules', $name, array());
  158. if (!isset($_module['_verified']) || $_module['_verified'] !== true) {
  159. if (empty($_module)) {
  160. $_module = $this->getConfig('modules', 'pattern', array());
  161. $_pattern = !empty($_module);
  162. }
  163. $_module = WindUtility::mergeArray($this->defaultModule, $_module);
  164. if (isset($_pattern) && $_pattern) {
  165. $_keys = array_keys($_module);
  166. $_replace = array(
  167. '{' . $this->handlerAdapter->getModuleKey() . '}' => $this->handlerAdapter->getModule(),
  168. '{' . $this->handlerAdapter->getControllerKey() . '}' => $this->handlerAdapter->getController(),
  169. '{' . $this->handlerAdapter->getActionKey() . '}' => $this->handlerAdapter->getAction());
  170. foreach ($_keys as $_key) {
  171. if (strrchr($_key, '-') !== '-path') continue;
  172. $_module[$_key] = strtr($_module[$_key], $_replace);
  173. }
  174. }
  175. $_module['_verified'] = true;
  176. $this->_config['modules'][$name] = $_module;
  177. }
  178. return $_module;
  179. }
  180. /**
  181. * 获得组件对象
  182. *
  183. * @param string $componentName 组件名称呢个
  184. * @return object
  185. */
  186. public function getComponent($componentName, $args = array()) {
  187. return $this->windFactory->getInstance($componentName, $args);
  188. }
  189. /**
  190. * 手动注册actionFilter
  191. *
  192. * 参数为数组格式:
  193. * @param array $filters
  194. */
  195. public function registeActionFilter($filters) {
  196. if (!$filters) return;
  197. if (empty($this->_config['filters']))
  198. $this->_config['filters'] = $filters;
  199. else
  200. $this->_config['filters'] += $filters;
  201. }
  202. /**
  203. * 解析action过滤链的配置信息
  204. *
  205. * @param WindSimpleController $handler
  206. * @return void
  207. */
  208. protected function resolveActionFilters(&$handler) {
  209. if (!$filters = $this->getConfig('filters')) return;
  210. /* @var $cache AbstractWindCache */
  211. $_filters = array();
  212. if ($cache = $this->getComponent('windCache')) {
  213. $_filters = $cache->get('filters');
  214. }
  215. $_token = $this->handlerAdapter->getModule() . '/' . $this->handlerAdapter->getController() . '/' . $this->handlerAdapter->getAction();
  216. if (!isset($_filters[$_token])) {
  217. foreach ($filters as $_filter) {
  218. if (empty($_filter['class'])) continue;
  219. $_pattern = empty($_filter['pattern']) ? '' : $_filter['pattern'];
  220. unset($_filter['pattern']);
  221. if ($_pattern) {
  222. $_pattern = str_replace(array('*', '/'), array('\w*', '\/'), $_pattern);
  223. if (in_array($_pattern[0], array('~', '!'))) {
  224. $_pattern = substr($_pattern, 1);
  225. if (preg_match('/^' . $_pattern . '$/i', $_token)) continue;
  226. } else {
  227. if (!preg_match('/^' . $_pattern . '$/i', $_token)) continue;
  228. }
  229. }
  230. $_filters[$_token][] = $_filter;
  231. }
  232. $cache && $cache->set('filters', $_filters);
  233. }
  234. if (empty($_filters[$_token])) return;
  235. /* @var $proxy WindClassProxy */
  236. $proxy = WindFactory::createInstance(Wind::import('WIND:factory.WindClassProxy'));
  237. $proxy->registerTargetObject($handler);
  238. foreach ($_filters[$_token] as $value) {
  239. $proxy->registerEventListener('doAction',
  240. $this->windFactory->createInstance(Wind::import($value['class']),
  241. array($handler->getForward(), $handler->getErrorMessage(), $this->handlerAdapter, $value)));
  242. }
  243. $handler = $proxy;
  244. }
  245. /**
  246. * 处理错误请求
  247. *
  248. * 根据错误请求的相关信息,将程序转向到错误处理句柄进行错误处理
  249. * @param WindErrorMessage $errorMessage
  250. * @param int $errorcode
  251. * @return void
  252. */
  253. protected function sendErrorMessage($errorMessage, $errorcode) {
  254. if (is_string($errorMessage)) {
  255. $_tmp = $errorMessage;
  256. /* @var $errorMessage WindErrorMessage */
  257. $errorMessage = $this->getComponent('errorMessage');
  258. $errorMessage->addError($_tmp);
  259. }
  260. /* @var $router WindRouter */
  261. $moduleName = $this->handlerAdapter->getModule();
  262. if ($moduleName === 'error') throw new WindFinalException($errorMessage->getError(0));
  263. if (!$_errorAction = $errorMessage->getErrorAction()) {
  264. $module = $this->getModules($moduleName);
  265. $_errorClass = Wind::import(@$module['error-handler']);
  266. $_errorAction = 'error/' . $_errorClass . '/run/';
  267. $this->setModules('error',
  268. array(
  269. 'controller-path' => array_search($_errorClass, Wind::$_imports),
  270. 'controller-suffix' => '',
  271. 'error-handler' => ''));
  272. }
  273. /* @var $forward WindForward */
  274. $forward = $this->getComponent('forward');
  275. $error = array('message' => $errorMessage->getError(), 'code' => $errorcode);
  276. $forward->forwardAction($_errorAction, array('__error' => $error), false, false);
  277. $this->doDispatch($forward);
  278. }
  279. /**
  280. * @return WindHttpRequest
  281. */
  282. public function getRequest() {
  283. return $this->request;
  284. }
  285. /**
  286. * @return WindHttpResponse
  287. */
  288. public function getResponse() {
  289. return $this->response;
  290. }
  291. /**
  292. * @return WindFactory
  293. */
  294. public function getWindFactory() {
  295. return $this->windFactory;
  296. }
  297. }