Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generators: don't print documentation title if there are no docs #755

Merged
merged 3 commits into from
Jan 23, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Generators/Markdown: don't print title if there is no content
This refactors the class to _retrieve_ the intended output, instead of echo-ing it out directly and validates whether it makes sense to print anything at all about a sniff before sending the output to screen.

It deprecates the following methods, which will be removed in PHPCS 4.0:
* `printHeader()` in favour of `getFormattedHeader()`
* `printFooter()` in favour of `getFormattedFooter()`
* `printTextBlock()` in favour of `getFormattedTextBlock()`
* `printCodeComparisonBlock()` in favour of `getFormattedCodeComparisonBlock()`
jrfnl committed Jan 23, 2025
commit 6ebb1dde673a6cbb1d0a68a7035f15ea80a265a4
149 changes: 117 additions & 32 deletions src/Generators/Markdown.php
Original file line number Diff line number Diff line change
@@ -32,53 +32,92 @@ public function generate()
}

ob_start();
$this->printHeader();

foreach ($this->docFiles as $file) {
$doc = new DOMDocument();
$doc->load($file);
$documentation = $doc->getElementsByTagName('documentation')->item(0);
$this->processSniff($documentation);
}

$this->printFooter();
$content = ob_get_contents();
ob_end_clean();

echo $content;
if (trim($content) !== '') {
echo $this->getFormattedHeader();
echo $content;
echo $this->getFormattedFooter();
}

}//end generate()


/**
* Print the markdown header.
*
* @deprecated 3.12.0 Use Markdown::getFormattedHeader() instead.
*
* @codeCoverageIgnore
*
* @return void
*/
protected function printHeader()
{
echo $this->getFormattedHeader();

}//end printHeader()


/**
* Format the markdown header.
*
* @since 3.12.0 Replaces the deprecated Markdown::printHeader() method.
*
* @return string
*/
protected function getFormattedHeader()
{
$standard = $this->ruleset->name;

echo "# $standard Coding Standard".PHP_EOL;
return "# $standard Coding Standard".PHP_EOL;

}//end printHeader()
}//end getFormattedHeader()


/**
* Print the markdown footer.
*
* @deprecated 3.12.0 Use Markdown::getFormattedFooter() instead.
*
* @codeCoverageIgnore
*
* @return void
*/
protected function printFooter()
{
echo $this->getFormattedFooter();

}//end printFooter()


/**
* Format the markdown footer.
*
* @since 3.12.0 Replaces the deprecated Markdown::printFooter() method.
*
* @return string
*/
protected function getFormattedFooter()
{
// Turn off errors so we don't get timezone warnings if people
// don't have their timezone set.
$errorLevel = error_reporting(0);
echo PHP_EOL.'Documentation generated on '.date('r');
echo ' by [PHP_CodeSniffer '.Config::VERSION.'](https://github.com/PHPCSStandards/PHP_CodeSniffer)'.PHP_EOL;
$output = PHP_EOL.'Documentation generated on '.date('r');
$output .= ' by [PHP_CodeSniffer '.Config::VERSION.'](https://github.com/PHPCSStandards/PHP_CodeSniffer)'.PHP_EOL;
error_reporting($errorLevel);

}//end printFooter()
return $output;

}//end getFormattedFooter()


/**
@@ -92,17 +131,21 @@ protected function printFooter()
*/
protected function processSniff(DOMNode $doc)
{
$title = $this->getTitle($doc);
echo PHP_EOL."## $title".PHP_EOL.PHP_EOL;

$content = '';
foreach ($doc->childNodes as $node) {
if ($node->nodeName === 'standard') {
$this->printTextBlock($node);
$content .= $this->getFormattedTextBlock($node);
} else if ($node->nodeName === 'code_comparison') {
$this->printCodeComparisonBlock($node);
$content .= $this->getFormattedCodeComparisonBlock($node);
}
}

if (trim($content) !== '') {
$title = $this->getTitle($doc);
echo PHP_EOL."## $title".PHP_EOL.PHP_EOL;
echo $content;
}

}//end processSniff()


@@ -111,9 +154,29 @@ protected function processSniff(DOMNode $doc)
*
* @param \DOMNode $node The DOMNode object for the text block.
*
* @deprecated 3.12.0 Use Markdown::getFormattedTextBlock() instead.
*
* @codeCoverageIgnore
*
* @return void
*/
protected function printTextBlock(DOMNode $node)
{
echo $this->getFormattedTextBlock($node);

}//end printTextBlock()


/**
* Format a text block found in a standard.
*
* @param \DOMNode $node The DOMNode object for the text block.
*
* @since 3.12.0 Replaces the deprecated Markdown::printTextBlock() method.
*
* @return string
*/
protected function getFormattedTextBlock(DOMNode $node)
{
$content = trim($node->nodeValue);
$content = htmlspecialchars($content, (ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401));
@@ -144,19 +207,39 @@ protected function printTextBlock(DOMNode $node)
}
}

echo implode(PHP_EOL, $lines).PHP_EOL;
return implode(PHP_EOL, $lines).PHP_EOL;

}//end printTextBlock()
}//end getFormattedTextBlock()


/**
* Print a code comparison block found in a standard.
*
* @param \DOMNode $node The DOMNode object for the code comparison block.
*
* @deprecated 3.12.0 Use Markdown::getFormattedCodeComparisonBlock() instead.
*
* @codeCoverageIgnore
*
* @return void
*/
protected function printCodeComparisonBlock(DOMNode $node)
{
echo $this->getFormattedCodeComparisonBlock($node);

}//end printCodeComparisonBlock()


/**
* Format a code comparison block found in a standard.
*
* @param \DOMNode $node The DOMNode object for the code comparison block.
*
* @since 3.12.0 Replaces the deprecated Markdown::printCodeComparisonBlock() method.
*
* @return string
*/
protected function getFormattedCodeComparisonBlock(DOMNode $node)
{
$codeBlocks = $node->getElementsByTagName('code');

@@ -174,22 +257,24 @@ protected function printCodeComparisonBlock(DOMNode $node)
$second = str_replace('<em>', '', $second);
$second = str_replace('</em>', '', $second);

echo ' <table>'.PHP_EOL;
echo ' <tr>'.PHP_EOL;
echo " <th>$firstTitle</th>".PHP_EOL;
echo " <th>$secondTitle</th>".PHP_EOL;
echo ' </tr>'.PHP_EOL;
echo ' <tr>'.PHP_EOL;
echo '<td>'.PHP_EOL.PHP_EOL;
echo " $first".PHP_EOL.PHP_EOL;
echo '</td>'.PHP_EOL;
echo '<td>'.PHP_EOL.PHP_EOL;
echo " $second".PHP_EOL.PHP_EOL;
echo '</td>'.PHP_EOL;
echo ' </tr>'.PHP_EOL;
echo ' </table>'.PHP_EOL;

}//end printCodeComparisonBlock()
$output = ' <table>'.PHP_EOL;
$output .= ' <tr>'.PHP_EOL;
$output .= " <th>$firstTitle</th>".PHP_EOL;
$output .= " <th>$secondTitle</th>".PHP_EOL;
$output .= ' </tr>'.PHP_EOL;
$output .= ' <tr>'.PHP_EOL;
$output .= '<td>'.PHP_EOL.PHP_EOL;
$output .= " $first".PHP_EOL.PHP_EOL;
$output .= '</td>'.PHP_EOL;
$output .= '<td>'.PHP_EOL.PHP_EOL;
$output .= " $second".PHP_EOL.PHP_EOL;
$output .= '</td>'.PHP_EOL;
$output .= ' </tr>'.PHP_EOL;
$output .= ' </table>'.PHP_EOL;

return $output;

}//end getFormattedCodeComparisonBlock()


}//end class
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# GeneratorTest Coding Standard

## No Content


## Code Comparison Only, Missing Standard Block

<table>

This file was deleted.

This file was deleted.

20 changes: 11 additions & 9 deletions tests/Core/Generators/Fixtures/MarkdownDouble.php
Original file line number Diff line number Diff line change
@@ -14,23 +14,25 @@ class MarkdownDouble extends Markdown
{

/**
* Print the markdown footer without the date or version nr to make the expectation fixtures stable.
* Format the markdown footer without the date or version nr to make the expectation fixtures stable.
*
* @return void
* @return string
*/
protected function printFooter()
protected function getFormattedFooter()
{
echo PHP_EOL.'Documentation generated on *REDACTED*';
echo ' by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer)'.PHP_EOL;
$output = PHP_EOL.'Documentation generated on *REDACTED*';
$output .= ' by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer)'.PHP_EOL;

return $output;
}

/**
* Print the _real_ footer of the markdown page.
* Retrieve the _real_ footer of the markdown page.
*
* @return void
* @return string
*/
public function printRealFooter()
public function getRealFooter()
{
parent::printFooter();
return parent::getFormattedFooter();
}
}
24 changes: 12 additions & 12 deletions tests/Core/Generators/MarkdownTest.php
Original file line number Diff line number Diff line change
@@ -175,7 +175,7 @@ public static function dataDocSpecifics()
],
'Unsupported: <code> element at the wrong level' => [
'sniffs' => 'StandardWithDocs.Unsupported.ElementAtWrongLevel',
'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputUnsupportedElementAtWrongLevel.md',
'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputEmpty.txt',
],
'Unsupported: one correct elm, one at wrong level' => [
'sniffs' => 'StandardWithDocs.Unsupported.OneElmAtWrongLevel',
@@ -187,7 +187,7 @@ public static function dataDocSpecifics()
],
'Unsupported: unknown element' => [
'sniffs' => 'StandardWithDocs.Unsupported.UnknownElement',
'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputUnsupportedUnknownElement.md',
'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputEmpty.txt',
],
];

@@ -208,10 +208,16 @@ public function testFooter()

$regex = '`^\RDocumentation generated on [A-Z][a-z]{2}, [0-9]{2} [A-Z][a-z]{2} 20[0-9]{2} [0-2][0-9](?::[0-5][0-9]){2} [+-][0-9]{4}';
$regex .= ' by \[PHP_CodeSniffer [3-9]\.[0-9]+.[0-9]+\]\(https://github\.com/PHPCSStandards/PHP_CodeSniffer\)\R$`';
$this->expectOutputRegex($regex);

$generator = new MarkdownDouble($ruleset);
$generator->printRealFooter();
$footer = $generator->getRealFooter();

if (method_exists($this, 'assertMatchesRegularExpression') === true) {
$this->assertMatchesRegularExpression($regex, $footer);
} else {
// PHPUnit < 9.1.0.
$this->assertRegExp($regex, $footer);
}

}//end testFooter()

@@ -233,11 +239,8 @@ public function testFooterResetsErrorReportingToOriginalSetting()
$config = new ConfigDouble(["--standard=$standard"]);
$ruleset = new Ruleset($config);

// We know there will be output, but we're not interested in the output for this test.
ob_start();
$generator = new MarkdownDouble($ruleset);
$generator->printRealFooter();
ob_end_clean();
$generator->getRealFooter();

$this->assertSame($expected, error_reporting());

@@ -275,11 +278,8 @@ public function testFooterDoesntThrowWarningOnMissingTimezone()
$config = new ConfigDouble(["--standard=$standard"]);
$ruleset = new Ruleset($config);

// We know there will be output, but we're not interested in the output for this test.
ob_start();
$generator = new MarkdownDouble($ruleset);
$generator->printRealFooter();
ob_end_clean();
$generator->getRealFooter();

// Reset the timezone to its original state.
ini_set('date.timezone', $originalIni);