587cd1e8a33122b3f44e69b78b884a912b1c9208
[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 * Read the title of the ref entry file
87 * @return string
88 */
89 public function getTitle() {
90 if ($this->isFile()) {
91 return $this->getFile()->readTitle();
92 }
93 if ($this->isRoot()) {
94 return $this->repo->getRootEntry()->getTitle();
95 }
96 return $this->name;
97 }
98
99 /**
100 * Read the description of the ref entry file
101 * @return string
102 */
103 public function getDescription() {
104 if ($this->isFile()) {
105 return $this->getFile()->readDescription();
106 }
107 if ($this->isRoot()) {
108 return $this->repo->getRootEntry()->getDescription();
109 }
110 return $this;
111 }
112
113 /**
114 * Read the intriductory section of the refentry file
115 * @return string
116 */
117 public function getIntro() {
118 if ($this->isFile()) {
119 return $this->getFile()->readIntro();
120 }
121 if ($this->isRoot()) {
122 return $this->repo->getRootEntry()->getIntro();
123 }
124 return "";
125 }
126
127 /**
128 * Check if the refentry exists
129 * @return bool
130 */
131 public function isFile() {
132 return strlen($this->path) > 0;
133 }
134
135 /**
136 * Check if this is the first entry of the reference tree
137 * @return bool
138 */
139 public function isRoot() {
140 return count($this->list) === 1;
141 }
142
143 /**
144 * Get the parent ref entry
145 * @return \mdref\Entry
146 */
147 public function getParent() {
148 if ("." !== ($dirn = dirname($this->name))) {
149 return $this->repo->getEntry($dirn);
150 }
151 }
152
153 /**
154 * Get the list of parents up-down
155 * @return array
156 */
157 public function getParents() {
158 $parents = array();
159 for ($parent = $this->getParent(); $parent; $parent = $parent->getParent()) {
160 array_unshift($parents, $parent);
161 }
162 return $parents;
163 }
164
165 /**
166 * Guess whether this ref entry is about a function or method
167 * @return bool
168 */
169 public function isFunction() {
170 $base = end($this->list);
171 return $base{0} === "_" || ctype_lower($base{0});
172 }
173
174 /**
175 * Guess whether this ref entry is about a namespace, interface or class
176 * @return bool
177 */
178 public function isNsClass() {
179 $base = end($this->list);
180 return ctype_upper($base{0});
181 }
182
183 /**
184 * Display name
185 * @return string
186 */
187 public function __toString() {
188 $parts = explode("/", trim($this->getName(), "/"));
189 $myself = array_pop($parts);
190 if (!$parts) {
191 return $myself;
192 }
193 $parent = end($parts);
194
195 switch ($myself{0}) {
196 case ":":
197 return "★" . substr($myself, 1);
198
199 default:
200 if (!ctype_lower($myself{0}) || ctype_lower($parent{0})) {
201 return $myself;
202 }
203 case "_":
204 return $parent . "::" . $myself;
205 }
206 }
207
208 /**
209 * Get the base name of this ref entry
210 * @return string
211 */
212 public function getBasename() {
213 return dirname($this->path) . "/" . basename($this->path, ".md");
214 }
215
216 /**
217 * Guess whether there are any child nodes
218 * @param string $glob
219 * @return boolean
220 */
221 function hasIterator($glob = null) {
222 if (strlen($glob)) {
223 return glob($this->getBasename() . "/$glob");
224 } elseif ($this->isRoot()) {
225 return true;
226 } else {
227 return is_dir($this->getBasename());
228 }
229 }
230
231 /**
232 * Guess whether there are namespace/interface/class child nodes
233 * @return bool
234 */
235 function hasNsClasses() {
236 return $this->hasIterator("/[A-Z]*.md");
237 }
238
239 /**
240 * Guess whether there are function/method child nodes
241 * @return bool
242 */
243 function hasFunctions() {
244 return $this->hasIterator("/[a-z_]*.md");
245 }
246
247 /**
248 * Implements \IteratorAggregate
249 * @return \mdref\Tree child nodes
250 */
251 function getIterator() {
252 return new Tree($this->getBasename(), $this->repo, $this->isRoot());
253 }
254 }