add og:title
[mdref/mdref] / mdref / Repo.php
1 <?php
2
3 namespace mdref;
4
5
6 use InvalidArgumentException;
7 use IteratorAggregate;
8 use function basename;
9 use function current;
10 use function file_get_contents;
11 use function glob;
12 use function is_file;
13 use function realpath;
14 use function rtrim;
15 use function sprintf;
16 use function trim;
17
18 /**
19 * A reference repo
20 */
21 class Repo implements IteratorAggregate {
22 /**
23 * The name of the repository
24 * @var string
25 */
26 private $name;
27
28 /**
29 * The path to the repository
30 * @var string
31 */
32 private $path;
33
34 /**
35 * The edit url template
36 * @var ?string
37 */
38 private $editUrl;
39
40 /**
41 * Origin url
42 * @var ?string
43 */
44 private $origin;
45
46 /**
47 * Git branch
48 * @var ?string
49 */
50 private $branch;
51
52 /**
53 * Comment provider configuration
54 * @var ?object
55 */
56 private $commentProvider;
57
58 /**
59 * Path to the repository containing the name.mdref file
60 * @param string $path
61 * @throws \InvalidArgumentException
62 */
63 public function __construct(string $path) {
64 if (!($glob = glob("$path/{mdref.*,*.mdref}", GLOB_BRACE))) {
65 throw new InvalidArgumentException("Not a reference, could not find any '{mdref.*,*.mdref}': '$path'");
66 }
67
68 foreach ($glob as $mdref) {
69 switch (pathinfo($mdref, PATHINFO_EXTENSION)) {
70 case "mdref":
71 $this->name = basename($mdref, ".mdref");
72 $this->editUrl = trim(file_get_contents($mdref));
73 break;
74 case "json":
75 $json = json_decode(file_get_contents($mdref));
76 if (!isset($json->name)) {
77 throw new InvalidArgumentException("Missing key 'path' in $mdref");
78 }
79 $this->name = $json->name;
80 foreach (["origin", "branch", "editUrl", "commentProvider"] as $key) {
81 if (isset($json->$key)) {
82 $this->$key = $json->$key;
83 }
84 }
85 break;
86 default:
87 throw InvalidArgumentException("Unknown $path");
88 }
89 $this->path = realpath($path);
90 }
91 }
92
93 /**
94 * Get the repository's name
95 * @return string
96 */
97 public function getName() : string {
98 return $this->name;
99 }
100
101 /**
102 * Get the path of the repository or a file in it
103 * @param string $file
104 * @return string
105 */
106 public function getPath(string $file = "") : string {
107 return $this->path . "/$file";
108 }
109
110 /**
111 * Get the edit url for a ref entry
112 * @param string $entry
113 * @return string
114 */
115 public function getEditUrl(string $entry) : string {
116 return sprintf($this->editUrl, $entry);
117 }
118
119 /**
120 * @return ?string
121 */
122 public function getBranch() {
123 return $this->branch;
124 }
125
126 /**
127 * @return ?string
128 */
129 public function getOrigin() {
130 return $this->origin;
131 }
132
133 /**
134 * @return ?object
135 */
136 public function getCommentProvider() {
137 return $this->commentProvider;
138 }
139
140 /**
141 * Get the file path of an entry in this repo
142 *
143 * @param string $entry
144 * @param string|null $canonical
145 * @return string file path
146 */
147 public function hasEntry(string $entry, ?string &$canonical = null) : ?string {
148 $trim = rtrim($entry, "/");
149 $file = $this->getPath("$trim.md");
150 if (is_file($file)) {
151 if ($trim !== $entry) {
152 $canonical = $trim;
153 }
154 return $file;
155 }
156 $file = $this->getPath($this->getName()."/$entry.md");
157 if (is_file($file)) {
158 $canonical = $this->getName() . "/" . $entry;
159 return $file;
160 }
161 return null;
162 }
163
164 /**
165 * Get the canonical entry name of a file in this repo
166 * @param string $file
167 * @return string entry
168 */
169 public function hasFile(string $file) : ?string {
170 if (($file = realpath($file))) {
171 $path = $this->getPath();
172 $plen = strlen($path);
173 if (!strncmp($file, $path, $plen)) {
174 $dirname = dirname(substr($file, $plen));
175 $basename = basename($file, ".md");
176
177 if ($dirname === ".") {
178 return $basename;
179 }
180
181 return $dirname . "/". $basename;
182 }
183 }
184 return null;
185 }
186
187 /**
188 * Check whether the repo has a stub file to serve
189 * @param string|null $path receives the path if there's a stub
190 * @return bool
191 */
192 public function hasStub(string &$path = null) : bool {
193 $path = $this->getPath($this->getName() . ".stub.php");
194 return is_file($path) && is_readable($path);
195 }
196
197 /**
198 * Get an Entry instance
199 * @param string $entry
200 * @return \mdref\Entry
201 * @throws \OutOfBoundsException
202 */
203 public function getEntry(string $entry) : Entry {
204 return new Entry($entry, $this);
205 }
206
207 /**
208 * Get the root Entry instance
209 * @return \mdref\Entry
210 */
211 public function getRootEntry() : Entry {
212 return new Entry($this->name, $this);
213 }
214
215 /**
216 * Implements \IteratorAggregate
217 * @return \mdref\Tree
218 */
219 public function getIterator() : Tree {
220 return new Tree($this->path, $this);
221 }
222 }