/
class.htmlpage.php
318 lines (285 loc) · 10.3 KB
/
class.htmlpage.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
<?php
/**
* @package toolkit
*/
/**
* HTMLPage extends the Page class to provide an object representation
* of a Symphony backend page.
*/
class HTMLPage extends Page
{
/**
* An XMLElement object for the `<html>` element. This is the parent
* DOM element for all other elements on the output page.
* @var XMLElement
*/
public $Html = null;
/**
* An XMLElement object for the `<head>`
* @var XMLElement
*/
public $Head = null;
/**
* An XMLElement object for the `<body>`
* @var XMLElement
*/
public $Body = null;
/**
* An XMLElement object for the `<form>`. Most Symphony backend pages
* are contained within a main form
* @var XMLElement
*/
public $Form = null;
/**
* This holds all the elements that will eventually be in the `$Head`.
* This allows extensions to add elements at certain indexes so
* resource dependancies can be met, and duplicates can be removed.
* Defaults to an empty array.
* @var array
*/
protected $_head = array();
/**
* Accessor function for `$this->_head`. Returns all the XMLElements that are
* about to be added to `$this->Head`.
*
* @since Symphony 2.3.3
* @return array
*/
public function Head()
{
return $this->_head;
}
/**
* Constructor for the HTMLPage. Intialises the class variables with
* empty instances of XMLElement
*/
public function __construct()
{
parent::__construct();
$this->Html = new XMLElement('html');
$this->Html->setIncludeHeader(false);
$this->Head = new XMLElement('head');
$this->Body = new XMLElement('body');
}
/**
* Setter function for the `<title>` of a backend page. Uses the
* `addElementToHead()` function to place into the `$this->_head` array.
* Makes sure that only one title can be set.
*
* @see addElementToHead()
* @param string $title
* @return int
* Returns the position that the title has been set in the $_head
*/
public function setTitle($title)
{
return $this->addElementToHead(
new XMLElement('title', $title),
null,
false
);
}
/**
* The generate function calls the `__build()` function before appending
* all the current page's headers and then finally calling the `$Html's`
* generate function which generates a HTML DOM from all the
* XMLElement children.
*
* @param null $page
* @return string
*/
public function generate($page = null)
{
$this->__build();
parent::generate($page);
return $this->Html->generate(true);
}
/**
* Called when page is generated, this function appends the `$Head`,
* `$Form` and `$Body` elements to the `$Html`.
*
* @see __generateHead()
*/
protected function __build()
{
$this->__generateHead();
$this->Html->appendChild($this->Head);
$this->Html->appendChild($this->Body);
}
/**
* Sorts the `$this->_head` elements by key, then appends them to the
* `$Head` XMLElement in order.
*/
protected function __generateHead()
{
ksort($this->_head);
foreach ($this->_head as $position => $obj) {
if (is_object($obj)) {
$this->Head->appendChild($obj);
}
}
}
/**
* Adds an XMLElement to the `$this->_head` array at a desired position.
* If no position is given, the object will be added to the end
* of the `$this->_head` array. If that position is already taken, it will
* add the object at the next available position.
*
* @see toolkit.General#array_find_available_index()
* @param XMLElement $object
* @param integer $position
* Defaults to null which will put the `$object` at the end of the
* `$this->_head`.
* @param boolean $allowDuplicate
* If set to false, make this function check if there is already an XMLElement that as the same name in the head.
* Defaults to true. @since Symphony 2.3.2
* @return integer
* Returns the position that the `$object` has been set in the `$this->_head`
*/
public function addElementToHead(XMLElement $object, $position = null, $allowDuplicate = true)
{
// find the right position
if (($position && isset($this->_head[$position]))) {
$position = General::array_find_available_index($this->_head, $position);
} elseif (is_null($position)) {
if (count($this->_head) > 0) {
$position = max(array_keys($this->_head))+1;
} else {
$position = 0;
}
}
// check if we allow duplicate
if (!$allowDuplicate && !empty($this->_head)) {
$this->removeFromHead($object->getName());
}
// append new element
$this->_head[$position] = $object;
return $position;
}
/**
* Given an elementName, this function will remove the corresponding
* XMLElement from the `$this->_head`
*
* @param string $elementName
*/
public function removeFromHead($elementName)
{
foreach ($this->_head as $position => $element) {
if ($element->getName() !== $elementName) {
continue;
}
$this->removeFromHeadByPosition($position);
}
}
/**
* Removes an item from `$this->_head` by it's index.
*
* @since Symphony 2.3.3
* @param integer $position
*/
public function removeFromHeadByPosition($position)
{
if (isset($position, $this->_head[$position])) {
unset($this->_head[$position]);
}
}
/**
* Determines if two elements are duplicates based on an attribute and value
*
* @param string $path
* The value of the attribute
* @param string $attribute
* The attribute to check
* @return boolean
*/
public function checkElementsInHead($path, $attribute)
{
foreach ($this->_head as $element) {
if (basename($element->getAttribute($attribute)) == basename($path)) {
return true;
}
}
return false;
}
/**
* Convenience function to add a `<script>` element to the `$this->_head`. By default
* the function will allow duplicates to be added to the `$this->_head`. A duplicate
* is determined by if the `$path` is unique.
*
* @param string $path
* The path to the script file
* @param integer $position
* The desired position that the resulting XMLElement will be placed
* in the `$this->_head`. Defaults to null which will append to the end.
* @param boolean $duplicate
* When set to false the function will only add the script if it doesn't
* already exist. Defaults to true which allows duplicates.
* @return integer
* Returns the position that the script has been set in the `$this->_head`
*/
public function addScriptToHead($path, $position = null, $duplicate = true)
{
if ($duplicate === true || ($duplicate === false && $this->checkElementsInHead($path, 'src') === false)) {
$script = new XMLElement('script');
$script->setSelfClosingTag(false);
$script->setAttributeArray(array('type' => 'text/javascript', 'src' => $path));
return $this->addElementToHead($script, $position);
}
}
/**
* Convenience function to add a stylesheet to the `$this->_head` in a `<link>` element.
* By default the function will allow duplicates to be added to the `$this->_head`.
* A duplicate is determined by if the `$path` is unique.
*
* @param string $path
* The path to the stylesheet file
* @param string $type
* The media attribute for this stylesheet, defaults to 'screen'
* @param integer $position
* The desired position that the resulting XMLElement will be placed
* in the `$this->_head`. Defaults to null which will append to the end.
* @param boolean $duplicate
* When set to false the function will only add the script if it doesn't
* already exist. Defaults to true which allows duplicates.
* @return integer
* Returns the position that the stylesheet has been set in the `$this->_head`
*/
public function addStylesheetToHead($path, $type = 'screen', $position = null, $duplicate = true)
{
if ($duplicate === true || ($duplicate === false && $this->checkElementsInHead($path, 'href') === false)) {
$link = new XMLElement('link');
$link->setAttributeArray(array('rel' => 'stylesheet', 'type' => 'text/css', 'media' => $type, 'href' => $path));
return $this->addElementToHead($link, $position);
}
}
/**
* This function builds a HTTP query string from `$_GET` parameters with
* the option to remove parameters with an `$exclude` array. Since Symphony 2.6.0
* it is also possible to override the default filters on the resulting string.
*
* @link http://php.net/manual/en/filter.filters.php
* @param array $exclude
* A simple array with the keys that should be omitted in the resulting
* query string.
* @param integer $filters
* The resulting query string is parsed through `filter_var`. By default
* the options are FILTER_FLAG_STRIP_LOW, FILTER_FLAG_STRIP_HIGH and
* FILTER_SANITIZE_STRING, but these can be overridden as desired.
* @return string
*/
public function __buildQueryString(array $exclude = array(), $filters = null)
{
$exclude[] = 'page';
if (is_null($filters)) {
$filters = FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_SANITIZE_STRING;
}
// Generate the full query string and then parse it back to an array
$pre_exclusion = http_build_query($_GET, null, '&');
parse_str($pre_exclusion, $query);
// Remove the excluded keys from query string and then build
// the query string again
$post_exclusion = array_diff_key($query, array_fill_keys($exclude, true));
$query = http_build_query($post_exclusion, null, '&');
return filter_var(urldecode($query), $filters);
}
}