Monday, December 27, 2010

Converting PHP_CodeSniffer XML report into HTML page (XSLT)

PHP CodeSniffer XML report will look similar to this:
<?xml version="1.0" encoding="UTF-8"?>
<phpcs version="1.2.2">
 <file name="/home/myhome/NetBeansProjects/LazyLoad/Libs/LazyLoad/Repositories/NestedSetNode.php" errors="7" warnings="1">
  <error line="39" column="11" source="Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase">Constants must be uppercase; expected LAZYLOAD but found LazyLoad</error>
  <error line="39" column="20" source="Generic.NamingConventions.UpperCaseConstantName.ConstantNotUpperCase">Constants must be uppercase; expected REPOSITORIES but found Repositories</error>
  <error line="58" column="1" source="PEAR.Commenting.ClassComment">Missing @link tag in class comment</error>
  <error line="69" column="13" source="PEAR.NamingConventions.ValidVariableName">Private member variable &quot;set&quot; must be prefixed with an underscore</error>
  <error line="75" column="13" source="PEAR.NamingConventions.ValidVariableName">Private member variable &quot;lft&quot; must be prefixed with an underscore</error>
  <error line="81" column="13" source="PEAR.NamingConventions.ValidVariableName">Private member variable &quot;rgt&quot; must be prefixed with an underscore</error>
  <warning line="148" column="9" source="PEAR.ControlStructures.InlineControlStructure">Inline control structures are discouraged</warning>
 </file>
</phpcs>
To transform PHP CodeSniffer XML report into human readable format XSLT stylesheet needs to be attached:
<?xml version="1.0" encoding="UTF-8"?>
<!-- add line -->
<?xml-stylesheet type="text/xsl" href="phpcs.xsl"?>
<!-- rest of PHP CodeSniffer XML report -->
XSLT stylesheet:
<?xml version="1.0" encoding="UTF-8"?>

<!--
    Document   : phpcs.xsl
    Created on : December 27, 2010, 1:42 PM
    Author     : schkovich
    Description:
        Transformation PHP_CodeSniffer xml report into human readable format.
-->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html"  encoding="UTF-8"/>

    <!-- TODO customize transformation rules
         syntax recommendation http://www.w3.org/TR/xslt
    -->
    <xsl:template match="/">
        <html>
            <head>
                <title>phpcs.xsl</title>
                <link href="./phpcs.css" rel="stylesheet" type="text/css" />
            </head>
            <body>
                <table>
                    <thead>
                        <tr>
                            <th class="file">Name</th>
                            <th class="notes">Errors</th>
                            <th class="notes">Warnings</th>
                        </tr>
                    </thead>
                    <tbody>
                        <xsl:for-each select="phpcs/file">
                            <tr>
                                <td>
                                    <xsl:value-of select="@name" />
                                </td>
                                <td>
                                    <xsl:value-of select="@errors" />
                                </td>
                                <td>
                                    <xsl:value-of select="@warnings" />
                                </td>
                            </tr>
                            <tr>
                                <td colspan="3">
                                    <xsl:for-each select="error">
                                        <span class="error">Error: </span>
                                        <xsl:value-of select="self::node()"/>
                                        <br />
                                        <b>Line:</b>
                                        <xsl:value-of select="@line" />
                                        <br />
                                        <b>Column:</b>
                                        <xsl:value-of select="@column" />
                                        <br />
                                        <b>Source:</b>
                                        <xsl:value-of select="@source" />
                                        <hr />
                                    </xsl:for-each>
                                    <xsl:for-each select="warning">
                                        <span class="warning">Warning: </span>
                                        <xsl:value-of select="self::node()"/>
                                        <br />
                                        <b>Line:</b>
                                        <xsl:value-of select="@line" />
                                        <br />
                                        <b>Column:</b>
                                        <xsl:value-of select="@column" />
                                        <br />
                                        <b>Source:</b>
                                        <xsl:value-of select="@source" />
                                        <hr />
                                    </xsl:for-each>
                                </td>
                            </tr>
                        </xsl:for-each>
                    </tbody>
                </table>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>
CSS
/*
    Document   : phpcs
    Created on : Dec 27, 2010, 1:34:02 PM
    Author     : schkovich
    Description:
        This stylesheet is designed to style phpcs XSLT stylessheet
*/

/*
   TODO customize this sample style
   Syntax recommendation http://www.w3.org/TR/REC-CSS2/
*/
table {
    width: 100%
}
th {
    text-align: left
}
th.file {
    width: 80%;
    color: green
}
th.notes {
    width: 10%;
    color: blue
}
span {
    font-weight: bold
}
span.error {
    color: red
}
span.warning {
    color: orange
}
Output will look like this:
To generate PHP CodeSniffer reports that will always have attached external XSLT stylesheet one PHP CodeSniffer file needs to be patched and one needs to be added.
New code generator CodeSniffer/Reports.Xls.php needs to be added:
<?php
/**
 * Xsl report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Goran Miskovic <schkovich@gmail.com>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
 * @version   CVS: $Id: IsCamelCapsTest.php 240585 2007-08-02 00:05:40Z squiz $
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Xml report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Goran Miskovic <schkovich@gmail.com>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
 * @version   Release: 1.2.2
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Xsl implements PHP_CodeSniffer_Report
{


    /**
     * Prints all violations for processed files, in a proprietary XML format.
     *
     * Errors and warnings are displayed together, grouped by file.
     * 
     * External XSLT stylesheet phpcs.xsl will be attached
     *
     * @param array   $report       Prepared report.
     * @param boolean $showWarnings Show warnings?
     * @param boolean $showSources  Show sources?
     * @param int     $width        Maximum allowed lne width.
     * 
     * @return string 
     */
    public function generate(
        $report,
        $showWarnings=true,
        $showSources=false,
        $width=80
    ) {
        echo '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
        echo '<?xml-stylesheet type="text/xsl" href="phpcs.xsl"?>'.PHP_EOL;
        echo '<phpcs version="1.2.2">'.PHP_EOL;

        $errorsShown = 0;

        foreach ($report['files'] as $filename => $file) {
            if (empty($file['messages']) === true) {
                continue;
            }

            echo ' <file name="'.$filename.'" errors="'.$file['errors'].'" warnings="'.$file['warnings'].'">'.PHP_EOL;

            foreach ($file['messages'] as $line => $lineErrors) {
                foreach ($lineErrors as $column => $colErrors) {
                    foreach ($colErrors as $error) {
                        $error['type'] = strtolower($error['type']);
                        echo '  <'.$error['type'].' line="'.$line.'" column="'.$column.'" source="'.$error['source'].'">';
                        echo htmlspecialchars($error['message']).'</'.$error['type'].'>'.PHP_EOL;
                        $errorsShown++;
                    }
                }
            }//end foreach

            echo ' </file>'.PHP_EOL;
        }//end foreach

        echo '</phpcs>'.PHP_EOL;

        return $errorsShown;

    }//end generate()


}//end class

?>
CodeSniffer/CLI.php needs to be patched. Find variable $validReports on line 262 and add 'xsl' as the last array element:
$validReports     = array(
                                     'full',
                                     'xml',
                                     'checkstyle',
                                     'csv',
                                     'emacs',
                                     'source',
                                     'summary',
                                     'svnblame',
                                     'xsl',
                                    );
Finally run from the command line:
phpcs --report=xsl --report-file=${HOME}/NetBeansProjects/LazyLoad/public_html/LazyLoad.xml NetBeansProjects/LazyLoad/Libs

Sunday, December 12, 2010

Help Petr to Improve the NetBeans IDE Performance

Petr Pisl is asking community in his latest post on The NetBeans PHP Team Blog to help him identify use case when PHP editor is slow.

Tuesday, November 9, 2010

NetCAT 7.0 Started

NetBeans IDE 7.0 Community Acceptance Testing program officially started yesterday.

The goal of NetCAT 7.0 program is very simple: stabilize NetBeans IDE 7.0. Over seventy active NetBeans community members will be involved in testing the NetBeans IDE development builds during next four months.

This is a brief time schedule of important announcements, milestones and tasks:
  • 11/1 - Program announced on nbusers and nbdev lists. Volunteers joining NetCAT.
  • 11/8 - NetCAT team starts testing daily builds.
  • 11/12 - NetBeans 7.0 Beta #1 release
  • 11/16 - First weekly report sent.
  • 12/24 - 12/31 - Christmas break
  • 1/18 - NetBeans 7.0 Beta #2 release
  • 1/19 - Early CA research
  • 1/20 - Documentation review
  • 1/28 - Final CA survey questions defined.
  • 2/10 - NetBeans 7.0 RC release, CA survey opened
  • 2/28 - CA survey closed, results processed.
  • 3/1 - Last weekly report sent.
  • 3/8 - NetBeans 7.0 FCS release, NetCAT game over

Thursday, October 28, 2010

Porting C# Code to PHP (Porter Stemming Algorithm)

Jeff Mose wrote absolutely great article Notes from porting C# code to PHP. It is perhaps the most objective article about PHP ever.

I was inspired to review porting of Kamil Bartocha C# implementation of the English (Porter2) stemming algorithm that I did few years ago.

My native language is PHP and, of course, my view on the problem is from the opposite direction.

PHP and C# are similar. It was not hard to understand C# code and port it to PHP. However, I do know that it will be much, much harder for me to do it vice versa.

The most notable difference was set of string manipulation functions that comes out of box in PHP. Although there was no need to port C# StringBuilder class I did it for the sake of clarity.

I made few changes to make it run on PHP 5.3 and added the test page. Porter2 Stemming Algorithm in PHP 5.3 project is available at Kenai.

Unfortunately, I made bad choice to use flat ini formatted text file to store sample English vocabulary and its stemmed equivalent. As a consequence, I have had to remove around 20 words like false, true, on, off, etc.

Since the vocabulary has almost 30.000 words if you decide to run the test you will have to increase maximum execution time in php.ini.

I am working on both problems. Most likely I will try to store the vocabulary and its stemmed equivalent in XML format. Further on, I am looking into option to use Dojo Data Grid to display test results.