running on php-7.3 now
[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 $edit;
39
40 /**
41 * Path to the repository containing the name.mdref file
42 * @param string $path
43 * @throws \InvalidArgumentException
44 */
45 public function __construct(string $path) {
46 if (!($mdref = current(glob("$path/*.mdref")))) {
47 throw new InvalidArgumentException(
48 sprintf("Not a reference, could not find '*.mdref': '%s'", $path));
49 }
50
51 $this->path = realpath($path);
52 $this->name = basename($mdref, ".mdref");
53 $this->edit = trim(file_get_contents($mdref));
54 }
55
56 /**
57 * Get the repository's name
58 * @return string
59 */
60 public function getName() : string {
61 return $this->name;
62 }
63
64 /**
65 * Get the path of the repository or a file in it
66 * @param string $file
67 * @return string
68 */
69 public function getPath(string $file = "") : string {
70 return $this->path . "/$file";
71 }
72
73 /**
74 * Get the edit url for a ref entry
75 * @param string $entry
76 * @return string
77 */
78 public function getEditUrl(string $entry) : string {
79 return sprintf($this->edit, $entry);
80 }
81
82 /**
83 * Get the file path of an entry in this repo
84 *
85 * @param string $entry
86 * @param string|null $canonical
87 * @return string file path
88 */
89 public function hasEntry(string $entry, ?string &$canonical = null) : ?string {
90 $trim = rtrim($entry, "/");
91 $file = $this->getPath("$trim.md");
92 if (is_file($file)) {
93 if ($trim !== $entry) {
94 $canonical = $trim;
95 }
96 return $file;
97 }
98 $file = $this->getPath($this->getName()."/$entry.md");
99 if (is_file($file)) {
100 $canonical = $this->getName() . "/" . $entry;
101 return $file;
102 }
103 return null;
104 }
105
106 /**
107 * Get the canonical entry name of a file in this repo
108 * @param string $file
109 * @return string entry
110 */
111 public function hasFile(string $file) : ?string {
112 if (($file = realpath($file))) {
113 $path = $this->getPath();
114 $plen = strlen($path);
115 if (!strncmp($file, $path, $plen)) {
116 $dirname = dirname(substr($file, $plen));
117 $basename = basename($file, ".md");
118
119 if ($dirname === ".") {
120 return $basename;
121 }
122
123 return $dirname . "/". $basename;
124 }
125 }
126 return null;
127 }
128
129 /**
130 * Check whether the repo has a stub file to serve
131 * @param string|null $path receives the path if there's a stub
132 * @return bool
133 */
134 public function hasStub(string &$path = null) : bool {
135 $path = $this->getPath($this->getName() . ".stub.php");
136 return is_file($path) && is_readable($path);
137 }
138
139 /**
140 * Get an Entry instance
141 * @param string $entry
142 * @return \mdref\Entry
143 * @throws \OutOfBoundsException
144 */
145 public function getEntry(string $entry) : Entry {
146 return new Entry($entry, $this);
147 }
148
149 /**
150 * Get the root Entry instance
151 * @return \mdref\Entry
152 */
153 public function getRootEntry() : Entry {
154 return new Entry($this->name, $this);
155 }
156
157 /**
158 * Implements \IteratorAggregate
159 * @return \mdref\Tree
160 */
161 public function getIterator() : Tree {
162 return new Tree($this->path, $this);
163 }
164 }