152ba47232c38f9a2e8a2d6c25c494d5b9ef0047
6 use function array_pop
;
8 use function ctype_lower
;
9 use function ctype_upper
;
20 * A single reference entry
22 class Entry
implements IteratorAggregate
{
36 * The containing repository
42 * The file path, if the refentry exists
48 * The file instance of this entry
54 * @param string $name the compound name of the ref entry, e.g. "pq/Connection/exec"
55 * @param Repo $repo the containing repository
57 public function __construct(string $name, Repo
$repo) {
60 $this->list = explode("/", $name);
61 $this->path
= $repo->hasEntry($name);
65 * Get the compound name, e.g. "pq/Connection/exec"
68 public function getName() : string {
73 * Get the containing repository
76 public function getRepo() : Repo
{
81 * Get the file path, if any
84 public function getPath() : ?
string {
89 * Get the file instance of this entry
94 public function getFile() : File
{
96 $this->file
= new File($this->path
);
105 public function getEditUrl() : string {
106 return $this->repo
->getEditUrl($this->name
);
110 * Read the title of the ref entry file
115 public function getTitle() : string {
116 if ($this->isFile()) {
117 return trim($this->getFile()->readTitle());
119 if ($this->isRoot()) {
120 return trim($this->repo
->getRootEntry()->getTitle());
126 * Read the first line of the description of the ref entry file
131 public function getDescription() : string {
132 if ($this->isFile()) {
133 return trim($this->getFile()->readDescription());
135 if ($this->isRoot()) {
136 return trim($this->repo
->getRootEntry()->getDescription());
142 * Read the full description of the ref entry file
147 public function getFullDescription() : string {
148 if ($this->isFile()) {
149 return trim($this->getFile()->readFullDescription());
151 if ($this->isRoot()) {
152 return trim($this->repo
->getRootEntry()->getFullDescription());
158 * Read the intriductory section of the refentry file
163 public function getIntro() : string {
164 if ($this->isFile()) {
165 return trim($this->getFile()->readIntro());
167 if ($this->isRoot()) {
168 return trim($this->repo
->getRootEntry()->getIntro());
174 * Check if the refentry exists
177 public function isFile() : bool {
178 return strlen($this->path
) > 0;
182 * Check if this is the first entry of the reference tree
185 public function isRoot() : bool {
186 return count($this->list) === 1;
190 * Get the parent ref entry
191 * @return \mdref\Entry
193 public function getParent() : ?Entry
{
194 switch ($dirn = dirname($this->name
)) {
199 return $this->repo
->getEntry($dirn);
204 * Get the list of parents up-down
207 public function getParents() : array {
209 for ($parent = $this->getParent(); $parent; $parent = $parent->getParent()) {
210 array_unshift($parents, $parent);
216 * Guess whether this ref entry is about a function or method
219 public function isFunction() : bool {
220 $base = end($this->list);
221 return $base[0] === "_" ||
ctype_lower($base[0]);
225 * Guess whether this ref entry is about a namespace, interface or class
228 public function isNsClass() : bool {
229 $base = end($this->list);
230 return ctype_upper($base[0]);
236 public function getEntryName() {
237 return end($this->list);
241 * Get namespaced name
244 public function getNsName() : string {
245 if ($this->isRoot()) {
246 return $this->getName();
247 } elseif ($this->isFunction()) {
248 $parts = explode("/", trim($this->getName(), "/"));
249 $self = array_pop($parts);
250 return implode("\\", $parts) . "::" . $self;
252 return strtr($this->getName(), "/", "\\");
260 public function __toString() : string {
261 $parts = explode("/", trim($this->getName(), "/"));
262 $myself = array_pop($parts);
266 $parent = end($parts);
268 switch ($myself[0]) {
270 return "★" . substr($myself, 1);
273 if (!ctype_lower($myself[0]) ||
ctype_lower($parent[0])) {
277 return $parent . "::" . $myself;
282 * Get the dirname for child entries
285 public function getNextDirname() : string {
286 return dirname($this->path
) . "/" . basename($this->path
, ".md");
290 * Guess whether there are any child nodes
291 * @param string $glob
295 function hasIterator(?
string $glob = null, bool $loose = false) : bool {
297 return glob($this->getNextDirname() . "/$glob") ||
298 ($loose && glob($this->getNextDirname() . "/*/$glob"));
299 } elseif ($this->isRoot()) {
301 } elseif ($this->getNextDirname() !== "/") {
302 return is_dir($this->getNextDirname());
309 * Guess whether there are namespace/interface/class child nodes
312 function hasNsClasses() : bool {
313 return $this->hasIterator("/[A-Z]*.md", true);
317 * Guess whether there are function/method child nodes
320 function hasFunctions() : bool {
321 return $this->hasIterator("/[a-z_]*.md");
325 * Implements IteratorAggregate
326 * @return Tree child nodes
328 function getIterator() : Tree
{
329 return new Tree($this->getNextDirname(), $this->repo
);
333 * Get the structure of the refentry
336 function getStructure() : Structure
{
337 return new Structure($this);