-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathViewValues.php
More file actions
163 lines (150 loc) · 5.12 KB
/
ViewValues.php
File metadata and controls
163 lines (150 loc) · 5.12 KB
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
<?php
/**
* Класс для хранения значений, передаваемых в html-шаблон.
* При получении значений из объектов данного класса автоматически происходит замена HTML сущностей (тегов) на их эквиваленты.
*
* @example
* Пример использования:
* $v = new ViewValues();
* $v[0] = array('A&B');
* echo $v[0][0]; // A&B
* echo $v[0]->html(0); //A&B
*
* @version 1.0
* @author Илья Савинков <staliniv@gmail.com>
*/
class ViewValues extends ArrayObject{
/** @var array Кэш для отфильтрованных значений */
protected $cache = array();
/**
* Рекурсивный конструктор
*
* @param array $array
* @return ViewValues
*/
function __construct($array = array()){
foreach ($array as $key => $value){
if (is_array($value)){
$array[$key] = new self($value);
}
}
parent::__construct($array);
}
/**
* Перегрузка метода класса ArrayObject:
* возвращаемые значения фильтруются через htmlentities() и кешируются
*
* @param mixed $offset Ключ
* @return mixed Отфильтрованное значение
*/
function offsetGet($offset){
//Необходимо для простой работы с многомерными массивами в случае, если значение не было инициализировано
if (!parent::offsetExists($offset)){
$this->offsetSet($offset, new self());
//как и обычный array() - кидаем notice
$trace = debug_backtrace();
$callee = $trace[0];
trigger_error("Undefined offset: '$offset' in {$callee['file']} on line {$callee['line']}");
}
$value = parent::offsetGet($offset);
//кеширование
if (!isset($cache[$offset])){
if (is_string($value)){
$this->cache[$offset] = htmlentities($value, ENT_QUOTES, 'UTF-8');
}else{
$this->cache[$offset] = $value;
}
}
return $this->cache[$offset];
}
/**
* Возвращает значение в исходном (неотфильтрованном) виде
* Используется, когда нужно отобразить текст с html тегами, не экранируя их
*
* @param mixed $offset Ключ
* @return mixed Значение
*/
function html($offset){
return parent::offsetGet($offset);
}
/**
* Перегрузка метода класса ArrayObject::offsetSet(): добавлена очистка кеша
*
* @param mixed $offset
* @param mixed $value
* @return void
*/
function offsetSet($offset, $value){
unset($this->cache[$offset]);
if (is_array($value)){
$value = new ViewValues($value);
}
return parent::offsetSet($offset, $value);
}
/**
* Перегрузка ArrayObject::offsetUnset(): добавлена очистка кеша
*
* @param unknown_type $offset
* @return unknown
*/
function offsetUnset($offset){
unset($this->cache[$offset]);
return parent::offsetUnset($offset);
}
/**
* Возвращает массив. Только первый уровень.
* Для преобразования всего объекта в многоуровневый массив используйте getAllRec()
*
* @param bool $html Вернуть исходные значения(true) или отфильтрованные(false)
* @return array
*/
function getAll($html = false){
if ($html){
return parent::getArrayCopy();
}
//Если не все значения отфильтрованы, то наполняем кеш
if ($this->count() != count($this->cache)){
$arr = parent::getArrayCopy();
$keys = array_diff(array_keys($arr), array_keys($this->cache));
foreach ($keys as $key){
if (is_string($arr[$key])){
$this->cache[$key] = htmlentities($arr[$key], ENT_QUOTES, 'UTF-8');
}else{
$this->cache[$key] = $arr[$key];
}
}
}
return $this->cache;
}
/**
* Рекурсивно преобразует объект в многомерный отфильтрованный массив
* См. также метод getAll()
*
* @param bool $html Вернуть исходные значения(true) или отфильтрованные(false)
* @return array
*/
function getAllRec($html = false){
$result = $this->getAll($html);
foreach ($result as $key => $value){
if ($value instanceof self){
$result[$key] = $value->getAllRec();
}
}
return $result;
}
/**
* Магический метод для преобразования в строку
*
* @return string
*/
function __toString(){
return '';
}
/**
* Явный запрет на использование итератора.
* Итерирование через ArrayObject слишком медленное
*/
function getIterator(){
throw new Exception('Для итерирования преобразуйте объект ' . __CLASS__ . ' в исходный массив с помощью getAll() или getAllRec()');
}
}