Skip to content

Commit a9f3305

Browse files
authored
Merge pull request #802 from phpDocumentor/feature/load-composer-json
[FEATURE] Load data from composer.json if present
2 parents 6f9742e + df864d0 commit a9f3305

File tree

8 files changed

+223
-3
lines changed

8 files changed

+223
-3
lines changed

composer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
},
1515
"sort-packages": true
1616
},
17+
"support": {
18+
"issues": "https://github.com/phpDocumentor/guides/issues",
19+
"source": "https://github.com/phpDocumentor/guides",
20+
"docs": "https://docs.phpdoc.org/3.0/guide/guides/index.html"
21+
},
1722
"autoload-dev": {
1823
"psr-4": {
1924
"phpDocumentor\\Guides\\": ["packages/guides/tests/unit/", "tests/"],

docs/index.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,23 @@
66
dev-main
77

88
====================
9-
phpDocumentor Guides
9+
|project|
1010
====================
1111

1212
This library can be used for rendering of
1313
`reStructuredText Markup <https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html>`__ and
1414
`Markdown <https://daringfireball.net/projects/markdown/>`__.
1515

16+
Description
17+
|composer_description|
18+
Source
19+
|composer_support_source|
20+
Report issues
21+
|composer_support_issues|
22+
Latest public documentation
23+
|composer_support_docs|
24+
25+
1626
Tip: Render this documentation
1727
==============================
1828

packages/guides-cli/src/Command/Run.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use phpDocumentor\Guides\Event\PostCollectFilesForParsingEvent;
1717
use phpDocumentor\Guides\Event\PostParseDocument;
1818
use phpDocumentor\Guides\Event\PostParseProcess;
19+
use phpDocumentor\Guides\Event\PostProjectNodeCreated;
1920
use phpDocumentor\Guides\Event\PostRenderDocument;
2021
use phpDocumentor\Guides\Event\PostRenderProcess;
2122
use phpDocumentor\Guides\Event\PreParseDocument;
@@ -41,6 +42,7 @@
4142
use Symfony\Component\EventDispatcher\EventDispatcher;
4243

4344
use function array_pop;
45+
use function assert;
4446
use function count;
4547
use function getcwd;
4648
use function implode;
@@ -199,7 +201,7 @@ static function (PostRenderProcess $event) use ($renderingProgressBar, $renderin
199201
);
200202
}
201203

202-
private function getSettingsOverridenWithInput(InputInterface $input): ProjectSettings
204+
private function getSettingsOverriddenWithInput(InputInterface $input): ProjectSettings
203205
{
204206
$settings = $this->settingsManager->getProjectSettings();
205207

@@ -249,7 +251,7 @@ private function getSettingsOverridenWithInput(InputInterface $input): ProjectSe
249251

250252
protected function execute(InputInterface $input, OutputInterface $output): int
251253
{
252-
$settings = $this->getSettingsOverridenWithInput($input);
254+
$settings = $this->getSettingsOverriddenWithInput($input);
253255
$inputDir = $this->getAbsolutePath($settings->getInput());
254256
if (!is_dir($inputDir)) {
255257
throw new RuntimeException(sprintf('Input directory "%s" was not found! ' . "\n" .
@@ -264,6 +266,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
264266
$this->clock->now(),
265267
);
266268

269+
$event = new PostProjectNodeCreated($projectNode, $settings);
270+
$event = $this->eventDispatcher->dispatch($event);
271+
assert($event instanceof PostProjectNodeCreated);
272+
$projectNode = $event->getProjectNode();
273+
$settings = $event->getSettings();
274+
267275
$outputDir = $this->getAbsolutePath($settings->getOutput());
268276
$sourceFileSystem = new Filesystem(new Local($settings->getInput()));
269277
$sourceFileSystem->addPlugin(new Finder());

packages/guides/resources/config/guides.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use phpDocumentor\Guides\Compiler\NodeTransformers\CustomNodeTransformerFactory;
1111
use phpDocumentor\Guides\Compiler\NodeTransformers\MenuNodeTransformers\InternalMenuEntryNodeTransformer;
1212
use phpDocumentor\Guides\Compiler\NodeTransformers\NodeTransformerFactory;
13+
use phpDocumentor\Guides\Event\PostProjectNodeCreated;
14+
use phpDocumentor\Guides\EventListener\LoadSettingsFromComposer;
1315
use phpDocumentor\Guides\NodeRenderers\Html\BreadCrumbNodeRenderer;
1416
use phpDocumentor\Guides\NodeRenderers\Html\DocumentNodeRenderer;
1517
use phpDocumentor\Guides\NodeRenderers\Html\MenuEntryRenderer;
@@ -47,6 +49,7 @@
4749
use phpDocumentor\Guides\Renderer\UrlGenerator\ConfigurableUrlGenerator;
4850
use phpDocumentor\Guides\Renderer\UrlGenerator\RelativeUrlGenerator;
4951
use phpDocumentor\Guides\Renderer\UrlGenerator\UrlGeneratorInterface;
52+
use phpDocumentor\Guides\Settings\ComposerSettingsLoader;
5053
use phpDocumentor\Guides\Settings\SettingsManager;
5154
use phpDocumentor\Guides\TemplateRenderer;
5255
use phpDocumentor\Guides\Twig\AssetsExtension;
@@ -217,6 +220,11 @@
217220
param('phpdoc.guides.base_template_paths'),
218221
)
219222

223+
->set(LoadSettingsFromComposer::class)
224+
->tag('event_listener', ['event' => PostProjectNodeCreated::class])
225+
226+
->set(ComposerSettingsLoader::class)
227+
220228
->set(EnvironmentBuilder::class)
221229
->arg('$extensions', tagged_iterator('twig.extension'))
222230
->arg('$themeManager', service(ThemeManager::class))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Guides\Event;
6+
7+
use phpDocumentor\Guides\Nodes\ProjectNode;
8+
use phpDocumentor\Guides\Settings\ProjectSettings;
9+
10+
final class PostProjectNodeCreated
11+
{
12+
public function __construct(
13+
private ProjectNode $projectNode,
14+
private ProjectSettings $settings,
15+
) {
16+
}
17+
18+
public function getProjectNode(): ProjectNode
19+
{
20+
return $this->projectNode;
21+
}
22+
23+
public function setProjectNode(ProjectNode $projectNode): void
24+
{
25+
$this->projectNode = $projectNode;
26+
}
27+
28+
public function getSettings(): ProjectSettings
29+
{
30+
return $this->settings;
31+
}
32+
33+
public function setSettings(ProjectSettings $settings): void
34+
{
35+
$this->settings = $settings;
36+
}
37+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Guides\EventListener;
6+
7+
use phpDocumentor\Guides\Event\PostProjectNodeCreated;
8+
use phpDocumentor\Guides\Settings\ComposerSettingsLoader;
9+
10+
use function dirname;
11+
use function file_exists;
12+
use function getcwd;
13+
use function is_string;
14+
15+
final class LoadSettingsFromComposer
16+
{
17+
public function __construct(private readonly ComposerSettingsLoader $composerSettingsLoader)
18+
{
19+
}
20+
21+
public function __invoke(PostProjectNodeCreated $event): void
22+
{
23+
$workDir = getcwd();
24+
if ($workDir === false) {
25+
return;
26+
}
27+
28+
$composerjson = $this->findComposerJson($workDir);
29+
if (!is_string($composerjson)) {
30+
return;
31+
}
32+
33+
$projectNode = $event->getProjectNode();
34+
$settings = $event->getSettings();
35+
36+
$this->composerSettingsLoader->loadSettings($projectNode, $settings, $composerjson);
37+
}
38+
39+
private function findComposerJson(string $currentDir): string|null
40+
{
41+
// Navigate up the directory structure until finding the composer.json file
42+
while (!file_exists($currentDir . '/composer.json') && $currentDir !== '/') {
43+
$currentDir = dirname($currentDir);
44+
}
45+
46+
// If found, return the path to the composer.json file; otherwise, return null
47+
return file_exists($currentDir . '/composer.json') ? $currentDir . '/composer.json' : null;
48+
}
49+
}

packages/guides/src/Nodes/ProjectNode.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
use phpDocumentor\Guides\Nodes\Inline\PlainTextInlineNode;
1414
use phpDocumentor\Guides\Nodes\Menu\NavMenuNode;
1515

16+
use function array_merge;
17+
use function array_unique;
18+
1619
use const DATE_RFC2822;
1720

1821
/** @extends CompoundNode<DocumentNode> */
@@ -40,6 +43,9 @@ class ProjectNode extends CompoundNode
4043
/** @var NavMenuNode[] */
4144
private array $globalMenues = [];
4245

46+
/** @var list<string> */
47+
private array $keywords = [];
48+
4349
public function __construct(
4450
private string|null $title = null,
4551
private string|null $version = null,
@@ -210,4 +216,22 @@ public function setGlobalMenues(array $globalMenues): ProjectNode
210216

211217
return $this;
212218
}
219+
220+
/** @return list<string> */
221+
public function getKeywords(): array
222+
{
223+
return $this->keywords;
224+
}
225+
226+
/** @param list<string> $keywords */
227+
public function setKeywords(array $keywords): void
228+
{
229+
$this->keywords = $keywords;
230+
}
231+
232+
/** @param list<string> $keywords */
233+
public function addKeywords(array $keywords): void
234+
{
235+
$this->keywords = array_unique(array_merge($this->keywords, $keywords));
236+
}
213237
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Guides\Settings;
6+
7+
use phpDocumentor\Guides\Nodes\Inline\PlainTextInlineNode;
8+
use phpDocumentor\Guides\Nodes\ProjectNode;
9+
10+
use function file_get_contents;
11+
use function implode;
12+
use function is_array;
13+
use function is_string;
14+
use function json_decode;
15+
use function sprintf;
16+
17+
final class ComposerSettingsLoader
18+
{
19+
public function loadSettings(ProjectNode $projectNode, ProjectSettings $projectSettings, string $pathToComposerJson): void
20+
{
21+
$jsonContents = file_get_contents($pathToComposerJson);
22+
if (!is_string($jsonContents)) {
23+
return;
24+
}
25+
26+
$composerData = json_decode($jsonContents, true);
27+
if (!is_array($composerData)) {
28+
return;
29+
}
30+
31+
if (isset($composerData['name']) && is_string($composerData['name'])) {
32+
$projectNode->addVariable('composer_name', new PlainTextInlineNode($composerData['name']));
33+
}
34+
35+
if (isset($composerData['description']) && is_string($composerData['description'])) {
36+
$projectNode->addVariable('composer_description', new PlainTextInlineNode($composerData['description']));
37+
}
38+
39+
if (isset($composerData['version']) && is_string($composerData['version'])) {
40+
if ($projectNode->getVersion() === null) {
41+
$projectNode->setVersion($composerData['version']);
42+
}
43+
}
44+
45+
if (isset($composerData['type']) && is_string($composerData['type'])) {
46+
$projectNode->addVariable('composer_type', new PlainTextInlineNode($composerData['type']));
47+
}
48+
49+
if (isset($composerData['license'])) {
50+
if (is_string($composerData['license'])) {
51+
$projectNode->addVariable('license', new PlainTextInlineNode($composerData['license']));
52+
} elseif (is_array($composerData['license'])) {
53+
$projectNode->addVariable(
54+
'license',
55+
new PlainTextInlineNode(sprintf('(%s)', implode(' or ', $composerData['license']))),
56+
);
57+
}
58+
}
59+
60+
if (isset($composerData['keywords']) && is_array($composerData['keywords'])) {
61+
$projectNode->addKeywords($composerData['keywords']);
62+
}
63+
64+
if (!isset($composerData['support']) || !is_array($composerData['support'])) {
65+
return;
66+
}
67+
68+
foreach ($composerData['support'] as $key => $support) {
69+
if (!is_string($support)) {
70+
continue;
71+
}
72+
73+
$projectNode->addVariable(
74+
'composer_support_' . $key,
75+
new PlainTextInlineNode($support),
76+
);
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)