Skip to content

Commit c2ccc64

Browse files
committed
add cache behavior to JsonGenerator
1 parent a6a37e4 commit c2ccc64

File tree

5 files changed

+130
-63
lines changed

5 files changed

+130
-63
lines changed

src/Command/BuildDocsCommand.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,14 @@ private function generateJson()
9595
$this->io->note('Start exporting doc into json files');
9696
$this->progressBar = new ProgressBar($this->output, $this->finder->count());
9797

98-
$jsonGenerator = new JsonGenerator();
99-
$jsonGenerator->generateJson($this->builder->getDocuments()->getAll(), $this->buildContext, $this->progressBar);
98+
$jsonGenerator = new JsonGenerator($this->buildContext);
99+
$jsonGenerator->generateJson($this->builder->getDocuments()->getAll(), $this->progressBar);
100100
}
101101

102102
private function renderDocForPDF()
103103
{
104-
$htmlForPdfGenerator = new HtmlForPdfGenerator();
105-
$htmlForPdfGenerator->generateHtmlForPdf($this->builder->getDocuments()->getAll(), $this->buildContext);
104+
$htmlForPdfGenerator = new HtmlForPdfGenerator($this->buildContext);
105+
$htmlForPdfGenerator->generateHtmlForPdf($this->builder->getDocuments()->getAll());
106106
}
107107

108108
public function preBuildRender()

src/Command/CommandInitializerTrait.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,6 @@ private function startBuild()
160160
*/
161161
private function sanitizeOutputDirs(Finder $finder)
162162
{
163-
if (!$this->filesystem->exists($this->buildContext->getHtmlOutputDir())) {
164-
return;
165-
}
166-
167163
$rstFiles = array_map(
168164
function (string $rstFile) {
169165
return str_replace([$this->buildContext->getSourceDir(), '.rst'], '', $rstFile);
@@ -177,6 +173,10 @@ function (string $rstFile) {
177173

178174
private function sanitizeOutputDir(array $existingRstFiles, string $outputDir, string $format)
179175
{
176+
if (!$this->filesystem->exists($outputDir)) {
177+
return;
178+
}
179+
180180
$htmlFinder = new Finder();
181181
$htmlFinder->in($outputDir)
182182
->name('*.html');

src/Generator/GeneratorTrait.php

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,75 @@
33
namespace SymfonyDocsBuilder\Generator;
44

55
use Doctrine\RST\Environment;
6+
use Doctrine\RST\Meta\CachedMetasLoader;
67
use Doctrine\RST\Meta\MetaEntry;
8+
use Doctrine\RST\Meta\Metas;
79
use Doctrine\RST\Nodes\DocumentNode;
10+
use SymfonyDocsBuilder\BuildContext;
811

912
trait GeneratorTrait
1013
{
11-
private function extractEnvironments(array $documents): array
14+
private $buildContext;
15+
16+
/** @var Environment[] */
17+
private $environments;
18+
/** @var Metas */
19+
private $cachedMetas;
20+
21+
public function __construct(BuildContext $buildContext)
22+
{
23+
$this->buildContext = $buildContext;
24+
}
25+
26+
private function extractEnvironmentsAndCachedMetas(array $documents): void
1227
{
13-
return array_map(
28+
$this->environments = array_map(
1429
function (DocumentNode $document) {
1530
return $document->getEnvironment();
1631
},
1732
$documents
1833
);
34+
35+
if ($this->buildContext->getDisableCache()) {
36+
return;
37+
}
38+
39+
$this->cachedMetas = new Metas();
40+
$cachedMetasLoader = new CachedMetasLoader();
41+
$cachedMetasLoader->loadCachedMetaEntries($this->buildContext->getHtmlOutputDir(), $this->cachedMetas);
1942
}
2043

2144
private function getParserFilename(string $filePath, string $inputDir): string
2245
{
2346
return $parserFilename = str_replace([$inputDir.'/', '.html'], ['', ''], $filePath);
2447
}
2548

26-
private function getEnvironment(array $environments, string $parserFilename): Environment
49+
private function getEnvironment(string $parserFilename): Environment
2750
{
28-
if (!isset($environments[$parserFilename])) {
51+
if (!isset($this->environments[$parserFilename])) {
2952
throw new \LogicException(sprintf('Cannot find environment for file "%s"', $parserFilename));
3053
}
3154

32-
return $environments[$parserFilename];
55+
return $this->environments[$parserFilename];
3356
}
3457

35-
private function getMeta(array $environments, string $parserFilename): MetaEntry
58+
private function loadMetaFromCache(string $parserFilename): MetaEntry
3659
{
37-
$environment = $this->getEnvironment($environments, $parserFilename);
60+
$meta = $this->cachedMetas->get($parserFilename);
61+
62+
if (!$meta) {
63+
throw new \LogicException(sprintf('Cannot find cached meta for file "%s"', $parserFilename));
64+
}
65+
66+
return $meta;
67+
}
68+
69+
private function getMeta(string $parserFilename): MetaEntry {
70+
if ($this->useCacheForFile($parserFilename)) {
71+
return $this->loadMetaFromCache($parserFilename);
72+
}
73+
74+
$environment = $this->getEnvironment($parserFilename);
3875

3976
$allMetas = $environment->getMetas()->getAll();
4077

@@ -44,4 +81,22 @@ private function getMeta(array $environments, string $parserFilename): MetaEntry
4481

4582
return $allMetas[$parserFilename];
4683
}
84+
85+
/**
86+
* @param Environment[] $environments
87+
*/
88+
private function useCacheForFile(string $parserFilename): bool
89+
{
90+
if ($this->buildContext->getDisableCache()) {
91+
return false;
92+
}
93+
94+
// if an environment exits for the given file, it means that the file has been built from the parser
95+
// thus it was not loaded from cache.
96+
if (isset($this->environments[$parserFilename])) {
97+
return false;
98+
}
99+
100+
return true;
101+
}
47102
}

src/Generator/HtmlForPdfGenerator.php

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,37 @@ class HtmlForPdfGenerator
1111
{
1212
use GeneratorTrait;
1313

14-
public function generateHtmlForPdf(array $documents, BuildContext $buildContext) {
15-
$environments = $this->extractEnvironments($documents);
14+
public function generateHtmlForPdf(array $documents) {
15+
$this->extractEnvironmentsAndCachedMetas($documents);
1616

1717
$finder = new Finder();
18-
$finder->in($buildContext->getHtmlOutputDir())
18+
$finder->in($this->buildContext->getHtmlOutputDir())
1919
->depth(0)
20-
->notName([$buildContext->getParseSubPath(), '_images']);
20+
->notName([$this->buildContext->getParseSubPath(), '_images']);
2121

2222
$fs = new Filesystem();
2323
foreach ($finder as $file) {
2424
$fs->remove($file->getRealPath());
2525
}
2626

27-
$basePath = sprintf('%s/%s', $buildContext->getHtmlOutputDir(), $buildContext->getParseSubPath());
27+
$basePath = sprintf('%s/%s', $this->buildContext->getHtmlOutputDir(), $this->buildContext->getParseSubPath());
2828
$indexFile = sprintf('%s/%s', $basePath, 'index.html');
2929
if (!$fs->exists($indexFile)) {
3030
throw new \InvalidArgumentException(sprintf('File "%s" does not exist', $indexFile));
3131
}
3232

3333
// extracting all files from index's TOC, in the right order
34-
$parserFilename = $this->getParserFilename($indexFile, $buildContext->getHtmlOutputDir());
35-
$meta = $this->getMeta($environments, $parserFilename);
34+
$parserFilename = $this->getParserFilename($indexFile, $this->buildContext->getHtmlOutputDir());
35+
$meta = $this->getMeta($parserFilename);
3636
$files = current($meta->getTocs());
37-
array_unshift($files, sprintf('%s/index', $buildContext->getParseSubPath()));
37+
array_unshift($files, sprintf('%s/index', $this->buildContext->getParseSubPath()));
3838

3939
// building one big html file with all contents
4040
$content = '';
41-
$htmlDir = $buildContext->getHtmlOutputDir();
42-
$relativeImagesPath = str_repeat('../', substr_count($buildContext->getParseSubPath(), '/'));
41+
$htmlDir = $this->buildContext->getHtmlOutputDir();
42+
$relativeImagesPath = str_repeat('../', substr_count($this->buildContext->getParseSubPath(), '/'));
4343
foreach ($files as $file) {
44-
$meta = $this->getMeta($environments, $file);
44+
$meta = $this->getMeta($file);
4545

4646
$filename = sprintf('%s/%s.html', $htmlDir, $file);
4747
if (!$fs->exists($filename)) {
@@ -66,13 +66,13 @@ public function generateHtmlForPdf(array $documents, BuildContext $buildContext)
6666

6767
$content = sprintf(
6868
'<html><head><title>%s</title></head><body>%s</body></html>',
69-
$buildContext->getParseSubPath(),
69+
$this->buildContext->getParseSubPath(),
7070
$content
7171
);
7272

7373
$content = $this->cleanupContent($content);
7474

75-
$filename = sprintf('%s/%s.html', $htmlDir, $buildContext->getParseSubPath());
75+
$filename = sprintf('%s/%s.html', $htmlDir, $this->buildContext->getParseSubPath());
7676
file_put_contents($filename, $content);
7777
$fs->remove($basePath);
7878
}
@@ -102,7 +102,7 @@ function ($matches) use ($dir) {
102102
$fileContent
103103
);
104104
}
105-
105+
106106
private function fixInternalImages(string $fileContent, string $relativeImagesPath): string
107107
{
108108
return $fileContent = preg_replace('{src="(?:\.\./)+([^"]+?)"}', "src=\"$relativeImagesPath$1\"", $fileContent);

src/Generator/JsonGenerator.php

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
namespace SymfonyDocsBuilder\Generator;
44

55
use Doctrine\RST\Environment;
6+
use Doctrine\RST\Meta\CachedMetasLoader;
67
use Doctrine\RST\Meta\MetaEntry;
8+
use Doctrine\RST\Meta\Metas;
79
use Symfony\Component\Console\Helper\ProgressBar;
810
use Symfony\Component\DomCrawler\Crawler;
911
use Symfony\Component\Filesystem\Filesystem;
1012
use Symfony\Component\Finder\Finder;
11-
use SymfonyDocsBuilder\BuildContext;
1213

1314
/**
1415
* Class JsonGenerator
@@ -17,44 +18,55 @@ class JsonGenerator
1718
{
1819
use GeneratorTrait;
1920

20-
public function generateJson(
21-
array $documents,
22-
BuildContext $buildContext,
23-
ProgressBar $progressBar
24-
) {
25-
$environments = $this->extractEnvironments($documents);
21+
public function generateJson(array $documents, ProgressBar $progressBar)
22+
{
23+
$this->extractEnvironmentsAndCachedMetas($documents);
24+
25+
if (!$this->buildContext->getDisableCache()) {
26+
$cachedMetasLoader = new CachedMetasLoader();
27+
$cachedMetasLoader->loadCachedMetaEntries($this->buildContext->getHtmlOutputDir(), $metas = new Metas());
28+
}
2629

2730
$finder = new Finder();
28-
$finder->in($buildContext->getHtmlOutputDir())
31+
$finder->in($this->buildContext->getHtmlOutputDir())
2932
->name('*.html')
3033
->files();
3134

3235
$fs = new Filesystem();
33-
$fs->remove($buildContext->getJsonOutputDir());
3436

3537
foreach ($finder as $file) {
38+
$parserFilename = $this->getParserFilename($file->getRealPath(), $this->buildContext->getHtmlOutputDir());
39+
$jsonFilename = str_replace([$this->buildContext->getHtmlOutputDir(), '.html'], [$this->buildContext->getJsonOutputDir(), '.json'], $file->getRealPath());
3640

41+
if ($this->useCacheForFile($parserFilename)) {
42+
if (!file_exists($jsonFilename)) {
43+
throw new \RuntimeException(
44+
sprintf('File %s does not exist although cache is enabled and related environment is not available', $jsonFilename)
45+
);
46+
}
3747

38-
$crawler = new Crawler($file->getContents());
48+
continue;
49+
}
50+
51+
$meta = $this->getMeta($parserFilename);
3952

40-
$parserFilename = $this->getParserFilename($file->getRealPath(), $buildContext->getHtmlOutputDir());
41-
$meta = $this->getMeta($environments, $parserFilename);
53+
$crawler = new Crawler($file->getContents());
4254

4355
$data = [
4456
'body' => $crawler->filter('body')->html(),
4557
'title' => $meta->getTitle(),
4658
'current_page_name' => $parserFilename,
4759
'toc' => $this->generateToc($meta, current($meta->getTitles())[1]),
48-
'next' => $this->guessNext($environments, $parserFilename),
49-
'prev' => $this->guessPrev($environments, $parserFilename),
60+
'next' => $this->guessNext($parserFilename),
61+
'prev' => $this->guessPrev($parserFilename),
5062
'rellinks' => [
51-
$this->guessNext($environments, $parserFilename),
52-
$this->guessPrev($environments, $parserFilename),
63+
$this->guessNext($parserFilename),
64+
$this->guessPrev($parserFilename),
5365
],
5466
];
5567

5668
$fs->dumpFile(
57-
str_replace([$buildContext->getHtmlOutputDir(), '.html'], [$buildContext->getJsonOutputDir(), '.json'], $file->getRealPath()),
69+
$jsonFilename,
5870
json_encode($data, JSON_PRETTY_PRINT)
5971
);
6072

@@ -83,20 +95,20 @@ private function generateToc(MetaEntry $metaEntry, ?array $titles): array
8395
return $tocTree;
8496
}
8597

86-
private function guessNext(array $environments, string $parserFilename): ?array
98+
private function guessNext(string $parserFilename): ?array
8799
{
88-
$meta = $this->getMeta($environments, $parserFilename);
100+
$meta = $this->getMeta($parserFilename);
89101
$parentFile = $meta->getParent();
90102

91103
// if current file is an index, next is the first chapter
92104
if ('index' === $parentFile && \count($tocs = $meta->getTocs()) === 1 && \count($tocs[0]) > 0) {
93105
return [
94-
'title' => $this->getMeta($environments, $tocs[0][0])->getTitle(),
95-
'link' => $this->getMeta($environments, $tocs[0][0])->getUrl(),
106+
'title' => $this->getMeta($tocs[0][0])->getTitle(),
107+
'link' => $this->getMeta($tocs[0][0])->getUrl(),
96108
];
97109
}
98110

99-
list($toc, $indexCurrentFile) = $this->getNextPrevInformation($environments, $parserFilename);
111+
list($toc, $indexCurrentFile) = $this->getNextPrevInformation($parserFilename);
100112

101113
if (!isset($toc[$indexCurrentFile + 1])) {
102114
return null;
@@ -105,28 +117,28 @@ private function guessNext(array $environments, string $parserFilename): ?array
105117
$nextFileName = $toc[$indexCurrentFile + 1];
106118

107119
return [
108-
'title' => $this->getMeta($environments, $nextFileName)->getTitle(),
109-
'link' => $this->getMeta($environments, $nextFileName)->getUrl(),
120+
'title' => $this->getMeta($nextFileName)->getTitle(),
121+
'link' => $this->getMeta($nextFileName)->getUrl(),
110122
];
111123
}
112124

113-
private function guessPrev(array $environments, string $parserFilename): ?array
125+
private function guessPrev(string $parserFilename): ?array
114126
{
115-
$meta = $this->getMeta($environments, $parserFilename);
127+
$meta = $this->getMeta($parserFilename);
116128
$parentFile = $meta->getParent();
117129

118130
// no prev if parent is an index
119131
if ('index' === $parentFile) {
120132
return null;
121133
}
122134

123-
list($toc, $indexCurrentFile) = $this->getNextPrevInformation($environments, $parserFilename);
135+
list($toc, $indexCurrentFile) = $this->getNextPrevInformation($parserFilename);
124136

125137
// if current file is the first one of the chapter, prev is the direct parent
126138
if (0 === $indexCurrentFile) {
127139
return [
128-
'title' => $this->getMeta($environments, $parentFile)->getTitle(),
129-
'link' => $this->getMeta($environments, $parentFile)->getUrl(),
140+
'title' => $this->getMeta($parentFile)->getTitle(),
141+
'link' => $this->getMeta($parentFile)->getUrl(),
130142
];
131143
}
132144

@@ -137,21 +149,21 @@ private function guessPrev(array $environments, string $parserFilename): ?array
137149
$prevFileName = $toc[$indexCurrentFile - 1];
138150

139151
return [
140-
'title' => $this->getMeta($environments, $prevFileName)->getTitle(),
141-
'link' => $this->getMeta($environments, $prevFileName)->getUrl(),
152+
'title' => $this->getMeta($prevFileName)->getTitle(),
153+
'link' => $this->getMeta($prevFileName)->getUrl(),
142154
];
143155
}
144156

145-
private function getNextPrevInformation(array $environments, string $parserFilename): ?array
157+
private function getNextPrevInformation(string $parserFilename): ?array
146158
{
147-
$meta = $this->getMeta($environments, $parserFilename);
159+
$meta = $this->getMeta($parserFilename);
148160
$parentFile = $meta->getParent();
149161

150162
if (!$parentFile) {
151163
return [null, null];
152164
}
153165

154-
$metaParent = $this->getMeta($environments, $parentFile);
166+
$metaParent = $this->getMeta($parentFile);
155167

156168
if (!$metaParent->getTocs() || \count($metaParent->getTocs()) !== 1) {
157169
return [null, null];

0 commit comments

Comments
 (0)