PageRenderTime 41ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/core/model/modx/modresponse.class.php

https://gitlab.com/haque.mdmanzurul/nga-loyaltymatters
PHP | 282 lines | 178 code | 15 blank | 89 comment | 53 complexity | 77b69df89301e70204bb4c465742b882 MD5 | raw file
  1. <?php
  2. /**
  3. * MODX Revolution
  4. *
  5. * Copyright 2006-2014 by MODX, LLC.
  6. * All rights reserved.
  7. *
  8. * This program is free software; you can redistribute it and/or modify it under
  9. * the terms of the GNU General Public License as published by the Free Software
  10. * Foundation; either version 2 of the License, or (at your option) any later
  11. * version.
  12. *
  13. * This program is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  15. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU General Public License along with
  19. * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  20. * Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. * @package modx
  23. */
  24. /**
  25. * Encapsulates a MODX response to a web request.
  26. *
  27. * Includes functions to manipluate header data, such as status codes, as well
  28. * as manipulating the response body.
  29. *
  30. * @package modx
  31. */
  32. class modResponse {
  33. /**
  34. * A reference to the modX instance
  35. * @var modX $modx
  36. */
  37. public $modx= null;
  38. /**
  39. * The HTTP header for this Response
  40. * @var string $header
  41. */
  42. public $header= null;
  43. /**
  44. * The body of this response
  45. * @var string $body
  46. */
  47. public $body= null;
  48. /**
  49. * The current content type on the resource
  50. * @var modContentType $contentType
  51. */
  52. public $contentType = null;
  53. /**
  54. * @param modX $modx A reference to the modX instance
  55. */
  56. function __construct(modX &$modx) {
  57. $this->modx= & $modx;
  58. }
  59. /**
  60. * Prepare the final response after the resource has been processed.
  61. *
  62. * @param array $options Various options that can be set.
  63. */
  64. public function outputContent(array $options = array()) {
  65. if (!($this->contentType = $this->modx->resource->getOne('ContentType'))) {
  66. if ($this->modx->getDebug() === true) {
  67. $this->modx->log(modX::LOG_LEVEL_DEBUG, "No valid content type for RESOURCE: " . print_r($this->modx->resource->toArray(), true));
  68. }
  69. $this->modx->log(modX::LOG_LEVEL_FATAL, "The requested resource has no valid content type specified.");
  70. }
  71. if (!$this->contentType->get('binary')) {
  72. $this->modx->resource->_output= $this->modx->resource->process();
  73. $this->modx->resource->_jscripts= $this->modx->jscripts;
  74. $this->modx->resource->_sjscripts= $this->modx->sjscripts;
  75. $this->modx->resource->_loadedjscripts= $this->modx->loadedjscripts;
  76. /* collect any uncached element tags in the content and process them */
  77. $this->modx->getParser();
  78. $maxIterations= intval($this->modx->getOption('parser_max_iterations', $options, 10));
  79. $this->modx->parser->processElementTags('', $this->modx->resource->_output, true, false, '[[', ']]', array(), $maxIterations);
  80. $this->modx->parser->processElementTags('', $this->modx->resource->_output, true, true, '[[', ']]', array(), $maxIterations);
  81. /*FIXME: only do this for HTML content ?*/
  82. if (strpos($this->contentType->get('mime_type'), 'text/html') !== false) {
  83. /* Insert Startup jscripts & CSS scripts into template - template must have a </head> tag */
  84. if (($js= $this->modx->getRegisteredClientStartupScripts()) && (strpos($this->modx->resource->_output, '</head>') !== false)) {
  85. /* change to just before closing </head> */
  86. $this->modx->resource->_output= preg_replace("/(<\/head>)/i", $js . "\n\\1", $this->modx->resource->_output,1);
  87. }
  88. /* Insert jscripts & html block into template - template must have a </body> tag */
  89. if ((strpos($this->modx->resource->_output, '</body>') !== false) && ($js= $this->modx->getRegisteredClientScripts())) {
  90. $this->modx->resource->_output= preg_replace("/(<\/body>)/i", $js . "\n\\1", $this->modx->resource->_output,1);
  91. }
  92. }
  93. $this->modx->beforeRender();
  94. /* invoke OnWebPagePrerender event */
  95. if (!isset($options['noEvent']) || empty($options['noEvent'])) {
  96. $this->modx->invokeEvent('OnWebPagePrerender');
  97. }
  98. $totalTime= (microtime(true) - $this->modx->startTime);
  99. $queryTime= $this->modx->queryTime;
  100. $queryTime= sprintf("%2.4f s", $queryTime);
  101. $queries= isset ($this->modx->executedQueries) ? $this->modx->executedQueries : 0;
  102. $totalTime= sprintf("%2.4f s", $totalTime);
  103. $phpTime= $totalTime - $queryTime;
  104. $phpTime= sprintf("%2.4f s", $phpTime);
  105. $source= $this->modx->resourceGenerated ? "database" : "cache";
  106. $this->modx->resource->_output= str_replace("[^q^]", $queries, $this->modx->resource->_output);
  107. $this->modx->resource->_output= str_replace("[^qt^]", $queryTime, $this->modx->resource->_output);
  108. $this->modx->resource->_output= str_replace("[^p^]", $phpTime, $this->modx->resource->_output);
  109. $this->modx->resource->_output= str_replace("[^t^]", $totalTime, $this->modx->resource->_output);
  110. $this->modx->resource->_output= str_replace("[^s^]", $source, $this->modx->resource->_output);
  111. } else {
  112. $this->modx->beforeRender();
  113. /* invoke OnWebPagePrerender event */
  114. if (!isset($options['noEvent']) || empty($options['noEvent'])) {
  115. $this->modx->invokeEvent("OnWebPagePrerender");
  116. }
  117. }
  118. /* send out content-type, content-disposition, and custom headers from the content type */
  119. if ($this->modx->getOption('set_header')) {
  120. $type= $this->contentType->get('mime_type') ? $this->contentType->get('mime_type') : 'text/html';
  121. $header= 'Content-Type: ' . $type;
  122. if (!$this->contentType->get('binary')) {
  123. $charset= $this->modx->getOption('modx_charset',null,'UTF-8');
  124. $header .= '; charset=' . $charset;
  125. }
  126. header($header);
  127. if (!$this->checkPreview()) {
  128. $dispositionSet= false;
  129. if ($customHeaders= $this->contentType->get('headers')) {
  130. foreach ($customHeaders as $headerKey => $headerString) {
  131. header($headerString);
  132. if (strpos($headerString, 'Content-Disposition:') !== false) $dispositionSet= true;
  133. }
  134. }
  135. if (!$dispositionSet && $this->modx->resource->get('content_dispo')) {
  136. if ($alias= $this->modx->resource->get('uri')) {
  137. $name= basename($alias);
  138. } elseif ($this->modx->resource->get('alias')) {
  139. $name= $this->modx->resource->get('alias');
  140. if ($ext= $this->contentType->getExtension()) {
  141. $name .= "{$ext}";
  142. }
  143. } elseif ($name= $this->modx->resource->get('pagetitle')) {
  144. $name= $this->modx->resource->cleanAlias($name);
  145. if ($ext= $this->contentType->getExtension()) {
  146. $name .= "{$ext}";
  147. }
  148. } else {
  149. $name= 'download';
  150. if ($ext= $this->contentType->getExtension()) {
  151. $name .= "{$ext}";
  152. }
  153. }
  154. $header= 'Cache-Control: public';
  155. header($header);
  156. $header= 'Content-Disposition: attachment; filename=' . $name;
  157. header($header);
  158. $header= 'Vary: User-Agent';
  159. header($header);
  160. }
  161. }
  162. }
  163. /* tell PHP to call _postProcess after returning the response (for caching) */
  164. register_shutdown_function(array (
  165. & $this->modx,
  166. "_postProcess"
  167. ));
  168. if ($this->modx->resource instanceof modStaticResource && $this->contentType->get('binary')) {
  169. $this->modx->resource->process();
  170. } else {
  171. if ($this->contentType->get('binary')) {
  172. $this->modx->resource->_output = $this->modx->resource->process();
  173. }
  174. @session_write_close();
  175. echo $this->modx->resource->_output;
  176. while (ob_get_level() && @ob_end_flush()) {}
  177. flush();
  178. exit();
  179. }
  180. }
  181. /**
  182. * Sends a redirect to the specified URL using the specified method.
  183. *
  184. * Valid $type values include:
  185. * REDIRECT_REFRESH Uses the header refresh method
  186. * REDIRECT_META Sends a a META HTTP-EQUIV="Refresh" tag to the output
  187. * REDIRECT_HEADER Uses the header location method
  188. *
  189. * REDIRECT_HEADER is the default.
  190. *
  191. * @param string $url The URL to redirect the client browser to.
  192. * @param array|boolean $options An array of options for the redirect OR
  193. * indicates if redirect attempts should be counted and limited to 3 (latter is deprecated
  194. * usage; use count_attempts in options array).
  195. * @param string $type The type of redirection to attempt (deprecated, use type in
  196. * options array).
  197. * @param string $responseCode The type of HTTP response code HEADER to send for the
  198. * redirect (deprecated, use responseCode in options array)
  199. * @return void|boolean
  200. */
  201. public function sendRedirect($url, $options= false, $type= '', $responseCode= '') {
  202. if (!is_array($options)) {
  203. $options = array('count_attempts' => (boolean) $options);
  204. }
  205. $options = array_merge(array('count_attempts' => false, 'type' => $type, 'responseCode' => $responseCode), $options);
  206. $url= str_replace('&amp;','&',$url);
  207. if (empty ($url)) {
  208. $this->modx->log(modX::LOG_LEVEL_ERROR, "Attempted to redirect to an empty URL.");
  209. return false;
  210. }
  211. if (!$this->modx->getRequest()) {
  212. $this->modx->log(modX::LOG_LEVEL_FATAL, "Could not load request class.");
  213. }
  214. if (isset($options['preserve_request']) && !empty($options['preserve_request'])) {
  215. $this->modx->request->preserveRequest('referrer.redirected');
  216. }
  217. if ($options['count_attempts']) {
  218. /* append the redirect count string to the url */
  219. $currentNumberOfRedirects= isset ($_REQUEST['err']) ? $_REQUEST['err'] : 0;
  220. if ($currentNumberOfRedirects > 3) {
  221. $this->modx->log(modX::LOG_LEVEL_FATAL, 'Redirection attempt failed - please ensure the resource you\'re trying to redirect to exists. <p>Redirection URL: <i>' . $url . '</i></p>');
  222. } else {
  223. $currentNumberOfRedirects += 1;
  224. if (strpos($url, "?") > 0) {
  225. $url .= "&err=$currentNumberOfRedirects";
  226. } else {
  227. $url .= "?err=$currentNumberOfRedirects";
  228. }
  229. }
  230. }
  231. switch ($options['type']) {
  232. case 'REDIRECT_REFRESH':
  233. $header= 'Refresh: 0;URL=' . $url;
  234. break;
  235. case 'REDIRECT_META':
  236. $header= '<META HTTP-EQUIV="Refresh" CONTENT="0; URL=' . $url . '" />';
  237. echo $header;
  238. exit();
  239. default:
  240. if (strpos($url, '://') === false && !(substr($url, 0, 1) === '/' || substr($url, 0, 2) === './' || substr($url, 0, 3) === '../')) {
  241. $url= $this->modx->getOption('site_url',null,'/') . $url;
  242. }
  243. $header= 'Location: ' . $url;
  244. break;
  245. }
  246. @session_write_close();
  247. if (!empty($options['responseCode']) && (strpos($options['responseCode'], '30') !== false)) {
  248. header($options['responseCode']);
  249. }
  250. header($header);
  251. exit();
  252. }
  253. /**
  254. * Checks to see if the preview parameter is set.
  255. *
  256. * @return boolean
  257. */
  258. public function checkPreview() {
  259. $preview= false;
  260. if ($this->modx->checkSession('mgr') === true) {
  261. if (isset ($_REQUEST['z']) && $_REQUEST['z'] == 'manprev') {
  262. $preview= true;
  263. }
  264. }
  265. return $preview;
  266. }
  267. }