Blog

  • PHP CodeSniffer and CodeIgniter

    I recently found out that Thomas Ernest have created a CodeIgniter standard for CodeSniffer. He mentioned on the CI formus that it’s not perfect and does spit out a few warnings and errors for things that are really OK in the CI style guide. False positives.

    This is the slightly modified welcome.php controller file I wanted to scan. According to my understanding of the CodeIgniter style guide, it should pass with flying colors:

    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    /**
    * File: welcome.php
    * 
    * PHP version 5
    *
    * @category Frontend
    * @package  Citest
    * @author   Erik Torsner <[email protected]>
    * @license  torgesta.com http://www.torgesta.com/  
    * @link     http://www.torgesta.com/  
    */
    
    /**
     * Class Welcome
     *
     * @category Frontend
     * @package  Citest
     * @author   Erik Torsner <[email protected]>
     * @license  torgesta.com http://www.torgesta.com/
     * @link     http://www.torgesta.com/  
     **/
    class Welcome extends CI_Controller {
    	/**
    	 * Index Page for this controller.
    	 *
    	 * Maps to the following URL
    	 * 		http://example.com/index.php/welcome
    	 *	- or -  
    	 * 		http://example.com/index.php/welcome/index
    	 *	- or -
    	 * Since this controller is set as the default controller in 
    	 * config/routes.php, it's displayed at http://example.com/
    	 *
    	 * So any other public methods not prefixed with an underscore will
    	 * map to /index.php/welcome/<method_name>
    	 *
    	 * @see http://codeigniter.com/user_guide/general/urls.html
    	 * @return void
    	 */
    	public function index()
    	{
    		$this->load->view('welcome_message');
    	}
    }
    
    /* End of file welcome.php */
    /* Location: ./controllers/welcome.php */

    See? File doc comment, class doc comment, function doc comment, no PHP end tag but the two standard comments instead. Beautiful. But scanning with CodeSniffer, I’d get something like this:

    $ phpcs --standard=CodeIgniter welcome.php 
    
    FILE: /home/foo/src/citest/application/controllers/welcome.php
    --------------------------------------------------------------------------------
    FOUND 3 ERROR(S) AFFECTING 3 LINE(S)
    --------------------------------------------------------------------------------
      1 | ERROR | Missing file doc comment
     47 | ERROR | Multi lines comments are not allowed; use "// Comment" DocBlock
        |       | comments instead
    --------------------------------------------------------------------------------
    
    Time: 0 seconds, Memory: 3.25Mb

    First problem, CodeSniffer doesn’t see the file doc comment at all. Turns out the CodeSniffer looks for the first non white space token after the PHP open tag. If it’s a valid file doc comment, all is good. In CodeIgniter, the standard behavior is to add a check for “BASEPATH” right at the top and it gets in the way of finding the existing file doc comment.

    Second problem. CodeIgniter style guide first say that all code comments should be one line comments. A few examples:

    <?php
    
    // One line comment using '//'. Fine with CodeIgniter 
    $foo = "bar";
    
    /*One line comment using '/*', not OK */
    $fuu = "bar";
    
    // Multi line comments, you should still use '//'
    // This is the next comment line
    $fuubar = NULL:
    
    /* Multi line comments, this way is not OK
    *This is the next comment line */
    $fuubar = 42:
    
    // But wait! at the end of the file. CI expects this:
    // Two single line comments using '/* ... */. 
    /* End of file welcome.php */
    /* Location: ./controllers/welcome.php */

    This is simply not consistent. To get clean scans using CodeSniffer, you have two options. Rewrite all end-of-file comments to use ‘//’ rather than ‘/*’ or fix CodeSniffer. Even if consistency is a good thing, this is a very well established style in CodeIgniter so I was inclined to fix CodeSniffer rather than fight.

    The CodeSniffer standard is installed (on Ubuntu) in

    /usr/share/php/PHP/CodeSniffer/Standards/CodeIgniter

     

    To fix the comments, I made the following change to

    /usr/share/php/PHP/CodeSniffer/Standards/CodeIgniter/Sniffs/Commenting/InlineCommentSniff.php

     

        private function _checkCommentStyle(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
        {
            $tokens = $phpcsFile->getTokens();
    
            $cmt = $tokens[$stackPtr]['content'];
            if($this->beginsWith($cmt, '/* End of file')) return TRUE;
            if($this->beginsWith($cmt, '/* Location:')) return TRUE;
            ...
            ...

    That it, to explicitly allow the two CodeIgniter specific comments. The second change was bigger. The CodeIgniter standard for CodeSniffer reuses PEAR’s check for file doc comments. Rather than modifying what is a built in CodeSniffer standard, I copied the correct file to the CodeIgniter standard and made modifications there. So I created the file

    /usr/share/php/PHP/CodeSniffer/Standards/CodeIgniter/Sniffs/Commenting/FileCommentsSniff.php

     

    as a copy of the corresponding file from the PEAR standard. Function process was modified:

        public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
        {
            $this->currentFile = $phpcsFile;
    
            // We are only interested if this is the first open tag.
            if ($stackPtr !== 0) {
                if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
                    return;
                }
            }
    
            $tokens = $phpcsFile->getTokens();
    
            // Allow CodeIgniter std "if ( ! defined('BASEPATH')).... on the first line
            // keep iterating until we find a token on line 2...
            $startLine = $tokens[$stackPtr]['line'];
            $lastToken = $stackPtr;
            while($tokens[$lastToken+1]['line'] == $startLine) {
              $lastToken++;
            }

    So, a simple loop that simply ignores whatever tokens that  is on the same line as the PHP open tag. Simple and it works. The last change I made was in

    /usr/share/php/PHP/CodeSniffer/Standards/CodeIgniter/ruleset.xml

     

    where the rule that refers to the FileCommentSniff file is modified so that it looks at the local copy rather than the one from the PEAR standard. Just change the line:

    <rule ref="PEAR.Commenting.FileComment">

    Into

    <rule ref="CodeIgniter.Commenting.FileComment">

    That’s it. A new test scan reveals that the perfectly decent looking welcome.php doesn’t generate any further errors:

    $ phpcs --standard=CodeIgniter welcome.php 
    Time: 0 seconds, Memory: 3.25Mb

    Now, go to github and get the repo.

  • Kvalet igång

    P11

      Körde just tamets 1:a 6-7 kvalvarv. Så långt på 3:e bästa tid. Permalink | Leave a comment

  • Heliga #14

    P48

    Vad har AJ Foyt IV, Kenny Bräck ( när han var som bäst ) och Vulkteamet gemensamt?

    Jo, nr 14 på bilen.

    Jag är nu ännu mer övertygad om att vi tar hem det här.

    Permalink | Leave a comment

  • God Morgon Mantorp

    Vakna, frukost avklarad, bilen varmkörd och värmda av en försiktig vårsol. Bra start på dagen helt enkelt. Nu väntar besiktningen.

    Om 3.5 timmar går starten.

    Permalink | Leave a comment

  • Mantorp calling

    Vi är på plats på Mantorp för årets race. Första (enda?) strulet har uppenbarat sig. Ett felmonterat däck som knappast hade gjort sig i tävling.

    Däckfirma sökes, helst nära Mantorp.

    Permalink | Leave a comment

  • Testar iphoneklienten

    Positivt:
    – Den finns
    – enkelt att lägga till flera bilder

    Negativt:
    – inget landscape?

    Permalink | Leave a comment

  • Sammanfattning av Skrotbilsloppet

    Det blev inte så mycket postat de sista 5-6 timmarna av skotbilsrejset. Det blev helt enkelt för intensivt, jag hade inte ro.

    Det blev inget särskilt spännande egentligen. Vi hade en match i matchen med Flat Out racing. När vi kom ut på banan efter våra två nattliga mekstopp hade vi 15 varv att plocka igen på Flat Out. Det hade säkert gått alldeles utmärkt att köra ikapp.

    Under min morgonstint mellan 06:00 och 08:00 tog vi igen runt 4 varv på Flat Out. Innan mig hade Fredrik och Mange plockat en del varv de också. Så när jag ställde mig i depån för att coacha John, Fredrik och Mange under de sista 4-5 timmarna så låg vi 5 varv bakom Flat Out. Det visade sig dock vara för svårt att ta igen. Båda bilarna gick utan några som helst problem men vi hade ett par sekunder per varv i övertag på Flat Out’s tider. Det räckte dock bara till att ta igen ett varv till. När 40 minuter återstod av racet låg vi tre varv bakom, de hade sig bästa förare i bilen och vi hade slutat att ta in tid, det var snarare så att Flat Out ökade på sitt försprång. Vi började så smått acceptera att vi skulle få stryk.

    Då kom anropet från bilen. Vi hade kört ner i Mjölby och behövde hjälp att bärgas därifrån. Det varvet tog 8 minuter att fullfölja och när bilen var uppdragen igen hade Flat Out ytterligare 3 varv på oss. Spelet var över.

    Men vi hänger f..n inte läpp för det. Så här väljer vi att se på det:

    1. Vi körde 24 timmar. Det är en prestation i sig

    2. Vi klarade av ett brott på en länkarm. Det är en riktigt stor prestation.

    3. Vi hade riktigt riktigt fina varvtider i vår 88 hästkrafters Mazda. Vi körde faktiskt ifrån många betydligt mer motorstarka konkurrenter och under ett par timmar på morgonkvisten var vi snabbast av alla på banan. Balans heter det.

    Så vi har minst 3 orsaker att vara riktigt glada. Dessutom blir det ett nytt race i Mars. Då ska det bli andra bullar….

    Permalink | Leave a comment