Skip to content

Commit 598df28

Browse files
authored
Merge branch 'main' into code-block-whitespace
2 parents ccb9b2c + 9a9b30f commit 598df28

File tree

42 files changed

+285
-158
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+285
-158
lines changed

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"autoload-dev": {
1818
"psr-4": {
1919
"phpDocumentor\\Guides\\": ["packages/guides/tests/unit/", "tests/"],
20+
"phpDocumentor\\Guides\\Cli\\": "packages/guides-cli/tests/unit",
2021
"phpDocumentor\\Guides\\Graphs\\": "packages/guides-graphs/tests/unit",
2122
"phpDocumentor\\Guides\\RestructuredText\\": "packages/guides-restructured-text/tests/unit",
2223
"phpDocumentor\\Guides\\Markdown\\": "packages/guides-markdown/tests/unit"
@@ -52,6 +53,7 @@
5253
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
5354
"doctrine/coding-standard": "^12.0",
5455
"fakerphp/faker": "^1.23",
56+
"fig/log-test": "^1.0",
5557
"gajus/dindent": "^2.0.1",
5658
"jangregor/phpstan-prophecy": "^1.0",
5759
"league/flysystem-memory": "^1.0",

composer.lock

Lines changed: 55 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/components/compiler.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,26 @@ This library uses a simplified compiler design. This basically means that our pi
88
than a regular compiler. But its following the same semantics.
99

1010
Lexing and Parsing
11+
==================
1112

12-
A typical compiler will have separate lexing, syntax analisys. However the parser
13-
was designed to do part of the lexing because of all context dependend logic of most Markup languages.
13+
A typical compiler will have separate lexing, syntax analysis. However the parser
14+
was designed to do part of the lexing because of all context-dependent logic of most Markup languages.
1415
We call this the parsing phase. This will result into an AST that is mostly close to the original source. It
1516
might contain some optimizations for later use.
1617

1718
Semantic analysis and Intermediate code generation
19+
==================================================
1820

1921
The semantic analysis phase of this library is performing a number of steps to collect information of the parsed markup
20-
language. An good example is the collection of the table of contents and the metadata of the parsed documents.
22+
language. A good example is the collection of the table of contents and the metadata of the parsed documents.
2123
This is the moment where document node traversers are executed.
2224

2325
Code optimization
26+
=================
2427

2528
Do some pre-rendering stuff, like buiding the TOC content and other rendering preparations before the real rendering starts.
2629

2730
Code generation
31+
===============
2832

29-
Code generation a.k. rendering. We do deliver a headless
33+
Code generation a.k.a. rendering. We do deliver a headless

docs/extension/index.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,28 @@
44
Extending the phpdocumentor/guides
55
==================================
66

7+
``phpdocumentor/guides`` relies on `Symfony Dependency Injection
8+
Container
9+
<https://symfony.com/doc/current/components/dependency_injection.html#setting-up-the-container-with-configuration-files>`__
10+
extensions. This means that to extend the guides, you need to define
11+
such an extension, after what it becomes possible to make the guides CLI
12+
aware of it by creating a ``guides.xml`` file in the directory from
13+
which you invoke the CLI.
14+
15+
It should look like this::
16+
17+
.. code-block:: xml
18+
19+
<?xml version="1.0" encoding="UTF-8" ?>
20+
<guides>
21+
<extension class="YourName\YourExtension\DependencyInjection\YourExtension"/>
22+
</guides>
23+
24+
Internally, the guides CLI defines and uses default extensions.
25+
Once you have that set up, you can create PHP classes, define services
26+
from it, and tag them so that they are recognized and usable by the
27+
guides CLI.
28+
729
Some ways to extend the guides:
830

931
.. toctree::

packages/guides-cli/composer.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
"phpDocumentor\\Guides\\Cli\\": "src/"
1212
}
1313
},
14+
"autoload-dev": {
15+
"psr-4": {
16+
"phpDocumentor\\Guides\\": [
17+
"tests/unit/"
18+
]
19+
}
20+
},
1421
"authors": [
1522
{
1623
"name": "jaapio",

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Monolog\Handler\ErrorLogHandler;
1212
use Monolog\Handler\StreamHandler;
1313
use Monolog\Logger;
14+
use phpDocumentor\Guides\Cli\Logger\SpyProcessor;
1415
use phpDocumentor\Guides\Compiler\CompilerContext;
1516
use phpDocumentor\Guides\Handlers\CompileDocumentsCommand;
1617
use phpDocumentor\Guides\Handlers\ParseDirectoryCommand;
@@ -83,6 +84,12 @@ public function __construct(
8384
'Write log to this path',
8485
'php://stder',
8586
);
87+
$this->addOption(
88+
'fail-on-log',
89+
null,
90+
InputOption::VALUE_NONE,
91+
'Use a non-zero exit code as soon as any log is written',
92+
);
8693

8794
$this->addOption(
8895
'theme',
@@ -136,6 +143,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int
136143
$this->logger->pushHandler(new StreamHandler($logPath . '/error.log', Logger::ERROR));
137144
}
138145

146+
$failOnLog = $input->getOption('fail-on-log') ?? false;
147+
148+
if ($failOnLog) {
149+
$spyProcessor = new SpyProcessor();
150+
$this->logger->pushProcessor($spyProcessor);
151+
}
152+
139153
$documents = $this->commandBus->handle(
140154
new ParseDirectoryCommand(
141155
$sourceFileSystem,
@@ -185,7 +199,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
185199
'Successfully placed ' . (is_countable($documents) ? count($documents) : 0) . ' rendered ' . $formatsText . ' files into ' . $outputDir,
186200
);
187201

188-
return 0;
202+
if ($failOnLog && $spyProcessor->hasBeenCalled()) {
203+
return Command::FAILURE;
204+
}
205+
206+
return Command::SUCCESS;
189207
}
190208

191209
private function getAbsolutePath(string $path): string

packages/guides-cli/src/DependencyInjection/ContainerFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,12 @@ private function resolveExtensionClass(string $name): string
9797

9898
$fqcn = implode('\\', [$fqcn, 'DependencyInjection', $package . 'Extension']);
9999
if (!class_exists($fqcn)) {
100-
throw new LogicException(sprintf('Extension "%s" does not exists.', $fqcn));
100+
throw new LogicException(sprintf('Extension "%s" does not exist.', $fqcn));
101101
}
102102
}
103103

104104
if (!is_a($fqcn, ExtensionInterface::class, true)) {
105-
throw new LogicException(sprintf('Extension "%s" does not exists.', $fqcn));
105+
throw new LogicException(sprintf('Extension "%s" does not exist.', $fqcn));
106106
}
107107

108108
return $fqcn;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Guides\Cli\Logger;
6+
7+
use Monolog\Processor\ProcessorInterface;
8+
9+
/**
10+
* This decorator has an extra method to check whether anything was logged
11+
*
12+
* @internal
13+
*/
14+
final class SpyProcessor implements ProcessorInterface
15+
{
16+
private bool $hasBeenCalled = false;
17+
18+
public function hasBeenCalled(): bool
19+
{
20+
return $this->hasBeenCalled;
21+
}
22+
23+
/** @inheritDoc */
24+
public function __invoke(array $record): array
25+
{
26+
$this->hasBeenCalled = true;
27+
28+
return $record;
29+
}
30+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Guides\Cli\Logger;
6+
7+
use PHPUnit\Framework\TestCase;
8+
9+
class SpyProcessorTest extends TestCase
10+
{
11+
public function testHasBeenCalledReturnsFalseByDefault(): void
12+
{
13+
$spyProcessor = new SpyProcessor();
14+
15+
$this->assertFalse($spyProcessor->hasBeenCalled());
16+
}
17+
18+
public function testItKnowsWhenALogIsEmitted(): void
19+
{
20+
$process = new SpyProcessor();
21+
$process(['channel' => 'test']);
22+
self::assertTrue($process->hasBeenCalled());
23+
}
24+
}

packages/guides-graphs/src/Graphs/Directives/UmlDirective.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use phpDocumentor\Guides\RestructuredText\Directives\BaseDirective;
1111
use phpDocumentor\Guides\RestructuredText\Parser\Directive;
1212
use phpDocumentor\Guides\RestructuredText\Parser\DocumentParserContext;
13+
use Psr\Log\LoggerInterface;
1314
use Webmozart\Assert\Assert;
1415

1516
use function dirname;
@@ -34,6 +35,10 @@
3435
*/
3536
final class UmlDirective extends BaseDirective
3637
{
38+
public function __construct(private readonly LoggerInterface $logger)
39+
{
40+
}
41+
3742
public function getName(): string
3843
{
3944
return 'uml';
@@ -72,9 +77,11 @@ private function loadExternalUmlFile(ParserContext $parserContext, string $path)
7277
);
7378

7479
if (!$parserContext->getOrigin()->has($fileName)) {
75-
$parserContext->addError(
76-
sprintf('Tried to include "%s" as a diagram but the file could not be found', $fileName),
77-
);
80+
$message =
81+
sprintf('Tried to include "%s" as a diagram but the file could not be found', $fileName);
82+
83+
84+
$this->logger->error($message, $parserContext->getLoggerInformation());
7885

7986
return null;
8087
}

0 commit comments

Comments
 (0)