1<?php
2/**
3 * A doc generator that outputs documentation in Markdown format.
4 *
5 * PHP version 5
6 *
7 * @category  PHP
8 * @package   PHP_CodeSniffer
9 * @author    Stefano Kowalke <blueduck@gmx.net>
10 * @copyright 2014 Arroba IT
11 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12 * @link      http://pear.php.net/package/PHP_CodeSniffer
13 */
14
15if (class_exists('PHP_CodeSniffer_DocGenerators_Generator', true) === false) {
16    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_DocGenerators_Generator not found');
17}
18
19/**
20 * A doc generator that outputs documentation in Markdown format.
21 *
22 * @category  PHP
23 * @package   PHP_CodeSniffer
24 * @author    Stefano Kowalke <blueduck@gmx.net>
25 * @copyright 2014 Arroba IT
26 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
27 * @version   Release: @package_version@
28 * @link      http://pear.php.net/package/PHP_CodeSniffer
29 */
30class PHP_CodeSniffer_DocGenerators_Markdown extends PHP_CodeSniffer_DocGenerators_Generator
31{
32
33
34    /**
35     * Generates the documentation for a standard.
36     *
37     * @return void
38     * @see    processSniff()
39     */
40    public function generate()
41    {
42        ob_start();
43        $this->printHeader();
44
45        $standardFiles = $this->getStandardFiles();
46
47        foreach ($standardFiles as $standard) {
48            $doc = new DOMDocument();
49            $doc->load($standard);
50            $documentation = $doc->getElementsByTagName('documentation')->item(0);
51            $this->processSniff($documentation);
52        }
53
54        $this->printFooter();
55        $content = ob_get_contents();
56        ob_end_clean();
57
58        echo $content;
59
60    }//end generate()
61
62
63    /**
64     * Print the markdown header.
65     *
66     * @return void
67     */
68    protected function printHeader()
69    {
70        $standard = $this->getStandard();
71
72        echo "# $standard Coding Standard".PHP_EOL;
73
74    }//end printHeader()
75
76
77    /**
78     * Print the markdown footer.
79     *
80     * @return void
81     */
82    protected function printFooter()
83    {
84        // Turn off errors so we don't get timezone warnings if people
85        // don't have their timezone set.
86        error_reporting(0);
87        echo 'Documentation generated on '.date('r');
88        echo ' by [PHP_CodeSniffer '.PHP_CodeSniffer::VERSION.'](https://github.com/squizlabs/PHP_CodeSniffer)';
89
90    }//end printFooter()
91
92
93    /**
94     * Process the documentation for a single sniff.
95     *
96     * @param DOMNode $doc The DOMNode object for the sniff.
97     *                     It represents the "documentation" tag in the XML
98     *                     standard file.
99     *
100     * @return void
101     */
102    protected function processSniff(DOMNode $doc)
103    {
104        $title = $this->getTitle($doc);
105        echo "## $title".PHP_EOL;
106
107        foreach ($doc->childNodes as $node) {
108            if ($node->nodeName === 'standard') {
109                $this->printTextBlock($node);
110            } else if ($node->nodeName === 'code_comparison') {
111                $this->printCodeComparisonBlock($node);
112            }
113        }
114
115    }//end processSniff()
116
117
118    /**
119     * Print a text block found in a standard.
120     *
121     * @param DOMNode $node The DOMNode object for the text block.
122     *
123     * @return void
124     */
125    protected function printTextBlock(DOMNode $node)
126    {
127        $content = trim($node->nodeValue);
128        $content = htmlspecialchars($content);
129
130        $content = str_replace('&lt;em&gt;', '*', $content);
131        $content = str_replace('&lt;/em&gt;', '*', $content);
132
133        echo $content.PHP_EOL;
134
135    }//end printTextBlock()
136
137
138    /**
139     * Print a code comparison block found in a standard.
140     *
141     * @param DOMNode $node The DOMNode object for the code comparison block.
142     *
143     * @return void
144     */
145    protected function printCodeComparisonBlock(DOMNode $node)
146    {
147        $codeBlocks = $node->getElementsByTagName('code');
148
149        $firstTitle = $codeBlocks->item(0)->getAttribute('title');
150        $first      = trim($codeBlocks->item(0)->nodeValue);
151        $first      = str_replace("\n", "\n    ", $first);
152        $first      = str_replace('<em>', '', $first);
153        $first      = str_replace('</em>', '', $first);
154
155        $secondTitle = $codeBlocks->item(1)->getAttribute('title');
156        $second      = trim($codeBlocks->item(1)->nodeValue);
157        $second      = str_replace("\n", "\n    ", $second);
158        $second      = str_replace('<em>', '', $second);
159        $second      = str_replace('</em>', '', $second);
160
161        echo '  <table>'.PHP_EOL;
162        echo '   <tr>'.PHP_EOL;
163        echo "    <th>$firstTitle</th>".PHP_EOL;
164        echo "    <th>$secondTitle</th>".PHP_EOL;
165        echo '   </tr>'.PHP_EOL;
166        echo '   <tr>'.PHP_EOL;
167        echo '<td>'.PHP_EOL.PHP_EOL;
168        echo "    $first".PHP_EOL.PHP_EOL;
169        echo '</td>'.PHP_EOL;
170        echo '<td>'.PHP_EOL.PHP_EOL;
171        echo "    $second".PHP_EOL.PHP_EOL;
172        echo '</td>'.PHP_EOL;
173        echo '   </tr>'.PHP_EOL;
174        echo '  </table>'.PHP_EOL;
175
176    }//end printCodeComparisonBlock()
177
178
179}//end class
180