├── tests
├── Fixtures
│ └── configs
│ │ ├── none
│ │ └── .styleci.yml
│ │ ├── none_with_rules
│ │ └── .styleci.yml
│ │ └── default
│ │ └── .styleci.yml
├── ConfigBridgeTest.php
└── StyleCI
│ └── ConfigurationTest.php
├── .gitignore
├── .editorconfig
├── UPGRADE-1.1.md
├── UPGRADE-2.0.md
├── .php_cs
├── .styleci.yml
├── phpunit.xml.dist
├── LICENSE
├── autoload.php
├── composer.json
├── .travis.yml
├── CHANGELOG.md
├── src
├── StyleCI
│ └── Configuration.php
└── ConfigBridge.php
└── README.md
/tests/Fixtures/configs/none/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: none
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | /composer.lock
3 | .php_cs.cache
4 | /build
5 | /*.phar
6 |
--------------------------------------------------------------------------------
/tests/Fixtures/configs/none_with_rules/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: none
2 |
3 | enabled:
4 | - align_double_arrow
5 | - ordered_use
6 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 |
7 | [composer.json]
8 | indent_style = space
9 | indent_size = 4
10 |
11 | [Makefile]
12 | indent_style = tab
13 |
--------------------------------------------------------------------------------
/UPGRADE-1.1.md:
--------------------------------------------------------------------------------
1 | # Upgrade from 1.0 to 1.1
2 |
3 | ## ConfigBridge::getLevel deprecated
4 |
5 | Because StyleCI does not follow PHP-CS-Fixer levels, this method is deprecated.
6 |
7 | Use directly `ConfigBridge::getFixers()` to get the whole set based on StyleCI preset and manual configuration.
8 |
--------------------------------------------------------------------------------
/UPGRADE-2.0.md:
--------------------------------------------------------------------------------
1 | # Upgrade from 1.x to 2.0
2 |
3 | ## Deprecations
4 |
5 | All the deprecated code introduced on 1.x is removed on 2.0.
6 |
7 | Please read 1.x upgrade guides for more information.
8 |
9 | See also the [diff code](https://github.com/Soullivaneuh/php-cs-fixer-styleci-bridge/compare/1.x...v2.0.0).
10 |
--------------------------------------------------------------------------------
/.php_cs:
--------------------------------------------------------------------------------
1 | setUsingCache(true);
9 |
10 | if (method_exists($config, 'setRiskyAllowed')) {
11 | $config->setRiskyAllowed(true);
12 | }
13 |
14 | return $config;
15 |
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: symfony
2 |
3 | enabled:
4 | - newline_after_open_tag
5 | - ordered_use
6 | - long_array_syntax
7 | - php_unit_construct
8 | - php_unit_strict
9 |
10 | disabled:
11 | - psr0
12 |
13 | finder:
14 | not-name:
15 | - "*.php.twig"
16 | not-path:
17 | - "src/StyleCI/Fixers.php"
18 |
--------------------------------------------------------------------------------
/tests/Fixtures/configs/default/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: symfony
2 |
3 | enabled:
4 | - align_double_arrow
5 | - newline_after_open_tag
6 | - ordered_use
7 | - long_array_syntax
8 |
9 | disabled:
10 | - psr0
11 | - unalign_double_arrow
12 | - unalign_equals
13 |
14 | finder:
15 | exclude:
16 | - tmp
17 | not-name:
18 | - autoload.php
19 | - skip_*_test.php
20 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 | ./tests/
16 |
17 |
18 |
19 |
20 |
21 | ./src
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Sullivan Senechal
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/autoload.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * @see https://github.com/composer/composer/issues/1493#issuecomment-12492276
7 | */
8 | class CustomLoader
9 | {
10 | /**
11 | * @var \Composer\Autoload\ClassLoader
12 | */
13 | private $loader;
14 |
15 | /**
16 | * @param \Composer\Autoload\ClassLoader $loader
17 | */
18 | public function __construct($loader)
19 | {
20 | $this->loader = $loader;
21 | }
22 |
23 | /**
24 | * @param string $class The class name
25 | *
26 | * @return bool|null
27 | */
28 | public function loadClass($class)
29 | {
30 | $result = $this->loader->loadClass($class);
31 |
32 | if ($result && method_exists($class, '__static')) {
33 | call_user_func(array($class, '__static'));
34 | }
35 |
36 | return $result;
37 | }
38 | }
39 |
40 | if (file_exists(__DIR__.'/../../autoload.php')) {
41 | $loader = require __DIR__.'/../../autoload.php';
42 | } else {
43 | $loader = require __DIR__.'/vendor/autoload.php';
44 | }
45 | $loader->unregister();
46 | spl_autoload_register(array(new CustomLoader($loader), 'loadClass'));
47 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sllh/php-cs-fixer-styleci-bridge",
3 | "description": "Auto configure PHP-CS-Fixer from StyleCI config file",
4 | "keywords": ["PHP-CS-Fixer", "StyleCI", "PSR", "PSR-1", "PSR-2", "PSR-4", "Symfony", "Laravel", "configuration"],
5 | "type": "library",
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "Sullivan SENECHAL",
10 | "email": "soullivaneuh@gmail.com"
11 | }
12 | ],
13 | "require": {
14 | "php": "^5.3 || ^7.0",
15 | "composer/semver": "^1.0",
16 | "doctrine/inflector": "^1.0",
17 | "sllh/styleci-fixers": "^3.0 || ^4.0",
18 | "symfony/config": "^2.3 || ^3.0",
19 | "symfony/console": "^2.3 || ^3.0",
20 | "symfony/yaml": "^2.3 || ^3.0"
21 | },
22 | "require-dev": {
23 | "friendsofphp/php-cs-fixer": "^1.6.1",
24 | "matthiasnoback/symfony-config-test": "^1.2",
25 | "symfony/phpunit-bridge": "^2.7.4 || ^3.0",
26 | "twig/twig": "^1.22"
27 | },
28 | "autoload": {
29 | "psr-4": { "SLLH\\StyleCIBridge\\": "src" }
30 | },
31 | "autoload-dev": {
32 | "psr-4": { "SLLH\\StyleCIBridge\\Tests\\": "tests" }
33 | },
34 | "config": {
35 | "sort-packages": true
36 | },
37 | "extra": {
38 | "branch-alias": {
39 | "dev-master": "2.x-dev"
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | branches:
2 | only:
3 | - master
4 | - 1.x
5 |
6 | language: php
7 |
8 | php:
9 | - 5.4
10 | - 5.5
11 | - 5.6
12 | - 7.0
13 | - 7.1
14 | - 7.2
15 | - nightly
16 | - hhvm
17 |
18 | env:
19 | global:
20 | - PATH="$HOME/.composer/vendor/bin:$PATH"
21 |
22 | matrix:
23 | fast_finish: true
24 | include:
25 | - php: 5.3
26 | dist: precise
27 | - php: 5.3
28 | dist: precise
29 | env: COMPOSER_FLAGS="--prefer-lowest"
30 | - php: 5.6
31 | env: PHP_CS_FIXER_VERSION=1.*
32 | - php: 5.6
33 | env: PHP_CS_FIXER_VERSION=2.*@dev
34 | - php: 5.6
35 | env: SYMFONY_VERSION=2.7.*
36 | - php: 5.6
37 | env: SYMFONY_VERSION=2.8.*
38 | - php: 5.6
39 | env: SYMFONY_VERSION=3.0.*
40 | - php: 5.6
41 | env: SYMFONY_VERSION=3.1.*
42 | - php: 5.6
43 | env: SYMFONY_VERSION=3.2.*@dev
44 | allow_failures:
45 | - php: nightly
46 | - env: PHP_CS_FIXER_VERSION=2.*@dev
47 | - env: SYMFONY_VERSION=3.2.*@dev
48 |
49 | sudo: false
50 |
51 | cache:
52 | directories:
53 | - $HOME/.composer/cache/files
54 |
55 | before_install:
56 | - if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then phpenv config-rm xdebug.ini; fi;
57 |
58 | install:
59 | - composer global require 'phpunit/phpunit:^4.0 || ^5.0' satooshi/php-coveralls:@stable codeclimate/php-test-reporter:@stable sllh/composer-lint:@stable --prefer-dist --no-interaction
60 | - if [ "$PHP_CS_FIXER_VERSION" != "" ]; then composer require "friendsofphp/php-cs-fixer:${PHP_CS_FIXER_VERSION}" --no-update; fi;
61 | - if [ "$SYMFONY_VERSION" != "" ]; then composer require "symfony/symfony:${SYMFONY_VERSION}" --no-update; fi;
62 | - composer update --prefer-dist --no-interaction $COMPOSER_FLAGS
63 |
64 | before_script:
65 | - if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then echo "zend_extension=xdebug.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi;
66 |
67 | script:
68 | - composer validate
69 | - phpunit -c phpunit.xml.dist --coverage-clover build/logs/clover.xml
70 |
71 | after_script:
72 | - coveralls -v
73 | - test-reporter
74 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | * 2.1.1 (2016-06-22)
4 |
5 | * Fix missing PHPDoc class for `php-cs-fixer` v1 compatibility.
6 | * Use `doctine/inflector` for finder method camelize
7 |
8 | * 2.1.0 (2016-06-10)
9 |
10 | * Manage `none` preset of configuration file.
11 |
12 | * 2.0.2 (2016-06-01)
13 |
14 | * Use new `friendsofphp` vendor name for `php-cs-fixer`.
15 |
16 | * 2.0.1 (2016-04-18)
17 |
18 | * Enable `sllh/styleci-fixers` 4.0.
19 |
20 | * 2.0.0 (2016-04-17)
21 |
22 | * Remove all 1.x deprecated stuff.
23 |
24 | * 1.6.2 (2016-04-18)
25 |
26 | * Enable `sllh/styleci-fixers` 4.0.
27 |
28 | * 1.6.1 (2016-04-17)
29 |
30 | * Fix bad namespace issue with php-cs-fixer 2.x.
31 |
32 | * 1.6.0 (2016-04-17)
33 |
34 | * StyleCI fixers updated (`sllh/styleci-fixers` 3.0).
35 | * Fix some compatibility issues with php-cs-fixer 2.x.
36 |
37 | * 1.5.0 (2015-12-06)
38 |
39 | * Manage StyleCI `risky` option.
40 |
41 | * 1.4.1 (2015-11-19)
42 |
43 | * Manage single scalar values for `enabled`, `disabled` and `finder` configuration keys.
44 |
45 | * 1.4.0 (2015-11-10)
46 |
47 | * Extract StyleCI fixers generator outside of this project,
48 | using [sllh/styleci-fixers](https://github.com/Soullivaneuh/styleci-fixers).
49 | * Allow Symfony 3 dependencies.
50 |
51 | * 1.3.3 (2015-10-16)
52 |
53 | * Use a custom psr-4 loader to avoid code conflict.
54 | * Guess config files path using php backtrace. This avoid issues on subdirectories.
55 |
56 | * 1.3.2 (2015-10-05)
57 |
58 | * Use [composer/semver](https://packagist.org/packages/composer/semver) for better compatibility check.
59 |
60 | * 1.3.1 (2015-09-30)
61 |
62 | * Use `FixerFactory::hasRule` instead of building our own fixers array by name.
63 |
64 | * 1.3.0 (2015-09-29)
65 |
66 | * PHP-CS-Fixer version check.
67 | * Use Symfony Config component for `.styleci.yml` parsing.
68 | * Manage fixers conflicts.
69 |
70 | * 1.2.1 (2015-09-28)
71 |
72 | * Fix some BC breaks with PHP-CS-Fixer 2.0.
73 |
74 | * 1.2.0 (2015-09-25)
75 |
76 | * Resolve fixer aliases for better compatibility with PHP-CS-Fixer 1.x and 2.x.
77 |
78 | * 1.1.0 (2015-09-24)
79 |
80 | * Load fixers from StyleCI config instead of PHP-CS-Fixer.
81 | * Deprecate `ConfigBridge::getFixers`.
82 |
--------------------------------------------------------------------------------
/tests/ConfigBridgeTest.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class ConfigBridgeTest extends \PHPUnit_Framework_TestCase
15 | {
16 | public function testDefaultConfig()
17 | {
18 | $config = ConfigBridge::create(__DIR__.'/Fixtures/configs/default');
19 |
20 | if (method_exists($config, 'getRules')) {
21 | $this->assertArraySubset(array(
22 | 'align_double_arrow' => true,
23 | 'long_array_syntax' => true,
24 | 'linebreak_after_opening_tag' => true,
25 | 'ordered_imports' => true,
26 | 'psr0' => false,
27 | 'unalign_double_arrow' => false,
28 | 'unalign_equals' => false,
29 | ), $config->getRules());
30 | } else { // PHP-CS-Fixer 1.x BC
31 | $expectedFixers = array(
32 | 'align_double_arrow',
33 | 'newline_after_open_tag',
34 | 'ordered_use',
35 | 'long_array_syntax',
36 | 'linebreak_after_opening_tag',
37 | '-psr0',
38 | '-unalign_double_arrow',
39 | '-unalign_equals',
40 | );
41 | foreach ($expectedFixers as $expectedFixer) {
42 | $this->assertTrue(
43 | in_array($expectedFixer, $config->getFixers()),
44 | 'The configuration must have the following fixer: "'.$expectedFixer.'".'
45 | );
46 | }
47 | }
48 |
49 | $this->assertAttributeContains('tmp', 'exclude', $config->getFinder());
50 | $this->assertAttributeContains('autoload.php', 'notNames', $config->getFinder());
51 | }
52 |
53 | public function testNonePreset()
54 | {
55 | $config = ConfigBridge::create(__DIR__.'/Fixtures/configs/none');
56 |
57 | if (method_exists($config, 'getRules')) {
58 | $this->assertSame(array(), $config->getRules());
59 | } else { // PHP-CS-Fixer 1.x BC
60 | $this->assertArraySubset(array(), $config->getFixers());
61 | }
62 | }
63 |
64 | public function testNonePresetWithRules()
65 | {
66 | $config = ConfigBridge::create(__DIR__.'/Fixtures/configs/none_with_rules');
67 |
68 | if (method_exists($config, 'getRules')) {
69 | $this->assertSame(array(
70 | 'align_double_arrow' => true,
71 | 'ordered_imports' => true,
72 | ), $config->getRules());
73 | } else { // PHP-CS-Fixer 1.x BC
74 | $this->assertArraySubset(array(
75 | 'align_double_arrow',
76 | 'ordered_use',
77 | ), $config->getFixers());
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/StyleCI/Configuration.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | final class Configuration implements ConfigurationInterface
16 | {
17 | /**
18 | * {@inheritdoc}
19 | */
20 | public function getConfigTreeBuilder()
21 | {
22 | $treeBuilder = new TreeBuilder();
23 | $rootNode = $treeBuilder->root('styleci');
24 |
25 | $validFixers = array_merge(Fixers::$valid, array_keys(Fixers::$aliases));
26 |
27 | $rootNode
28 | ->children()
29 | ->enumNode('preset')
30 | ->isRequired()
31 | ->values(array_merge(array_keys(Fixers::getPresets()), array(ConfigBridge::PRESET_NONE)))
32 | ->end()
33 | ->booleanNode('linting')
34 | ->defaultTrue()
35 | ->end()
36 | ->arrayNode('enabled')
37 | ->beforeNormalization()
38 | ->ifString()
39 | ->then(function ($v) {
40 | return array($v);
41 | })
42 | ->end()
43 | ->prototype('scalar')
44 | ->validate()
45 | ->ifNotInArray($validFixers)
46 | ->thenInvalid('Invalid enabled fixer %s.')
47 | ->end()
48 | ->end()
49 | ->end()
50 | ->arrayNode('disabled')
51 | ->beforeNormalization()
52 | ->ifString()
53 | ->then(function ($v) {
54 | return array($v);
55 | })
56 | ->end()
57 | ->prototype('scalar')
58 | ->validate()
59 | ->ifNotInArray($validFixers)
60 | ->thenInvalid('Invalid disabled fixer %s.')
61 | ->end()
62 | ->end()
63 | ->end()
64 | ->append($this->getFinderConfigurationNode())
65 | ->booleanNode('risky')
66 | ->defaultTrue()
67 | ->end()
68 | ->end()
69 | ->validate()
70 | ->ifTrue(function ($config) {
71 | $presets = Fixers::getPresets();
72 | $enabledFixers = ConfigBridge::PRESET_NONE === $config['preset']
73 | ? $config['enabled']
74 | : array_merge($presets[$config['preset']], $config['enabled']);
75 | $disabledFixers = $config['disabled'];
76 | $fixers = array_diff($enabledFixers, $disabledFixers);
77 |
78 | // See: https://github.com/StyleCI/Config/blob/f9747aba632aa4d272f212b5b9c9942234f4f074/src/Config.php#L549-L553
79 | foreach (Fixers::$conflicts as $first => $second) {
80 | if (in_array($first, $fixers, true) && in_array($second, $fixers, true)) {
81 | return true;
82 | }
83 | }
84 |
85 | return false;
86 | })
87 | ->thenInvalid('Conflicted fixers. Check conflicts definition.')
88 | ->end()
89 | ;
90 |
91 | return $treeBuilder;
92 | }
93 |
94 | /**
95 | * @return ArrayNodeDefinition|NodeDefinition
96 | */
97 | private function getFinderConfigurationNode()
98 | {
99 | $treeBuilder = new TreeBuilder();
100 | $node = $treeBuilder->root('finder');
101 |
102 | $node
103 | ->beforeNormalization()
104 | ->always(function ($v) {
105 | foreach ($v as $option => $value) {
106 | $v[$option] = (array) $value;
107 | }
108 |
109 | return $v;
110 | })
111 | ->end()
112 | ->children()
113 | ->arrayNode('exclude')
114 | ->prototype('scalar')->end()
115 | ->end()
116 | ->arrayNode('name')
117 | ->prototype('scalar')->end()
118 | ->end()
119 | ->arrayNode('not_name')
120 | ->prototype('scalar')->end()
121 | ->end()
122 | ->arrayNode('contains')
123 | ->prototype('scalar')->end()
124 | ->end()
125 | ->arrayNode('not_contains')
126 | ->prototype('scalar')->end()
127 | ->end()
128 | ->arrayNode('path')
129 | ->prototype('scalar')->end()
130 | ->end()
131 | ->arrayNode('not_path')
132 | ->prototype('scalar')->end()
133 | ->end()
134 | ->arrayNode('depth')
135 | ->prototype('scalar')->end()
136 | ->end()
137 | ->end()
138 | ;
139 |
140 | return $node;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/tests/StyleCI/ConfigurationTest.php:
--------------------------------------------------------------------------------
1 | assertConfigurationIsValid(array('styleci' => $configuration));
27 |
28 | // Set default expected configuration
29 | $expectedProcessedConfiguration = array_merge(array(
30 | 'linting' => true,
31 | 'enabled' => array(),
32 | 'disabled' => array(),
33 | 'risky' => true,
34 | ), $expectedProcessedConfiguration ?: $configuration);
35 |
36 | if (isset($configuration['finder'])) {
37 | $expectedFinderProcessedConfiguration = array_merge_recursive(array(
38 | 'exclude' => array(),
39 | 'name' => array(),
40 | 'not_name' => array(),
41 | 'contains' => array(),
42 | 'not_contains' => array(),
43 | 'path' => array(),
44 | 'not_path' => array(),
45 | 'depth' => array(),
46 | ), !empty($expectedProcessedConfiguration) && isset($expectedProcessedConfiguration['finder'])
47 | ? $expectedProcessedConfiguration['finder']
48 | : $configuration['finder']
49 | );
50 |
51 | $expectedProcessedConfiguration['finder'] = $expectedFinderProcessedConfiguration;
52 | }
53 |
54 | $this->assertProcessedConfigurationEquals(array('styleci' => $configuration), $expectedProcessedConfiguration);
55 | }
56 |
57 | public function validConfigurations()
58 | {
59 | return array(
60 | array(
61 | array(
62 | 'preset' => 'none',
63 | ),
64 | ),
65 | array(
66 | array(
67 | 'preset' => 'psr1',
68 | ),
69 | ),
70 | array(
71 | array(
72 | 'preset' => 'psr2',
73 | ),
74 | ),
75 | array(
76 | array(
77 | 'preset' => 'symfony',
78 | ),
79 | ),
80 | array(
81 | array(
82 | 'preset' => 'laravel',
83 | ),
84 | ),
85 | array(
86 | array(
87 | 'preset' => 'recommended',
88 | ),
89 | ),
90 | array(
91 | array(
92 | 'preset' => 'symfony',
93 | 'linting' => false,
94 | 'enabled' => array(
95 | 'return',
96 | 'phpdoc_params',
97 | ),
98 | 'disabled' => array(
99 | 'short_array_syntax',
100 | ),
101 | 'finder' => array(
102 | 'not_name' => array('*.dummy'),
103 | ),
104 | ),
105 | ),
106 | array(
107 | array(
108 | 'preset' => 'symfony',
109 | 'finder' => array(
110 | 'not-name' => array('*.dummy'),
111 | ),
112 | ),
113 | array(
114 | 'preset' => 'symfony',
115 | 'finder' => array(
116 | 'not_name' => array('*.dummy'),
117 | ),
118 | ),
119 | ),
120 | array(
121 | array(
122 | 'preset' => 'symfony',
123 | 'enabled' => array(
124 | 'align_double_arrow',
125 | ),
126 | 'disabled' => array(
127 | 'unalign_double_arrow',
128 | ),
129 | ),
130 | ),
131 | // Scalar values
132 | array(
133 | array(
134 | 'preset' => 'symfony',
135 | 'enabled' => 'return',
136 | 'disabled' => 'long_array_syntax',
137 | 'finder' => array(
138 | 'exclude' => 'foo',
139 | 'name' => 'foo',
140 | 'not_name' => 'foo',
141 | 'contains' => 'foo',
142 | 'not_contains' => 'foo',
143 | 'path' => 'foo',
144 | 'not_path' => 'foo',
145 | 'depth' => 'foo',
146 | ),
147 | ),
148 | array(
149 | 'preset' => 'symfony',
150 | 'enabled' => array('return'),
151 | 'disabled' => array('long_array_syntax'),
152 | 'finder' => array(
153 | 'exclude' => array('foo'),
154 | 'name' => array('foo'),
155 | 'not_name' => array('foo'),
156 | 'contains' => array('foo'),
157 | 'not_contains' => array('foo'),
158 | 'path' => array('foo'),
159 | 'not_path' => array('foo'),
160 | 'depth' => array('foo'),
161 | ),
162 | ),
163 | ),
164 | );
165 | }
166 |
167 | /**
168 | * @dataProvider invalidConfigurations
169 | *
170 | * @param array $configuration
171 | */
172 | public function testInvalidConfiguration(array $configuration)
173 | {
174 | $this->assertConfigurationIsInvalid(array('styleci' => $configuration));
175 | }
176 |
177 | public function invalidConfigurations()
178 | {
179 | return array(
180 | array(
181 | array(),
182 | ),
183 | array(
184 | array(
185 | 'preset' => 'dummy',
186 | ),
187 | ),
188 | array(
189 | array(
190 | 'preset' => 'symfony',
191 | 'linting' => 42,
192 | ),
193 | ),
194 | array(
195 | array(
196 | 'preset' => 'symfony',
197 | 'linting' => false,
198 | 'enabled' => false,
199 | ),
200 | ),
201 | array(
202 | array(
203 | 'preset' => 'symfony',
204 | 'disabled' => false,
205 | ),
206 | ),
207 | array(
208 | array(
209 | 'preset' => 'symfony',
210 | 'enabled' => array(
211 | 'dummy',
212 | 'phpdoc_params',
213 | ),
214 | ),
215 | ),
216 | array(
217 | array(
218 | 'preset' => 'symfony',
219 | 'disabled' => array(
220 | 'dummy',
221 | 'short_array_syntax',
222 | ),
223 | ),
224 | ),
225 | array(
226 | array(
227 | 'preset' => 'symfony',
228 | 'finder' => array(
229 | 'not-existing-method' => array('*.dummy'),
230 | ),
231 | ),
232 | ),
233 | array(
234 | array(
235 | 'preset' => 'symfony',
236 | 'enabled' => array(
237 | 'align_double_arrow',
238 | ),
239 | ),
240 | ),
241 | array(
242 | array(
243 | 'preset' => 'psr1',
244 | 'enabled' => array(
245 | 'no_blank_lines_before_namespace',
246 | 'single_blank_line_before_namespace',
247 | ),
248 | ),
249 | ),
250 | );
251 | }
252 | }
253 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PHP-CS-Fixer StyleCI bridge
2 |
3 | :warning: **This package is not maintained anymore.** :warning:
4 |
5 | **PHP-CS-Fixer v2 came with a brand new configuration structure but StyleCI decided to keep the old way.**
6 |
7 | **Because of that, it's now very hard to maintain this bridge and it's still not compatible with PHP-CS-Fixer v2.**
8 |
9 | **This is also why I decided to abandon this package and write [FlintCI](https://flintci.io),
10 | my own Code Review service for multiple fixers and linters without any required configuration bridge.**
11 |
12 | **You can try it [here](https://flintci.io) (flintci.io), or keep using StyleCI without this bridge.**
13 |
14 | Auto configure [PHP-CS-Fixer](http://cs.sensiolabs.org/) from [StyleCI](https://styleci.io/) config file.
15 |
16 | This library permits to generate php-cs-fixer configuration directly from your `.styleci.yml` config file.
17 |
18 | With that, you will avoid the pain of both config files maintenance.
19 |
20 | [](https://packagist.org/packages/sllh/php-cs-fixer-styleci-bridge)
21 | [](https://packagist.org/packages/sllh/php-cs-fixer-styleci-bridge)
22 | [](https://packagist.org/packages/sllh/php-cs-fixer-styleci-bridge)
23 | [](https://www.versioneye.com/php/sllh:php-cs-fixer-styleci-bridge)
24 | [](https://www.versioneye.com/php/sllh:php-cs-fixer-styleci-bridge/references)
25 |
26 | [](https://packagist.org/packages/sllh/php-cs-fixer-styleci-bridge)
27 | [](https://packagist.org/packages/sllh/php-cs-fixer-styleci-bridge)
28 | [](https://packagist.org/packages/sllh/php-cs-fixer-styleci-bridge)
29 |
30 | [](https://travis-ci.org/Soullivaneuh/php-cs-fixer-styleci-bridge)
31 | [](https://scrutinizer-ci.com/g/Soullivaneuh/php-cs-fixer-styleci-bridge/?branch=master)
32 | [](https://codeclimate.com/github/Soullivaneuh/php-cs-fixer-styleci-bridge)
33 | [](https://coveralls.io/r/Soullivaneuh/php-cs-fixer-styleci-bridge?branch=master)
34 | [](https://insight.sensiolabs.com/projects/f04c9b72-91a8-4ad7-9e7f-ce6dfc66df78)
35 |
36 | ## Who is using this?
37 |
38 | You can see which projects are using this package on the dedicated [Packagist page](https://packagist.org/packages/sllh/php-cs-fixer-styleci-bridge/dependents).
39 |
40 | ## Installation
41 |
42 | Include this library on your dev dependencies:
43 |
44 | ```bash
45 | composer require --dev sllh/php-cs-fixer-styleci-bridge
46 | ```
47 |
48 | ## Usage
49 |
50 | You can use this bridge with several manners.
51 |
52 | ### Basic usage
53 |
54 | Put the following config on your `.php_cs` file:
55 |
56 | ```php
57 | setUsingCache(true) // Enable the cache
112 | ;
113 | ```
114 |
115 | ### Using the bridge
116 |
117 | You can also using bridge method, part by part.
118 |
119 | ```php
120 | finder($bridge->getFinder())
131 | ->fixers(['dummy', 'foo', '-bar'])
132 | ->setUsingCache(true)
133 | ;
134 | ```
135 |
136 | ### Manually enable or disable fixers
137 |
138 | To enable or disable some fixers manually on the `.php_cs` file,
139 | you will have to use merge system to keep fixers defined by the bridge:
140 |
141 | ```php
142 | require_once __DIR__.'/vendor/sllh/php-cs-fixer-styleci-bridge/autoload.php';
143 |
144 | use SLLH\StyleCIBridge\ConfigBridge;
145 |
146 | $config = ConfigBridge::create();
147 |
148 | return $config
149 | ->setUsingCache(true)
150 | ->fixers(array_merge($config->getFixers(), ['-psr0', 'custom', 'foo', '-bar']))
151 | ;
152 | ```
153 |
154 | ### Header comment
155 |
156 | Unfortunately, header comment option [is not available](https://twitter.com/soullivaneuh/status/644795113399582720) on StyleCI config file.
157 |
158 | You will have to copy it from StyleCI web interface and set it manually.
159 |
160 | The config bridge will automatically detect the fixer and add it on CS configuration.
161 |
162 | #### PHP-CS-Fixer 1.x
163 |
164 | ```php
165 |
176 |
177 | This source file is subject to the MIT license that is bundled
178 | with this source code in the file LICENSE.
179 | EOF;
180 |
181 | HeaderCommentFixer::setHeader($header);
182 |
183 | return ConfigBridge::create();
184 | ```
185 |
186 | #### PHP-CS-Fixer 2.x
187 |
188 | ```php
189 |
199 |
200 | This source file is subject to the MIT license that is bundled
201 | with this source code in the file LICENSE.
202 | EOF;
203 |
204 | $config = ConfigBridge::create();
205 |
206 | return $config
207 | ->setRules(array_merge($config->getRules(), array(
208 | 'header_comment' => array('header' => $header)
209 | )))
210 | ;
211 | ```
212 |
213 | #### Both versions
214 |
215 | You can handle both versions easily with some magic `method_exists` tricks:
216 |
217 | ```php
218 |
229 |
230 | This source file is subject to the MIT license that is bundled
231 | with this source code in the file LICENSE.
232 | EOF;
233 |
234 | // PHP-CS-Fixer 1.x
235 | if (method_exists('Symfony\CS\Fixer\Contrib\HeaderCommentFixer', 'getHeader')) {
236 | HeaderCommentFixer::setHeader($header);
237 | }
238 |
239 | $config = ConfigBridge::create();
240 |
241 | // PHP-CS-Fixer 2.x
242 | if (method_exists($config, 'setRules')) {
243 | $config->setRules(array_merge($config->getRules(), array(
244 | 'header_comment' => array('header' => $header)
245 | )));
246 | }
247 |
248 | return $config;
249 | ```
250 |
251 | ## Troubleshooting
252 |
253 | ### Conflict with code or vendor library
254 |
255 | In some edge cases, the bridge code may conflict with your code or your included vendor.
256 |
257 | This kind of issue was discovered in [puli/cli#21 (comment)](https://github.com/puli/cli/pull/21#issuecomment-148438983)
258 | and fixed since `v1.3.3` in [#47](https://github.com/Soullivaneuh/php-cs-fixer-styleci-bridge/pull/47).
259 |
260 | Before that, you had to require the vendor autoload like this:
261 |
262 | ```php
263 | require __DIR__.'/vendor/autoload.php';
264 | ```
265 |
266 | This is not the secured way. Make sure to require our custom loader instead:
267 |
268 | ```php
269 | require __DIR__.'/vendor/sllh/php-cs-fixer-styleci-bridge/autoload.php';
270 | ```
271 |
--------------------------------------------------------------------------------
/src/ConfigBridge.php:
--------------------------------------------------------------------------------
1 |
24 | */
25 | final class ConfigBridge
26 | {
27 | const CS_FIXER_MIN_VERSION = '1.6.1';
28 |
29 | const PRESET_NONE = 'none';
30 |
31 | /**
32 | * @var OutputInterface
33 | */
34 | private $output;
35 |
36 | /**
37 | * @var FixerFactory
38 | */
39 | private $fixerFactory = null;
40 |
41 | /**
42 | * @var string
43 | */
44 | private $styleCIConfigDir;
45 |
46 | /**
47 | * @var array|null
48 | */
49 | private $styleCIConfig = null;
50 |
51 | /**
52 | * @var string|array
53 | */
54 | private $finderDirs;
55 |
56 | /**
57 | * @param string|null $styleCIConfigDir StyleCI config directory. Called script dir as default
58 | * @param string|array|null $finderDirs A directory path or an array of directories for Finder. Called script dir as default
59 | */
60 | public function __construct($styleCIConfigDir = null, $finderDirs = null)
61 | {
62 | if (!Semver::satisfies(
63 | class_exists('Symfony\CS\Fixer') ? Fixer::VERSION : Application::VERSION, // PHP-CS-Fixer 1.x BC
64 | sprintf('>=%s', self::CS_FIXER_MIN_VERSION)
65 | )) {
66 | throw new \RuntimeException(sprintf(
67 | 'PHP-CS-Fixer v%s is not supported, please upgrade to v%s or higher.',
68 | Fixer::VERSION,
69 | self::CS_FIXER_MIN_VERSION
70 | ));
71 | }
72 |
73 | // Guess config files path if not specified.
74 | // getcwd function is not enough. See: https://github.com/Soullivaneuh/php-cs-fixer-styleci-bridge/issues/46
75 | if (null === $styleCIConfigDir || null === $finderDirs) {
76 | $dbt = version_compare(PHP_VERSION, '5.4.0', '>=') ? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2) : debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
77 |
78 | // Static call
79 | if (isset($dbt[1]['class']) && 'SLLH\StyleCIBridge\ConfigBridge' === $dbt[1]['class'] && 'create' === $dbt[1]['function']) {
80 | $configsPath = dirname($dbt[1]['file']);
81 | } elseif (isset($dbt[0]['class']) && 'SLLH\StyleCIBridge\ConfigBridge' === $dbt[0]['class'] && '__construct' === $dbt[0]['function']) { // Manual instance
82 | $configsPath = dirname($dbt[0]['file']);
83 | } else { // If no case found, fallback to not reliable getcwd method.
84 | $configsPath = getcwd();
85 | }
86 |
87 | $this->styleCIConfigDir = $styleCIConfigDir ?: $configsPath;
88 | $this->finderDirs = $finderDirs ?: $configsPath;
89 | }
90 |
91 | $this->output = new ConsoleOutput();
92 | $this->output->getFormatter()->setStyle('warning', new OutputFormatterStyle('black', 'yellow'));
93 | // PHP-CS-Fixer 1.x BC
94 | if (class_exists('PhpCsFixer\FixerFactory')) { // PHP-CS-Fixer 2.x only
95 | $this->fixerFactory = FixerFactory::create();
96 | $this->fixerFactory->registerBuiltInFixers();
97 | }
98 |
99 | $this->parseStyleCIConfig();
100 | }
101 |
102 | /**
103 | * @param string $styleCIConfigDir
104 | * @param string|array $finderDirs A directory path or an array of directories for Finder
105 | *
106 | * @return Config|\Symfony\CS\Config|\Symfony\CS\Config\Config
107 | */
108 | public static function create($styleCIConfigDir = null, $finderDirs = null)
109 | {
110 | $bridge = new static($styleCIConfigDir, $finderDirs);
111 |
112 | if (class_exists('\Symfony\CS\Config')) { // PHP-CS-Fixer >=1.12,<2.0
113 | $config = \Symfony\CS\Config::create();
114 | } elseif (class_exists('\Symfony\CS\Config\Config')) { // PHP-CS-Fixer 1.x
115 | $config = \Symfony\CS\Config\Config::create();
116 | } else { // PHP-CS-Fixer 2.x
117 | $config = Config::create();
118 | }
119 |
120 | // PHP-CS-Fixer 1.x BC
121 | if (method_exists($config, 'level')) {
122 | $config->level(FixerInterface::NONE_LEVEL);
123 | }
124 |
125 | if (method_exists($config, 'setRules')) {
126 | $config->setRules($bridge->getRules());
127 | } else { // PHP-CS-Fixer 1.x BC
128 | $config->fixers($bridge->getFixers());
129 | }
130 |
131 | // PHP-CS-Fixer 1.x BC
132 | if (method_exists($config, 'setRiskyAllowed')) {
133 | $config->setRiskyAllowed($bridge->getRisky());
134 | }
135 |
136 | // PHP-CS-Fixer 1.x BC
137 | if (method_exists($config, 'setFinder')) {
138 | $config->setFinder($bridge->getFinder());
139 | } else {
140 | $config->finder($bridge->getFinder());
141 | }
142 |
143 | return $config;
144 | }
145 |
146 | /**
147 | * @return Finder|\Symfony\CS\Finder|\Symfony\CS\Finder\DefaultFinder
148 | */
149 | public function getFinder()
150 | {
151 | // PHP-CS-Fixer 1.x BC
152 | if (class_exists('\Symfony\CS\Finder')) { // PHP-CS-Fixer >=1.12,<2.0
153 | $finder = \Symfony\CS\Finder::create()->in($this->finderDirs);
154 | } elseif (class_exists('\Symfony\CS\Finder\DefaultFinder')) { // PHP-CS-Fixer 1.x
155 | $finder = \Symfony\CS\Finder\DefaultFinder::create()->in($this->finderDirs);
156 | } else { // PHP-CS-Fixer 2.x
157 | $finder = Finder::create()->in($this->finderDirs);
158 | }
159 |
160 | if (isset($this->styleCIConfig['finder'])) {
161 | $finderConfig = $this->styleCIConfig['finder'];
162 | foreach ($finderConfig as $key => $values) {
163 | $finderMethod = Inflector::camelize($key);
164 | foreach ($values as $value) {
165 | if (method_exists($finder, $finderMethod)) {
166 | $finder->$finderMethod($value);
167 | } else {
168 | $this->output->writeln(sprintf(
169 | 'Can not apply "%s" finder option with PHP-CS-Fixer v%s. You fixer config may be erroneous. Consider upgrading to fix it.',
170 | str_replace('_', '-', $key),
171 | Fixer::VERSION
172 | ));
173 | }
174 | }
175 | }
176 | }
177 |
178 | return $finder;
179 | }
180 |
181 | /**
182 | * @return string[]
183 | */
184 | public function getFixers()
185 | {
186 | $presetFixers = $this->resolveAliases($this->getPresetFixers());
187 | $enabledFixers = $this->resolveAliases($this->styleCIConfig['enabled']);
188 | $disabledFixers = $this->resolveAliases($this->styleCIConfig['disabled']);
189 |
190 | $fixers = array_merge(
191 | $enabledFixers,
192 | array_map(function ($disabledFixer) {
193 | return '-'.$disabledFixer;
194 | }, $disabledFixers),
195 | array_diff($presetFixers, $disabledFixers) // Remove disabled fixers from preset
196 | );
197 |
198 | // PHP-CS-Fixer 1.x BC
199 | if (method_exists('Symfony\CS\Fixer\Contrib\HeaderCommentFixer', 'getHeader') && HeaderCommentFixer::getHeader()) {
200 | array_push($fixers, 'header_comment');
201 | }
202 |
203 | return $fixers;
204 | }
205 |
206 | /**
207 | * Returns fixers converted to rules for PHP-CS-Fixer 2.x.
208 | *
209 | * @return array
210 | */
211 | public function getRules()
212 | {
213 | $fixers = $this->getFixers();
214 |
215 | $rules = array();
216 | foreach ($fixers as $fixer) {
217 | if ('-' === $fixer[0]) {
218 | $name = substr($fixer, 1);
219 | $enabled = false;
220 | } else {
221 | $name = $fixer;
222 | $enabled = true;
223 | }
224 |
225 | if ($this->isFixerAvailable($name)) {
226 | $rules[$name] = $enabled;
227 | } else {
228 | $this->output->writeln(sprintf('Fixer "%s" does not exist, skipping.', $name));
229 | }
230 | }
231 |
232 | return $rules;
233 | }
234 |
235 | /**
236 | * @return bool
237 | */
238 | public function getRisky()
239 | {
240 | return $this->styleCIConfig['risky'];
241 | }
242 |
243 | /**
244 | * @return string[]
245 | */
246 | private function getPresetFixers()
247 | {
248 | if (static::PRESET_NONE === $this->styleCIConfig['preset']) {
249 | return array();
250 | }
251 | $validPresets = Fixers::getPresets();
252 |
253 | return $validPresets[$this->styleCIConfig['preset']];
254 | }
255 |
256 | /**
257 | * Adds both aliases and real fixers if set. PHP-CS-Fixer would not take care if not existing.
258 | * Better compatibility between PHP-CS-Fixer 1.x and 2.x.
259 | *
260 | * @param string[] $fixers
261 | *
262 | * @return string[]
263 | */
264 | private function resolveAliases(array $fixers)
265 | {
266 | foreach (Fixers::$aliases as $alias => $name) {
267 | if (in_array($alias, $fixers, true) && !in_array($name, $fixers, true) && $this->isFixerAvailable($name)) {
268 | array_push($fixers, $name);
269 | }
270 | if (in_array($name, $fixers, true) && !in_array($alias, $fixers, true) && $this->isFixerAvailable($alias)) {
271 | array_push($fixers, $alias);
272 | }
273 | }
274 |
275 | return $fixers;
276 | }
277 |
278 | /**
279 | * @param string $name
280 | *
281 | * @return bool
282 | */
283 | private function isFixerAvailable($name)
284 | {
285 | // PHP-CS-Fixer 1.x BC
286 | if (null === $this->fixerFactory) {
287 | return true;
288 | }
289 |
290 | return $this->fixerFactory->hasRule($name);
291 | }
292 |
293 | private function parseStyleCIConfig()
294 | {
295 | if (null === $this->styleCIConfig) {
296 | $config = Yaml::parse(file_get_contents(sprintf('%s/.styleci.yml', $this->styleCIConfigDir)));
297 | $processor = new Processor();
298 | $this->styleCIConfig = $processor->processConfiguration(new Configuration(), array('styleci' => $config));
299 | }
300 | }
301 | }
302 |
--------------------------------------------------------------------------------