Skip to content
This repository has been archived by the owner on Oct 17, 2019. It is now read-only.

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Octav committed Jun 20, 2017
0 parents commit 7527df5
Show file tree
Hide file tree
Showing 25 changed files with 2,191 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/.buildpath
/.project
/.settings
/.metadata
/.externalToolBuilders
/.idea
/composer.phar
/nbproject/private
/nbproject
/vendor
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# PHP Code Sniffer Changelog

## [0.6.1] - 2017-04-26
* Fixed sniffing failure for files without class or interface declaration.

## [0.6.0] - 2017-03-22
* Updated `PHP_CodeSniffer` version to 2.8.1.
* Improved determining test classes for PHPUnit 6.
* Excluded some of the rules which are added by new PHP_CodeSniffer version:
* `Generic.Formatting.SpaceAfterNot`
* `Squiz.WhiteSpace.ControlStructureSpacing`
20 changes: 20 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
The MIT License (MIT)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

181 changes: 181 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# PHP Code Sniffer

PHP Code Sniffer is a PHP code standard checker/beautifier/fixer tool
based on [PHP_CodeSniffer] and includes [custom sniffs](#custom-sniffs) used in PHP projects developed by I2ct.

## Requirements

PHP Code Sniffer requires PHP 5.6 or later.

## Install via Composer

```json
{
"require-dev": {
"tavy315/php-code-sniffer": "*"
}
}
```

## Binaries

Binaries are located in `bin` directory but composer installer creates links under
your vendor binary directory depending on your composer configuration.

* **phpcs :** Checks PHP files against defined coding standard rules.
* **phpcbf :** Corrects fixable coding standard violations.
* **phpcs-pre-commit :** Runs phpcs for modified files in git repository.

## Pre-Commit Hook
Save the following script as `.git/hooks/pre-commit` by replacing `COMPOSER_BIN_DIR`
as your vendor binary directory name depending on your composer configuration.

```sh
#!/bin/sh
./COMPOSER_BIN_DIR/phpcs-pre-commit
```

Make sure the hook script is executable.

```sh
chmod +x .git/hooks/pre-commit
```

## Customize

You can customize configuration by adding a file called `phpcs.xml` file into
the root directory of your project. The phpcs.xml file has exactly the same
format as a normal ruleset.xml file, so all the same options are available in
it. You need to define `I2ct` rule to import all the `I2ct` rules.

```xml
<?xml version="1.0" encoding="UTF-8"?>
<ruleset>
<rule ref="I2ct" />
</ruleset>
```

### Using a custom bootstrap file
You can add custom bootstrap files to be included before beginning the run.
Some sniffs need to load classes from your project; so adding a autoload file
will allow sniffs to do this.

```xml
<?xml version="1.0" encoding="UTF-8"?>
<ruleset>
<rule ref="I2ct" />
<arg name="bootstrap" value="vendor/autoload.php" />
</ruleset>
```

## Imported Standards

### PSR2
All PSR2 sniffs except `Squiz.WhiteSpace.ControlStructureSpacing` are imported by default.
* `PSR2.ControlStructures.ElseIfDeclaration.NotAllowed` rule type is considered as `error` instead of `warning`.

### Generic
Imported sniffs:
* All sniffs in `Generic.Formatting` category except:
* `DisallowMultipleStatements` (replaced by [`I2ct.Formatting.DisallowMultipleStatements`](#i2ctformattingdisallowmultiplestatements))
* `NoSpaceAfterCast`
* `SpaceAfterNot`
* `Generic.Arrays.DisallowLongArraySyntax`

### Squiz
Imported sniffs:
* `Squiz.Commenting.DocCommentAlignment`
* `Squiz.Commenting.InlineComment`
* `InvalidEndChar` rule type is considered as `warning` instead of `error`.
* `Squiz.WhiteSpace.SuperfluousWhitespace`
* `Squiz.WhiteSpace.OperatorSpacing`

## Custom Sniffs

### I2ct.Arrays.ArrayDeclaration
* Extended from `Squiz.Arrays.ArrayDeclaration`.
* Arranged array element indents by start position of the first (declaration) line.
* Number of spaces before array elements is increased from 1 to 4.
* Removed rules:
* `NoKeySpecified`
* `KeySpecified`
* `MultiLineNotAllowed`
* `NoCommaAfterLast`
* `NoComma`

### I2ct.Commenting.DocComment
* Extended from `Generic.Commenting.DocComment`.
* Ignored `MissingShort` rule for PHPUnit test class methods <sup name="fn1c1">[[1]](#fn1)</sup>.
* Changed `MissingShort` rule type from `error` to `warning`.
* Removed rules for comments with long descriptions:
* `SpacingBetween`
* `LongNotCapital`
* `SpacingBeforeTags`
* `ParamGroup`
* `NonParamGroup`
* `SpacingAfterTagGroup`
* `TagValueIndent`
* `ParamNotFirst`
* `TagsNotGrouped`

### I2ct.Commenting.FunctionComment
* Extended from `PEAR.Commenting.FunctionComment`.
* Added PHPUnit test class control for methods without doc comment <sup name="fn1c2">[[1]](#fn1)</sup>.
* Added `{@inheritdoc}` validation for overrided methods <sup name="fn1c3">[[1]](#fn1)</sup>.
* Removed `MissingParamComment`, `MissingReturn`, `SpacingAfterParamType` and `SpacingAfterParamName` rules.
* Ignored `MissingParamTag` rule for PHPUnit test class methods <sup name="fn1c4">[[1]](#fn1)</sup>.

### I2ct.Commenting.VariableComment
* Extended from `Squiz.Commenting.VariableComment`.
* Added `bool` and `int` into allowed variable types.

### I2ct.Formatting.DisallowMultipleStatements
* Extended from `Generic.Formatting.DisallowMultipleStatements`.
* Fixed adding 2 blank lines when applying `SameLine` fixer with `Squiz.Functions.MultiLineFunctionDeclaration.ContentAfterBrace` fixer together.

### I2ct.Strings.ConcatenationSpacing
This sniff has two rules and fixes.
* `PaddingFound`: There must be only one space between the concatenation operator (.) and the strings being concatenated.
* `NotAligned`: Multiline string concatenations must be aligned.

### I2ct.WhiteSpace.FunctionSpacing
* Extended from `Squiz.WhiteSpace.FunctionSpacing`.
* Expected no blank lines before the method which is the first defined element of a class.
* Expected no blank lines after the method which is the last defined element of a class.
* Fixed fixing spaces before method definitions.

### I2ct.WhiteSpace.MemberVarSpacing
* Extended from `Squiz.WhiteSpace.MemberVarSpacing`.
* Expected no blank lines before the property which is the first defined element of a class.
* Fixed fixing spaces before property definitions.

## Development

### Live Testing
You can test any modifications by running [phpcs.php](scripts/phpcs.php), [phpcbf.php](scripts/phpcbf.php) and
[phpcs-pre-commit.php](scripts/phpcs-pre-commit.php) scripts under `scripts` directory.

### Building Binaries
Run the command below to re-build binaries:

```sh
php scripts/build.php
```

### PHP_CodeSniffer Dependency
Current version is built on [PHP_CodeSniffer 2.8.1](https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/2.8.1)
which is locked in [composer.lock](composer.lock) file. To import new versions; edit [composer.json](composer.json) file if required and
run `composer update` command, then commit the modified [composer.lock](composer.lock) file. Updating [PHP_CodeSniffer] version may
break some of [I2ct sniffs](#custom-sniffs), so you must carefully track any changes on [PHP_CodeSniffer] before updating.

___
<a name="fn1"><sup>[1]</sup></a> A class loader is required (eg. via a bootstrap file),
otherwise a warning (`Internal.I2ct.NeedClassLoader`) will be generated.
You can override this rule in `phpcs.xml` file in your project to prevent warnings.
[](#fn1c1) [](#fn1c2) [](#fn1c3) [](#fn1c4)
___
#### License Notices
[PHP_CodeSniffer] is licensed under the [BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license.

[PHP_CodeSniffer]: https://github.com/squizlabs/PHP_CodeSniffer

Binary file added bin/phpcbf
Binary file not shown.
Binary file added bin/phpcs
Binary file not shown.
Binary file added bin/phpcs-pre-commit
Binary file not shown.
34 changes: 34 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "tavy315/php-code-sniffer",
"type": "library",
"license": "MIT",
"description": "PHP Code Sniffer",
"autoload": {
"psr-4": {
"": "src/"
}
},
"bin": [
"bin/phpcs",
"bin/phpcs-pre-commit",
"bin/phpcbf"
],
"require": {
"php": ">=5.5.9"
},
"require-dev": {
"squizlabs/php_codesniffer": "2.*"
},
"authors": [
{
"name": "Safak Ozpinar",
"email": "safak@gamegos.com",
"role": "Developer"
},
{
"name": "Octavian Matei",
"homepage": "https://www.octav.name",
"role": "Contributor"
}
]
}
18 changes: 18 additions & 0 deletions scripts/build.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
chdir(dirname(__DIR__));

$binaries = [
'phpcs',
'phpcbf',
'phpcs-pre-commit',
];
foreach ($binaries as $binary) {
$command = sprintf('php -d phar.readonly=0 scripts/create-phar.php %s', $binary);
$output = [];
$return = null;
exec($command, $output, $return);
if ($return != 0 || !empty($output)) {
echo implode(PHP_EOL, $output) . PHP_EOL;
exit(1);
}
}
11 changes: 11 additions & 0 deletions scripts/cli.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
include dirname(__DIR__) . '/vendor/autoload.php';

$PHP_CODESNIFFER_CONFIG_DATA = [
'installed_paths' => dirname(__DIR__) . '/src',
'default_standard' => 'I2ct',
'php_path' => 'php',
'report_width' => 80,
];

return new PHP_CodeSniffer_CLI();
54 changes: 54 additions & 0 deletions scripts/create-phar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
chdir(dirname(__DIR__));

$binary = $argv[1];

$scriptFilename = 'scripts/' . $binary . '.php';
$pharFilename = 'bin/' . $binary . '.phar';
$binaryFilename = 'bin/' . $binary;

if (file_exists($pharFilename)) {
Phar::unlinkArchive($pharFilename);
}
if (file_exists($binaryFilename)) {
Phar::unlinkArchive($binaryFilename);
}

$phar = new Phar(
$pharFilename,
FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO,
$binary
);
$phar->startBuffering();

$directories = [
'src',
'vendor',
'scripts',
];

foreach ($directories as $dirname) {
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirname));
while ($iterator->valid()) {
if ($iterator->isFile()) {
$path = $iterator->getPathName();
if (strtolower($iterator->getExtension()) === 'php') {
$contents = php_strip_whitespace($path);
$phar->addFromString($path, $contents);
} else {
$phar->addFile($path);
}
}
$iterator->next();
}
}

$stub = '#!/usr/bin/env php' . PHP_EOL . $phar->createDefaultStub($scriptFilename);
$phar->setStub($stub);

$phar->compressFiles(Phar::GZ);

$phar->stopBuffering();

rename($pharFilename, $binaryFilename);
chmod($binaryFilename, 0775);
3 changes: 3 additions & 0 deletions scripts/phpcbf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php
$cli = include 'cli.inc';
$cli->runphpcbf();
40 changes: 40 additions & 0 deletions scripts/phpcs-pre-commit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
$exit = 0;

$runningPhar = Phar::running(false);

if (empty($runningPhar)) {
$phpcode = sprintf('include "%s";', __DIR__ . '/phpcs.php');
} else {
$phpcode = sprintf('Phar::loadPhar("%s");', $runningPhar);
$phpcode .= sprintf('include "phar://%s/scripts/phpcs.php";', $runningPhar);
}

$output = [];
exec('git diff --cached --name-status --diff-filter=ACM', $output);

foreach ($output as $file) {
if (substr($file, 0, 1) === 'D') {
// Deleted file; do nothing.
continue;
}

$fileName = trim(substr($file, 1));

$extension = pathinfo($fileName, PATHINFO_EXTENSION);
if (!preg_match('/^ph(p|tml)$/', $extension)) {
continue;
}

$command = sprintf('php -r %s -- -n %s', escapeshellarg($phpcode), escapeshellarg($fileName));
$output = [];
$return = null;

exec($command, $output, $return);
if ($return != 0 || !empty($output)) {
echo implode("\n", $output) . "\n";
$exit = 1;
}
}

exit($exit);
3 changes: 3 additions & 0 deletions scripts/phpcs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php
$cli = include 'cli.inc';
$cli->runphpcs();
Loading

0 comments on commit 7527df5

Please sign in to comment.