docs & typos
[mdref/mdref] / mdref / RefEntry.php
1 <?php
2
3 namespace mdref;
4
5 /**
6 * The RefEntry class represents a reference entry, i.e. a .md file
7 */
8 class RefEntry
9 {
10 /**
11 * @var \mdref\Path
12 */
13 protected $path;
14
15 /**
16 * @var string
17 */
18 protected $entry;
19
20 /**
21 * @var resource
22 */
23 protected $file;
24
25 /**
26 * @param \mdref\Path $path
27 * @param type $entry
28 */
29 function __construct(Path $path, $entry = null) {
30 $this->path = $path;
31 $this->entry = trim($entry ?: $path->getPathName(), DIRECTORY_SEPARATOR);
32 }
33
34 /**
35 * Clean up the file handle
36 */
37 function __destruct() {
38 if (is_resource($this->file)) {
39 fclose($this->file);
40 }
41 }
42
43 /**
44 * Format as URL
45 * @return string
46 */
47 function formatUrl() {
48 return htmlspecialchars($this->entry);
49 }
50
51 private function joinLink(array $parts) {
52 $link = "";
53 $upper = ctype_upper($parts[0][0]);;
54 for ($i = 0; $i < count($parts); ++$i) {
55 if (!strlen($parts[$i]) || $parts[$i] === ".") {
56 continue;
57 }
58 if (strlen($link)) {
59 if ($upper && !ctype_upper($parts[$i][0])) {
60 $link .= "::";
61 } else {
62 $link .= "\\";
63 }
64 }
65 $link .= $parts[$i];
66 $upper = ctype_upper($parts[$i][0]);
67 }
68 return $link;
69 }
70
71 /**
72 * Format as link text
73 * @param bool $basename whether to use the basename only
74 * @return string
75 */
76 function formatLink($basename = false) {
77 $link = "";
78 if (strlen($this->entry)) {
79 $parts = explode(DIRECTORY_SEPARATOR, $this->entry);
80 $link = $basename ? end($parts) : $this->joinLink($parts);
81 }
82 return htmlspecialchars($link);
83 }
84
85 /**
86 * Create a consolidated Path of this entry
87 * @return \mdref\Path
88 */
89 function getPath() {
90 $path = $this->path;
91 $file = $path($this->entry);
92 return $file;
93 }
94
95 private function openFile() {
96 if (!is_resource($this->file)) {
97 $file = $this->getPath();
98
99 if (!$file->isFile()) {
100 throw new \Exception("Not a file: '{$file}'");
101 }
102 if (!$this->file = fopen($file->getFullPath(".md"), "r")) {
103 throw new \Exception("Could not open {$file}");
104 }
105 }
106 }
107
108 /**
109 * Read the title of the refentry
110 * @return string
111 */
112 function readTitle() {
113 $this->openFile();
114 fseek($this->file, 1, SEEK_SET);
115 return htmlspecialchars(fgets($this->file));
116 }
117
118 /**
119 * Read the description of the refentry
120 * @return string
121 */
122 function readDescription() {
123 $this->openFile();
124 fseek($this->file, 0, SEEK_SET);
125 fgets($this->file);
126 fgets($this->file);
127 return htmlspecialchars(fgets($this->file));
128 }
129
130 /**
131 * Format a "Edit me" URL. The project reference top directory needs a
132 * »name«.mdref file besides its »name«.md entry point with the edit URL
133 * printf template as content. The sole printf argument is the relative
134 * path of the entry.
135 * @return string
136 */
137 function formatEditUrl() {
138 $path = $this->path;
139 $base = current(explode(DIRECTORY_SEPARATOR, $path->getPathName()));
140 $file = $path($base);
141 if ($file->isFile(".mdref")) {
142 return sprintf(file_get_contents($file->getFullPath(".mdref")),
143 $this->entry);
144 }
145 }
146
147 /**
148 * Recurse into the reference tree
149 * @param \mdref\Finder $refs
150 * @param string $pattern
151 * @param callable $cb
152 */
153 function recurse(Finder $refs, $pattern, callable $cb) {
154 $path = $refs->find($refs->getBaseUrl()->mod($this->entry));
155 foreach (new RefListing($path, $refs->glob($path, $pattern)) as $entry) {
156 /* @var $entry RefEntry */
157 $cb($entry, $pattern, function($entry, $pattern) use ($refs, $cb) {
158 $entry->recurse($refs, $pattern, $cb);
159 });
160 }
161 }
162 }