Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/view/AphrontView.php
12240 views
1
<?php
2
3
/**
4
* @task children Managing Children
5
*/
6
abstract class AphrontView extends Phobject
7
implements PhutilSafeHTMLProducerInterface {
8
9
private $viewer;
10
protected $children = array();
11
12
13
/* -( Configuration )------------------------------------------------------ */
14
15
16
/**
17
* Set the user viewing this element.
18
*
19
* @param PhabricatorUser Viewing user.
20
* @return this
21
*/
22
public function setViewer(PhabricatorUser $viewer) {
23
$this->viewer = $viewer;
24
return $this;
25
}
26
27
28
/**
29
* Get the user viewing this element.
30
*
31
* Throws an exception if no viewer has been set.
32
*
33
* @return PhabricatorUser Viewing user.
34
*/
35
public function getViewer() {
36
if (!$this->viewer) {
37
throw new PhutilInvalidStateException('setViewer');
38
}
39
40
return $this->viewer;
41
}
42
43
44
/**
45
* Test if a viewer has been set on this element.
46
*
47
* @return bool True if a viewer is available.
48
*/
49
public function hasViewer() {
50
return (bool)$this->viewer;
51
}
52
53
54
/**
55
* Deprecated, use @{method:setViewer}.
56
*
57
* @task config
58
* @deprecated
59
*/
60
public function setUser(PhabricatorUser $user) {
61
return $this->setViewer($user);
62
}
63
64
65
/**
66
* Deprecated, use @{method:getViewer}.
67
*
68
* @task config
69
* @deprecated
70
*/
71
protected function getUser() {
72
if (!$this->hasViewer()) {
73
return null;
74
}
75
return $this->getViewer();
76
}
77
78
79
/* -( Managing Children )-------------------------------------------------- */
80
81
82
/**
83
* Test if this View accepts children.
84
*
85
* By default, views accept children, but subclases may override this method
86
* to prevent children from being appended. Doing so will cause
87
* @{method:appendChild} to throw exceptions instead of appending children.
88
*
89
* @return bool True if the View should accept children.
90
* @task children
91
*/
92
protected function canAppendChild() {
93
return true;
94
}
95
96
97
/**
98
* Append a child to the list of children.
99
*
100
* This method will only work if the view supports children, which is
101
* determined by @{method:canAppendChild}.
102
*
103
* @param wild Something renderable.
104
* @return this
105
*/
106
final public function appendChild($child) {
107
if (!$this->canAppendChild()) {
108
$class = get_class($this);
109
throw new Exception(
110
pht("View '%s' does not support children.", $class));
111
}
112
113
$this->children[] = $child;
114
115
return $this;
116
}
117
118
119
/**
120
* Produce children for rendering.
121
*
122
* Historically, this method reduced children to a string representation,
123
* but it no longer does.
124
*
125
* @return wild Renderable children.
126
* @task
127
*/
128
final protected function renderChildren() {
129
return $this->children;
130
}
131
132
133
/**
134
* Test if an element has no children.
135
*
136
* @return bool True if this element has children.
137
* @task children
138
*/
139
final public function hasChildren() {
140
if ($this->children) {
141
$this->children = $this->reduceChildren($this->children);
142
}
143
return (bool)$this->children;
144
}
145
146
147
/**
148
* Reduce effectively-empty lists of children to be actually empty. This
149
* recursively removes `null`, `''`, and `array()` from the list of children
150
* so that @{method:hasChildren} can more effectively align with expectations.
151
*
152
* NOTE: Because View children are not rendered, a View which renders down
153
* to nothing will not be reduced by this method.
154
*
155
* @param list<wild> Renderable children.
156
* @return list<wild> Reduced list of children.
157
* @task children
158
*/
159
private function reduceChildren(array $children) {
160
foreach ($children as $key => $child) {
161
if ($child === null) {
162
unset($children[$key]);
163
} else if ($child === '') {
164
unset($children[$key]);
165
} else if (is_array($child)) {
166
$child = $this->reduceChildren($child);
167
if ($child) {
168
$children[$key] = $child;
169
} else {
170
unset($children[$key]);
171
}
172
}
173
}
174
return $children;
175
}
176
177
public function getDefaultResourceSource() {
178
return 'phabricator';
179
}
180
181
public function requireResource($symbol) {
182
$response = CelerityAPI::getStaticResourceResponse();
183
$response->requireResource($symbol, $this->getDefaultResourceSource());
184
return $this;
185
}
186
187
public function initBehavior($name, $config = array()) {
188
Javelin::initBehavior(
189
$name,
190
$config,
191
$this->getDefaultResourceSource());
192
return $this;
193
}
194
195
196
/* -( Rendering )---------------------------------------------------------- */
197
198
199
/**
200
* Inconsistent, unreliable pre-rendering hook.
201
*
202
* This hook //may// fire before views render. It is not fired reliably, and
203
* may fire multiple times.
204
*
205
* If it does fire, views might use it to register data for later loads, but
206
* almost no datasources support this now; this is currently only useful for
207
* tokenizers. This mechanism might eventually see wider support or might be
208
* removed.
209
*/
210
public function willRender() {
211
return;
212
}
213
214
215
abstract public function render();
216
217
218
/* -( PhutilSafeHTMLProducerInterface )------------------------------------ */
219
220
221
public function producePhutilSafeHTML() {
222
return $this->render();
223
}
224
225
}
226
227