├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── RELEASE_NOTES.txt ├── Vagrantfile ├── build.xml ├── checkstyle_result └── .gitignore ├── composer.json ├── config ├── codeigniter.cfg.xml ├── default.cfg.xml ├── sameline.cfg.xml ├── spaceindent.cfg.xml ├── symfony.cfg.xml ├── test.cfg.xml └── zend.cfg.xml ├── html ├── README ├── css │ └── global.css ├── images │ ├── Logo_phpcheckstyle.png │ ├── Logo_phpcheckstyle.svg │ └── spacer.gif └── template │ ├── detail.tmpl │ ├── detail_body.tmpl │ ├── detail_foot.tmpl │ ├── detail_head.tmpl │ ├── files.tmpl │ ├── files_body.tmpl │ ├── files_foot.tmpl │ ├── footer.tmpl │ ├── header.tmpl │ └── summary.tmpl ├── index.php ├── phpcheckstyle ├── phpcheckstyle.cmd ├── phpcheckstyle.sh ├── phpcheckstyle_sample.sh ├── phpunit.sh ├── phpunit.xml ├── run.php ├── runFromWeb.php ├── src └── PHPCheckstyle │ ├── Config │ ├── CheckArrayStyleConfig.php │ ├── CheckStyleConfig.php │ └── CheckXMLStyleConfig.php │ ├── Lang │ ├── en-us.ini │ ├── fr-fr.ini │ └── kr.ini │ ├── PHPCheckstyle.php │ ├── Reporter │ ├── ArrayReporter.php │ ├── ConsoleReporter.php │ ├── HTMLConsoleFormatReporter.php │ ├── HTMLFormatReporter.php │ ├── NullReporter.php │ ├── PlainFormatReporter.php │ ├── Reporter.php │ ├── Reporters.php │ ├── XmlConsoleFormatReporter.php │ ├── XmlFormatReporter.php │ └── XmlNCSSReporter.php │ ├── StatementItem.php │ ├── StatementStack.php │ ├── TokenInfo.php │ ├── Tokenizer.php │ ├── VariableInfo.php │ └── _Constants.php ├── test ├── AliasesTest.php ├── CommentsTest.php ├── DeprecationTest.php ├── GoodTest.php ├── IndentationTest.php ├── MetricsTest.php ├── NamingTest.php ├── OptimizationTest.php ├── OtherTest.php ├── PHPTagsTest.php ├── ProhibitedTest.php ├── StrictCompareTest.php ├── TestRunner.php ├── UnusedTest.php └── sample │ ├── _bad_naming.php │ ├── bad_alias.php │ ├── bad_comments.php │ ├── bad_deprecation.php │ ├── bad_indentation.php │ ├── bad_indentation_array.php │ ├── bad_metrics.php │ ├── bad_optimisation.php │ ├── bad_other.php │ ├── bad_php_tags_end_not_needed.php │ ├── bad_php_tags_text_after_end.php │ ├── bad_prohibited.php │ ├── bad_space_after_control.php │ ├── bad_spaces.php │ ├── bad_strictcompare.php │ ├── bad_unused.php │ ├── closure_in_string.php │ ├── empty.php │ ├── emptyline.php │ ├── good.php │ ├── good_anonymous_function.php │ ├── good_do_while.php │ ├── good_doc.php │ ├── good_exception.php │ ├── good_function_naming.php │ ├── good_indentation_array.php │ ├── good_indentation_newline.php │ ├── good_indentation_space.php │ ├── good_unused.php │ ├── issue29.php │ ├── issue48sample.php │ ├── issue53.php │ ├── issue55.php │ ├── issue56.php │ ├── issue58.php │ ├── issue59.php │ ├── issue61.php │ ├── issue69.php │ ├── issue70.php │ ├── issue73.php │ ├── issue78.php │ ├── issuegithub32.php │ ├── issuegithub40.php │ ├── issuegithub62.php │ ├── issuegithub65.php │ ├── issuegithub66.php │ ├── issuegithub89.php │ ├── switch_multi_case.php │ ├── t_and_equal.php │ ├── test_unused_2.php │ ├── todo.php │ └── unterminated_comment.php ├── vagrant_config └── scripts │ ├── install_composer.sh │ └── install_composer_libraries.sh └── vendor ├── autoload.php ├── composer ├── ClassLoader.php ├── autoload_classmap.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php ├── autoload_static.php └── platform_check.php ├── myclabs └── deep-copy │ └── src │ └── DeepCopy │ └── deep_copy.php └── phpunit └── phpunit └── src └── Framework └── Assert └── Functions.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vagrant/ 3 | composer.lock 4 | style-report/ 5 | vendor/ 6 | checkstyle_resultncss.xml 7 | .project 8 | .models 9 | .buildpath 10 | .settings 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - '5.6' 4 | - '7.0' 5 | - '7.1' 6 | before_install: 7 | - chmod +x phpunit.sh 8 | - chmod +x phpcheckstyle.sh 9 | before_script: composer update 10 | script: 11 | - ./phpunit.sh 12 | - ./phpcheckstyle.sh -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHPCheckstyle 2 | 3 | [![Build Status](https://travis-ci.org/PHPCheckstyle/phpcheckstyle.svg?branch=master)](https://travis-ci.org/PHPCheckstyle/phpcheckstyle) 4 | 5 | ## Overview 6 | 7 | PHPCheckstyle is an open-source tool that helps PHP programmers 8 | adhere to certain coding conventions. The tools checks the input PHP 9 | source code and reports any deviations from the coding convention. 10 | 11 | The tool uses the PEAR Coding Standards as the default coding convention. 12 | But it allows you to configure it to suit your coding standards. 13 | 14 | Please visit [https://github.com/PHPCheckstyle/phpcheckstyle/wiki](https://github.com/PHPCheckstyle/phpcheckstyle/wiki) for 15 | more information and documentation 16 | 17 | 18 | ## Requirements 19 | 20 | - PHP 5.0 or newer. 21 | - Web browser to view the checkstyle report (only for html view) 22 | - That's all. 23 | 24 | 25 | ## Installation 26 | 27 | ### Installation with Composer 28 | 29 | ```sh 30 | composer require phpcheckstyle/phpcheckstyle 31 | ``` 32 | 33 | or Add `phpcheckstyle/phpcheckstyle` as a requirement to `composer.json`: 34 | 35 | ```json 36 | { 37 | "require": { 38 | "phpcheckstyle/phpcheckstyle": "dev-master" 39 | } 40 | } 41 | ``` 42 | 43 | Update your packages with `composer update` or if installing from fresh, with `composer install`. 44 | 45 | ### Manual Installation 46 | 47 | Just download [https://github.com/PHPCheckstyle/phpcheckstyle/archive/master.zip](https://github.com/PHPCheckstyle/phpcheckstyle/archive/master.zip) and unzip the distribution. 48 | 49 | ```bash 50 | $> unzip PhpCheckstyle.zip 51 | ``` 52 | 53 | This will create a directory called `phpcheckstyle` and expand all 54 | files in it. 55 | 56 | 57 | ### Testing with Vagrant 58 | 59 | * install [VirtualBox](https://www.virtualbox.org/) 60 | * install [Vagrant](https://www.vagrantup.com/) 61 | * launch `vagrant up` in the project root directory to start the VM 62 | 63 | * In case of problem with the "guest additions", launch : 64 | 65 | >vagrant plugin install vagrant-vbguest 66 | 67 | * to run PHPCheckstyle on itself, type `vagrant provision --provision-with run_phpcheckstyle` 68 | * to run PHPUnit, type `vagrant provision --provision-with run_phpunit` 69 | * to log inside the VM, type `vagrant ssh` 70 | 71 | ## Usage 72 | 73 | - Change directory to the PHPCheckstyle installation directory. 74 | 75 | ```bash 76 | $> cd phpcheckstyle 77 | ``` 78 | 79 | - Execute the `run.php` script providing the `--src` option. 80 | 81 | ```bash 82 | $> php run.php --src 83 | ``` 84 | 85 | - Use the `--help` option to see more options 86 | 87 | ```bash 88 | $> php run.php --help 89 | ``` 90 | 91 | 92 | # License 93 | See [LICENSE](/LICENSE.txt) 94 | -------------------------------------------------------------------------------- /RELEASE_NOTES.txt: -------------------------------------------------------------------------------- 1 | PHPCheckstyle Release Notes 2 | =========================== 3 | 4 | 5 | Version 0.14.9 6 | -------------- 7 | * Issue #93 : Use Bootstrap4 for styling (thanks to HCrane) 8 | * Issue #94 : Add no space after control stmt test option (thanks to CharlotteDunois) 9 | 10 | Version 0.14.8 11 | -------------- 12 | * Issue #92 : checkWhiteSpaceBefore "{", unless it's in ${var} 13 | * Issue #89 : False error "The function parameters must match those in its docblock @param" when using local variable tag 14 | 15 | 16 | Version 0.14.7 17 | -------------- 18 | * Issue #81 : Fail to detect private functions with spaces after function (thanks to Hans-Christian Halfbrodt) 19 | * Fix square bracket for arrays on method assignation with test case. (thanks to GuillermoMI) 20 | * Add flag to force error level only on console report (thanks to Jean-Philippe Quéméner) 21 | * Issue #82 : Cannot define independent rules for function parameter namings and local variable namings (thanks to dpalic) 22 | * Issue #84 : Set maximum errors for build fail (thanks to hafah) 23 | 24 | 25 | Version 0.14.6 26 | -------------- 27 | * Added config for Symfony standards 28 | * Issue #70 : List the statement types in a interface 29 | * Issue #69 : Whitespace must not follow : exception for comments 30 | * Issue #66 : Indentation level inside an array 31 | * Issue #65 : Indentation level should increase inside a case 32 | * Issue #64 : Silence doc warnings when @inheritdoc is present 33 | 34 | 35 | Version 0.14.5 36 | -------------- 37 | * Issue #62 : Corrected the indentation level count for short array syntax 38 | * Issue #41 : Ability to add exceptions to "unused variable" test 39 | * Issue #24 : Grouped cases must contain a break 40 | * Issue #23 : Added a --time option on the CLI to print the processing time 41 | * Corrected line numbering for indentation check 42 | * Added PHPUnit tests 43 | * Added Vagrant configuration files to spawn a local VirtualBox VM 44 | * Added TravisCI configuration file 45 | * When running from CLI PHPCheckstyle return code is now <> 0 if some errors are detected 46 | 47 | 48 | Version 0.14.4 49 | -------------- 50 | * Moved the project from SourceForge to Github 51 | 52 | 53 | Version 0.14.3 54 | -------------- 55 | * New check : thisInStatic. 56 | 57 | 58 | Version 0.14.2 59 | -------------- 60 | * Added a summary output on the command line (thanks to jarrettchisholm). 61 | * New check : Detect forbidden keywords (thanks to jarrettchisholm). 62 | * New check : Detect forbidden regular expressions like IP address, etc. (thanks to jarrettchisholm). 63 | * New check : Detect variable variable. 64 | 65 | 66 | Version 0.14.1 67 | -------------- 68 | * Improved performances A LOT ! 69 | * Better checking of ignored files/directories 70 | * Added T_FINALLY token to the parser 71 | * Better messages for logical operators && and || 72 | * Outsourced the error messages 73 | * Added French translation 74 | * New check : NPath complexity 75 | * New check : Prefered quotes style 76 | 77 | 78 | Version 0.14.0 79 | -------------- 80 | * PSR-0 Compliance (thanks to James Brooks). 81 | * new Array Reporter (thanks to James Brooks). 82 | * Allow an array of configuration values to be passed through, rather than XML (thanks to James Brooks). 83 | * Better detection of package names for NCSS report (filename by default, namespace if present). 84 | * New check : "mandatoryHeader" to verify the presence of a header for each file. 85 | * New check : "localScopeVariableLength" to verify the lenght of the variable names. 86 | NOTE : This may generate lots of new warnings. 87 | 88 | 89 | Version 0.13.2 90 | -------------- 91 | * Change in the default configurations : White spaces are required before and after the concatenation operator ".". 92 | NOTE : This may generate lots of new warnings. 93 | * Issue 77: Exclude files/directories option from the web launcher. 94 | 95 | 96 | Version 0.13.1 97 | -------------- 98 | * Issue 71: False positive : close() 99 | * Issue 72: Allow the config file to be in any directory 100 | * Issue 73: False positive : delete() 101 | * Issue 74: Allow multiple src directories/files in the command line. 102 | 103 | 104 | Version 0.13.0 105 | -------------- 106 | * Issue 70: Simplification of the "strictCompare" rule. When active this rule will be checked everywhere. 107 | This may generate lots of warnings. 108 | 109 | 110 | Version 0.12.5 111 | -------------- 112 | * Issue 69: PHP tag should be at the beginning of the line 113 | 114 | 115 | Version 0.12.4 116 | -------------- 117 | * Issue 59: Enhancement: Add allowed exceptions to docBlocks section of configuration 118 | * Issue 63: Catch parsing exceptions and other PHP errors 119 | * Issue 65: Add composer.json file 120 | * Issue 66: block closure '}' detected in a string 121 | 122 | 123 | Version 0.12.3 124 | -------------- 125 | * Issue 52: Config for PHP frameworks 126 | * Issue 54: Detect empty files 127 | 128 | 129 | Version 0.12.2 130 | -------------- 131 | * Issue 53: else/ elseif without curly braces (thanks to Maximilian Pachl) 132 | * Added a check of the curly braces after a "else" statement 133 | 134 | 135 | Version 0.12.1 136 | -------------- 137 | * Issue 50 : --exclude flag is not honoured 138 | * No space expected after '=' when used in assignation by reference 139 | 140 | 141 | Version 0.12.0 142 | -------------- 143 | * New reporter : xml_console (for use with Netbeans plugin : http://sourceforge.net/projects/phpmdnb/), thanks to Jens Radtke 144 | * Issue 47 : False docBlock error when using empty return in a method 145 | * Added the version number in the run.php file 146 | 147 | 148 | Version 0.11.0 149 | -------------- 150 | * Issue 1 : Refactoring of the code 151 | * Issue 43: False positive for "The function throws an exception" 152 | * Issue 41: False positive : The statement 'while' must contain its code within a {} block. 153 | * Issue 24: Line length checking of non-PHP code should be toggleable in a config option. 154 | * Added Zend Framework style configuration file 155 | 156 | 157 | Version 0.10.6 158 | -------------- 159 | * Issue 40: Propose replacement for PHP aliases 160 | * Now generates absolute file path in the reports (allow Jenkins to display the source code) 161 | 162 | 163 | Version 0.10.5 164 | -------------- 165 | * Issue 39: Error on closing tag for space-based indentation checks 166 | * Issue 38: False positive for : The function XXX must have a docblock comment 167 | 168 | 169 | Version 0.10.4 170 | -------------- 171 | * Issue 37: Web interface (currently very limited) 172 | 173 | 174 | Version 0.10.3 175 | -------------- 176 | * Issue 35: New Rule : Use of "==" in strpos 177 | * Bug correction: Not correctly counting the end of a stack item after a "ELSE IF" 178 | 179 | 180 | Version 0.10.2 181 | -------------- 182 | * issue 27 : Unused code is wrongly detected 183 | * issue 26 : Empty lines in comments will corrupt line numbering 184 | * issue 25 : Error: Notice: Trying to get property of non-object 185 | * issue 23 : Wrong indentation level for curly braces on new line 186 | * Embedding of CSS inside HTML Header 187 | * Fix for null pointer exceptions when run against newer code 188 | 189 | 190 | Version 0.10.1 191 | -------------- 192 | * Fixed Rule encapsedVariablesInsideString : False positive when using heredoc 193 | * Rule needBraces : False positive for do/while 194 | 195 | 196 | Version 0.10.0 197 | -------------- 198 | * Added support for interfaces 199 | * Improved checking of variables by scope 200 | * Rewrote the _checkLargeLine() function 201 | * Added rudimentary progress reporting, invoked with the parameter --progress 202 | * Edited Style errors for clarity 203 | * Included regex in the error report for appropriate types 204 | * Errors are now described in much greater detail and more consistent language 205 | * Removed 'old : ' and 'new : ' prefixes from constructor name hints 206 | * New output type - html console 207 | * Removed "controlStructNeedCurly" rule, duplicate with "needBraces" rule 208 | * Completed the test cases 209 | * The tokenizer now returns T_TAB separately from T_WHITESPACE 210 | 211 | Thanks a lot to Justin Creasey and Adam King 212 | 213 | 214 | Version 0.9.8 215 | ------------- 216 | * Issue 3: Check for unreachable code 217 | 218 | 219 | Version 0.9.7 220 | ------------- 221 | * Deprecation of long $HTTP_*_VARS predefined variables 222 | * Configuration of system variables lists 223 | * Issue 10: Don't blindly remove first 2 chars of file path 224 | 225 | 226 | Version 0.9.6 227 | ------------- 228 | * Corrected the inner assignement rule (wasn't detecting the end of a control statement if no brackets). 229 | * Corrected the file exclusion list. 230 | * Corrected a bug with nextToken at the end of a file. 231 | * Added the possibility to add exceptions to the checkVariableNaming rule 232 | 233 | 234 | Version 0.9.5 235 | ------------- 236 | * Corrected a bug with @SuppressWarnings on a class. 237 | 238 | 239 | Version 0.9.4 240 | ------------- 241 | * Add __invoke and __callStatic to the special functions. 242 | 243 | 244 | Version 0.9.3 245 | ------------- 246 | * Refactoring of the indentation check (thanks to Charles Marion). The "noTabs" rule is replaced by the "indentation" rule. 247 | * Reactivation of the "noSpaceAfterControlStmt" rule. 248 | * Correction of a bug with multiple output files. 249 | * Added a rule for the naming of protected functions. 250 | 251 | 252 | Version 0.9.2 253 | ------------- 254 | * Multiple output files (separated by a comma in the --format command line parameter) 255 | 256 | 257 | Version 0.9.1 258 | ------------- 259 | * Possibility to scan multiple source directories (separated by a comma in the --src command line parameter) 260 | 261 | 262 | Version 0.9 263 | ------------- 264 | * Dependency on lib_xsl removed 265 | * Documentation updated to link to the new project home (http://code.google.com/p/phpcheckstyle/) 266 | * HTML Report validated with W3C validator, HTML characters escaped 267 | * Possibility to suppress some warnings using annotations before a class or a function in the code (@SuppressWarnings) 268 | * New logo 269 | 270 | 271 | Version 0.8.11 272 | ------------- 273 | * Refactoring : Added the current stack of instruction to provide contextual information 274 | * New test : unusedCode 275 | * New test : deprecated functions 276 | 277 | 278 | Version 0.8.10 279 | ------------- 280 | * Corrected JavaNCSS count of packages 281 | * New test : functionInsideLoop 282 | 283 | 284 | Version 0.8.9 285 | ------------- 286 | * Corrected LevelOfNesting calculation 287 | * New test : oneClassPerFile 288 | 289 | 290 | Version 0.8.8 291 | ------------- 292 | * New test : variableNaming 293 | * Added the possibility to configure the regular expressions for the naming rules 294 | * A taste of it's own dog food 295 | 296 | 297 | Version 0.8.7 298 | ------------- 299 | * New test : checkUnusedVariables 300 | * New test : checkUnusedFunctionParameters 301 | 302 | 303 | Version 0.8.6 304 | ------------- 305 | * Correction in the controlStructOpenCurly check. 306 | 307 | 308 | Version 0.8.5 309 | ------------- 310 | * New test : empty statement (;;) 311 | * New test : inner assignment 312 | * New test : unused private functions 313 | 314 | 315 | Version 0.8.4 316 | ------------- 317 | * Refactored the whiteSpaceBore / noSpaceBefore / whiteSpaceAfter / noSpaceAfter methods. 318 | * Refactored peekNextValidToken and peekPrvsValidToken to avoid using call by reference 319 | * New test : function length 320 | * New test : empty block (if ($a) {} ) 321 | * New test : avoid heredoc 322 | * New test : excessive function parameters 323 | * New test : need braces 324 | * New test : switch have a default and default is at the end 325 | * New test : switch case should have a break 326 | 327 | 328 | Version 0.8.3 329 | ------------- 330 | * Added some tests on the docbloc (@param and @return) 331 | * Added a test on unary operators 332 | * Corrected a bug in the detection of the end of a function 333 | 334 | 335 | Version 0.8.2 336 | ------------- 337 | * Added new test (Use boolean operators instead of logical operators) 338 | 339 | 340 | Version 0.8.1 341 | ------------- 342 | * Corrected a bug with NEW_LINE caracter inside a constant string 343 | 344 | 345 | Version 0.8 346 | ----------- 347 | * Replaced the token_get_all() function by token_get_all_nl() found here : http://php.net/manual/fr/function.token-get-all.php 348 | This function returns the new line caracters as a token. This solve some problems and impact a lot of code. 349 | * Added the possibility to generate a report on the number of lines of code compatible with the JavaNCSS format (http://kclee.de/clemens/java/javancss/) 350 | * Added new tests (Extract TODOs, Avoid passing references) 351 | * Some refactoring 352 | 353 | 354 | Version 0.7.1 355 | ------------- 356 | * Added new tests (Cyclomatic Complexity, ...) 357 | 358 | 359 | Version 0.7 360 | ----------- 361 | * All tests are now configurable 362 | * Included some propositions from the forum 363 | * Added the possibility to define a severity level for each test rule 364 | * Ignoring the .svn repositories 365 | * Changed the XML outpout in order to be compatible with the checkstyle format (http://checkstyle.sourceforge.net/) 366 | 367 | 368 | Version 0.6.1 369 | ------------- 370 | * Bugs Fixes 371 | * HTML Ouput changes 372 | 373 | 374 | Version 0.6 375 | ----------- 376 | 377 | This is the very first release of Spike PHPCheckstyle. It is an alpha release. 378 | 379 | * Known Issues 380 | 381 | 1. Indentation: The tools checks only for existence of tabs in a line. It 382 | does not check that every line follows the 4 space indentation rule. 383 | 2. Issue with do/while loop: The tool generates wrong errors when a do/while 384 | loop contains a while loop or another do/while loop. 385 | 3. Global variable nameing: Global variable naming convention checks are 386 | not implemented. 387 | 4. Docblocks: The tool currently checks only for the existence of docblocks 388 | but not for all the required elements within it. 389 | 5. Issue: when a cpp comment (starting with //) is followed by "}" in the 390 | next line, reports that the "}" should be on a new line (even though it 391 | is on a new line). 392 | 6. Expects the configuration file to be {install-dir}/config/pear.cfg.xml. 393 | Can not change it. 394 | 7. Some of the tests are not configurable (that is, they are checked, but can not 395 | disable them). They are: "spaceAfterControlStmt", "spaceAfterSemicolon", 396 | "noSpaceAfterFuncCall" and "spaceAfterFuncNameDefn". (Refer documentation 397 | for more details on configurations). 398 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | 5 | # Vagrantfile API/syntax version. 6 | VAGRANTFILE_API_VERSION = "2" 7 | 8 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 9 | 10 | config.vm.box = "geerlingguy/debian9" 11 | 12 | #Dev config 13 | config.vm.define "phpcheckstyle_dev" do |phpcheckstyle_dev| 14 | end 15 | config.vm.provider "virtualbox" do |v| 16 | v.memory = 3072 17 | v.cpus = 4 18 | v.name = "phpcheckstyle_dev" 19 | end 20 | 21 | config.vm.network "private_network", ip: "192.168.50.66" 22 | 23 | 24 | config.vm.synced_folder ".", "/vagrant", type: "virtualbox" 25 | 26 | # 27 | # Middleware installation 28 | # The following provisions are executed as "root" 29 | # 30 | config.vm.provision "install_composer", privileged: true, type: "shell", inline: "/vagrant/vagrant_config/scripts/install_composer.sh" 31 | 32 | # 33 | # Middleware installation 34 | # The following provisions are executed as "vagrant" 35 | # 36 | config.vm.provision "install_composer_libraries", privileged: false, type: "shell", inline: "/vagrant/vagrant_config/scripts/install_composer_libraries.sh" 37 | 38 | # 39 | # Documentation & Code quality & Developers provisions 40 | # The following provisions are executed as "vagrant" and are only run when called explicitly 41 | # 42 | 43 | if ARGV.include? '--provision-with' 44 | config.vm.provision "run_phpunit", privileged: false, type: "shell", inline: "/vagrant/vendor/bin/phpunit" 45 | end 46 | 47 | if ARGV.include? '--provision-with' 48 | config.vm.provision "run_phpcheckstyle", privileged: false, type: "shell", inline: "/vagrant/phpcheckstyle.sh" 49 | end 50 | 51 | config.vm.provision "shell", inline: "echo 'The VM is ready on 192.168.50.66'", run: "always" 52 | 53 | end 54 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | Static Analysis tool for PHP. 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 43 | 44 | 45 | 46 | 47 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | Windows 108 | 109 | 110 | 111 | 112 | 113 | 114 | Unix 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /checkstyle_result/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "phpcheckstyle/phpcheckstyle", 3 | "description" : "PHPCheckstyle is an open-source tool that helps PHP programmers adhere to certain coding conventions", 4 | "type" : "library", 5 | "keywords" : [ 6 | "checkstyle", 7 | "standard", 8 | "convention" 9 | ], 10 | "homepage" : "https://github.com/phpcheckstyle/phpcheckstyle/", 11 | "license" : "OSL-2.1", 12 | "require" : { 13 | "php" : ">=5.0.0" 14 | }, 15 | "require-dev" : { 16 | "phpunit/phpunit" : ">=7.0.0" 17 | }, 18 | "support" : { 19 | "wiki" : "https://github.com/phpcheckstyle/phpcheckstyle/wiki", 20 | "source" : "https://github.com/phpcheckstyle/phpcheckstyle" 21 | }, 22 | "autoload" : { 23 | "psr-0" : { 24 | "PHPCheckstyle\\" : "src/" 25 | }, 26 | "files" : [ 27 | "src/PHPCheckstyle/_Constants.php" 28 | ] 29 | }, 30 | "bin" : [ 31 | "phpcheckstyle" 32 | ] 33 | } -------------------------------------------------------------------------------- /config/sameline.cfg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 324 | 325 | 326 | 327 | 328 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | -------------------------------------------------------------------------------- /html/README: -------------------------------------------------------------------------------- 1 | Holds files required for html format reporting. 2 | -------------------------------------------------------------------------------- /html/css/global.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #ffffff; 3 | color: #000000; 4 | margin: 10px; 5 | font-family: Verdana, Arial, Helvetica, sans-serif; 6 | font-size: 13px; 7 | } 8 | 9 | .banner { 10 | width: 100%; 11 | font-size: 20px; 12 | text-align: center; 13 | } 14 | 15 | .banner a { 16 | text-decoration: none; 17 | } 18 | 19 | .title { 20 | font-size: 30px; 21 | font-weight: bold; 22 | vertical-align: top; 23 | } 24 | 25 | h1 { 26 | font-size: 20px; 27 | font-weight: bold; 28 | text-align: center; 29 | } 30 | 31 | h2 { 32 | font-size: 15px; 33 | font-weight: bold; 34 | text-align: center; 35 | } 36 | 37 | .dataTable { 38 | border: 1px solid #CCCCCC; 39 | border-spacing: 0px; 40 | background-color: #F1F1F1; 41 | border-collapse: collapse; 42 | } 43 | 44 | .tableHead { 45 | background-color: #92A9ED; 46 | font-weight: bold; 47 | padding: 2px; 48 | padding-left: 5px; 49 | text-align: center; 50 | vertical-align: top; 51 | border: 1px solid #CCCCCC; 52 | } 53 | 54 | .tableCell { 55 | border: 1px solid #CCCCCC; 56 | padding: 2px; 57 | } 58 | 59 | .tableCellBold { 60 | border: 1px solid #CCCCCC; 61 | padding: 2px; 62 | font-weight: bold; 63 | } 64 | 65 | .emphasis { 66 | color: #990000; 67 | font-weight: bold; 68 | } 69 | 70 | .footer { 71 | 72 | } 73 | 74 | .copyright { 75 | color: #4076B9; 76 | font-size: 10px; 77 | } 78 | 79 | .tableHead { 80 | background-color: #92A9ED; 81 | font-weight: bold; 82 | padding: 2px; 83 | padding-left: 5px; 84 | text-align: center; 85 | vertical-align: top; 86 | border: 1px solid #CCCCCC; 87 | } 88 | 89 | .tableCell { 90 | border: 1px solid #CCCCCC; 91 | padding: 2px; 92 | } 93 | 94 | .tableCellBold { 95 | border: 1px solid #CCCCCC; 96 | padding: 2px; 97 | font-weight: bold; 98 | } 99 | 100 | .emphasis { 101 | color: #990000; 102 | font-weight: bold; 103 | } 104 | 105 | .footer { 106 | 107 | } 108 | 109 | .copyright { 110 | color: #4076B9; 111 | font-size: 10px; 112 | } 113 | 114 | 115 | .badge-error { 116 | color: #212529; 117 | background-color: #dc3545; 118 | } -------------------------------------------------------------------------------- /html/images/Logo_phpcheckstyle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPCheckstyle/phpcheckstyle/aa5c8f2229f6137fc1866faa5bf0569103e760a0/html/images/Logo_phpcheckstyle.png -------------------------------------------------------------------------------- /html/images/spacer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPCheckstyle/phpcheckstyle/aa5c8f2229f6137fc1866faa5bf0569103e760a0/html/images/spacer.gif -------------------------------------------------------------------------------- /html/template/detail.tmpl: -------------------------------------------------------------------------------- 1 |
2 |

Detail

-------------------------------------------------------------------------------- /html/template/detail_body.tmpl: -------------------------------------------------------------------------------- 1 | 2 | %%line%% 3 | %%message%% 4 | %%level%% 5 | -------------------------------------------------------------------------------- /html/template/detail_foot.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | -------------------------------------------------------------------------------- /html/template/detail_head.tmpl: -------------------------------------------------------------------------------- 1 |

%%filepath%%

2 | 3 | 4 | 5 | 8 | 11 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /html/template/files.tmpl: -------------------------------------------------------------------------------- 1 |
2 |

Files With Errors

3 |
6 | Line # 7 | 9 | Error Message 10 | 12 | Level 13 |
4 | 5 | 6 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /html/template/files_body.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /html/template/files_foot.tmpl: -------------------------------------------------------------------------------- 1 | 2 |
7 | Filename 8 | 10 | Number of Errors 11 |
3 | %%filepath%% 4 | %%file_errors%%
3 | -------------------------------------------------------------------------------- /html/template/footer.tmpl: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /html/template/header.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PHPCheckstyle Results 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /html/template/summary.tmpl: -------------------------------------------------------------------------------- 1 |
2 |

Summary

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
Report generated at%%nb_timestamp%%
Number of Files Tested%%nb_files%%
Number of Files With Errors%%nb_files_error%%
Total Number of Errors%%nb_total_errors%%
21 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PHPCheckstyle Web Interface 5 | 6 | 7 | 8 | 9 | 10 |

 PHPCheckstyle

11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 44 | 45 | 46 |
File(s) to analyse *
Destination directory
Configuration file
Exclude Files or Directories *
Language 39 | 40 | 41 | 42 | 43 |
47 | 48 |
49 |
50 | 51 | 52 | 53 |
54 |
55 | 56 |
57 | 58 | * Multiple filenames or directory names can be added, comma separated. 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /phpcheckstyle: -------------------------------------------------------------------------------- 1 | BASEDIR=$(dirname "$0") 2 | 3 | php $BASEDIR/run.php "$@" 4 | -------------------------------------------------------------------------------- /phpcheckstyle.cmd: -------------------------------------------------------------------------------- 1 | echo "PHP Checkstyle script" 2 | php -c C:\ms4w\Apache\cgi-bin\php.ini run.php --src ./test/issue56.php --outdir ./checkstyle_result --format html,xml --linecount --debug 3 | pause 4 | -------------------------------------------------------------------------------- /phpcheckstyle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "PHP CheckStyle script" 3 | # php run.php --src ./test/sample/issuegithub89.php --outdir ./checkstyle_result --config default.cfg.xml --format html,xml --linecount --debug 4 | php run.php --src ./src --outdir ./checkstyle_result --config default.cfg.xml --format html,xml --linecount 5 | 6 | -------------------------------------------------------------------------------- /phpcheckstyle_sample.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "PHP CheckStyle script" 3 | php run.php --src ./test/sample --outdir ./checkstyle_result --config default.cfg.xml --format html,xml --linecount 4 | 5 | -------------------------------------------------------------------------------- /phpunit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./vendor/bin/phpunit -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ./test/AliasesTest.php 5 | ./test/CommentsTest.php 6 | ./test/DeprecationTest.php 7 | ./test/GoodTest.php 8 | ./test/IndentationTest.php 9 | ./test/MetricsTest.php 10 | ./test/NamingTest.php 11 | ./test/OptimizationTest.php 12 | ./test/OtherTest.php 13 | ./test/PHPTagsTest.php 14 | ./test/ProhibitedTest.php 15 | ./test/StrictCompareTest.php 16 | ./test/UnusedTest.php 17 | 18 | 19 | 20 | 21 | ./src 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /run.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | 12 | "Root of the source directory tree or a file (can be repeated for multiple sources).", 13 | 14 | "--exclude" => 15 | "[Optional] A directory or file that needs to be excluded (can be repeated for multiple exclusions).", 16 | 17 | "--format" => 18 | "[Optional] Output format (html/text/xml/xml_console/console/html_console). Defaults to 'html'.", 19 | 20 | "--outdir" => 21 | "[Optional] Report Directory. Defaults to './style-report'.", 22 | 23 | "--config" => 24 | "[Optional] The name of the config file'.", 25 | 26 | "--debug" => 27 | "[Optional] Add some debug logs (warning, very verbose)'.", 28 | 29 | "--linecount" => 30 | "[Optional] Generate a report on the number of lines of code (JavaNCSS format)'.", 31 | 32 | "--progress" => 33 | "[Optional] Prints a message noting the file and every line that is covered by PHPCheckStyle.", 34 | 35 | "--lang" => 36 | "[Optional] Language file to use for the result (en-us by default).", 37 | 38 | "--max-errors" => 39 | "[Optional] Defines how many errors are still allowed for a pass (0 by default)", 40 | 41 | "--level" => 42 | "[Optional] Specifies the output level (info, warning, error). For console report only.", 43 | 44 | "--quiet" => 45 | "[Optional] Quiet mode.", 46 | 47 | "--time" => 48 | "[Optional] Display the process time in ms .", 49 | 50 | "--help" => 51 | "Display this usage information.", 52 | ); 53 | 54 | echo "Usage: " . $_SERVER['argv'][0] . " \n"; 55 | echo "\n"; 56 | echo " Options: \n"; 57 | foreach ($options as $option => $description) { 58 | echo " " . str_pad($option, 16, " ") . $description . "\n"; 59 | } 60 | exit(); 61 | } 62 | 63 | // default values 64 | $options['src'] = false; 65 | $options['exclude'] = array(); 66 | $options['format'] = "html"; // default format 67 | $options['outdir'] = "./style-report"; // default ouput directory 68 | $options['config'] = "default.cfg.xml"; 69 | $options['debug'] = false; 70 | $options['progress'] = false; 71 | $options['lang'] = 'en-us'; 72 | $options['quiet'] = false; 73 | $options['time'] = false; 74 | $options['max-errors'] = 0; 75 | $lineCountFile = null; 76 | 77 | // loop through user input 78 | for ($i = 1; $i < $_SERVER["argc"]; $i ++) { 79 | switch ($_SERVER["argv"][$i]) { 80 | case "--src": 81 | $i++; 82 | $options['src'][] = $_SERVER['argv'][$i]; 83 | break; 84 | 85 | case "--outdir": 86 | $i++; 87 | $options['outdir'] = $_SERVER['argv'][$i]; 88 | break; 89 | 90 | case "--exclude": 91 | $i++; 92 | $options['exclude'][] = $_SERVER['argv'][$i]; 93 | break; 94 | 95 | case "--format": 96 | $i++; 97 | $options['format'] = $_SERVER['argv'][$i]; 98 | break; 99 | 100 | case "--lang": 101 | $i++; 102 | $options['lang'] = $_SERVER['argv'][$i]; 103 | break; 104 | 105 | case "--level": 106 | $i++; 107 | $options['level'] = $_SERVER['argv'][$i]; 108 | break; 109 | 110 | case "--config": 111 | $i++; 112 | $options['config'] = $_SERVER['argv'][$i]; 113 | break; 114 | 115 | case "--debug": 116 | $options['debug'] = true; 117 | break; 118 | 119 | case "--linecount": 120 | $options['linecount'] = true; 121 | break; 122 | 123 | case "--max-errors": 124 | $i++; 125 | $options['max-errors'] = $_SERVER['argv'][$i]; 126 | break; 127 | 128 | case "--progress": 129 | $options['progress'] = true; 130 | break; 131 | 132 | case "--quiet": 133 | $options['quiet'] = true; 134 | break; 135 | 136 | case "--time": 137 | $options['time'] = true; 138 | break; 139 | 140 | case "--help": 141 | usage(); 142 | break; 143 | 144 | default: 145 | usage(); 146 | break; 147 | } 148 | } 149 | 150 | define("PHPCHECKSTYLE_HOME_DIR", dirname(__FILE__)); 151 | // require_once PHPCHECKSTYLE_HOME_DIR."/src/PHPCheckstyle.php"; 152 | require_once "vendor/autoload.php"; 153 | 154 | // check for valid format and set the output file name 155 | // right now the output file name is not configurable, only 156 | // the output directory is configurable (from command line) 157 | $knownFormats = array( 158 | 'html', 159 | 'html_console', 160 | 'console', 161 | 'text', 162 | 'xml', 163 | 'xml_console', 164 | 'array', 165 | 'null' 166 | ); 167 | $formats = explode(',', $options['format']); 168 | $unknownFormats = array_diff($formats, $knownFormats); 169 | if (!empty($unknownFormats)) { 170 | echo sprintf("\nUnknown format %s.\n\n", implode(', ', $unknownFormats)); 171 | usage(); 172 | } 173 | 174 | // check that source directory is specified and is valid 175 | if (!$options['src']) { 176 | echo "\nPlease specify a source directory/file using --src option.\n\n"; 177 | usage(); 178 | } 179 | if (isset($options['max-errors']) && $options['max-errors'] === '') { 180 | echo "\nPlease specify a number when using --max-errors option.\n\n"; 181 | usage(); 182 | } 183 | 184 | if (!empty($options['linecount'])) { 185 | $lineCountFile = "ncss.xml"; 186 | } 187 | 188 | if ($options['time']) { 189 | $time_start = microtime(); 190 | } 191 | $level = INFO; 192 | if (isset($options['level'])) { 193 | switch ($options['level']) { 194 | case INFO: 195 | $level = INFO; 196 | break; 197 | case WARNING: 198 | $level = WARNING; 199 | break; 200 | case ERROR: 201 | $level = ERROR; 202 | break; 203 | default: 204 | echo "Unkown level '" . $options['level'] . "'. Ingnoring level'\n"; 205 | } 206 | } 207 | 208 | 209 | $style = new PHPCheckstyle\PHPCheckstyle($formats, $options['outdir'], $options['config'], $lineCountFile, $options['debug'], $options['progress'], $level); 210 | 211 | if (file_exists(__DIR__ . '/src/PHPCheckstyle/Lang/' . $options['lang'] . '.ini')) { 212 | $style->setLang($options['lang']); 213 | } 214 | 215 | $style->processFiles($options['src'], $options['exclude']); 216 | 217 | $errorCounts = $style->getErrorCounts(); 218 | 219 | if (!$options['quiet']) { 220 | echo PHP_EOL . "Summary" . PHP_EOL; 221 | echo "=======" . PHP_EOL . PHP_EOL; 222 | echo "Errors: " . $errorCounts[ERROR] . PHP_EOL; 223 | echo "Ignores: " . $errorCounts[IGNORE] . PHP_EOL; 224 | echo "Infos: " . $errorCounts[INFO] . PHP_EOL; 225 | echo "Warnings: " . $errorCounts[WARNING] . PHP_EOL; 226 | echo "=======" . PHP_EOL . PHP_EOL; 227 | echo "Reporting Completed." . PHP_EOL; 228 | 229 | if ($options['time']) { 230 | $time_end = microtime(); 231 | $time = $time_end - $time_start; 232 | 233 | echo "Processing ended in " . $time . " ms" . PHP_EOL; 234 | } 235 | 236 | } 237 | 238 | $exitCode = ($errorCounts[ERROR] > $options['max-errors']) ? 1 : 0; 239 | exit($exitCode); 240 | -------------------------------------------------------------------------------- /runFromWeb.php: -------------------------------------------------------------------------------- 1 | array( 30 | "type" => "spaces", 31 | "number" => 2 32 | ) 33 | ); 34 | 35 | // Launch PHPCheckstyle 36 | $style = new PHPCheckstyle\PHPCheckstyle($formats, $resultDir, $configFile, null, false, true); 37 | if (file_exists(__DIR__ . '/src/PHPCheckstyle/Lang/' . $options['lang'] . '.ini')) { 38 | $style->setLang($options['lang']); 39 | } 40 | $style->processFiles($sources, $options['exclude']); 41 | 42 | echo "
" . print_r($style->_reporter->reporters[0]->outputFile, TRUE) . "
"; 43 | 44 | echo "Reporting Completed.

"; 45 | 46 | echo 'Display Results : ' . $resultDir . ''; 47 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Config/CheckArrayStyleConfig.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | class CheckArrayStyleConfig extends CheckStyleConfig { 10 | 11 | /** 12 | * Constructor. 13 | * 14 | * @param String $configArray 15 | * The path of the config file 16 | */ 17 | public function __construct($configArray) { 18 | 19 | // If the path is a valid file we use it as is 20 | if (is_array($configArray)) { 21 | $this->config = $configArray; 22 | } else { 23 | echo "Config must be an array"; 24 | exit(0); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Config/CheckStyleConfig.php: -------------------------------------------------------------------------------- 1 | 8 | * @SuppressWarnings docBlocks 9 | */ 10 | abstract class CheckStyleConfig { 11 | 12 | /** 13 | * Stores the check configuration. 14 | * 15 | * @var array 16 | */ 17 | public $config = array(); 18 | 19 | /** 20 | * Return a true if the test exist, false otherwise. 21 | * 22 | * @param String $test 23 | * name of the test 24 | * @return Boolean true if test exists. 25 | */ 26 | public function getTest($test) { 27 | return (array_key_exists(strtolower($test), $this->config)); 28 | } 29 | 30 | /** 31 | * Return a list of items associed with a test. 32 | * 33 | * @param String $test 34 | * name of the test 35 | * @return array the list of items for this test. 36 | */ 37 | public function getTestItems($test) { 38 | $test = strtolower($test); 39 | return isset($this->config[$test]['item']) ? $this->config[$test]['item'] : false; 40 | } 41 | 42 | /** 43 | * Return a list of exception for a test. 44 | * 45 | * @param String $test 46 | * name of the test 47 | * @return array the list of exceptions for this test. 48 | */ 49 | public function getTestExceptions($test) { 50 | $test = strtolower($test); 51 | return isset($this->config[$test]['exception']) ? $this->config[$test]['exception'] : false; 52 | } 53 | 54 | /** 55 | * Return a list of items associed with a configuration. 56 | * 57 | * @param String $config 58 | * name of the config 59 | * @return array the list of items for this config. 60 | */ 61 | public function getConfigItems($config) { 62 | $config = strtolower($config); 63 | return isset($this->config[$config]) ? $this->config[$config] : array(); 64 | } 65 | 66 | /** 67 | * Return the level of severity of a test. 68 | * 69 | * @param String $test 70 | * name of the test 71 | * @return the level of severity. 72 | */ 73 | public function getTestLevel($test) { 74 | $ret = WARNING; 75 | 76 | $test = strtolower($test); 77 | 78 | if (array_key_exists($test, $this->config) && array_key_exists('level', $this->config[$test])) { 79 | $ret = strtolower($this->config[$test]['level']); 80 | } 81 | 82 | $invalidLevels = array( 83 | ERROR, 84 | IGNORE, 85 | INFO, 86 | WARNING 87 | ); 88 | 89 | if (!in_array($ret, $invalidLevels)) { 90 | echo "Invalid level for test " . $test . " : " . $ret; 91 | $ret = WARNING; 92 | } 93 | 94 | return $ret; 95 | } 96 | 97 | /** 98 | * Return the regular expression linked to the test. 99 | * 100 | * @param String $test 101 | * name of the test 102 | * @return the regular expression. 103 | */ 104 | public function getTestRegExp($test) { 105 | $test = strtolower($test); 106 | $ret = ""; 107 | if (array_key_exists($test, $this->config) && array_key_exists('regexp', $this->config[$test])) { 108 | $ret = $this->config[$test]['regexp']; 109 | } 110 | 111 | return $ret; 112 | } 113 | 114 | /** 115 | * Return the list of deprecated method and their replacement. 116 | * 117 | * @param String $test 118 | * name of the test 119 | * @return the list of depecated values. 120 | */ 121 | public function getTestDeprecations($test) { 122 | $test = strtolower($test); 123 | $ret = ""; 124 | if (array_key_exists($test, $this->config)) { 125 | $ret = $this->config[$test]; 126 | } 127 | 128 | return $ret; 129 | } 130 | 131 | /** 132 | * Return the list of aliases and their replacement. 133 | * 134 | * @param String $test 135 | * name of the test 136 | * @return the list of replaced values. 137 | */ 138 | public function getTestAliases($test) { 139 | $test = strtolower($test); 140 | $ret = ""; 141 | if (array_key_exists($test, $this->config)) { 142 | $ret = $this->config[$test]; 143 | } 144 | 145 | return $ret; 146 | } 147 | 148 | /** 149 | * Return the list of replacements. 150 | * 151 | * @param String $test 152 | * name of the test 153 | * @return the list of replaced values. 154 | */ 155 | public function getTestReplacements($test) { 156 | $test = strtolower($test); 157 | $ret = ""; 158 | if (array_key_exists($test, $this->config)) { 159 | $ret = $this->config[$test]; 160 | } 161 | 162 | return $ret; 163 | } 164 | 165 | /** 166 | * Return the value of a property 167 | * 168 | * @param String $test 169 | * name of the test 170 | * @param String $property 171 | * name of the property 172 | * @return the value. 173 | */ 174 | public function getTestProperty($test, $property) { 175 | $test = strtolower($test); 176 | $property = strtolower($property); 177 | if (array_key_exists($test, $this->config) && array_key_exists($property, $this->config[$test])) { 178 | return $this->config[$test][$property]; 179 | } else { 180 | return false; 181 | } 182 | } 183 | 184 | /** 185 | * Change the value of a property 186 | * 187 | * @param String $test 188 | * name of the test 189 | * @param String $property 190 | * name of the property 191 | * @param String $value 192 | * the value. 193 | */ 194 | public function setTestProperty($test, $property, $value) { 195 | $test = strtolower($test); 196 | $property = strtolower($property); 197 | if (array_key_exists($test, $this->config) && array_key_exists($property, $this->config[$test])) { 198 | $this->config[$test][$property] = $value; 199 | } 200 | } 201 | 202 | /** 203 | * Indicate if a value is an exception for the test. 204 | * 205 | * @param String $test 206 | * name of the test 207 | * @param String $value 208 | * the value 209 | * @return Boolean true is the value is listed as an exception. 210 | */ 211 | public function isException($test, $value) { 212 | $exceptions = $this->getTestExceptions($test); 213 | return (!empty($exceptions) && in_array($value, $exceptions)); 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Config/CheckXMLStyleConfig.php: -------------------------------------------------------------------------------- 1 | 8 | * @SuppressWarnings checkUnusedPrivateFunctions 9 | */ 10 | class CheckXMLStyleConfig extends CheckStyleConfig { 11 | 12 | // The configuration file 13 | private $file; 14 | private $currentTest = false; 15 | private $currentConfig = false; 16 | private $xmlParser; 17 | 18 | /** 19 | * Constructor. 20 | * 21 | * @param String $configFile 22 | * The path of the config file 23 | */ 24 | public function __construct($configFile) { 25 | 26 | // If the path is a valid file we use it as is 27 | if (is_file($configFile)) { 28 | $this->file = $configFile; 29 | } else { 30 | // Otherwise we look in the config directory 31 | $this->file = PHPCHECKSTYLE_HOME_DIR . "/config/" . $configFile; 32 | 33 | if (!is_file($this->file)) { 34 | echo "Config file not found : " . $configFile; 35 | exit(0); 36 | } 37 | } 38 | 39 | $this->xmlParser = xml_parser_create(); 40 | xml_set_object($this->xmlParser, $this); 41 | xml_set_element_handler($this->xmlParser, "_startElement", "_endElement"); 42 | xml_set_character_data_handler($this->xmlParser, "_gotCdata"); 43 | xml_set_default_handler($this->xmlParser, "_gotCdata"); 44 | } 45 | 46 | /** 47 | * Destructor. 48 | */ 49 | public function __destruct() { 50 | if ($this->xmlParser !== null && is_resource($this->xmlParser)) { 51 | xml_parser_free($this->xmlParser); 52 | } 53 | } 54 | 55 | /** 56 | * Parses the configuration file and stores the values. 57 | * 58 | * @throws Exception if cannot access file 59 | */ 60 | public function parse() { 61 | $fp = fopen($this->file, "r"); 62 | if (!$fp) { 63 | throw new Exception("Could not open XML input file"); 64 | } 65 | 66 | $data = fread($fp, 4096); 67 | while ($data) { 68 | if (!xml_parse($this->xmlParser, $data, feof($fp))) { 69 | $errorString = xml_error_string(xml_get_error_code($this->xmlParser)); 70 | $errorLineNo = xml_get_current_line_number($this->xmlParser); 71 | $msg = sprintf("Warning: XML error: %s at line %d", $errorString, $errorLineNo); 72 | echo $msg; 73 | $this->config = array(); 74 | } 75 | 76 | $data = fread($fp, 4096); 77 | } 78 | } 79 | 80 | /** 81 | * SAX function indicating start of an element 82 | * Store the TEST and PROPERTY values in an array 83 | * 84 | * @param Parser $parser 85 | * the parser 86 | * @param Elem $elem 87 | * name of element 88 | * @param Attributes $attrs 89 | * list of attributes of the element 90 | * @SuppressWarnings cyclomaticComplexity checkUnusedFunctionParameters 91 | */ 92 | private function _startElement($parser, $elem, $attrs) { 93 | switch ($elem) { 94 | 95 | // Case of a configuration property 96 | case 'CONFIG': 97 | $this->currentConfig = strtolower($attrs['NAME']); 98 | $this->config[$this->currentConfig] = array(); 99 | break; 100 | 101 | // Case of a configuration property item 102 | case 'CONFIGITEM': 103 | $this->config[$this->currentConfig][] = $attrs['VALUE']; 104 | break; 105 | 106 | // Case of a test rule 107 | case 'TEST': 108 | $this->currentTest = strtolower($attrs['NAME']); 109 | $this->config[$this->currentTest] = array(); 110 | 111 | if (isset($attrs['LEVEL'])) { 112 | $this->config[$this->currentTest]['level'] = $attrs['LEVEL']; 113 | } 114 | 115 | if (isset($attrs['REGEXP'])) { 116 | $this->config[$this->currentTest]['regexp'] = $attrs['REGEXP']; 117 | } 118 | break; 119 | 120 | // Case of a propertie of a rule (name / value) 121 | case 'PROPERTY': 122 | $pname = $attrs['NAME']; 123 | $pval = true; 124 | if (array_key_exists('VALUE', $attrs)) { 125 | $pval = $attrs['VALUE']; 126 | } 127 | $this->config[$this->currentTest][strtolower($pname)] = $pval; 128 | break; 129 | 130 | // Case of a item of a list of values of a rule 131 | case 'ITEM': 132 | if (isset($attrs['VALUE'])) { 133 | $this->config[$this->currentTest]['item'][] = $attrs['VALUE']; 134 | } 135 | break; 136 | 137 | // Case of an exception to a rule 138 | case 'EXCEPTION': 139 | if (isset($attrs['VALUE'])) { 140 | $this->config[$this->currentTest]['exception'][] = $attrs['VALUE']; 141 | } 142 | break; 143 | 144 | // Case of a deprecated function 145 | case 'DEPRECATED': 146 | if (isset($attrs['OLD'])) { 147 | $this->config[$this->currentTest][strtolower($attrs['OLD'])]['old'] = $attrs['OLD']; 148 | } 149 | if (isset($attrs['NEW'])) { 150 | $this->config[$this->currentTest][strtolower($attrs['OLD'])]['new'] = $attrs['NEW']; 151 | } 152 | if (isset($attrs['VERSION'])) { 153 | $this->config[$this->currentTest][strtolower($attrs['OLD'])]['version'] = $attrs['VERSION']; 154 | } 155 | break; 156 | 157 | // Case of an alias function 158 | case 'ALIAS': 159 | if (isset($attrs['OLD'])) { 160 | $this->config[$this->currentTest][strtolower($attrs['OLD'])]['old'] = $attrs['OLD']; 161 | } 162 | if (isset($attrs['NEW'])) { 163 | $this->config[$this->currentTest][strtolower($attrs['OLD'])]['new'] = $attrs['NEW']; 164 | } 165 | break; 166 | 167 | // Case of a replacement 168 | case 'REPLACEMENT': 169 | if (isset($attrs['OLD'])) { 170 | $this->config[$this->currentTest][strtolower($attrs['OLD'])]['old'] = $attrs['OLD']; 171 | } 172 | if (isset($attrs['NEW'])) { 173 | $this->config[$this->currentTest][strtolower($attrs['OLD'])]['new'] = $attrs['NEW']; 174 | } 175 | break; 176 | 177 | default: 178 | break; 179 | } 180 | } 181 | 182 | /** 183 | * SAX function indicating end of element 184 | * Currently we dont need to do anything here 185 | * 186 | * @param Parser $parser 187 | * @param String $name 188 | */ 189 | private function _endElement($parser, $name) {} 190 | 191 | /** 192 | * SAX function for processing CDATA 193 | * Currently we dont need to do anything here 194 | * 195 | * @param Parser $parser 196 | * @param String $name 197 | */ 198 | private function _gotCdata($parser, $name) {} 199 | } 200 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Lang/en-us.ini: -------------------------------------------------------------------------------- 1 | [messages] 2 | PHP_EXPCEPTION="PHP Exception: %s." 3 | INDENTATION_TAB="Tab indentation must not be used." 4 | INDENTATION_WHITESPACE="Whitespace indentation must not be used." 5 | INDENTATION_LEVEL="The indentation level must be %s but was %s." 6 | WRONG_OPEN_TAG="The PHP open tag must be ' 8 | */ 9 | class ArrayReporter extends Reporter { 10 | 11 | /** 12 | * Constructor. 13 | */ 14 | public function __construct() { 15 | $this->outputFile = array(); 16 | } 17 | 18 | /** 19 | * {@inheritdoc} 20 | * 21 | * @param Integer $line 22 | * the line number 23 | * @param String $check 24 | * the name of the check 25 | * @param String $message 26 | * the text to log 27 | * @param String $level 28 | * the severity level 29 | */ 30 | public function writeError($line, $check, $message, $level = WARNING) { 31 | // echo $this->currentPhpFile . " " . $level . " Line:" . $line . " - " . $message . "\n"; 32 | $this->outputFile[$this->currentPhpFile][$line][] = array( 33 | "level" => $level, 34 | "line" => $line, 35 | "message" => $message, 36 | "check" => $check, 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Reporter/ConsoleReporter.php: -------------------------------------------------------------------------------- 1 | reportingLevel = $this->_calculateLevel($level); 22 | parent::__construct(); 23 | } 24 | 25 | /** 26 | * 27 | * {@inheritdoc} 28 | * 29 | * @param Integer $line 30 | * the line number 31 | * @param String $check 32 | * the name of the check 33 | * @param String $message 34 | * the text to log 35 | * @param String $level 36 | * the severity level 37 | * @SuppressWarnings 38 | */ 39 | public function writeError($line, $check, $message, $level = WARNING) { 40 | $messageLevel = $this->_calculateLevel($level); 41 | if ($messageLevel >= $this->reportingLevel) { 42 | echo "File \"" . $this->currentPhpFile . "\"" . " " . $level . ", line " . $line . " - " . $message . "\n"; 43 | } 44 | } 45 | 46 | /** 47 | * Transforms a specified level from a String to an Integer 48 | * so one can check if the level is above or below a 49 | * certain threshold. 50 | * 51 | * Unknown level will return 1 which is equal to INFO 52 | * 53 | * @param String $level 54 | * 55 | * @return int INFO = 1 56 | * WARNING = 2 57 | * ERROR = 3 58 | * unknown = 1 59 | */ 60 | private function _calculateLevel($level) { 61 | switch ($level) { 62 | case INFO: 63 | return 1; 64 | case WARNING: 65 | return 2; 66 | case ERROR: 67 | return 3; 68 | default: 69 | return 1; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Reporter/HTMLConsoleFormatReporter.php: -------------------------------------------------------------------------------- 1 | ofile); 33 | $this->ofolder = $ofolder; 34 | } 35 | 36 | /** 37 | * 38 | * @see Reporter::start 39 | */ 40 | public function start() { 41 | parent::start(); 42 | } 43 | 44 | /** 45 | * 46 | * @see Reporter::stop 47 | */ 48 | public function stop() { 49 | // Call a last time the currentlyProcessing function for the last file in memory 50 | $this->currentlyProcessing(''); 51 | 52 | // Write the HTML header 53 | $this->writeFragment($this->_readTemplate("header")); 54 | 55 | // Write the summary 56 | $summaryTmpl = $this->_readTemplate("summary"); 57 | $values = array(); 58 | $values['%%nb_files%%'] = $this->nbfiles - 1; 59 | $values['%%nb_files_error%%'] = $this->nbfilesError; 60 | $values['%%nb_total_errors%%'] = $this->nbErrors; 61 | $values['%%nb_timestamp%%'] = date('Y-m-d H:i:s'); 62 | $this->writeFragment($this->_fillTemplate($summaryTmpl, $values)); 63 | 64 | // Write the list of files 65 | $this->writeFragment($this->_readTemplate("files")); 66 | $this->writeFragment($this->files); 67 | $this->writeFragment($this->_readTemplate("files_foot")); 68 | 69 | // Write the detail of the checks 70 | $this->writeFragment($this->_readTemplate("detail")); 71 | $this->writeFragment($this->detail); 72 | 73 | // Write the footer 74 | $this->writeFragment($this->_readTemplate("footer")); 75 | 76 | // Copy the CSS file 77 | copy(PHPCHECKSTYLE_HOME_DIR . "/html/css/global.css", $this->ofolder . "/global.css"); 78 | copy(PHPCHECKSTYLE_HOME_DIR . "/html/images/Logo_phpcheckstyle.png", $this->ofolder . "/Logo_phpcheckstyle.png"); 79 | } 80 | 81 | /** 82 | * Writes an HTML fragment to the output file. 83 | * 84 | * @param $fragment string 85 | * The HTML fragment to write. 86 | */ 87 | protected function writeFragment($fragment) { 88 | $fileHandle = fopen($this->outputFile, $this->writeMode); 89 | 90 | fwrite($fileHandle, $fragment); 91 | fclose($fileHandle); 92 | 93 | // appends to the file initially created with $writeMode = "w" 94 | $this->writeMode = 'a'; 95 | } 96 | 97 | /** 98 | * Read the content of a template file. 99 | * 100 | * @param $templateFile The 101 | * name of the file 102 | */ 103 | private function _readTemplate($templateFile) { 104 | $filename = PHPCHECKSTYLE_HOME_DIR . "/html/template/" . $templateFile . ".tmpl"; 105 | $handle = fopen($filename, "r"); 106 | $contents = fread($handle, filesize($filename)); 107 | fclose($handle); 108 | 109 | return $contents; 110 | } 111 | 112 | /** 113 | * Replace some values in a template file. 114 | * 115 | * @param $template The 116 | * content of the template 117 | * @param $values The 118 | * array of values to replace 119 | */ 120 | private function _fillTemplate($template, $values) { 121 | foreach ($values as $key => $value) { 122 | $template = str_replace($key, $value, $template); 123 | } 124 | 125 | return $template; 126 | } 127 | 128 | /** 129 | * 130 | * @see Reporter::currentlyProcessing Process a new PHP file. 131 | * 132 | * @param $phpFile the 133 | * file currently processed 134 | */ 135 | public function currentlyProcessing($phpFile) { 136 | 137 | // Update the counters 138 | $this->nbfiles ++; 139 | 140 | // If the previous file contained errors 141 | if ($this->fileErrors !== 0) { 142 | 143 | // Add the previous file to the summary 144 | if ($this->previousFile !== '') { 145 | $fileBody = $this->_readTemplate("files_body"); 146 | $values = array(); 147 | $values['%%filepath%%'] = $this->previousFile; 148 | $values['%%file_errors%%'] = $this->fileErrors; 149 | $fileBody = $this->_fillTemplate($fileBody, $values); 150 | $this->files .= $fileBody; 151 | } 152 | 153 | // Add the previous file to the details 154 | $detailHead = $this->_readTemplate("detail_head"); 155 | $values = array(); 156 | $values['%%filepath%%'] = $this->previousFile; 157 | $detailHead = $this->_fillTemplate($detailHead, $values); 158 | $this->detail .= $detailHead; 159 | $this->detail .= $this->fileDetail; 160 | $this->detail .= $this->_readTemplate("detail_foot"); 161 | } 162 | 163 | $this->previousFile = $phpFile; 164 | $this->fileDetail = ''; 165 | $this->fileErrors = 0; 166 | $this->fileInError = false; 167 | } 168 | 169 | /** 170 | * {@inheritdoc} 171 | * 172 | * @param Integer $line 173 | * the line number 174 | * @param String $check 175 | * the name of the check 176 | * @param String $message 177 | * the text 178 | * @param String $level 179 | * the severity level 180 | */ 181 | public function writeError($line, $check, $message, $level = WARNING) { 182 | 183 | // Update the counters 184 | $this->nbErrors ++; 185 | $this->fileErrors ++; 186 | if ($this->fileInError === false) { 187 | $this->nbfilesError ++; 188 | $this->fileInError = true; 189 | } 190 | 191 | // Add the check to the details 192 | $detail = $this->_readTemplate("detail_body"); 193 | $values = array(); 194 | $values['%%message%%'] = htmlspecialchars($message); 195 | $values['%%check%%'] = $check; 196 | $values['%%line%%'] = $line; 197 | $values['%%level%%'] = $level; 198 | $detail = $this->_fillTemplate($detail, $values); 199 | $this->fileDetail .= $detail; 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Reporter/NullReporter.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class PlainFormatReporter extends Reporter { 20 | 21 | private $ofile = "/style-report.txt"; // The output file name 22 | 23 | /** 24 | * Constructor; calls parent's constructor 25 | * 26 | * @param $ofolder the 27 | * folder name 28 | */ 29 | public function __construct($ofolder = false) { 30 | parent::__construct($ofolder, $this->ofile); 31 | } 32 | 33 | /** 34 | * 35 | * @see Reporter::start make sure that the file is opened 36 | * 37 | */ 38 | public function start() { 39 | $this->_ensureFileOpen(); 40 | } 41 | 42 | /** 43 | * 44 | * @see Reporter::stop make sure that the file is closed 45 | */ 46 | public function stop() { 47 | $this->_ensureFileClosed(); 48 | } 49 | 50 | /** 51 | * 52 | * @see Reporter::stop Add a new line with the new file name 53 | * 54 | * @param $phpFile the 55 | * file currently processed 56 | */ 57 | public function currentlyProcessing($phpFile) { 58 | parent::currentlyProcessing($phpFile); 59 | $this->_write("\nFile: " . $this->currentPhpFile . PHP_EOL); 60 | } 61 | 62 | /** 63 | * {@inheritdoc} 64 | * 65 | * @param Integer $line 66 | * the line number 67 | * @param String $check 68 | * the name of the check 69 | * @param String $message 70 | * the text 71 | * @param String $level 72 | * the severity level 73 | * @SuppressWarnings checkUnusedFunctionParameters 74 | */ 75 | public function writeError($line, $check, $message, $level = WARNING) { 76 | $msg = "\t" . $level . " Line:" . $line . ": " . $message . PHP_EOL; 77 | $this->_write($msg); 78 | } 79 | 80 | private function _write($message) { 81 | if ($this->_ensureFileOpen()) { 82 | fwrite($this->fileHandle, $message); 83 | } 84 | } 85 | 86 | private function _ensureFileOpen() { 87 | if ($this->fileHandle === false) { 88 | $this->fileHandle = fopen($this->outputFile, "w"); 89 | } 90 | return $this->fileHandle; 91 | } 92 | 93 | private function _ensureFileClosed() { 94 | if ($this->fileHandle) { 95 | fclose($this->fileHandle); 96 | $this->outputFile = false; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Reporter/Reporter.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | abstract class Reporter { 12 | 13 | public $outputFile; 14 | 15 | protected $currentPhpFile; 16 | 17 | /** 18 | * Constructor 19 | * Intializes variables. 20 | * Note that the output file is initialized 21 | * to stdout if not provided 22 | * 23 | * @param $ofolder the 24 | * output folder 25 | * @param $ofile the 26 | * output filename 27 | */ 28 | public function __construct($ofolder = false, $ofile = "error.txt") { 29 | 30 | // creating the folder if it does not already exist. 31 | if ($ofolder !== false && !file_exists($ofolder)) { 32 | mkdir($ofolder, 0755, true); 33 | } 34 | 35 | // setting the output file to default. 36 | $this->outputFile = $ofolder . $ofile; 37 | 38 | if (!($this->outputFile)) { 39 | $this->outputFile = "php://output"; 40 | } 41 | } 42 | 43 | /** 44 | * Any initialization before starting to write should be done here 45 | */ 46 | public function start() {} 47 | 48 | /** 49 | * Any cleanup work before closing should be done here. 50 | */ 51 | public function stop() {} 52 | 53 | /** 54 | * this function called everytime a new file has been started for 55 | * checkstyle processing. 56 | * 57 | * @param $phpFile new 58 | * file's name 59 | */ 60 | public function currentlyProcessing($phpFile) { 61 | $this->currentPhpFile = $phpFile; 62 | } 63 | 64 | /** 65 | * abstract function. 66 | * For every error, this function is called once with the line where 67 | * the error occurred and the actual error message 68 | * It is the responsibility of the derived class to appropriately 69 | * format it and write it into the output file 70 | * 71 | * @param $line line 72 | * number of the error 73 | * @param String $check 74 | * the name of the check 75 | * @param $message error 76 | * message 77 | * @param $regex the 78 | * regular expression (if applicable) 79 | * @param $level the 80 | * severity level 81 | */ 82 | public abstract function writeError($line, $check, $message, $level = WARNING); 83 | } 84 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Reporter/Reporters.php: -------------------------------------------------------------------------------- 1 | reporters[] = $reported; 20 | } 21 | 22 | /** 23 | * Any initialization before starting to write should be done here 24 | */ 25 | public function start() { 26 | foreach ($this->reporters as $reporter) { 27 | $reporter->start(); 28 | } 29 | } 30 | 31 | /** 32 | * Any cleanup work before closing should be done here. 33 | */ 34 | public function stop() { 35 | foreach ($this->reporters as $reporter) { 36 | $reporter->stop(); 37 | } 38 | } 39 | 40 | /** 41 | * this function called everytime a new file has been started for 42 | * checkstyle processing. 43 | * 44 | * @param $phpFile new 45 | * file's name 46 | */ 47 | public function currentlyProcessing($phpFile) { 48 | foreach ($this->reporters as $reporter) { 49 | $reporter->currentlyProcessing($phpFile); 50 | } 51 | } 52 | 53 | /** 54 | * For every error, this function is called once with the line where 55 | * the error occurred and the actual error message 56 | * It is the responsibility of the derived class to appropriately 57 | * format it and write it into the output file 58 | * 59 | * @param $line line 60 | * number of the error 61 | * @param String $check 62 | * the name of the check 63 | * @param $message error 64 | * message 65 | * @param $level the 66 | * severity level 67 | */ 68 | public function writeError($line, $check, $message, $level = WARNING) { 69 | foreach ($this->reporters as $reporter) { 70 | $reporter->writeError($line, $check, $message, $level); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Reporter/XmlConsoleFormatReporter.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * 11 | * 12 | * 13 | * 14 | * 15 | * 16 | * 17 | * 18 | * ================================ 19 | * 20 | * @author Hari Kodungallur 21 | */ 22 | class XmlConsoleFormatReporter extends XmlFormatReporter { 23 | 24 | /** 25 | * 26 | * @see Reporter::start add the last element to the tree and save the DOM tree to the 27 | * xml file 28 | * 29 | */ 30 | public function stop() { 31 | $this->_endCurrentElement(); 32 | echo $this->getDocument()->saveXML(); 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Reporter/XmlFormatReporter.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * 13 | * 14 | * 15 | * 16 | * 17 | * 18 | * 19 | * 20 | * ================================ 21 | * 22 | * @author Hari Kodungallur 23 | */ 24 | class XmlFormatReporter extends Reporter { 25 | 26 | private $document = false; 27 | 28 | private $root = false; 29 | 30 | private $currentElement = false; 31 | 32 | private $ofile = "/style-report.xml"; // The output file name 33 | 34 | /** 35 | * Constructor; calls parent's constructor 36 | * 37 | * @param $ofolder the 38 | * folder name 39 | */ 40 | public function __construct($ofolder = false) { 41 | parent::__construct($ofolder, $this->ofile); 42 | } 43 | 44 | /** 45 | * 46 | * @see Reporter::start create the document root () 47 | * 48 | */ 49 | public function start() { 50 | $this->initXml(); 51 | } 52 | 53 | /** 54 | * 55 | * @see Reporter::start add the last element to the tree and save the DOM tree to the 56 | * xml file 57 | * 58 | */ 59 | public function stop() { 60 | $this->endCurrentElement(); 61 | $this->document->save($this->outputFile); 62 | } 63 | 64 | /** 65 | * 66 | * @see Reporter::currentlyProcessing add the previous element to the tree and start a new element 67 | * for the new file 68 | * 69 | * @param $phpFile the 70 | * file currently processed 71 | */ 72 | public function currentlyProcessing($phpFile) { 73 | parent::currentlyProcessing($phpFile); 74 | $this->endCurrentElement(); 75 | $this->startNewElement($phpFile); 76 | } 77 | 78 | /** 79 | * {@inheritdoc} 80 | * 81 | * @param Integer $line 82 | * the line number 83 | * @param String $check 84 | * the name of the check 85 | * @param String $message 86 | * error message 87 | * @param String $level 88 | * the severity level 89 | */ 90 | public function writeError($line, $check, $message, $level = WARNING) { 91 | $errEl = $this->document->createElement("error"); 92 | $errEl->setAttribute("line", $line); 93 | $errEl->setAttribute("column", "1"); 94 | $errEl->setAttribute("severity", $level); 95 | $errEl->setAttribute("message", $message); 96 | $errEl->setAttribute("source", $check); 97 | 98 | if (empty($this->currentElement)) { 99 | $this->startNewElement(""); 100 | } 101 | $this->currentElement->appendChild($errEl); 102 | } 103 | 104 | /** 105 | * XML header. 106 | */ 107 | protected function initXml() { 108 | $this->document = new DomDocument("1.0"); 109 | $this->root = $this->document->createElement('checkstyle'); 110 | $this->root->setAttribute("version", "1.0.0"); 111 | $this->document->appendChild($this->root); 112 | } 113 | 114 | /** 115 | * Creates a new file element. 116 | * 117 | * @param string file 118 | */ 119 | protected function startNewElement($fileEl) { 120 | $this->currentElement = $this->document->createElement("file"); 121 | 122 | // remove the "./" at the beginning ot the path in case of relative path 123 | if (substr($fileEl, 0, 2) === './') { 124 | $fileEl = substr($fileEl, 2); 125 | } 126 | $this->currentElement->setAttribute("name", $fileEl); 127 | } 128 | 129 | /** 130 | * Returns the document. 131 | * 132 | * @return DomDocument object 133 | */ 134 | protected function getDocument() { 135 | return $this->document; 136 | } 137 | 138 | /** 139 | * Close the current element. 140 | */ 141 | protected function endCurrentElement() { 142 | if ($this->currentElement) { 143 | $this->root->appendChild($this->currentElement); 144 | } 145 | } 146 | } 147 | 148 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/Reporter/XmlNCSSReporter.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * 2009-09-01 13 | * 14 | * 15 | * 16 | * fr.ifn.calcul 17 | * 3 18 | * 9 19 | * 186 20 | * 12 21 | * 41 22 | * 24 23 | * 0 24 | * 25 | * ================================ 26 | */ 27 | class XmlNCSSReporter { 28 | 29 | private $document = false; 30 | 31 | private $root = false; 32 | 33 | private $packages = false; 34 | 35 | private $objects = false; 36 | 37 | private $outputFile; 38 | 39 | private $lastPackageName = false; 40 | 41 | private $lastPackageChild = false; 42 | 43 | private $nbPackages = 0; 44 | 45 | private $packageClasses = 0; 46 | 47 | private $packageInterfaces = 0; 48 | 49 | private $packageFunctions = 0; 50 | 51 | private $packageNCSS = 0; 52 | 53 | private $packageJavadocs = 0; 54 | 55 | private $packageJavadocLines = 0; 56 | 57 | private $packageSingleCommentLines = 0; 58 | 59 | private $packageMultiCommentLines = 0; 60 | 61 | /** 62 | * Constructor; calls parent's constructor 63 | * 64 | * @param String $ofolder 65 | * the output folder 66 | * @param String $ofile 67 | * the output filename 68 | */ 69 | public function __construct($ofolder = false, $ofile = null) { 70 | $this->outputFile = $ofolder . $ofile; 71 | if (!$this->outputFile) { 72 | $this->outputFile = "php://output"; 73 | } 74 | // creating the folder if it does not already exist. 75 | if (!file_exists($ofolder)) { 76 | mkdir($ofolder, 0755, true); 77 | } 78 | } 79 | 80 | /** 81 | * 82 | * @see Reporter::start create the document root () 83 | * 84 | */ 85 | public function start() { 86 | $this->_initXml(); 87 | } 88 | 89 | /** 90 | * 91 | * @see Reporter::start add the last element to the tree and save the DOM tree to the 92 | * xml file 93 | * 94 | */ 95 | public function stop() { 96 | $this->root->appendChild($this->objects); 97 | $this->document->save($this->outputFile); 98 | } 99 | 100 | /** 101 | * 102 | * @see Reporter::currentlyProcessing add the previous element to the tree and start a new elemtn 103 | * for the new file 104 | * 105 | * @param String $phpFile 106 | * the file currently processed 107 | * @SuppressWarnings checkUnusedFunctionParameters The parameter is inherited 108 | */ 109 | public function currentlyProcessing($phpFile) {} 110 | 111 | /** 112 | * Write the count of lines for one file 113 | * 114 | * @param Integer $packageName 115 | * the package name 116 | * @param Integer $classes 117 | * the number of classes in the file 118 | * @param Integer $interfaces 119 | * the number of interfaces in the file 120 | * @param Integer $functions 121 | * the number of functions 122 | * @param Integer $ncss 123 | * the number of non empty lines of code 124 | * @param Integer $javadocs 125 | * the number of PHPDoc blocks 126 | * @param Integer $javadocLines 127 | * the number of PHPDoc lines 128 | * @param Integer $singleCommentLines 129 | * the number of single line comments 130 | * @param Integer $multiCommentLines 131 | * the number of multi-line comments 132 | */ 133 | public function writeFileCount($packageName, $classes, $interfaces, $functions, $ncss, $javadocs, $javadocLines, $singleCommentLines, $multiCommentLines) { 134 | 135 | if ($this->lastPackageName === $packageName) { 136 | 137 | // Add the values 138 | $this->packageClasses = $this->packageClasses + $classes; 139 | $this->packageInterfaces = $this->packageInterfaces + $interfaces; 140 | $this->packageFunctions = $this->packageFunctions + $functions; 141 | $this->packageNCSS = $this->packageNCSS + $ncss; 142 | $this->packageJavadocs = $this->packageJavadocs + $javadocs; 143 | $this->packageJavadocLines = $this->packageJavadocLines + $javadocLines; 144 | $this->packageSingleCommentLines = $this->packageSingleCommentLines + $singleCommentLines; 145 | $this->packageMultiCommentLines = $this->packageMultiCommentLines + $multiCommentLines; 146 | 147 | // Remove the last node 148 | $this->packages->removeChild($this->lastPackageChild); 149 | } else { 150 | 151 | $this->nbPackages ++; 152 | 153 | // Reset the values 154 | $this->packageClasses = $classes; 155 | $this->packageInterfaces = $interfaces; 156 | $this->packageFunctions = $functions; 157 | $this->packageNCSS = $ncss; 158 | $this->packageJavadocs = $javadocs; 159 | $this->packageJavadocLines = $javadocLines; 160 | $this->packageSingleCommentLines = $singleCommentLines; 161 | $this->packageMultiCommentLines = $multiCommentLines; 162 | } 163 | 164 | // 165 | // Create the package bloc 166 | // 167 | $e = $this->document->createElement("package"); 168 | 169 | $name = $this->document->createElement('name', $packageName); 170 | $e->appendChild($name); 171 | 172 | $classesE = $this->document->createElement('classes', $this->packageClasses + $this->packageInterfaces); 173 | $e->appendChild($classesE); 174 | 175 | // $interfacesE = $this->document->createElement('interfaces', $this->packageInterfaces); 176 | // $e->appendChild($interfacesE); 177 | 178 | $functionsE = $this->document->createElement('functions', $this->packageFunctions); 179 | $e->appendChild($functionsE); 180 | 181 | $ncssE = $this->document->createElement('ncss', $this->packageNCSS); 182 | $e->appendChild($ncssE); 183 | 184 | $javadocsE = $this->document->createElement('javadocs', $this->packageJavadocs); 185 | $e->appendChild($javadocsE); 186 | 187 | $javadocLinesE = $this->document->createElement('javadoc_lines', $this->packageJavadocLines); 188 | $e->appendChild($javadocLinesE); 189 | 190 | $singleCommentLinesE = $this->document->createElement('single_comment_lines', $this->packageSingleCommentLines); 191 | $e->appendChild($singleCommentLinesE); 192 | 193 | $multiCommentLinesE = $this->document->createElement('multi_comment_lines', $this->packageMultiCommentLines); 194 | $e->appendChild($multiCommentLinesE); 195 | 196 | $this->packages->appendChild($e); 197 | $this->lastPackageChild = $e; 198 | 199 | // 200 | // Create the object bloc 201 | // 202 | $obj = $this->document->createElement("object"); 203 | 204 | $objname = $this->document->createElement('name', $packageName); 205 | $obj->appendChild($objname); 206 | 207 | $objncss = $this->document->createElement('ncss', $ncss); 208 | $obj->appendChild($objncss); 209 | 210 | $objfunctions = $this->document->createElement('functions', $functions); 211 | $obj->appendChild($objfunctions); 212 | 213 | $objclasses = $this->document->createElement('classes', $classes); 214 | $obj->appendChild($objclasses); 215 | 216 | $objjavadocs = $this->document->createElement('javadocs', $javadocs); 217 | $obj->appendChild($objjavadocs); 218 | 219 | $this->objects->appendChild($obj); 220 | 221 | $this->lastPackageName = $packageName; 222 | } 223 | 224 | /** 225 | * Write the total count of lines for the project. 226 | * 227 | * @param Integer $nbFiles 228 | * the number of files. 229 | * @param Integer $classes 230 | * the number of classes 231 | * @param Integer $interfaces 232 | * the number of interfaces 233 | * @param Integer $functions 234 | * the number of functions 235 | * @param Integer $ncss 236 | * the number of non empty lines of code 237 | * @param Integer $javadocs 238 | * the number of PHPDoc blocks 239 | * @param Integer $javadocLines 240 | * the number of PHPDoc lines 241 | * @param Integer $singleCommentLines 242 | * the number of single line comments 243 | * @param Integer $multiCommentLines 244 | * the number of multi-line comments 245 | */ 246 | public function writeTotalCount($nbFiles, $classes, $interfaces, $functions, $ncss, $javadocs, $javadocLines, $singleCommentLines, $multiCommentLines) { 247 | 248 | // 249 | // Create the total bloc 250 | // 251 | $e = $this->document->createElement("total"); 252 | 253 | $classesE = $this->document->createElement('classes', $classes + $interfaces); 254 | $e->appendChild($classesE); 255 | 256 | // $interfacesE = $this->document->createElement('interfaces', $interfaces); 257 | // $e->appendChild($interfacesE); 258 | 259 | $functionsE = $this->document->createElement('functions', $functions); 260 | $e->appendChild($functionsE); 261 | 262 | $ncssE = $this->document->createElement('ncss', $ncss); 263 | $e->appendChild($ncssE); 264 | 265 | $javadocsE = $this->document->createElement('javadocs', $javadocs); 266 | $e->appendChild($javadocsE); 267 | 268 | $javadocLinesE = $this->document->createElement('javadoc_lines', $javadocLines); 269 | $e->appendChild($javadocLinesE); 270 | 271 | $singleCommentLinesE = $this->document->createElement('single_comment_lines', $singleCommentLines); 272 | $e->appendChild($singleCommentLinesE); 273 | 274 | $multiCommentLinesE = $this->document->createElement('multi_comment_lines', $multiCommentLines); 275 | $e->appendChild($multiCommentLinesE); 276 | 277 | $this->packages->appendChild($e); 278 | 279 | // 280 | // Create the table bloc 281 | // 282 | $table = $this->document->createElement("table"); 283 | $this->packages->appendChild($table); 284 | 285 | $header = $this->_createDOMLine("Packages", "Classes", "Functions", "NCSS", "Javadocs", "per"); 286 | $table->appendChild($header); 287 | 288 | $projectLine = $this->_createDOMLine($this->nbPackages, $classes, $functions, $ncss, $javadocs, "Project"); 289 | $table->appendChild($projectLine); 290 | 291 | if ($this->nbPackages === 0) { 292 | $packageLine = $this->_createDOMLine("", "", "", "", "", "Package"); 293 | } else { 294 | $packageLine = $this->_createDOMLine("", $classes / $this->nbPackages, $functions / $this->nbPackages, $ncss / $this->nbPackages, $javadocs / $this->nbPackages, "Package"); 295 | } 296 | $table->appendChild($packageLine); 297 | 298 | if ($classes === 0) { 299 | $packageLine = $this->_createDOMLine("", "", "", "", "", "Class"); 300 | } else { 301 | $packageLine = $this->_createDOMLine("", "", $functions / $classes, $ncss / $classes, $javadocs / $classes, "Class"); 302 | } 303 | $table->appendChild($packageLine); 304 | 305 | if ($functions === 0) { 306 | $packageLine = $this->_createDOMLine("", "", "", "", "", "Function"); 307 | } else { 308 | $packageLine = $this->_createDOMLine("", "", "", $ncss / $functions, $javadocs / $functions, "Function"); 309 | } 310 | $table->appendChild($packageLine); 311 | 312 | // 313 | // Create the averages bloc 314 | // 315 | $averages = $this->document->createElement("averages"); 316 | 317 | $avgNcss = $this->document->createElement('ncss', ($nbFiles === 0) ? 0 : ($ncss / $nbFiles)); 318 | $averages->appendChild($avgNcss); 319 | 320 | $avgNcss = $this->document->createElement('functions', ($nbFiles === 0) ? 0 : ($functions / $nbFiles)); 321 | $averages->appendChild($avgNcss); 322 | 323 | $avgNcss = $this->document->createElement('classes', ($nbFiles === 0) ? 0 : ($classes / $nbFiles)); 324 | $averages->appendChild($avgNcss); 325 | 326 | $avgNcss = $this->document->createElement('javadoc', ($nbFiles === 0) ? 0 : ($javadocs / $nbFiles)); 327 | $averages->appendChild($avgNcss); 328 | 329 | $this->objects->appendChild($averages); 330 | 331 | // 332 | // Complete the objects bloc 333 | // 334 | $ncssobj = $this->document->createElement('ncss', $ncss); 335 | $this->objects->appendChild($ncssobj); 336 | } 337 | 338 | /** 339 | * Create the DOM for a line of a table 340 | * @SuppressWarnings functionMaxParameters 341 | */ 342 | private function _createDOMLine($a1, $b1, $c1, $d1, $e1, $f1) { 343 | $line = $this->document->createElement("tr"); 344 | $cola = $this->document->createElement("td", $a1); 345 | $colb = $this->document->createElement("td", $b1); 346 | $colc = $this->document->createElement("td", $c1); 347 | $cold = $this->document->createElement("td", $d1); 348 | $cole = $this->document->createElement("td", $e1); 349 | $colf = $this->document->createElement("td", $f1); 350 | 351 | $line->appendChild($cola); 352 | $line->appendChild($colb); 353 | $line->appendChild($colc); 354 | $line->appendChild($cold); 355 | $line->appendChild($cole); 356 | $line->appendChild($colf); 357 | 358 | return $line; 359 | } 360 | 361 | private function _initXml() { 362 | $this->document = new DomDocument("1.0"); 363 | $this->root = $this->document->createElement('javancss'); 364 | $this->document->appendChild($this->root); 365 | 366 | $date = $this->document->createElement('date', date("Y-m-d")); 367 | $this->root->appendChild($date); 368 | 369 | $time = $this->document->createElement('time', date("G:i:s")); 370 | $this->root->appendChild($time); 371 | 372 | $this->packages = $this->document->createElement('packages'); 373 | $this->root->appendChild($this->packages); 374 | 375 | $this->objects = $this->document->createElement('objects'); // added later 376 | } 377 | } 378 | 379 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/StatementItem.php: -------------------------------------------------------------------------------- 1 | statements); 29 | } 30 | 31 | /** 32 | * Add a statement to the stack. 33 | * 34 | * @param StatementItem $item 35 | */ 36 | function push($item) { 37 | array_push($this->statements, $item); 38 | } 39 | 40 | /** 41 | * Get the top statement from the stack. 42 | * 43 | * @return StatementItem 44 | */ 45 | function pop() { 46 | return array_pop($this->statements); 47 | } 48 | 49 | /** 50 | * Display the current branching stack. 51 | * 52 | * @return String 53 | */ 54 | function getStackDump() { 55 | $dump = ""; 56 | $stackTypes = array( 57 | "FUNCTION", 58 | "INTERFACE", 59 | "CLASS" 60 | ); 61 | foreach ($this->statements as $item) { 62 | $dump .= $item->type; 63 | if (in_array($item->type, $stackTypes)) { 64 | $dump .= "(" . $item->name . ")"; 65 | } 66 | $dump .= " -> "; 67 | } 68 | 69 | return $dump; 70 | } 71 | 72 | /** 73 | * Return the top stack item. 74 | * 75 | * @return StatementItem 76 | */ 77 | function getCurrentStackItem() { 78 | $topItem = end($this->statements); 79 | 80 | if (!empty($topItem)) { 81 | return $topItem; 82 | } else { 83 | // In case of a empty stack, we are at the root of a PHP file (with no class or function). 84 | // We return the default values 85 | return $this->getDefaultItem(); 86 | } 87 | } 88 | 89 | /** 90 | * Return the parent stack item. 91 | * 92 | * @return StatementItem 93 | */ 94 | function getParentStackItem() { 95 | if ($this->count() > 1) { 96 | return $this->statements[$this->count() - 2]; 97 | } else { 98 | // In case of a empty stack, we are at the root of a PHP file (with no class or function). 99 | // We return the default values 100 | return $this->getDefaultItem(); 101 | } 102 | } 103 | 104 | /** 105 | * Return the parent function. 106 | * 107 | * @return StatementItem 108 | */ 109 | function getParentFunction() { 110 | for ($i = $this->count() - 1; $i >= 0; $i --) { 111 | $item = $this->statements[$i]; 112 | if ($item->type === "FUNCTION") { 113 | return $item; 114 | } 115 | } 116 | // In case of a empty stack, we are at the root of a PHP file (with no class or function). 117 | // We return the default values 118 | return $this->getDefaultItem(); 119 | } 120 | 121 | /** 122 | * Return the parent class. 123 | * 124 | * @return StatementItem 125 | */ 126 | function getParentClass() { 127 | for ($i = $this->count() - 1; $i >= 0; $i --) { 128 | $item = $this->statements[$i]; 129 | if ($item->type === "CLASS" || $item->type === "INTERFACE") { 130 | return $item; 131 | } 132 | } 133 | // In case of a empty stack, we are at the root of a PHP file (with no class or function). 134 | return $this->getDefaultItem(); 135 | } 136 | 137 | /** 138 | * return a Singleton of a StackItem corresponding to the file level. 139 | */ 140 | function getDefaultItem() { 141 | if ($this->defaultItem == null) { 142 | $this->defaultItem = new StatementItem(); 143 | } 144 | return $this->defaultItem; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/TokenInfo.php: -------------------------------------------------------------------------------- 1 | line; 51 | $result .= ", pos : " . $this->position; 52 | $result .= ", id : " . $this->getName($this->id); 53 | 54 | // Rename some special chars 55 | $text = str_replace("\r\n", "\\r\\n", $this->text); 56 | $text = str_replace("\r", "\\r", $text); 57 | $text = str_replace("\n", "\\n", $text); 58 | 59 | $result .= ", text : " . $text; 60 | return $result; 61 | } 62 | 63 | /** 64 | * Return the name of a token, including the NEW_LINE one. 65 | * 66 | * @return String the name of the token 67 | */ 68 | public function getName() { 69 | $tagNames = array( 70 | T_NEW_LINE => 'T_NEW_LINE', 71 | T_TAB => 'T_TAB', 72 | T_SEMICOLON => 'T_SEMICOLON', 73 | T_BRACES_OPEN => 'T_BRACES_OPEN', 74 | T_BRACES_CLOSE => 'T_BRACES_CLOSE', 75 | T_PARENTHESIS_OPEN => 'T_PARENTHESIS_OPEN', 76 | T_PARENTHESIS_CLOSE => 'T_PARENTHESIS_CLOSE', 77 | T_COMMA => 'T_COMMA', 78 | T_EQUAL => 'T_EQUAL', 79 | T_CONCAT => 'T_CONCAT', 80 | T_COLON => 'T_COLON', 81 | T_MINUS => 'T_MINUS', 82 | T_PLUS => 'T_PLUS', 83 | T_IS_GREATER => 'T_IS_GREATER', 84 | T_IS_SMALLER => 'T_IS_SMALLER', 85 | T_MULTIPLY => 'T_MULTIPLY', 86 | T_DIVIDE => 'T_DIVIDE', 87 | T_QUESTION_MARK => 'T_QUESTION_MARK', 88 | T_MODULO => 'T_MODULO', 89 | T_EXCLAMATION_MARK => 'T_EXCLAMATION_MARK', 90 | T_AMPERSAND => 'T_AMPERSAND', 91 | T_SQUARE_BRACKET_OPEN => 'T_SQUARE_BRACKET_OPEN', 92 | T_SQUARE_BRACKET_CLOSE => 'T_SQUARE_BRACKET_CLOSE', 93 | T_AROBAS => 'T_AROBAS', 94 | T_UNKNOWN => 'T_UNKNOWN', 95 | T_DOLLAR => 'T_DOLLAR', 96 | ); 97 | 98 | if (isset($tagNames[$this->id])) { 99 | $result = $tagNames[$this->id]; 100 | } else { 101 | $result = token_name($this->id); 102 | } 103 | 104 | return $result; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/PHPCheckstyle/VariableInfo.php: -------------------------------------------------------------------------------- 1 | 35 | define('T_IS_SMALLER', 10014); // < 36 | define('T_MULTIPLY', 10015); // * 37 | define('T_DIVIDE', 10016); // / 38 | define('T_QUESTION_MARK', 10017); // ? 39 | define('T_MODULO', 10018); // % 40 | define('T_EXCLAMATION_MARK', 10019); // ! 41 | define('T_AMPERSAND', 10020); // % 42 | define('T_SQUARE_BRACKET_OPEN', 10021); // [ 43 | define('T_SQUARE_BRACKET_CLOSE', 10022); // ] 44 | define('T_AROBAS', 10023); // @ 45 | define('T_QUOTE', 10024); // " only detected before and after a T_ENCAPSED_AND_WHITESPACE otherwise should be included in T_CONSTANT_ENCAPSED_STRING 46 | 47 | // PHP 5.3 parsing with an older version 48 | if (!defined('T_FINALLY')) { 49 | define('T_FINALLY', 10025); 50 | } 51 | if (!defined('T_CALLABLE')) { 52 | define('T_CALLABLE', 10026); 53 | } 54 | if (!defined('T_TRAIT')) { 55 | define('T_TRAIT', 10027); 56 | } 57 | if (!defined('T_TRAIT_C')) { 58 | define('T_TRAIT_C', 10028); 59 | } 60 | if (!defined('T_INSTEADOF')) { 61 | define('T_INSTEADOF', 10029); 62 | } 63 | if (!defined('T_YIELD')) { 64 | define('T_YIELD', 10030); 65 | } 66 | define('T_DOLLAR', 10032); // $ detected before a variable in the case of a variable variable ($$a) otherwise should be included in T_VARIABLE 67 | 68 | 69 | define("SHORT_OPEN_TAG", ""); 72 | -------------------------------------------------------------------------------- /test/AliasesTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/bad_alias.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 24 | $this->assertEquals(3, $errorCounts['warning'], 'We expect 3 warnings'); 25 | } 26 | } 27 | ?> -------------------------------------------------------------------------------- /test/CommentsTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/good_doc.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 24 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 25 | } 26 | 27 | /** 28 | * Test for bad comments. 29 | */ 30 | public function testComments() { 31 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 32 | 33 | $phpcheckstyle->processFiles(array( 34 | './test/sample/bad_comments.php' 35 | )); 36 | 37 | $errorCounts = $phpcheckstyle->getErrorCounts(); 38 | 39 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 40 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 41 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 42 | $this->assertEquals(6, $errorCounts['warning'], 'We expect 6 warnings'); 43 | } 44 | 45 | /** 46 | * Test for TODOs. 47 | */ 48 | public function testTODOs() { 49 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 50 | 51 | $phpcheckstyle->processFiles(array( 52 | './test/sample/todo.php' 53 | )); 54 | 55 | $errorCounts = $phpcheckstyle->getErrorCounts(); 56 | 57 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 58 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 59 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 60 | $this->assertEquals(1, $errorCounts['warning'], 'We expect 1 warnings'); 61 | } 62 | } 63 | ?> -------------------------------------------------------------------------------- /test/DeprecationTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/bad_deprecation.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 24 | $this->assertEquals(5, $errorCounts['warning'], 'We expect 5 warnings'); 25 | } 26 | } 27 | ?> -------------------------------------------------------------------------------- /test/GoodTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/good.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 24 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 25 | } 26 | 27 | 28 | 29 | /** 30 | * Test for good iterators. 31 | */ 32 | public function testDoWhile() { 33 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 34 | 35 | $phpcheckstyle->processFiles(array( 36 | './test/sample/good_do_while.php' 37 | )); 38 | 39 | $errorCounts = $phpcheckstyle->getErrorCounts(); 40 | 41 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 42 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 43 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 44 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 45 | } 46 | 47 | /** 48 | * Test for good_anonymous_function. 49 | */ 50 | public function testAnonymousFunction() { 51 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 52 | 53 | $phpcheckstyle->processFiles(array( 54 | './test/sample/good_anonymous_function.php' 55 | )); 56 | 57 | $errorCounts = $phpcheckstyle->getErrorCounts(); 58 | 59 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 60 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 61 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 62 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 63 | } 64 | 65 | /** 66 | * Test for try/catch/finally. 67 | */ 68 | public function testException() { 69 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 70 | 71 | $phpcheckstyle->processFiles(array( 72 | './test/sample/good_exception.php' 73 | )); 74 | 75 | $errorCounts = $phpcheckstyle->getErrorCounts(); 76 | 77 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 78 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 79 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 80 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 81 | } 82 | } 83 | ?> -------------------------------------------------------------------------------- /test/IndentationTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/bad_indentation.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 24 | $this->assertEquals(6, $errorCounts['warning'], 'We expect 6 warnings'); 25 | } 26 | 27 | /** 28 | * Test tabs indentation. 29 | */ 30 | public function testSpaceIndentation() { 31 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 32 | 33 | // Change the configuration to check for spaces instead of tabs 34 | $phpcheckstyle->getConfig()->setTestProperty('indentation', 'type', 'spaces'); 35 | 36 | $phpcheckstyle->processFiles(array( 37 | './test/sample/bad_indentation.php' 38 | )); 39 | 40 | $errorCounts = $phpcheckstyle->getErrorCounts(); 41 | 42 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 43 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 44 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 45 | $this->assertEquals(11, $errorCounts['warning'], 'We expect 11 warnings'); 46 | } 47 | 48 | /** 49 | * Test tabs indentation. 50 | */ 51 | public function testSpaceIndentationArray() { 52 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 53 | 54 | // Change the configuration to check for spaces instead of tabs 55 | $phpcheckstyle->getConfig()->setTestProperty('indentation', 'type', 'spaces'); 56 | 57 | $phpcheckstyle->processFiles(array( 58 | './test/sample/bad_indentation_array.php' 59 | )); 60 | 61 | $errorCounts = $phpcheckstyle->getErrorCounts(); 62 | 63 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 64 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 65 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 66 | $this->assertEquals(11, $errorCounts['warning'], 'We expect 11 warnings'); 67 | } 68 | 69 | /** 70 | * Test tabs indentation. 71 | */ 72 | public function testGoodSpaceIndentationArray() { 73 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 74 | 75 | // Change the configuration to check for spaces instead of tabs 76 | $phpcheckstyle->getConfig()->setTestProperty('indentation', 'type', 'spaces'); 77 | 78 | $phpcheckstyle->processFiles(array( 79 | './test/sample/good_indentation_array.php' 80 | )); 81 | 82 | $errorCounts = $phpcheckstyle->getErrorCounts(); 83 | 84 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 85 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 86 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 87 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 88 | } 89 | 90 | /** 91 | * Test for indentation with new line indentation. 92 | */ 93 | public function testGoodIndentationNewLine() { 94 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 95 | 96 | // Change the configuration to check for spaces instead of tabs 97 | $phpcheckstyle->getConfig()->setTestProperty('controlStructOpenCurly', 'position', 'nl'); 98 | $phpcheckstyle->getConfig()->setTestProperty('funcDefinitionOpenCurly', 'position', 'nl'); 99 | $phpcheckstyle->getConfig()->setTestProperty('controlStructElse', 'position', 'nl'); 100 | 101 | $phpcheckstyle->processFiles(array( 102 | './test/sample/good_indentation_newline.php' 103 | )); 104 | 105 | $errorCounts = $phpcheckstyle->getErrorCounts(); 106 | 107 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 108 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 109 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 110 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 111 | } 112 | 113 | /** 114 | * Test for indentation with spaces. 115 | */ 116 | public function testGoodIndentationSpaces() { 117 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 118 | 119 | // Change the configuration to check for spaces instead of tabs 120 | $phpcheckstyle->getConfig()->setTestProperty('indentation', 'type', 'spaces'); 121 | 122 | $phpcheckstyle->processFiles(array( 123 | './test/sample/good_indentation_space.php' 124 | )); 125 | 126 | $errorCounts = $phpcheckstyle->getErrorCounts(); 127 | 128 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 129 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 130 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 131 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 132 | } 133 | 134 | /** 135 | * Test for for spaces missing or in excedent. 136 | */ 137 | public function testBadSpaces() { 138 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 139 | 140 | $phpcheckstyle->processFiles(array( 141 | './test/sample/bad_spaces.php' 142 | )); 143 | 144 | $errorCounts = $phpcheckstyle->getErrorCounts(); 145 | 146 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 147 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 148 | $this->assertEquals(2, $errorCounts['info'], 'We expect 2 info'); 149 | $this->assertEquals(7, $errorCounts['warning'], 'We expect 7 warnings'); 150 | } 151 | 152 | /** 153 | * Test for space after control statement (no space after control statement). 154 | */ 155 | public function testBadSpaceAfterControl() { 156 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 157 | 158 | // Change the configuration to check for spaces instead of tabs 159 | $phpcheckstyle->getConfig()->setTestProperty('spaceaftercontrolstmt', 'type', 'spaces'); 160 | 161 | // Change the configuration to check for no spaces after control statement 162 | $config = $phpcheckstyle->getConfig(); 163 | $refl = new \ReflectionProperty($config, 'config'); 164 | $refl->setAccessible(true); 165 | $value = $refl->getValue($config); 166 | unset($value['spaceaftercontrolstmt']); 167 | $value['nospaceaftercontrolstmt'] = array(); 168 | $refl->setValue($config, $value); 169 | 170 | $phpcheckstyle->processFiles(array( 171 | './test/sample/bad_space_after_control.php' 172 | )); 173 | 174 | $errorCounts = $phpcheckstyle->getErrorCounts(); 175 | 176 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors'); 177 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 178 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 179 | $this->assertEquals(1, $errorCounts['warning'], 'We expect 1 warning'); 180 | } 181 | } 182 | ?> -------------------------------------------------------------------------------- /test/MetricsTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/bad_metrics.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(1, $errorCounts['info'], 'We expect 1 info'); 24 | $this->assertEquals(3, $errorCounts['warning'], 'We expect 3 warnings'); 25 | } 26 | 27 | 28 | } 29 | ?> -------------------------------------------------------------------------------- /test/NamingTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/_bad_naming.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | // echo print_r($errorCounts, true); 22 | 23 | $this->assertEquals(8, $errorCounts['error'], 'We expect 8 errors of naming'); 24 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 25 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 26 | $this->assertEquals(5, $errorCounts['warning'], 'We expect 5 warnings'); 27 | } 28 | 29 | /** 30 | * Test function naming rules. 31 | */ 32 | public function testFunctionNaming() { 33 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 34 | 35 | // Change the default configuration, function parameters should start with "_" 36 | $phpcheckstyle->getConfig()->setTestProperty('functionParameterNaming', 'regexp', "/^[_][a-zA-Z0-9]*$/"); 37 | 38 | $phpcheckstyle->processFiles(array( 39 | './test/sample/good_function_naming.php' 40 | )); 41 | 42 | $errorCounts = $phpcheckstyle->getErrorCounts(); 43 | 44 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 45 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 46 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 47 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 48 | } 49 | } 50 | ?> -------------------------------------------------------------------------------- /test/OptimizationTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/bad_optimisation.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 24 | $this->assertEquals(2, $errorCounts['warning'], 'We expect 2 warnings'); 25 | } 26 | 27 | 28 | } 29 | ?> -------------------------------------------------------------------------------- /test/OtherTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/bad_other.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 24 | $this->assertEquals(20, $errorCounts['warning'], 'We expect 20 warnings'); 25 | } 26 | 27 | 28 | /** 29 | * Test for PHP exceptions during parsing. 30 | */ 31 | public function testException() { 32 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 33 | 34 | $phpcheckstyle->processFiles(array( 35 | './test/sample/unterminated_comment.php' 36 | )); 37 | 38 | $errorCounts = $phpcheckstyle->getErrorCounts(); 39 | 40 | $this->assertEquals(1, $errorCounts['error'], 'We expect 1 error'); 41 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 42 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 43 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 44 | } 45 | 46 | 47 | /** 48 | * Test for empty PHP file. 49 | */ 50 | public function testEmpty() { 51 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 52 | 53 | $phpcheckstyle->processFiles(array( 54 | './test/sample/empty.php' 55 | )); 56 | 57 | $errorCounts = $phpcheckstyle->getErrorCounts(); 58 | 59 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 error'); 60 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 61 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 62 | $this->assertEquals(1, $errorCounts['warning'], 'We expect 1 warnings'); 63 | } 64 | 65 | 66 | /** 67 | * Test for the presence of a break in a switch case. 68 | */ 69 | public function testSwitchCaseNeedBreak() { 70 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 71 | 72 | $phpcheckstyle->processFiles(array( 73 | './test/sample/switch_multi_case.php' 74 | )); 75 | 76 | $errorCounts = $phpcheckstyle->getErrorCounts(); 77 | 78 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 error'); 79 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 80 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 81 | $this->assertEquals(1, $errorCounts['warning'], 'We expect 1 warnings'); 82 | } 83 | 84 | } 85 | ?> -------------------------------------------------------------------------------- /test/PHPTagsTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/bad_php_tags_text_after_end.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 24 | $this->assertEquals(1, $errorCounts['warning'], 'We expect 1 warnings'); 25 | } 26 | 27 | /** 28 | * Test PHP Tags rules. 29 | */ 30 | public function testClosingTagNotNeeded() { 31 | $phpcheckstyle = $GLOBALS['runner']->getInstance(); 32 | 33 | $phpcheckstyle->processFiles(array( 34 | './test/sample/bad_php_tags_end_not_needed.php' 35 | )); 36 | 37 | $errorCounts = $phpcheckstyle->getErrorCounts(); 38 | 39 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 40 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 41 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 42 | $this->assertEquals(1, $errorCounts['warning'], 'We expect 1 warnings'); 43 | } 44 | } 45 | ?> -------------------------------------------------------------------------------- /test/ProhibitedTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 16 | 17 | $phpcheckstyle->processFiles(array( 18 | './test/sample/bad_prohibited.php' 19 | )); 20 | 21 | $errorCounts = $phpcheckstyle->getErrorCounts(); 22 | 23 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 24 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 25 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 26 | $this->assertEquals(2, $errorCounts['warning'], 'We expect 2 warnings'); 27 | } 28 | } 29 | ?> -------------------------------------------------------------------------------- /test/StrictCompareTest.php: -------------------------------------------------------------------------------- 1 | getInstance(); 14 | 15 | $phpcheckstyle->processFiles(array( 16 | './test/sample/bad_strictcompare.php' 17 | )); 18 | 19 | $errorCounts = $phpcheckstyle->getErrorCounts(); 20 | 21 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 22 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 23 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 24 | $this->assertEquals(4, $errorCounts['warning'], 'We expect 4 warnings'); 25 | } 26 | 27 | 28 | } 29 | ?> -------------------------------------------------------------------------------- /test/TestRunner.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | setLang($options['lang']); 33 | } 34 | 35 | return $phpcheckstyle; 36 | } 37 | } 38 | 39 | $runner = new Runner(); 40 | $GLOBALS['runner'] = $runner; 41 | 42 | -------------------------------------------------------------------------------- /test/UnusedTest.php: -------------------------------------------------------------------------------- 1 | getInstance();; 16 | 17 | $phpcheckstyle->processFiles(array( 18 | './test/sample/good_unused.php' 19 | )); 20 | 21 | $errorCounts = $phpcheckstyle->getErrorCounts(); 22 | 23 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 24 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 25 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 26 | $this->assertEquals(0, $errorCounts['warning'], 'We expect 0 warnings'); 27 | } 28 | 29 | /** 30 | * Test for unused functions or variables. 31 | */ 32 | public function testBadUnused() 33 | { 34 | $phpcheckstyle = $GLOBALS['runner']->getInstance();; 35 | 36 | $phpcheckstyle->processFiles(array( 37 | './test/sample/bad_unused.php' 38 | )); 39 | 40 | $errorCounts = $phpcheckstyle->getErrorCounts(); 41 | 42 | $this->assertEquals(0, $errorCounts['error'], 'We expect 0 errors of naming'); 43 | $this->assertEquals(0, $errorCounts['ignore'], 'We expect 0 ignored checks'); 44 | $this->assertEquals(0, $errorCounts['info'], 'We expect 0 info'); 45 | $this->assertEquals(4, $errorCounts['warning'], 'We expect 4 warnings'); 46 | } 47 | } 48 | ?> -------------------------------------------------------------------------------- /test/sample/_bad_naming.php: -------------------------------------------------------------------------------- 1 | 'y' // same level 17 | ); 18 | 19 | $bVar = array( 20 | 'x' => 'y' 21 | ); // extra level 22 | 23 | $cVar = [ 24 | 'x' => 'y' // same level 25 | ]; 26 | 27 | $dVar = [ 28 | 'x' => 'y' 29 | ]; // extra level 30 | } 31 | } -------------------------------------------------------------------------------- /test/sample/bad_metrics.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/sample/bad_php_tags_text_after_end.php: -------------------------------------------------------------------------------- 1 | test -------------------------------------------------------------------------------- /test/sample/bad_prohibited.php: -------------------------------------------------------------------------------- 1 | badlyNamedPrivateFunction(); 88 | 89 | if ($c > $a) { 90 | return $a + $b; 91 | } else { 92 | return $a; 93 | } 94 | } 95 | 96 | var $test; 97 | 98 | /** 99 | * Function having an exception. 100 | * 101 | * @throws Exception 102 | */ 103 | public function functionWithException() { 104 | 105 | // Call the private function 106 | $this->_privateFunction(); 107 | 108 | $this->test; 109 | 110 | // do something 111 | throw new Exception('Exception'); 112 | } 113 | 114 | /** 115 | * Error of naming, but for a good reason we decide to suppress the warning using an annotation. 116 | * @SuppressWarnings privateFunctionNaming 117 | */ 118 | private function badlyNamedPrivateFunction() { // should have a underscore because it is private 119 | 120 | // Call the private function 121 | $this->_privateFunction(); 122 | 123 | // This used to generate a false positive for "needBraces" rule with the while statement 124 | do { 125 | toto(); 126 | } while (true); 127 | 128 | } 129 | 130 | /** 131 | * False positive for docbloc detection. 132 | * The final keyword was causing a problem. 133 | */ 134 | final protected function finalFunction() { 135 | 136 | $a = null; 137 | } 138 | } -------------------------------------------------------------------------------- /test/sample/good_anonymous_function.php: -------------------------------------------------------------------------------- 1 | $a) { 19 | return $a + $b; 20 | } else { 21 | return $a; 22 | } 23 | } 24 | 25 | /** 26 | * Correctly documented function 2. 27 | * 28 | * The "return" should not count. 29 | * 30 | * @param String $a a string 31 | * @param array $b an array 32 | */ 33 | function privateFunction2($a, array $b = array()) { 34 | 35 | if ($b > $a) { 36 | return; 37 | } 38 | 39 | // do something else 40 | } 41 | 42 | 43 | /** 44 | * Doc is inherited. 45 | * 46 | * @inheritdoc 47 | */ 48 | function privateFunction2($a, array $b = array()) { 49 | 50 | // function parameters are not used, but we don't care 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /test/sample/good_exception.php: -------------------------------------------------------------------------------- 1 | getMessage(); 21 | } finally { 22 | echo "Finally does it!"; 23 | } 24 | 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /test/sample/good_function_naming.php: -------------------------------------------------------------------------------- 1 | 'y', 15 | 'z' => $this->check() 16 | ); 17 | 18 | $cVar = [ 19 | 'x' => 'y', 20 | 'z' => $this->check() 21 | ]; 22 | 23 | unset($bVar, $cVar); 24 | } 25 | 26 | /** 27 | * Test2. 28 | */ 29 | public function check() { 30 | return; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/sample/good_indentation_newline.php: -------------------------------------------------------------------------------- 1 | toto; 22 | 23 | return $result; 24 | 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /test/sample/issue29.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /test/sample/issue56.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | // ok 7 | 8 | // nok 13 | 14 | 15 | // nok -------------------------------------------------------------------------------- /test/sample/issue70.php: -------------------------------------------------------------------------------- 1 | db->query($sql, $valeurs); 26 | 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /test/sample/issue73.php: -------------------------------------------------------------------------------- 1 | _utilisateur->delete(); 18 | 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /test/sample/issue78.php: -------------------------------------------------------------------------------- 1 | 23 | * @author Another Author 24 | */ 25 | 26 | 27 | 28 | /** 29 | * Test class. 30 | */ 31 | class Toto { 32 | 33 | /** 34 | * Test. 35 | */ 36 | public function test() { 37 | 38 | 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /test/sample/issuegithub32.php: -------------------------------------------------------------------------------- 1 | commit(function () use ($params) { 8 | $whatever = 5; 9 | return $whatever; 10 | }); 11 | } 12 | 13 | private function commit($callback) { 14 | // complex logic using $callback can go here 15 | $callback(); 16 | } 17 | } -------------------------------------------------------------------------------- /test/sample/issuegithub62.php: -------------------------------------------------------------------------------- 1 | 'CouchUnauthorizedException', 11 | 403 => 'CouchForbiddenException', 12 | 404 => 'CouchNotFoundException', 13 | 417 => 'CouchExpectationException' 14 | ]; 15 | 16 | 17 | /** 18 | * Test 19 | * 20 | * @return result 21 | */ 22 | function test() 23 | { 24 | $classes = array( 25 | $this->em->getClassMetadata(self::ITEM_GROUP_CLASS), 26 | $this->em->getClassMetadata(self::SINGLE_IDENT_CLASS), 27 | $this->em->getClassMetadata(self::SINGLE_IDENT_NO_TO_STRING_CLASS) 28 | ); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /test/sample/issuegithub65.php: -------------------------------------------------------------------------------- 1 | em->getClassMetadata(self::ITEM_GROUP_CLASS), 19 | $this->em->getClassMetadata(self::SINGLE_IDENT_CLASS), 20 | $this->em->getClassMetadata(self::SINGLE_IDENT_NO_TO_STRING_CLASS), 21 | $this->em->getClassMetadata(self::SINGLE_STRING_IDENT_CLASS), 22 | $this->em->getClassMetadata(self::SINGLE_ASSOC_IDENT_CLASS), 23 | $this->em->getClassMetadata(self::SINGLE_STRING_CASTABLE_IDENT_CLASS), 24 | $this->em->getClassMetadata(self::COMPOSITE_IDENT_CLASS), 25 | $this->em->getClassMetadata(self::COMPOSITE_STRING_IDENT_CLASS), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/sample/issuegithub89.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/sample/test_unused_2.php: -------------------------------------------------------------------------------- 1 | 4 | ... 5 | 6 | -------------------------------------------------------------------------------- /test/sample/todo.php: -------------------------------------------------------------------------------- 1 | > /home/vagrant/.profile -------------------------------------------------------------------------------- /vagrant_config/scripts/install_composer_libraries.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # --------------------------------------------------------------- 4 | # This provision is executed as "vagrant" 5 | # --------------------------------------------------------------- 6 | 7 | 8 | 9 | echo "--------------------------------------------------" 10 | echo " Install Composer Libraries " 11 | echo "--------------------------------------------------" 12 | 13 | cd /vagrant/ 14 | 15 | composer install 16 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | array($baseDir . '/src'), 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/nikic/php-parser/lib/PhpParser'), 10 | 'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'), 11 | 'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'), 12 | ); 13 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | register(true); 35 | 36 | $includeFiles = \Composer\Autoload\ComposerStaticInitd82a833b8dfd91b3221618a75dc60ba2::$files; 37 | foreach ($includeFiles as $fileIdentifier => $file) { 38 | composerRequired82a833b8dfd91b3221618a75dc60ba2($fileIdentifier, $file); 39 | } 40 | 41 | return $loader; 42 | } 43 | } 44 | 45 | /** 46 | * @param string $fileIdentifier 47 | * @param string $file 48 | * @return void 49 | */ 50 | function composerRequired82a833b8dfd91b3221618a75dc60ba2($fileIdentifier, $file) 51 | { 52 | if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { 53 | $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; 54 | 55 | require $file; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /vendor/composer/platform_check.php: -------------------------------------------------------------------------------- 1 | = 50000)) { 8 | $issues[] = 'Your Composer dependencies require a PHP version ">= 5.0.0". You are running ' . PHP_VERSION . '.'; 9 | } 10 | 11 | if ($issues) { 12 | if (!headers_sent()) { 13 | header('HTTP/1.1 500 Internal Server Error'); 14 | } 15 | if (!ini_get('display_errors')) { 16 | if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { 17 | fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); 18 | } elseif (!headers_sent()) { 19 | echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; 20 | } 21 | } 22 | trigger_error( 23 | 'Composer detected issues in your platform: ' . implode(' ', $issues), 24 | E_USER_ERROR 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php: -------------------------------------------------------------------------------- 1 | copy($value); 19 | } 20 | } 21 | --------------------------------------------------------------------------------