Passed
Pull Request — master (#1005)
by Fabio
17:26 queued 11:05
created

THttpHeadersManager   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 95
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 32
c 1
b 0
f 0
dl 0
loc 95
rs 10
wmc 16

6 Methods

Rating   Name   Duplication   Size   Complexity  
A sendHeaders() 0 6 2
B loadHeaders() 0 19 7
A ensureHeadersSent() 0 4 2
A buildHeader() 0 12 3
A init() 0 4 1
A getDefaultMappingClass() 0 3 1
1
<?php
2
3
/**
4
 * THttpHeadersManager class file
5
 *
6
 * @author Fabio Bas <ctrlaltca[at]gmail[dot]com>
7
 * @link https://github.com/pradosoft/prado
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 */
10
11
namespace Prado\Web;
12
13
use Prado\Exceptions\TConfigurationException;
14
use Prado\Prado;
15
use Prado\TApplication;
16
use Prado\TPropertyValue;
17
use Prado\Xml\TXmlDocument;
18
use Prado\Xml\TXmlElement;
19
20
/**
21
 * THttpHeadersManager class
22
 *
23
 * THttpHeadersManager is a module that can be used to provide
24
 * additional custom headers to be sent alongside responses.
25
 *
26
 * By default, {@see \Prado\Web\THttpResponse} doesn't use any THttpHeadersManager.
27
 * If you want to use your customized headers manager, load your manager class
28
 * as an application module and set {@see \Prado\Web\THttpResponse::setHeadersManager() THttpResponse.HeadersManager}
29
 * with the ID of your URL manager module:
30
 *
31
 * ```xml
32
 * <module id="headers" class="THttpHeadersManager">
33
 *   <header Name="Strict-Transport-Security" Value="max-age=31536000" />
34
 *   <header Name="X-Content-Type-Options" Value="nosniff" />
35
 *   <header Name="X-Frame-Options" Value="DENY" />
36
 * </module>
37
 * <module id="response" class="THttpResponse" HeadersManager="headers" />
38
 * ```
39
 *
40
 * @author Fabio Bas <ctrlaltca[at]gmail[dot]com>
41
 * @since 4.3.2
42
 */
43
class THttpHeadersManager extends \Prado\TModule
44
{
45
	/**
46
	 * @var THttpHeader[] list of key:value headers.
47
	 */
48
	protected $_headers = [];
49
50
	/**
51
	 * @var bool whether headers has been sent
52
	 */
53
	private $_headersSent;
54
55
	private $_defaultMappingClass = \Prado\Web\THttpHeader::class;
56
57
	/**
58
	 * Initializes this module.
59
	 * This method is required by the IModule interface.
60
	 * @param mixed $config configuration for this module, can be null
61
	 */
62
	public function init($config)
63
	{
64
		parent::init($config);
65
		$this->loadHeaders($config);
66
	}
67
68
	/**
69
	 * @return string the default class of headers. Defaults to THttpHeader.
70
	 * @since 3.1.1
71
	 */
72
	public function getDefaultMappingClass()
73
	{
74
		return $this->_defaultMappingClass;
75
	}
76
77
	/**
78
	 * Load and configure each header.
79
	 * @param mixed $config configuration node
80
	 * @throws TConfigurationException if specific header class is invalid
81
	 */
82
	protected function loadHeaders($config)
83
	{
84
		$defaultClass = $this->getDefaultMappingClass();
85
86
		if (is_array($config)) {
87
			if (isset($config['urls']) && is_array($config['urls'])) {
88
				foreach ($config['urls'] as $header) {
89
					$class = $header['class'] ?? $defaultClass;
90
					$properties = $header['properties'] ?? [];
91
					$this->buildHeader($class, $properties, $header);
92
				}
93
			}
94
		} else {
95
			foreach ($config->getElementsByTagName('header') as $header) {
96
				$properties = $header->getAttributes();
97
				if (($class = $properties->remove('class')) === null) {
98
					$class = $defaultClass;
99
				}
100
				$this->buildHeader($class, $properties, $header);
101
			}
102
		}
103
	}
104
105
	private function buildHeader($class, $properties, $config)
106
	{
107
		$header = Prado::createComponent($class, $this);
108
		if (!($header instanceof THttpHeader)) {
109
			throw new TConfigurationException('httpheadersmanager_header_required');
110
		}
111
		foreach ($properties as $name => $value) {
112
			$header->setSubproperty($name, $value);
113
		}
114
115
		$this->_headers[] = $header;
116
		$header->init($config);
117
	}
118
119
	/**
120
	 * Ensures that custom headers are sent by the module
121
	 */
122
	public function ensureHeadersSent()
123
	{
124
		if (!$this->_headersSent) {
125
			$this->sendHeaders();
126
		}
127
	}
128
129
	/**
130
	 * Send the HTTP headers
131
	 */
132
	protected function sendHeaders()
133
	{
134
		foreach ($this->_headers as $header) {
135
			$this->getResponse()->appendHeader($header->getName() . ': ' . $header->getValue());
136
		}
137
		$this->_headersSent = true;
138
	}
139
}
140