Passed
Branch php-cs-fixer (b9836a)
by Fabio
15:02
created

THttpResponse::flushContent()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 4
nop 1
dl 0
loc 21
rs 9.0534
c 0
b 0
f 0
1
<?php
2
/**
3
 * THttpResponse class
4
 *
5
 * @author Qiang Xue <[email protected]>
6
 * @link https://github.com/pradosoft/prado
7
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 * @package Prado\Web
10
 */
11
12
namespace Prado\Web;
13
14
use Prado\Exceptions\TInvalidDataValueException;
15
use Prado\Exceptions\TInvalidOperationException;
16
use Prado\Prado;
17
use Prado\TPropertyValue;
18
19
/**
20
 * THttpResponse class
21
 *
22
 * THttpResponse implements the mechanism for sending output to client users.
23
 *
24
 * To output a string to client, use {@link write()}. By default, the output is
25
 * buffered until {@link flush()} is called or the application ends. The output in
26
 * the buffer can also be cleaned by {@link clear()}. To disable output buffering,
27
 * set BufferOutput property to false.
28
 *
29
 * To send cookies to client, use {@link getCookies()}.
30
 * To redirect client browser to a new URL, use {@link redirect()}.
31
 * To send a file to client, use {@link writeFile()}.
32
 *
33
 * By default, THttpResponse is registered with {@link TApplication} as the
34
 * response module. It can be accessed via {@link TApplication::getResponse()}.
35
 *
36
 * THttpResponse may be configured in application configuration file as follows
37
 *
38
 * <module id="response" class="System.Web.THttpResponse" CacheExpire="20" CacheControl="nocache" BufferOutput="true" />
39
 *
40
 * where {@link getCacheExpire CacheExpire}, {@link getCacheControl CacheControl}
41
 * and {@link getBufferOutput BufferOutput} are optional properties of THttpResponse.
42
 *
43
 * THttpResponse sends charset header if either {@link setCharset() Charset}
44
 * or {@link TGlobalization::setCharset() TGlobalization.Charset} is set.
45
 *
46
 * Since 3.1.2, HTTP status code can be set with the {@link setStatusCode StatusCode} property.
47
 *
48
 * Note: Some HTTP Status codes can require additional header or body information. So, if you use {@link setStatusCode StatusCode}
49
 * in your application, be sure to add theses informations.
50
 * E.g : to make an http authentication :
51
 * <code>
52
 *  public function clickAuth ($sender, $param)
53
 *  {
54
 *     $response=$this->getResponse();
55
 *     $response->setStatusCode(401);
56
 *     $response->appendHeader('WWW-Authenticate: Basic realm="Test"');
57
 *  }
58
 * </code>
59
 *
60
 * This event handler will sent the 401 status code (Unauthorized) to the browser, with the WWW-Authenticate header field. This
61
 * will force the browser to ask for a username and a password.
62
 *
63
 * @author Qiang Xue <[email protected]>
64
 * @package Prado\Web
65
 * @since 3.0
66
 */
67
class THttpResponse extends \Prado\TModule implements \Prado\IO\ITextWriter
68
{
69
	const DEFAULT_CONTENTTYPE = 'text/html';
70
	const DEFAULT_CHARSET = 'UTF-8';
71
72
	/**
73
	 * @var The differents defined status code by RFC 2616 {@link http://www.faqs.org/rfcs/rfc2616}
0 ignored issues
show
Bug introduced by
The type Prado\Web\The was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
74
	 */
75
	private static $HTTP_STATUS_CODES = [
76
		100 => 'Continue', 101 => 'Switching Protocols',
77
		200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content',
78
		300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect',
79
		400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed',
80
		500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported'
81
	];
82
83
	/**
84
	 * @var boolean whether to buffer output
85
	 */
86
	private $_bufferOutput = true;
87
	/**
88
	 * @var boolean if the application is initialized
89
	 */
90
	private $_initialized = false;
91
	/**
92
	 * @var THttpCookieCollection list of cookies to return
93
	 */
94
	private $_cookies;
95
	/**
96
	 * @var integer response status code
97
	 */
98
	private $_status = 200;
99
	/**
100
	 * @var string reason correspond to status code
101
	 */
102
	private $_reason = 'OK';
103
	/**
104
	 * @var string HTML writer type
105
	 */
106
	private $_htmlWriterType = '\Prado\Web\UI\THtmlWriter';
107
	/**
108
	 * @var string content type
109
	 */
110
	private $_contentType;
111
	/**
112
	 * @var string|boolean character set, e.g. UTF-8 or false if no character set should be send to client
113
	 */
114
	private $_charset = '';
115
	/**
116
	 * @var THttpResponseAdapter adapter.
117
	 */
118
	private $_adapter;
119
	/**
120
	 * @var boolean whether http response header has been sent
121
	 */
122
	private $_httpHeaderSent;
123
	/**
124
	 * @var boolean whether content-type header has been sent
125
	 */
126
	private $_contentTypeHeaderSent;
127
128
	/**
129
	 * Destructor.
130
	 * Flushes any existing content in buffer.
131
	 */
132
	public function __destruct()
133
	{
134
		//if($this->_bufferOutput)
135
		//	@ob_end_flush();
136
	}
137
138
	/**
139
	 * @param THttpResponseAdapter response adapter
0 ignored issues
show
Bug introduced by
The type Prado\Web\response was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
140
	 */
141
	public function setAdapter(THttpResponseAdapter $adapter)
142
	{
143
		$this->_adapter = $adapter;
144
	}
145
146
	/**
147
	 * @return THttpResponseAdapter response adapter, null if not exist.
148
	 */
149
	public function getAdapter()
150
	{
151
		return $this->_adapter;
152
	}
153
154
	/**
155
	 * @return boolean true if adapter exists, false otherwise.
156
	 */
157
	public function getHasAdapter()
158
	{
159
		return $this->_adapter !== null;
160
	}
161
162
	/**
163
	 * Initializes the module.
0 ignored issues
show
Bug introduced by
The type Prado\Web\module was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
164
	 * This method is required by IModule and is invoked by application.
165
	 * It starts output buffer if it is enabled.
166
	 * @param TXmlElement module configuration
167
	 */
168
	public function init($config)
169
	{
170
		if($this->_bufferOutput)
171
			ob_start();
172
		$this->_initialized = true;
173
		$this->getApplication()->setResponse($this);
174
	}
175
176
	/**
177
	 * @return integer time-to-live for cached session pages in minutes, this has no effect for nocache limiter. Defaults to 180.
178
	 */
179
	public function getCacheExpire()
180
	{
181
		return session_cache_expire();
182
	}
183
184
	/**
185
	 * @param integer time-to-live for cached session pages in minutes, this has no effect for nocache limiter.
186
	 */
0 ignored issues
show
Documentation Bug introduced by
The doc comment time-to-live at position 0 could not be parsed: Unknown type name 'time-to-live' at position 0 in time-to-live.
Loading history...
187
	public function setCacheExpire($value)
188
	{
189
		session_cache_expire(TPropertyValue::ensureInteger($value));
190
	}
191
192
	/**
193
	 * @return string cache control method to use for session pages
194
	 */
195
	public function getCacheControl()
196
	{
197
		return session_cache_limiter();
198
	}
199
200
	/**
201
	 * @param string cache control method to use for session pages. Valid values
0 ignored issues
show
Bug introduced by
The type Prado\Web\cache was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
202
	 *               include none/nocache/private/private_no_expire/public
203
	 */
204
	public function setCacheControl($value)
205
	{
206
		session_cache_limiter(TPropertyValue::ensureEnum($value, ['none','nocache','private','private_no_expire','public']));
207
	}
208
209
	/**
210
	 * @return string content type, default is text/html
211
	 */
212
	public function setContentType($type)
213
	{
214
		if ($this->_contentTypeHeaderSent)
215
			throw new \Exception('Unable to alter content-type as it has been already sent');
216
		$this->_contentType = $type;
217
	}
218
219
	/**
220
	 * @return string current content type
221
	 */
222
	public function getContentType()
223
	{
224
		return $this->_contentType;
225
	}
226
227
	/**
228
	 * @return string|boolean output charset.
229
	 */
230
	public function getCharset()
231
	{
232
		return $this->_charset;
233
	}
234
235
	/**
236
	 * @param string|boolean output charset.
0 ignored issues
show
Bug introduced by
The type Prado\Web\output was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
237
	 */
238
	public function setCharset($charset)
239
	{
240
		$this->_charset = (strToLower($charset) === 'false') ? false : (string)$charset;
241
	}
242
243
	/**
244
	 * @return boolean whether to enable output buffer
245
	 */
246
	public function getBufferOutput()
247
	{
248
		return $this->_bufferOutput;
249
	}
250
251
	/**
252
	 * @param boolean whether to enable output buffer
0 ignored issues
show
Bug introduced by
The type Prado\Web\whether was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
253
	 * @throws TInvalidOperationException if session is started already
254
	 */
255
	public function setBufferOutput($value)
256
	{
257
		if($this->_initialized)
258
			throw new TInvalidOperationException('httpresponse_bufferoutput_unchangeable');
259
		else
260
			$this->_bufferOutput = TPropertyValue::ensureBoolean($value);
261
	}
262
263
	/**
264
	 * @return integer HTTP status code, defaults to 200
265
	 */
266
	public function getStatusCode()
267
	{
268
		return $this->_status;
269
	}
270
271
	/**
272
	 * Set the HTTP status code for the response.
0 ignored issues
show
Bug introduced by
The type Prado\Web\HTTP was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
273
	 * The code and its reason will be sent to client using the currently requested http protocol version (see {@link THttpRequest::getHttpProtocolVersion})
274
	 * Keep in mind that HTTP/1.0 clients might not understand all status codes from HTTP/1.1
275
	 *
276
	 * @param integer HTTP status code
277
	 * @param string HTTP status reason, defaults to standard HTTP reasons
278
	 */
279
	public function setStatusCode($status, $reason = null)
280
	{
281
		if ($this->_httpHeaderSent)
282
			throw new \Exception('Unable to alter response as HTTP header already sent');
283
		$status = TPropertyValue::ensureInteger($status);
284
		if(isset(self::$HTTP_STATUS_CODES[$status])) {
285
			$this->_reason = self::$HTTP_STATUS_CODES[$status];
286
		}else{
287
			if($reason === null || $reason === '') {
288
				throw new TInvalidDataValueException("response_status_reason_missing");
289
			}
290
			$reason = TPropertyValue::ensureString($reason);
291
			if(strpos($reason, "\r") != false || strpos($reason, "\n") != false) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing strpos($reason, ' ') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
Bug Best Practice introduced by
It seems like you are loosely comparing strpos($reason, ' ') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
292
				throw new TInvalidDataValueException("response_status_reason_barchars");
293
			}
294
			$this->_reason = $reason;
295
		}
296
		$this->_status = $status;
297
	}
298
299
	/**
300
	 * @param string HTTP status reason
301
	 */
302
	public function getStatusReason() {
303
		return $this->_reason;
304
	}
305
306
	/**
307
	 * @return THttpCookieCollection list of output cookies
308
	 */
309
	public function getCookies()
310
	{
311
		if($this->_cookies === null)
312
			$this->_cookies = new THttpCookieCollection($this);
313
		return $this->_cookies;
314
	}
315
316
	/**
317
	 * Outputs a string.
318
	 * It may not be sent back to user immediately if output buffer is enabled.
319
	 * @param string string to be output
320
	 */
321
	public function write($str)
322
	{
323
		// when starting output make sure we send the headers first
324
		if (!$this->_bufferOutput and !$this->_httpHeaderSent)
325
			$this->ensureHeadersSent();
326
		echo $str;
327
	}
328
329
	/**
330
	 * Sends a file back to user.
331
	 * Make sure not to output anything else after calling this method.
332
	 * @param string file name
333
	 * @param string content to be set. If null, the content will be read from the server file pointed to by $fileName.
334
	 * @param string mime type of the content.
335
	 * @param array list of headers to be sent. Each array element represents a header string (e.g. 'Content-Type: text/plain').
0 ignored issues
show
Bug introduced by
The type Prado\Web\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
336
	 * @param boolean force download of file, even if browser able to display inline. Defaults to 'true'.
0 ignored issues
show
Bug introduced by
The type Prado\Web\force was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
337
	 * @param string force a specific file name on client side. Defaults to 'null' means auto-detect.
338
	 * @param integer size of file or content in bytes if already known. Defaults to 'null' means auto-detect.
0 ignored issues
show
Bug introduced by
The type Prado\Web\size was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
339
	 * @throws TInvalidDataValueException if the file cannot be found
340
	 */
341
	public function writeFile($fileName, $content = null, $mimeType = null, $headers = null, $forceDownload = true, $clientFileName = null, $fileSize = null)
342
	{
343
		static $defaultMimeTypes = [
344
			'css' => 'text/css',
345
			'gif' => 'image/gif',
346
			'png' => 'image/png',
347
			'jpg' => 'image/jpeg',
348
			'jpeg' => 'image/jpeg',
349
			'htm' => 'text/html',
350
			'html' => 'text/html',
351
			'js' => 'javascript/js',
352
			'pdf' => 'application/pdf',
353
			'xls' => 'application/vnd.ms-excel',
354
		];
355
356
		if($mimeType === null)
357
		{
358
			$mimeType = 'text/plain';
359
			if(function_exists('mime_content_type'))
360
				$mimeType = mime_content_type($fileName);
361
			elseif(($ext = strrchr($fileName, '.')) !== false)
0 ignored issues
show
introduced by
The condition $ext = strrchr($fileName, '.') !== false can never be false.
Loading history...
362
			{
363
				$ext = substr($ext, 1);
364
				if(isset($defaultMimeTypes[$ext]))
365
					$mimeType = $defaultMimeTypes[$ext];
366
			}
367
		}
368
369
		if($clientFileName === null)
370
			$clientFileName = basename($fileName);
371
		else
372
			$clientFileName = basename($clientFileName);
373
374
		if($fileSize === null || $fileSize < 0)
375
			$fileSize = ($content === null?filesize($fileName):strlen($content));
376
377
		$this->sendHttpHeader();
378
		if(is_array($headers))
379
		{
380
			foreach($headers as $h)
381
				header($h);
382
		}
383
		else
384
		{
385
			header('Pragma: public');
386
			header('Expires: 0');
387
			header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
388
			header("Content-Type: $mimeType");
389
			$this->_contentTypeHeaderSent = true;
390
		}
391
392
		header('Content-Length: ' . $fileSize);
393
		header("Content-Disposition: " . ($forceDownload ? 'attachment' : 'inline') . "; filename=\"$clientFileName\"");
394
		header('Content-Transfer-Encoding: binary');
395
		if($content === null)
396
			readfile($fileName);
397
		else
398
			echo $content;
399
	}
400
401
	/**
402
	 * Redirects the browser to the specified URL.
0 ignored issues
show
Bug introduced by
The type Prado\Web\URL was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
403
	 * The current application will be terminated after this method is invoked.
404
	 * @param string URL to be redirected to. If the URL is a relative one, the base URL of
405
	 * the current request will be inserted at the beginning.
406
	 */
407
	public function redirect($url)
408
	{
409
		if($this->getHasAdapter())
410
			$this->_adapter->httpRedirect($url);
411
		else
412
			$this->httpRedirect($url);
413
	}
414
415
	/**
416
	 * Redirect the browser to another URL and exists the current application.
417
	 * This method is used internally. Please use {@link redirect} instead.
418
	 *
419
	 * @since 3.1.5
420
	 * You can set the set {@link setStatusCode StatusCode} to a value between 300 and 399 before
421
	 * calling this function to change the type of redirection.
422
	 * If not specified, StatusCode will be 302 (Found) by default
423
	 *
424
	 * @param string URL to be redirected to. If the URL is a relative one, the base URL of
425
	 * the current request will be inserted at the beginning.
426
	 */
427
	public function httpRedirect($url)
428
	{
429
		$this->ensureHeadersSent();
430
431
		// Under IIS, explicitly send an HTTP response including the status code
432
		// this is handled automatically by PHP on Apache and others
433
		$isIIS = (stripos($this->getRequest()->getServerSoftware(), "microsoft-iis") !== false);
434
		if($url[0] === '/')
435
			$url = $this->getRequest()->getBaseUrl() . $url;
436
		if ($this->_status >= 300 && $this->_status < 400)
437
		{
438
			// The status code has been modified to a valid redirection status, send it
439
			if($isIIS)
440
			{
441
				header('HTTP/1.1 ' . $this->_status . ' ' . self::$HTTP_STATUS_CODES[
442
					array_key_exists($this->_status, self::$HTTP_STATUS_CODES)
0 ignored issues
show
Bug introduced by
self::HTTP_STATUS_CODES of type Prado\Web\The is incompatible with the type array expected by parameter $search of array_key_exists(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

442
					array_key_exists($this->_status, /** @scrutinizer ignore-type */ self::$HTTP_STATUS_CODES)
Loading history...
443
						? $this->_status
444
						: 302
445
					]);
446
			}
447
			header('Location: ' . str_replace('&amp;', '&', $url), true, $this->_status);
448
		} else {
449
			if($isIIS)
450
				header('HTTP/1.1 302 ' . self::$HTTP_STATUS_CODES[302]);
451
			header('Location: ' . str_replace('&amp;', '&', $url));
452
		}
453
454
		if(!$this->getApplication()->getRequestCompleted())
455
			$this->getApplication()->onEndRequest();
456
457
		exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
458
	}
459
460
	/**
461
	 * Reloads the current page.
462
	 * The effect of this method call is the same as user pressing the
463
	 * refresh button on his browser (without post data).
464
	 **/
465
	public function reload()
466
	{
467
		$this->redirect($this->getRequest()->getRequestUri());
468
	}
469
470
	/**
471
	 * Flush the response contents and headers.
472
	 */
473
	public function flush($continueBuffering = true)
474
	{
475
		if($this->getHasAdapter())
476
			$this->_adapter->flushContent($continueBuffering);
0 ignored issues
show
Unused Code introduced by
The call to Prado\Web\THttpResponseAdapter::flushContent() has too many arguments starting with $continueBuffering. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

476
			$this->_adapter->/** @scrutinizer ignore-call */ 
477
                    flushContent($continueBuffering);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
477
		else
478
			$this->flushContent($continueBuffering);
479
	}
480
481
	/**
482
	 * Ensures that HTTP response and content-type headers are sent
483
	 */
484
	public function ensureHeadersSent()
485
	{
486
		$this->ensureHttpHeaderSent();
487
		$this->ensureContentTypeHeaderSent();
488
	}
489
490
	/**
491
	 * Outputs the buffered content, sends content-type and charset header.
492
	 * This method is used internally. Please use {@link flush} instead.
493
	 * @param boolean whether to continue buffering after flush if buffering was active
494
	 */
495
	public function flushContent($continueBuffering = true)
496
	{
497
		Prado::trace("Flushing output", 'Prado\Web\THttpResponse');
498
		$this->ensureHeadersSent();
499
		if($this->_bufferOutput)
500
		{
501
			// avoid forced send of http headers (ob_flush() does that) if there's no output yet
502
			if (ob_get_length() > 0)
503
			{
504
				if (!$continueBuffering)
505
				{
506
					$this->_bufferOutput = false;
507
					ob_end_flush();
508
				}
509
				else
510
					ob_flush();
511
				flush();
512
			}
513
		}
514
		else
515
			flush();
516
	}
517
518
	/**
519
	 * Ensures that the HTTP header with the status code and status reason are sent
520
	 */
521
	protected function ensureHttpHeaderSent()
522
	{
523
		if (!$this->_httpHeaderSent)
524
			$this->sendHttpHeader();
525
	}
526
527
	/**
528
	 * Send the HTTP header with the status code (defaults to 200) and status reason (defaults to OK)
529
	 */
530
	protected function sendHttpHeader()
531
	{
532
		$protocol = $this->getRequest()->getHttpProtocolVersion();
533
		if($this->getRequest()->getHttpProtocolVersion() === null)
534
			$protocol = 'HTTP/1.1';
535
536
		header($protocol . ' ' . $this->_status . ' ' . $this->_reason, true, TPropertyValue::ensureInteger($this->_status));
537
538
		$this->_httpHeaderSent = true;
539
	}
540
541
	/**
542
	 * Ensures that the HTTP header with the status code and status reason are sent
543
	 */
544
	protected function ensureContentTypeHeaderSent()
545
	{
546
		if (!$this->_contentTypeHeaderSent)
547
			$this->sendContentTypeHeader();
548
	}
549
550
	/**
551
	 * Sends content type header with optional charset.
552
	 */
553
	protected function sendContentTypeHeader()
554
	{
555
		$contentType = $this->_contentType === null?self::DEFAULT_CONTENTTYPE:$this->_contentType;
0 ignored issues
show
introduced by
The condition $this->_contentType === null can never be true.
Loading history...
556
		$charset = $this->getCharset();
557
		if($charset === false) {
558
			$this->appendHeader('Content-Type: ' . $contentType);
559
			return;
560
		}
561
562
		if($charset === '' && ($globalization = $this->getApplication()->getGlobalization(false)) !== null)
563
			$charset = $globalization->getCharset();
564
565
		if($charset === '') $charset = self::DEFAULT_CHARSET;
566
		$this->appendHeader('Content-Type: ' . $contentType . ';charset=' . $charset);
0 ignored issues
show
Bug introduced by
Are you sure $charset of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

566
		$this->appendHeader('Content-Type: ' . $contentType . ';charset=' . /** @scrutinizer ignore-type */ $charset);
Loading history...
567
568
		$this->_contentTypeHeaderSent = true;
569
	}
570
571
	/**
572
	 * Returns the content in the output buffer.
573
	 * The buffer will NOT be cleared after calling this method.
574
	 * Use {@link clear()} is you want to clear the buffer.
575
	 * @return string output that is in the buffer.
576
	 */
577
	public function getContents()
578
	{
579
		Prado::trace("Retrieving output", 'Prado\Web\THttpResponse');
580
		return $this->_bufferOutput?ob_get_contents():'';
581
	}
582
583
	/**
584
	 * Clears any existing buffered content.
585
	 */
586
	public function clear()
587
	{
588
		if($this->_bufferOutput)
589
			ob_clean();
590
		Prado::trace("Clearing output", 'Prado\Web\THttpResponse');
591
	}
592
593
	/**
594
	 * @param integer|null Either {@link CASE_UPPER} or {@link CASE_LOWER} or as is null (default)
0 ignored issues
show
Bug introduced by
The type Prado\Web\Either was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
595
	 * @return array
596
	 */
597
	public function getHeaders($case = null)
598
	{
599
		$result = [];
600
		$headers = headers_list();
601
		foreach($headers as $header) {
602
			$tmp = explode(':', $header);
603
			$key = trim(array_shift($tmp));
604
			$value = trim(implode(':', $tmp));
605
			if(isset($result[$key]))
606
				$result[$key] .= ', ' . $value;
607
			else
608
				$result[$key] = $value;
609
		}
610
611
		if($case !== null)
612
			return array_change_key_case($result, $case);
613
614
		return $result;
615
	}
616
617
	/**
618
	 * Sends a header.
0 ignored issues
show
Bug introduced by
The type Prado\Web\header was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
619
	 * @param string header
620
	 * @param boolean whether the header should replace a previous similar header, or add a second header of the same type
621
	 */
622
	public function appendHeader($value, $replace = true)
623
	{
624
		Prado::trace("Sending header '$value'", 'Prado\Web\THttpResponse');
625
		header($value, $replace);
626
	}
627
628
	/**
629
	 * Writes a log message into error log.
630
	 * This method is simple wrapper of PHP function error_log.
631
	 * @param string The error message that should be logged
632
	 * @param integer where the error should go
0 ignored issues
show
Bug introduced by
The type Prado\Web\where was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
633
	 * @param string The destination. Its meaning depends on the message parameter as described above
634
	 * @param string The extra headers. It's used when the message parameter is set to 1. This message type uses the same internal function as mail() does.
635
	 * @see http://us2.php.net/manual/en/function.error-log.php
636
	 */
637
	public function appendLog($message, $messageType = 0, $destination = '', $extraHeaders = '')
638
	{
639
		error_log($message, $messageType, $destination, $extraHeaders);
640
	}
641
642
	/**
643
	 * Sends a cookie.
0 ignored issues
show
Bug introduced by
The type Prado\Web\cook was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
644
	 * Do not call this method directly. Operate with the result of {@link getCookies} instead.
645
	 * @param THttpCookie cook to be sent
646
	 */
647
	public function addCookie($cookie)
648
	{
649
		$request = $this->getRequest();
650
		if($request->getEnableCookieValidation())
651
		{
652
			$value = $this->getApplication()->getSecurityManager()->hashData($cookie->getValue());
653
			setcookie(
654
				$cookie->getName(),
655
				$value,
656
				$cookie->getExpire(),
657
				$cookie->getPath(),
658
				$cookie->getDomain(),
659
				$cookie->getSecure(),
660
				$cookie->getHttpOnly()
661
			);
662
		}
663
		else {
664
			setcookie(
665
				$cookie->getName(),
666
				$cookie->getValue(),
667
				$cookie->getExpire(),
668
				$cookie->getPath(),
669
				$cookie->getDomain(),
670
				$cookie->getSecure(),
671
				$cookie->getHttpOnly()
672
			);
673
		}
674
	}
675
676
	/**
677
	 * Deletes a cookie.
678
	 * Do not call this method directly. Operate with the result of {@link getCookies} instead.
679
	 * @param THttpCookie cook to be deleted
680
	 */
681
	public function removeCookie($cookie)
682
	{
683
		setcookie(
684
			$cookie->getName(),
685
			null,
686
			0,
687
			$cookie->getPath(),
688
			$cookie->getDomain(),
689
			$cookie->getSecure(),
690
			$cookie->getHttpOnly()
691
		);
692
	}
693
694
	/**
695
	 * @return string the type of HTML writer to be used, defaults to THtmlWriter
696
	 */
697
	public function getHtmlWriterType()
698
	{
699
		return $this->_htmlWriterType;
700
	}
701
702
	/**
703
	 * @param string the type of HTML writer to be used, may be the class name or the namespace
0 ignored issues
show
Bug introduced by
The type Prado\Web\the was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
704
	 */
705
	public function setHtmlWriterType($value)
706
	{
707
		$this->_htmlWriterType = $value;
708
	}
709
710
	/**
711
	 * Creates a new instance of HTML writer.
712
	 * If the type of the HTML writer is not supplied, {@link getHtmlWriterType HtmlWriterType} will be assumed.
0 ignored issues
show
Bug introduced by
The type Prado\Web\type was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
713
	 * @param string type of the HTML writer to be created. If null, {@link getHtmlWriterType HtmlWriterType} will be assumed.
714
	 */
715
	public function createHtmlWriter($type = null)
716
	{
717
		if($type === null)
718
			$type = $this->getHtmlWriterType();
719
		if($this->getHasAdapter())
720
			return $this->_adapter->createNewHtmlWriter($type, $this);
721
		else
722
			return $this->createNewHtmlWriter($type, $this);
723
	}
724
725
	/**
726
	 * Create a new html writer instance.
727
	 * This method is used internally. Please use {@link createHtmlWriter} instead.
728
	 * @param string type of HTML writer to be created.
729
	 * @param ITextWriter text writer holding the contents.
0 ignored issues
show
Bug introduced by
The type Prado\Web\text was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
730
	 */
731
	public function createNewHtmlWriter($type, $writer)
732
	{
733
		return Prado::createComponent($type, $writer);
734
	}
735
}
736
737