fix ignore refs
[mdref/mdref] / mdref / Entry.php
1 <?php
2
3 namespace mdref;
4
5 /**
6 * A single reference entry
7 */
8 class Entry implements \IteratorAggregate {
9 /**
10 * Compound name
11 * @var string
12 */
13 private $name;
14
15 /**
16 * Split name
17 * @var array
18 */
19 private $list;
20
21 /**
22 * The containing repository
23 * @var \mdref\Repo
24 */
25 private $repo;
26
27 /**
28 * The file path, if the refentry exists
29 * @var type
30 */
31 private $path;
32
33 /**
34 * The file instance of this entry
35 * @var \mdref\File
36 */
37 private $file;
38
39 /**
40 * @param string $name the compound name of the ref entry, e.g. "pq/Connection/exec"
41 * @param \mdref\Repo $repo the containing repository
42 */
43 public function __construct($name, Repo $repo) {
44 $this->repo = $repo;
45 $this->name = $name;
46 $this->list = explode("/", $name);
47 $this->path = $repo->hasEntry($name);
48 }
49
50 /**
51 * Get the compound name, e.g. "pq/Connection/exec"
52 * @return string
53 */
54 public function getName() {
55 return $this->name;
56 }
57
58 /**
59 * Get the containing repository
60 * @return \mdref\Repo
61 */
62 public function getRepo() {
63 return $this->repo;
64 }
65
66 /**
67 * Get the file path, if any
68 * @return string
69 */
70 public function getPath() {
71 return $this->path;
72 }
73
74 /**
75 * Get the file instance of this entry
76 * @return \mdref\File
77 */
78 public function getFile() {
79 if (!$this->file) {
80 $this->file = new File($this->path);
81 }
82 return $this->file;
83 }
84
85 /**
86 * Get edit URL
87 * @return string
88 */
89 public function getEditUrl() {
90 return $this->repo->getEditUrl($this->name);
91 }
92
93 /**
94 * Read the title of the ref entry file
95 * @return string
96 */
97 public function getTitle() {
98 if ($this->isFile()) {
99 return trim($this->getFile()->readTitle());
100 }
101 if ($this->isRoot()) {
102 return trim($this->repo->getRootEntry()->getTitle());
103 }
104 return $this->name;
105 }
106
107 /**
108 * Read the first line of the description of the ref entry file
109 * @return string
110 */
111 public function getDescription() {
112 if ($this->isFile()) {
113 return trim($this->getFile()->readDescription());
114 }
115 if ($this->isRoot()) {
116 return trim($this->repo->getRootEntry()->getDescription());
117 }
118 return $this;
119 }
120
121 /**
122 * Read the full description of the ref entry file
123 * @return string
124 */
125 public function getFullDescription() {
126 if ($this->isFile()) {
127 return trim($this->getFile()->readFullDescription());
128 }
129 if ($this->isRoot()) {
130 return trim($this->repo->getRootEntry()->getFullDescription());
131 }
132 return $this;
133 }
134
135 /**
136 * Read the intriductory section of the refentry file
137 * @return string
138 */
139 public function getIntro() {
140 if ($this->isFile()) {
141 return trim($this->getFile()->readIntro());
142 }
143 if ($this->isRoot()) {
144 return trim($this->repo->getRootEntry()->getIntro());
145 }
146 return "";
147 }
148
149 /**
150 * Check if the refentry exists
151 * @return bool
152 */
153 public function isFile() {
154 return strlen($this->path) > 0;
155 }
156
157 /**
158 * Check if this is the first entry of the reference tree
159 * @return bool
160 */
161 public function isRoot() {
162 return count($this->list) === 1;
163 }
164
165 /**
166 * Get the parent ref entry
167 * @return \mdref\Entry
168 */
169 public function getParent() {
170 switch ($dirn = dirname($this->name)) {
171 case ".":
172 case "/":
173 break;
174 default:
175 return $this->repo->getEntry($dirn);
176 }
177 }
178
179 /**
180 * Get the list of parents up-down
181 * @return array
182 */
183 public function getParents() {
184 $parents = array();
185 for ($parent = $this->getParent(); $parent; $parent = $parent->getParent()) {
186 array_unshift($parents, $parent);
187 }
188 return $parents;
189 }
190
191 /**
192 * Guess whether this ref entry is about a function or method
193 * @return bool
194 */
195 public function isFunction() {
196 $base = end($this->list);
197 return $base{0} === "_" || ctype_lower($base{0});
198 }
199
200 /**
201 * Guess whether this ref entry is about a namespace, interface or class
202 * @return bool
203 */
204 public function isNsClass() {
205 $base = end($this->list);
206 return ctype_upper($base{0});
207 }
208
209 public function getEntryName() {
210 return end($this->list);
211 }
212
213 public function getNsName() {
214 if ($this->isRoot()) {
215 return $this->getName();
216 } elseif ($this->isFunction()) {
217 $parts = explode("/", trim($this->getName(), "/"));
218 $self = array_pop($parts);
219 return implode("\\", $parts) . "::" . $self;
220 } else {
221 return strtr($this->getName(), "/", "\\");
222 }
223 }
224
225 /**
226 * Display name
227 * @return string
228 */
229 public function __toString() {
230 $parts = explode("/", trim($this->getName(), "/"));
231 $myself = array_pop($parts);
232 if (!$parts) {
233 return $myself;
234 }
235 $parent = end($parts);
236
237 switch ($myself{0}) {
238 case ":":
239 return "★" . substr($myself, 1);
240
241 default:
242 if (!ctype_lower($myself{0}) || ctype_lower($parent{0})) {
243 return $myself;
244 }
245 case "_":
246 return $parent . "::" . $myself;
247 }
248 }
249
250 /**
251 * Get the base name of this ref entry
252 * @return string
253 */
254 public function getBasename() {
255 return dirname($this->path) . "/" . basename($this->path, ".md");
256 }
257
258 /**
259 * Guess whether there are any child nodes
260 * @param string $glob
261 * @return boolean
262 */
263 function hasIterator($glob = null, $loose = false) {
264 if (strlen($glob)) {
265 return glob($this->getBasename() . "/$glob") ||
266 ($loose && glob($this->getBasename() . "/*/$glob"));
267 } elseif ($this->isRoot()) {
268 return true;
269 } elseif ($this->getBasename() !== "/") {
270 return is_dir($this->getBasename());
271 } else {
272 return false;
273 }
274 }
275
276 /**
277 * Guess whether there are namespace/interface/class child nodes
278 * @return bool
279 */
280 function hasNsClasses() {
281 return $this->hasIterator("/[A-Z]*.md", true);
282 }
283
284 /**
285 * Guess whether there are function/method child nodes
286 * @return bool
287 */
288 function hasFunctions() {
289 return $this->hasIterator("/[a-z_]*.md");
290 }
291
292 /**
293 * Implements \IteratorAggregate
294 * @return \mdref\Tree child nodes
295 */
296 function getIterator() {
297 return new Tree($this->getBasename(), $this->repo);
298 }
299
300 function getStructure() {
301 return new Structure($this);
302 }
303 }