Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/diviner/publisher/DivinerStaticPublisher.php
12256 views
1
<?php
2
3
final class DivinerStaticPublisher extends DivinerPublisher {
4
5
private $publishCache;
6
private $atomNameMap;
7
8
private function getPublishCache() {
9
if (!$this->publishCache) {
10
$dir = implode(
11
DIRECTORY_SEPARATOR,
12
array(
13
$this->getConfig('root'),
14
'.divinercache',
15
$this->getConfig('name'),
16
'static',
17
));
18
$this->publishCache = new DivinerPublishCache($dir);
19
}
20
21
return $this->publishCache;
22
}
23
24
protected function loadAllPublishedHashes() {
25
return array_keys($this->getPublishCache()->getPathMap());
26
}
27
28
protected function deleteDocumentsByHash(array $hashes) {
29
$root = $this->getConfig('root');
30
$cache = $this->getPublishCache();
31
32
foreach ($hashes as $hash) {
33
$paths = $cache->getAtomPathsFromCache($hash);
34
foreach ($paths as $path) {
35
$abs = $root.DIRECTORY_SEPARATOR.$path;
36
Filesystem::remove($abs);
37
38
// If the parent directory is now empty, clean it up.
39
$dir = dirname($abs);
40
while (true) {
41
if (!Filesystem::isDescendant($dir, $root)) {
42
// Directory is outside of the root.
43
break;
44
}
45
if (Filesystem::listDirectory($dir)) {
46
// Directory is not empty.
47
break;
48
}
49
50
Filesystem::remove($dir);
51
$dir = dirname($dir);
52
}
53
}
54
55
$cache->removeAtomPathsFromCache($hash);
56
$cache->deleteAtomFromIndex($hash);
57
}
58
}
59
60
protected function createDocumentsByHash(array $hashes) {
61
$indexes = array();
62
$cache = $this->getPublishCache();
63
64
foreach ($hashes as $hash) {
65
$atom = $this->getAtomFromGraphHash($hash);
66
67
$paths = array();
68
if ($this->shouldGenerateDocumentForAtom($atom)) {
69
$content = $this->getRenderer()->renderAtom($atom);
70
71
$this->writeDocument($atom, $content);
72
73
$paths[] = $this->getAtomRelativePath($atom);
74
if ($this->getAtomSimilarIndex($atom) !== null) {
75
$index = dirname($this->getAtomRelativePath($atom)).'index.html';
76
$indexes[$index] = $atom;
77
$paths[] = $index;
78
}
79
80
$this->addAtomToIndex($hash, $atom);
81
}
82
83
$cache->addAtomPathsToCache($hash, $paths);
84
}
85
86
foreach ($indexes as $index => $atoms) {
87
// TODO: Publish disambiguation pages.
88
}
89
90
$this->publishIndex();
91
$cache->writePathMap();
92
$cache->writeIndex();
93
}
94
95
private function publishIndex() {
96
$index = $this->getPublishCache()->getIndex();
97
$refs = array();
98
99
foreach ($index as $hash => $dictionary) {
100
$refs[$hash] = DivinerAtomRef::newFromDictionary($dictionary);
101
}
102
103
$content = $this->getRenderer()->renderAtomIndex($refs);
104
105
$path = implode(
106
DIRECTORY_SEPARATOR,
107
array(
108
$this->getConfig('root'),
109
'docs',
110
$this->getConfig('name'),
111
'index.html',
112
));
113
114
Filesystem::writeFile($path, $content);
115
}
116
117
public function findAtomByRef(DivinerAtomRef $ref) {
118
if ($ref->getBook() != $this->getConfig('name')) {
119
return null;
120
}
121
122
if ($this->atomNameMap === null) {
123
$name_map = array();
124
foreach ($this->getPublishCache()->getIndex() as $hash => $dict) {
125
$name_map[$dict['name']][$hash] = $dict;
126
}
127
$this->atomNameMap = $name_map;
128
}
129
130
$name = $ref->getName();
131
if (empty($this->atomNameMap[$name])) {
132
return null;
133
}
134
135
$candidates = $this->atomNameMap[$name];
136
foreach ($candidates as $key => $dict) {
137
$candidates[$key] = DivinerAtomRef::newFromDictionary($dict);
138
if ($ref->getType()) {
139
if ($candidates[$key]->getType() != $ref->getType()) {
140
unset($candidates[$key]);
141
}
142
}
143
144
if ($ref->getContext()) {
145
if ($candidates[$key]->getContext() != $ref->getContext()) {
146
unset($candidates[$key]);
147
}
148
}
149
}
150
151
// If we have exactly one uniquely identifiable atom, return it.
152
if (count($candidates) == 1) {
153
return $this->getAtomFromNodeHash(last_key($candidates));
154
}
155
156
return null;
157
}
158
159
private function addAtomToIndex($hash, DivinerAtom $atom) {
160
$ref = $atom->getRef();
161
$ref->setIndex($this->getAtomSimilarIndex($atom));
162
$ref->setSummary($this->getRenderer()->renderAtomSummary($atom));
163
164
$this->getPublishCache()->addAtomToIndex($hash, $ref->toDictionary());
165
}
166
167
private function writeDocument(DivinerAtom $atom, $content) {
168
$root = $this->getConfig('root');
169
$path = $root.DIRECTORY_SEPARATOR.$this->getAtomRelativePath($atom);
170
171
if (!Filesystem::pathExists($path)) {
172
Filesystem::createDirectory($path, $umask = 0755, $recursive = true);
173
}
174
175
Filesystem::writeFile($path.'index.html', $content);
176
177
return $this;
178
}
179
180
private function getAtomRelativePath(DivinerAtom $atom) {
181
$ref = $atom->getRef();
182
183
$book = $ref->getBook();
184
$type = $ref->getType();
185
$context = $ref->getContext();
186
$name = $ref->getName();
187
188
$path = array(
189
'docs',
190
$book,
191
$type,
192
);
193
if ($context !== null) {
194
$path[] = $context;
195
}
196
$path[] = $name;
197
198
$index = $this->getAtomSimilarIndex($atom);
199
if ($index !== null) {
200
$path[] = '@'.$index;
201
}
202
203
$path[] = null;
204
205
return implode(DIRECTORY_SEPARATOR, $path);
206
}
207
208
}
209
210