├── .gitignore ├── .gitattributes ├── config ├── silverstripe-4-1.php ├── silverstripe-4-2.php ├── silverstripe-4-3.php ├── silverstripe-4-4.php ├── silverstripe-4-5.php ├── silverstripe-4-6.php ├── silverstripe-4-7.php ├── silverstripe-4-8.php ├── silverstripe-4-9.php ├── silverstripe-5-1.php ├── silverstripe-5-2.php ├── silverstripe-4-10.php ├── silverstripe-4-11.php ├── silverstripe-4-12.php ├── silverstripe-4-13.php ├── level │ ├── up-to-silverstripe-4-1.php │ ├── up-to-silverstripe-4-10.php │ ├── up-to-silverstripe-4-2.php │ ├── up-to-silverstripe-4-3.php │ ├── up-to-silverstripe-4-4.php │ ├── up-to-silverstripe-4-5.php │ ├── up-to-silverstripe-4-6.php │ ├── up-to-silverstripe-4-7.php │ ├── up-to-silverstripe-4-8.php │ ├── up-to-silverstripe-4-9.php │ ├── up-to-silverstripe-5-0.php │ ├── up-to-silverstripe-5-1.php │ ├── up-to-silverstripe-5-2.php │ ├── up-to-silverstripe-5-3.php │ ├── up-to-silverstripe-4-11.php │ ├── up-to-silverstripe-4-12.php │ ├── up-to-silverstripe-4-13.php │ ├── up-to-silverstripe-5-4.php │ └── up-to-silverstripe-6-0.php ├── silverstripe-5-4.php ├── code-style.php ├── silverstripe-5-3.php ├── silverstripe-4-0.php ├── silverstripe-5-0.php └── silverstripe-6-0.php ├── .github ├── dependabot.yml └── workflows │ ├── phpunit.yml │ └── docs.yml ├── phpunit.xml.dist ├── composer.json ├── LICENSE ├── src ├── Set │ ├── SilverstripeSetList.php │ └── SilverstripeLevelSetList.php └── Rector │ ├── Misc │ ├── RenameAddFieldsToTabWithoutArrayParamRector.php │ └── AddConfigPropertiesRector.php │ ├── DataObject │ └── EnsureTableNameIsSetRector.php │ └── Injector │ └── UseCreateRector.php ├── docs └── all_rectors_overview.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /.idea/ 3 | composer.lock 4 | .phpunit.result.cache 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | rector.php export-ignore 2 | /stubs export-ignore 3 | /tests export-ignore 4 | /.ddev export-ignore -------------------------------------------------------------------------------- /config/silverstripe-4-1.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeSetList::SS_4_0, 13 | SilverstripeSetList::SS_4_1, 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-10.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_9, 13 | SilverstripeSetList::SS_4_10 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-2.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_1, 13 | SilverstripeSetList::SS_4_2 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-3.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_2, 13 | SilverstripeSetList::SS_4_3 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-4.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_3, 13 | SilverstripeSetList::SS_4_4 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-5.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_4, 13 | SilverstripeSetList::SS_4_5 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-6.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_5, 13 | SilverstripeSetList::SS_4_6 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-7.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_6, 13 | SilverstripeSetList::SS_4_7 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-8.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_7, 13 | SilverstripeSetList::SS_4_8 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-9.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_8, 13 | SilverstripeSetList::SS_4_9 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-5-0.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_13, 13 | SilverstripeSetList::SS_5_0 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-5-1.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_5_0, 13 | SilverstripeSetList::SS_5_1 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-5-2.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_5_1, 13 | SilverstripeSetList::SS_5_2 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-5-3.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_5_2, 13 | SilverstripeSetList::SS_5_3 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-11.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_10, 13 | SilverstripeSetList::SS_4_11 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-12.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_11, 13 | SilverstripeSetList::SS_4_12 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-4-13.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_4_12, 13 | SilverstripeSetList::SS_4_13 14 | ]); 15 | }; -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-5-4.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_5_3, 13 | SilverstripeSetList::SS_5_4 14 | ]); 15 | }; 16 | -------------------------------------------------------------------------------- /config/level/up-to-silverstripe-6-0.php: -------------------------------------------------------------------------------- 1 | sets([ 12 | SilverstripeLevelSetList::UP_TO_SS_5_4, 13 | SilverstripeSetList::SS_6_0 14 | ]); 15 | }; 16 | -------------------------------------------------------------------------------- /config/silverstripe-5-4.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | tests 6 | 7 | 8 | 9 | 10 | src 11 | config 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /config/code-style.php: -------------------------------------------------------------------------------- 1 | rule(UseCreateRector::class); 11 | 12 | // ->owner => ->getOwner() 13 | $rectorConfig->ruleWithConfiguration( 14 | PropertyFetchToMethodCallRector::class, 15 | [ 16 | new PropertyFetchToMethodCall( 17 | 'SilverStripe\Core\Extension', 18 | 'owner', 19 | 'getOwner', 20 | ) 21 | ] 22 | ); 23 | }; -------------------------------------------------------------------------------- /config/silverstripe-5-3.php: -------------------------------------------------------------------------------- 1 | rule(RenameAddFieldsToTabWithoutArrayParamRector::class); 11 | 12 | $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ 13 | 'SilverStripe\ORM\DataExtension' => 'SilverStripe\Core\Extension', 14 | 'SilverStripe\CMS\Model\SiteTreeExtension' => 'SilverStripe\Core\Extension', 15 | 'SilverStripe\Admin\LeftAndMainExtension' => 'SilverStripe\Core\Extension', 16 | ]); 17 | $rectorConfig->importNames(); 18 | $rectorConfig->removeUnusedImports(); 19 | }; 20 | -------------------------------------------------------------------------------- /.github/workflows/phpunit.yml: -------------------------------------------------------------------------------- 1 | name: PHPunit 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | phpunit: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | php: 14 | # - '7.4' 15 | # - '8.0' 16 | # - '8.1' 17 | - '8.2' 18 | - '8.3' 19 | - '8.4' 20 | 21 | name: PHPunit - PHP ${{ matrix.php }} 22 | 23 | steps: 24 | - name: Checkout code 25 | uses: actions/checkout@v5 26 | 27 | - name: Setup PHP 28 | uses: shivammathur/setup-php@v2 29 | with: 30 | php-version: ${{ matrix.php }} 31 | 32 | - name: Composer update 33 | run: composer update --no-progress --no-interaction 34 | 35 | - name: PHPunit 36 | run: vendor/bin/phpunit # --coverage-text 37 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wernerkrauss/silverstripe-rector", 3 | "description": "Rector rules for Silverstripe CMS", 4 | "type": "rector-extension", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Werner Krauß", 9 | "email": "werner.krauss@netwerkstatt.at" 10 | } 11 | ], 12 | "require": { 13 | "php": "^7.4 | ^8", 14 | "rector/rector": "^2" 15 | }, 16 | "require-dev": { 17 | "phpunit/phpunit": "^11.3" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "Netwerkstatt\\SilverstripeRector\\": "src/", 22 | "Rector\\":"rules" 23 | } 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "Netwerkstatt\\SilverstripeRector\\Tests\\": "tests" 28 | }, 29 | "classmap": ["stubs"], 30 | "exclude-from-classmap": [ 31 | "**.php.inc" 32 | ] 33 | }, 34 | "scripts": { 35 | "docs:generate": "@php rule-doc-generator generate --output-file docs/all_rectors_overview.md --ansi --categorize 2 -- ./src/" 36 | }, 37 | "minimum-stability": "dev", 38 | "prefer-stable": true 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 wernerkrauss 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | 8 | env: 9 | # see https://github.com/composer/composer/issues/9368#issuecomment-718112361 10 | COMPOSER_ROOT_VERSION: "dev-main" 11 | 12 | jobs: 13 | docs: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v5 17 | 18 | - uses: shivammathur/setup-php@v2 19 | with: 20 | php-version: 8.2 21 | coverage: none 22 | env: 23 | COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | 25 | # see https://github.com/ramsey/composer-install 26 | - uses: "ramsey/composer-install@v3" 27 | 28 | - name: Install rule doc generator 29 | run: composer require symplify/rule-doc-generator:^12.1 --with-all-dependencies 30 | 31 | - name: Generate documentation 32 | run: "composer docs:generate" 33 | 34 | - name: Uninstall rule doc generator 35 | run: composer remove symplify/rule-doc-generator 36 | 37 | - uses: stefanzweifel/git-auto-commit-action@v6.0.1 38 | with: 39 | commit_message: '[DOCS] Generate documentation' 40 | commit_options: '--no-verify --signoff' 41 | branch: "main" 42 | push_options: '--force' 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /src/Set/SilverstripeSetList.php: -------------------------------------------------------------------------------- 1 | addFieldsToTab($name, $singleField) to ->addFieldToTab($name, $singleField)', [new CodeSample(<<<'CODE_SAMPLE' 21 | class SomeClass extends \SilverStripe\ORM\DataObject 22 | { 23 | public function getCMSFields() { 24 | $myfield = FormField::create(); 25 | $fields->addFieldsToTab('Root.Main', $myfield); 26 | } 27 | } 28 | CODE_SAMPLE 29 | , <<<'CODE_SAMPLE' 30 | class SomeClass extends \SilverStripe\ORM\DataObject 31 | { 32 | public function getCMSFields() { 33 | $myfield = FormField::create(); 34 | $fields->addFieldToTab('Root.Main', $myfield); 35 | } 36 | } 37 | CODE_SAMPLE 38 | )]); 39 | } 40 | 41 | /** 42 | * @return array> 43 | */ 44 | public function getNodeTypes() : array 45 | { 46 | return [MethodCall::class, NullsafeMethodCall::class]; 47 | } 48 | /** 49 | * @param FuncCall $node 50 | */ 51 | public function refactor(Node $node) : ?Node 52 | { 53 | if (!$node->name === 'addFieldsToTab') { 54 | return null; 55 | } 56 | 57 | if ($node->args !== [] && $node->args[1]->value instanceof Node\Expr\Array_) { 58 | return null; 59 | } 60 | $node->name = new Name('addFieldToTab'); 61 | return $node; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /docs/all_rectors_overview.md: -------------------------------------------------------------------------------- 1 | # 4 Rules Overview 2 | 3 |
4 | 5 | ## Categories 6 | 7 | - [Rector](#rector) (4) 8 | 9 |
10 | 11 | ## Rector 12 | 13 | ### AddConfigPropertiesRector 14 | 15 | Adds `@config` property to predefined private statics, e.g. `$db` or `$allowed_actions` 16 | 17 | :wrench: **configure it!** 18 | 19 | - class: [`Netwerkstatt\SilverstripeRector\Rector\Misc\AddConfigPropertiesRector`](../src/Rector/Misc/AddConfigPropertiesRector.php) 20 | 21 | ```diff 22 | class SomeClass extends \SilverStripe\ORM\DataObject 23 | { 24 | + /** 25 | + * @config 26 | + */ 27 | private static $db = []; 28 | } 29 | ``` 30 | 31 |
32 | 33 | ### EnsureTableNameIsSetRector 34 | 35 | DataObject subclasses must have "$table_name" defined 36 | 37 | - class: [`Netwerkstatt\SilverstripeRector\Rector\DataObject\EnsureTableNameIsSetRector`](../src/Rector/DataObject/EnsureTableNameIsSetRector.php) 38 | 39 | ```diff 40 | class SomeClass extends \SilverStripe\ORM\DataObject 41 | { 42 | + private static $table_name = 'SomeClass'; 43 | + 44 | private static $db = []; 45 | } 46 | ``` 47 | 48 |
49 | 50 | ### RenameAddFieldsToTabWithoutArrayParamRector 51 | 52 | Renames ->addFieldsToTab($name, `$singleField)` to ->addFieldToTab($name, `$singleField)` 53 | 54 | - class: [`Netwerkstatt\SilverstripeRector\Rector\Misc\RenameAddFieldsToTabWithoutArrayParamRector`](../src/Rector/Misc/RenameAddFieldsToTabWithoutArrayParamRector.php) 55 | 56 | ```diff 57 | class SomeClass extends \SilverStripe\ORM\DataObject 58 | { 59 | public function getCMSFields() { 60 | $myfield = FormField::create(); 61 | - $fields->addFieldsToTab('Root.Main', $myfield); 62 | + $fields->addFieldToTab('Root.Main', $myfield); 63 | } 64 | } 65 | ``` 66 | 67 |
68 | 69 | ### UseCreateRector 70 | 71 | Change new Object to static call for classes that use Injectable trait 72 | 73 | - class: [`Netwerkstatt\SilverstripeRector\Rector\Injector\UseCreateRector`](../src/Rector/Injector/UseCreateRector.php) 74 | 75 | ```diff 76 | class SomeClass 77 | { 78 | public function run() 79 | { 80 | - new InjectableClass($name); 81 | + InjectableClass::create($name); 82 | } 83 | } 84 | ``` 85 | 86 |
87 | -------------------------------------------------------------------------------- /src/Rector/DataObject/EnsureTableNameIsSetRector.php: -------------------------------------------------------------------------------- 1 | > 45 | */ 46 | public function getNodeTypes(): array 47 | { 48 | return [Class_::class]; 49 | } 50 | 51 | /** 52 | * @param Class_ $node 53 | */ 54 | public function refactor(\PhpParser\Node $node): ?\PhpParser\Node 55 | { 56 | if (!$this->isObjectType($node, new ObjectType(\SilverStripe\ORM\DataObject::class))) { 57 | return null; 58 | } 59 | 60 | //check if table_name is already set; don't modify 61 | if ($node->getProperty('table_name') instanceof \PhpParser\Node\Stmt\Property) { 62 | return null; 63 | } 64 | 65 | $name = $this->nodeNameResolver->getShortName($this->getName($node)); 66 | // change the node 67 | $tableName = new Property('table_name'); 68 | $tableName->makePrivate(); 69 | $tableName->makeStatic(); 70 | $tableName->setDefault($name); 71 | 72 | array_unshift($node->stmts, $tableName->getNode(), new Node\Stmt\Nop()); 73 | 74 | return $node; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Rector/Injector/UseCreateRector.php: -------------------------------------------------------------------------------- 1 | reflectionProvider = $reflectionProvider; 28 | } 29 | 30 | public function getRuleDefinition(): RuleDefinition 31 | { 32 | return new RuleDefinition('Change new Object to static call for classes that use Injectable trait', [ 33 | new CodeSample(<<<'CODE_SAMPLE' 34 | class SomeClass 35 | { 36 | public function run() 37 | { 38 | new InjectableClass($name); 39 | } 40 | } 41 | CODE_SAMPLE 42 | , <<<'CODE_SAMPLE' 43 | class SomeClass 44 | { 45 | public function run() 46 | { 47 | InjectableClass::create($name); 48 | } 49 | } 50 | CODE_SAMPLE 51 | ) 52 | ]); 53 | } 54 | 55 | /** 56 | * @inheritDoc 57 | */ 58 | public function getNodeTypes(): array 59 | { 60 | return [New_::class]; 61 | } 62 | 63 | /** 64 | * @inheritDoc 65 | */ 66 | public function refactor(Node $node): ?Node 67 | { 68 | $traits = []; 69 | $class = $node->class; 70 | if (!method_exists($class, 'toString')) { 71 | return null; //we have something like "new $foo" 72 | } 73 | 74 | $className = $class->toString(); 75 | if (!$this->reflectionProvider->hasClass($className)) { 76 | return null; 77 | } 78 | 79 | $classReflection = $this->reflectionProvider->getClass($className); 80 | 81 | if (!$classReflection->hasTraitUse(\SilverStripe\Core\Injector\Injectable::class)) { 82 | return null; 83 | } 84 | 85 | return $this->nodeFactory->createStaticCall($node->class, 'create', $node->args); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /config/silverstripe-4-0.php: -------------------------------------------------------------------------------- 1 | rule(EnsureTableNameIsSetRector::class); 12 | 13 | //pre 4.0 14 | $object_traits = [ 15 | 'SilverStripe\Core\Injector\Injectable', 16 | 'SilverStripe\Core\Config\Configurable', 17 | 'SilverStripe\Core\Extensible' 18 | ]; 19 | $rectorConfig->ruleWithConfiguration( 20 | ParentClassToTraitsRector::class, 21 | [ 22 | new ParentClassToTraits('Object', $object_traits), 23 | new ParentClassToTraits('SS_Object', $object_traits), 24 | ] 25 | ); 26 | 27 | 28 | //4.0 https://docs.silverstripe.org/en/4/changelogs/4.0.0/#dataobject-versioned 29 | //Versioned::publish Replaced by Versioned::copyVersionToStage 30 | 31 | //Versioned::doPublish Replaced by Versioned::publishRecursive 32 | 33 | //The Config::inst()->update() method is deprecated, and replaced with Config::modify()->set() and Config::modify()->merge() to respectively replace and merge config. 34 | 35 | //https://docs.silverstripe.org/en/4/changelogs/4.0.0/#overview-general 36 | 37 | //SiteTree.alternatePreviewLink is deprecated. Use updatePreviewLink instead. 38 | 39 | //Deprecated Member::checkPassword(). Use Authenticator::checkPassword() instead 40 | 41 | //Deprecated ClassInfo::baseDataClass(). Use DataObject::getSchema()->baseDataClass() instead. 42 | 43 | //Deprecated ClassInfo::table_for_object_field(). Use DataObject::getSchema()->tableForField() instead 44 | 45 | //https://docs.silverstripe.org/en/4/changelogs/4.0.0/#overview-orm 46 | //Deprecated SQLQuery in favour SQLSelect 47 | 48 | //Renamed String::NoHTML() to Plain() 49 | 50 | //Removed String::LimitWordCountXML(). Use LimitWordCount() instead. 51 | 52 | //Removed String::BigSummary(). Use Summary() instead. 53 | 54 | //Renamed FormField#createTag() to FormField::create_tag() 55 | 56 | //Permission::flush_permission_cache() renamed to reset() and added to Resettable interface. 57 | 58 | //Renamed Versioned::reading_stage() to set_stage() (throws an error if setting an invalid stage) 59 | //Renamed Versioned::current_stage() to get_stage() 60 | //Removed Versioned::get_live_stage(). Use the Versioned::LIVE constant instead. 61 | //Removed Versioned::getDefaultStage(). Use the Versioned::DRAFT constant instead. 62 | 63 | 64 | }; -------------------------------------------------------------------------------- /config/silverstripe-5-0.php: -------------------------------------------------------------------------------- 1 | Note: if you need to use PHPStan v1 in your project, use v0.x of this module 19 | 20 | ```bash 21 | composer require phpstan/extension-installer --dev 22 | composer require cambis/silverstan --dev 23 | composer require wernerkrauss/silverstripe-rector --dev 24 | vendor/bin/rector init 25 | ``` 26 | 27 | Create a basic `phpstan.neon` file in your project root: 28 | 29 | ```yaml 30 | parameters: 31 | level: 1 32 | paths: 33 | - app/src 34 | ``` 35 | 36 | This will add all requirements and create a file called `rector.php` in your project root. You'll need to adjust it, e.g. add the code directories to upgrade and the rules to use. 37 | 38 | A basic Rector config can look like 39 | 40 | ```php 41 | withPreparedSets( 51 | deadCode: true, 52 | codeQuality: true, 53 | codingStyle: true, 54 | typeDeclarations: true, 55 | instanceOf: true, 56 | earlyReturn: true, 57 | rectorPreset: true 58 | ) 59 | ->withPhpSets() //automatically gets the PHP version from composer.json 60 | ->withSets([ 61 | //silverstripe rector 62 | SilverstripeSetList::CODE_STYLE, 63 | SilverstripeLevelSetList::UP_TO_SS_6_0 64 | ]); 65 | 66 | ``` 67 | 68 | Silverstripe-rector comes with two types of SetLists: `SilverstripeSetList` for single sets of rectors (e.g. upgrading from 5.0 to 5.1 or for general Silverstripe code styles) and `SilverstripeLevelSetList` for combining all set lists up to a given Silverstripe CMS version, e.g. running all upgrades to Silverstripe 5.1. 69 | 70 | See also [Rector documentation](https://getrector.com/documentation) for more configuration possibilities. 71 | 72 | ## Running rector 73 | 74 | Once it's configured, you can run Rector in the command line using the following command: 75 | 76 | ```bash 77 | vendor/bin/rector --dry-run 78 | ``` 79 | 80 | The option `--dry-run` prints the code changes; if you're happy with the changes, you can remove that option and rector will actually change the files. 81 | 82 | ### Useful options: 83 | 84 | - `--debug` for debugging verbosity. Which files and rules are processed? 85 | - `--xdebug` switch that allows running xdebug. 86 | 87 | See `vendor/bin/rector --help` for more options. 88 | 89 | ## Docs 90 | 91 | See a [list of custom Silverstripe related rectors](./docs/all_rectors_overview.md) in the docs. 92 | 93 | 94 | ## Other useful modules you should know about 95 | * [cambis/silverstripe-rector](https://packagist.org/packages/cambis/silverstripe-rector) 96 | 97 | ## TODO 98 | 99 | ### SS3 to SS4 upgrades (before running official upgrader tool) 100 | - [ ] rename `Foo_Controller` to `FooController` 101 | - how can this be made dynamically? via config script that scans the current project? 102 | - [ ] configure PSR4 Class To File 103 | - [ ] maybe add namespace to `src` dir 104 | - [ ] various deprecations. 105 | - Is it possible to automate stuff that was once configured in PHP and is now configured in YML? 106 | - easy fix would be to switch to new config layer in PHP and add an annotation to fix this manually 107 | - [ ] fix old `Image` functions in templates that got deprecated in SS3.2 108 | - this needs another file parser for Silverstripe templates 109 | - [ ] class `Object` to trait, see [ParentClassToTraitsRector](https://github.com/rectorphp/rector/blob/main/docs/rector_rules_overview.md#parentclasstotraitsrector) 110 | 111 | ### SS4 upgrades 112 | - [X] add `$table_name` if missing - use short classname instead 113 | - see similar [UnifyModelDatesWithCastsRector](https://github.com/rectorphp/rector-laravel/blob/main/src/Rector/Class_/UnifyModelDatesWithCastsRector.php) 114 | - [ ] various deprecations 115 | - to be configured manually in set lists 116 | - [ ] fix missing `$owns` for Image and File relations 117 | - [ ] configurable exclude list if it's not wanted 118 | - [ ] configurable which relations should be automatically owned (e.g. other versioned DataObjects) 119 | 120 | ### General 121 | #### Misc 122 | - [X] create SetLists for easier configuration 123 | 124 | #### Code Quality 125 | - [X] convert `new Foo()` to `Foo::create()` if it's a Silverstripe / Injectable class 126 | - see [NewToStaticCallRector](https://github.com/rectorphp/rector/blob/main/docs/rector_rules_overview.md#newtomethodcallrector) 127 | - [X] add `@config` param to `$db`, `$has_one`, etc. 128 | - [ ] use Request handler instead of superglobal `$_GET` and `$_POST` 129 | 130 | ## Thanks to 131 | [xini](https://github.com/xini) for updating this module to Rector V2 and adding a lot of Silverstripe 6 rules. 132 | 133 | ## Need Help? 134 | 135 | If you need some help with your Silverstripe project, feel free to [contact me](mailto:werner.krauss@netwerkstatt.at) ✉️. 136 | 137 | See you at next [StripeCon](https://stripecon.eu) 👋 138 | -------------------------------------------------------------------------------- /src/Rector/Misc/AddConfigPropertiesRector.php: -------------------------------------------------------------------------------- 1 | [ 43 | 'table_name', 44 | 'db', 45 | 'has_one', 46 | 'belongs_to', 47 | 'has_many', 48 | 'many_many', 49 | 'many_many_extraFields', 50 | 'belongs_many_many', 51 | 'default_sort', 52 | 'cascade_deletes', 53 | 'cascade_duplicates', 54 | 'searchable_fields', 55 | 'summary_fields', 56 | 'casting', 57 | 'singular_name', 58 | 'plural_name', 59 | 'owns', 60 | 'translate', 61 | 'defaults', 62 | 'extensions' 63 | ], 64 | Controller::class => [ 65 | 'allowed_actions', 66 | 'url_handlers', 67 | 'url_segment', 68 | 'extensions' 69 | ], 70 | LeftAndMain::class => [ 71 | 'menu_icon', 72 | 'menu_priority', 73 | 'url_priority', 74 | ], 75 | ModelAdmin::class => [ 76 | 'managed_models', 77 | 'page_length', 78 | 'menu_title', 79 | 'menu_icon_class', 80 | ], 81 | \SilverStripe\Core\Extension::class => [ 82 | 'allowed_actions', 83 | 'url_handlers', 84 | 'db', 85 | 'has_one', 86 | 'belongs_to', 87 | 'has_many', 88 | 'many_many', 89 | 'many_many_extraFields', 90 | 'belongs_many_many', 91 | 'default_sort', 92 | 'cascade_deletes', 93 | 'cascade_duplicates', 94 | 'searchable_fields', 95 | 'summary_fields', 96 | 'casting', 97 | 'singular_name', 98 | 'plural_name', 99 | 'owns', 100 | 'translate', 101 | 'defaults', 102 | 'required_fields' 103 | ], 104 | 'SilverStripe\Dev\BuildTask' => [ 105 | 'segment', 106 | 'title', 107 | 'description', 108 | 'is_enabled' 109 | ], 110 | 'SilverStripe\CMS\Model\SiteTree' => [ 111 | 'icon' 112 | ], 113 | //Elemental 114 | 'DNADesign\Elemental\Models\BaseElement' => [ 115 | 'icon', 116 | 'inline_editable', 117 | 'description' 118 | ], 119 | ]; 120 | 121 | public function __construct(PhpDocTypeChanger $phpDocTypeChanger, DocBlockUpdater $docBlockUpdater, PhpDocInfoFactory $phpDocInfoFactory) 122 | { 123 | $this->phpDocTypeChanger = $phpDocTypeChanger; 124 | $this->docBlockUpdater = $docBlockUpdater; 125 | $this->phpDocInfoFactory = $phpDocInfoFactory; 126 | } 127 | 128 | /** 129 | * @var false 130 | */ 131 | private bool $nodeIsChanged; 132 | 133 | public function getRuleDefinition(): RuleDefinition 134 | { 135 | return new RuleDefinition('Adds @config property to predefined private statics, e.g. $db or $allowed_actions', 136 | [ 137 | new ConfiguredCodeSample(<<<'CODE_SAMPLE' 138 | class SomeClass extends \SilverStripe\ORM\DataObject 139 | { 140 | private static $db = []; 141 | } 142 | CODE_SAMPLE 143 | , <<<'CODE_SAMPLE' 144 | class SomeClass extends \SilverStripe\ORM\DataObject 145 | { 146 | /** 147 | * @config 148 | */ 149 | private static $db = []; 150 | } 151 | CODE_SAMPLE, 152 | [ 153 | 'ClassName' => [ 154 | 'config_param' 155 | ], 156 | ] 157 | ) 158 | ]); 159 | } 160 | 161 | /** 162 | * @inheritDoc 163 | */ 164 | public function getNodeTypes(): array 165 | { 166 | return [Class_::class]; 167 | } 168 | 169 | /** 170 | * @inheritDoc 171 | */ 172 | public function refactor(Node $node): ?Node 173 | { 174 | $config = $this->getConfig(); 175 | $this->nodeIsChanged = \false; 176 | $propertiesToCheck = []; 177 | 178 | foreach ($config as $className => $configProperties) { 179 | if (!$this->isObjectType($node, new ObjectType($className))) { 180 | continue; 181 | } 182 | 183 | $propertiesToCheck = array_merge($propertiesToCheck, $configProperties); 184 | } 185 | 186 | if ($propertiesToCheck !== []) { 187 | $node = $this->checkConfigProperties($node, array_unique($propertiesToCheck)); 188 | } 189 | 190 | return $this->nodeIsChanged ? $node : null; 191 | } 192 | 193 | private function getConfig(): array 194 | { 195 | $config = array_merge_recursive($this->defaultClassConfigPairs, $this->classConfigPairs); 196 | //loop through the config and remove duplicate entries in the arrays 197 | //caused by e.g. $db being in default config and in project's rector.php 198 | foreach ($config as $className => $configProperties) { 199 | $config[$className] = array_unique($configProperties); 200 | } 201 | 202 | return $config; 203 | } 204 | 205 | private function checkConfigProperties(Node $node, array $configProperties): Node 206 | { 207 | foreach ($configProperties as $configProperty) { 208 | $property = $node->getProperty($configProperty); 209 | if (!$property) { 210 | continue; 211 | } 212 | 213 | //check if it's a private static 214 | 215 | $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property); 216 | if ($phpDocInfo->hasByName('@config')) { 217 | continue; 218 | } 219 | 220 | $phpDocInfo->addPhpDocTagNode(new PhpDocTextNode('@config')); 221 | $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($property); 222 | 223 | $this->nodeIsChanged = \true; 224 | } 225 | 226 | return $node; 227 | } 228 | 229 | public function configure(array $configuration): void 230 | { 231 | $this->classConfigPairs = $configuration; 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /config/silverstripe-6-0.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameClassRector::class, [ 21 | 'SilverStripe\ORM\ArrayLib' => 'SilverStripe\Core\ArrayLib', 22 | 'SilverStripe\ORM\ArrayList' => 'SilverStripe\Model\List\ArrayList', 23 | 'SilverStripe\ORM\GroupedList' => 'SilverStripe\Model\List\GroupedList', 24 | 'SilverStripe\ORM\ListDecorator' => 'SilverStripe\Model\List\ListDecorator', 25 | 'SilverStripe\ORM\Map' => 'SilverStripe\Model\List\Map', 26 | 'SilverStripe\ORM\PaginatedList' => 'SilverStripe\Model\List\PaginatedList', 27 | 'SilverStripe\ORM\SS_List' => 'SilverStripe\Model\List\SS_List', 28 | 'SilverStripe\ORM\ValidationException' => 'SilverStripe\Core\Validation\ValidationException', 29 | 'SilverStripe\ORM\ValidationResult' => 'SilverStripe\Core\Validation\ValidationResult', 30 | 'SilverStripe\View\ArrayData' => 'SilverStripe\Model\ArrayData', 31 | 'SilverStripe\View\ViewableData' => 'SilverStripe\Model\ModelData', 32 | 'SilverStripe\View\ViewableData_Customised' => 'SilverStripe\Model\ModelDataCustomised', 33 | 'SilverStripe\View\ViewableData_Debugger' => 'SilverStripe\Model\ModelDataDebugger', 34 | 'SilverStripe\Logging\HTTPOutputHandler' => 'SilverStripe\Logging\ErrorOutputHandler', 35 | 'SilverStripe\GraphQL\Extensions\DevBuildExtension' => 'SilverStripe\GraphQL\Extensions\DbBuildExtension', 36 | 'SilverStripe\Security\PasswordValidator' => 'SilverStripe\Security\Validation\RulesPasswordValidator', 37 | 'SilverStripe\View\SSViewer_Scope' => 'SilverStripe\TemplateEngine\ScopeManager', 38 | 'SilverStripe\Forms\Validator' => 'SilverStripe\Forms\Validation\Validator', 39 | 'SilverStripe\Forms\RequiredFields' => 'SilverStripe\Forms\Validation\RequiredFieldsValidator', 40 | 'SilverStripe\Forms\CompositeValidator' => 'SilverStripe\Forms\Validation\CompositeValidator', 41 | 'SilverStripe\UserForms\Form\UserFormsRequiredFields' => 'SilverStripe\UserForms\Form\UserFormsRequiredFieldsValidator', 42 | 'Symbiote\AdvancedWorkflow\Forms\AWRequiredFields' => 'Symbiote\AdvancedWorkflow\Forms\AWRequiredFieldsValidator', 43 | 'SilverStripe\CMS\Model\CurrentPageIdentifier' => 'SilverStripe\CMS\Model\CurrentRecordIdentifier', 44 | 'DNADesign\Elemental\TopPage\DataExtension' => 'DNADesign\Elemental\Extensions\TopPageElementExtension', 45 | 'DNADesign\Elemental\TopPage\FluentExtension' => 'DNADesign\Elemental\Extensions\TopPageFluentElementExtension', 46 | 'DNADesign\Elemental\TopPage\SiteTreeExtension' => 'DNADesign\Elemental\Extensions\TopPageSiteTreeExtension', 47 | 'SilverStripe\View\SSViewer_BasicIteratorSupport' => 'SilverStripe\TemplateEngine\BasicIteratorSupport', 48 | 'SilverStripe\View\SSTemplateParseException' => 'SilverStripe\TemplateEngine\Exception\SSTemplateParseException', 49 | 'SilverStripe\View\SSTemplateParser' => 'SilverStripe\TemplateEngine\SSTemplateParser', 50 | 'SilverStripe\View\TemplateIteratorProvider' => 'SilverStripe\TemplateEngine\TemplateIteratorProvider', 51 | 'SilverStripe\View\TemplateParser' => 'SilverStripe\TemplateEngine\TemplateParser', 52 | 'SilverStripe\AssetAdmin\Extensions\CampaignAdminExtension' => 'SilverStripe\CampaignAdmin\Extensions\FileFormFactoryExtension', 53 | 'SilverStripe\CMS\Controllers\LeftAndMainPageIconsExtension' => 'SilverStripe\CMS\Controllers\LeftAndMainRecordIconsExtension', 54 | 'SilverStripe\Forms\HTMLEditor\TinyMCECombinedGenerator' => 'SilverStripe\TinyMCE\TinyMCECombinedGenerator', 55 | 'SilverStripe\Forms\HTMLEditor\TinyMCEConfig' => 'SilverStripe\TinyMCE\TinyMCEConfig', 56 | 'SilverStripe\Forms\HTMLEditor\TinyMCEScriptGenerator' => 'SilverStripe\TinyMCE\TinyMCEScriptGenerator', 57 | 58 | 'SilverStripe\ORM\Filterable' => 'SilverStripe\Model\List\Filterable', 59 | 'SilverStripe\ORM\Limitable' => 'SilverStripe\Model\List\Limitable', 60 | 'SilverStripe\ORM\Sortable' => 'SilverStripe\Model\List\Sortable', 61 | 62 | 'SilverStripe\SecurityReport\Forms\GridFieldExportReportButton' => 'SilverStripe\Reports\SecurityReport\Forms\GridFieldExportReportButton', 63 | 'SilverStripe\SecurityReport\Forms\GridFieldPrintReportButton' => 'SilverStripe\Reports\SecurityReport\Forms\GridFieldPrintReportButton', 64 | 'SilverStripe\SecurityReport\MemberReportExtension' => 'SilverStripe\Reports\SecurityReport\MemberReportExtension', 65 | 'SilverStripe\SecurityReport\UserSecurityReport' => 'SilverStripe\Reports\SecurityReport\UserSecurityReport', 66 | 'SilverStripe\SiteWideContentReport\Form\GridFieldBasicContentReport' => 'SilverStripe\Reports\SiteWideContentReport\Form\GridFieldBasicContentReport', 67 | 'SilverStripe\SiteWideContentReport\Model\SitewideContentTaxonomy' => 'SilverStripe\Reports\SiteWideContentReport\Model\SitewideContentTaxonomy', 68 | 'SilverStripe\SiteWideContentReport\SitewideContentReport' => 'SilverStripe\Reports\SiteWideContentReport\SitewideContentReport', 69 | 'SilverStripe\ExternalLinks\Controllers\CMSExternalLinksController' => 'SilverStripe\Reports\ExternalLinks\Controllers\CMSExternalLinksController', 70 | 'SilverStripe\ExternalLinks\Jobs\CheckExternalLinksJob' => 'SilverStripe\Reports\ExternalLinks\Jobs\CheckExternalLinksJob', 71 | 'SilverStripe\ExternalLinks\Model\BrokenExternalLink' => 'SilverStripe\Reports\ExternalLinks\Model\BrokenExternalLink', 72 | 'SilverStripe\ExternalLinks\Model\BrokenExternalPageTrack' => 'SilverStripe\Reports\ExternalLinks\Model\BrokenExternalPageTrack', 73 | 'SilverStripe\ExternalLinks\Model\BrokenExternalPageTrackStatus' => 'SilverStripe\Reports\ExternalLinks\Model\BrokenExternalPageTrackStatus', 74 | 'SilverStripe\ExternalLinks\BrokenExternalLinksReport' => 'SilverStripe\Reports\ExternalLinks\Reports\BrokenExternalLinksReport', 75 | 'SilverStripe\ExternalLinks\Tasks\CheckExternalLinksTask' => 'SilverStripe\Reports\ExternalLinks\Tasks\CheckExternalLinksTask', 76 | 'SilverStripe\ExternalLinks\Tasks\CurlLinkChecker' => 'SilverStripe\Reports\ExternalLinks\Tasks\CurlLinkChecker', 77 | 'SilverStripe\ExternalLinks\Tasks\LinkChecker' => 'SilverStripe\Reports\ExternalLinks\Tasks\LinkChecker', 78 | 79 | 80 | //removed extensions 81 | 'SilverStripe\ORM\DataExtension' => 'SilverStripe\Core\Extension', 82 | 'SilverStripe\CMS\Model\SiteTreeExtension' => 'SilverStripe\Core\Extension', 83 | 'SilverStripe\Admin\LeftAndMainExtension' => 'SilverStripe\Core\Extension', 84 | 85 | ]); 86 | $rectorConfig->importNames(); 87 | $rectorConfig->removeUnusedImports(); 88 | $rectorConfig->ruleWithConfiguration(RenameStaticMethodRector::class, [ 89 | new RenameStaticMethod('SilverStripe\View\SSViewer', 'flush', 'SilverStripe\TemplateEngine\SSTemplateEngine', 'flush'), 90 | new RenameStaticMethod('SilverStripe\ORM\FieldType\DBEnum', 'flushCache', 'SilverStripe\ORM\FieldType\DBEnum', 'reset'), 91 | ]); 92 | $rectorConfig->ruleWithConfiguration(RenamePropertyRector::class, [ 93 | new RenameProperty('SilverStripe\Admin\LeftAndMain', 'tree_class', 'model_class'), 94 | new RenameProperty('SilverStripe\CMS\Model\SiteTree', 'description', 'class_description'), 95 | new RenameProperty('SilverStripe\CMS\Model\SiteTree', 'icon', 'cms_icon'), 96 | new RenameProperty('SilverStripe\CMS\Model\SiteTree', 'icon_class', 'cms_icon_class'), 97 | new RenameProperty('DNADesign\Elemental\Models\BaseElement', 'description', 'class_description'), 98 | ]); 99 | $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ 100 | new MethodCallRename('SilverStripe\TemplateEngine\ScopeManager', 'obj', 'scopeToIntermediateValue'), 101 | new MethodCallRename('SilverStripe\ORM\CMSPreviewable', 'CMSEditLink', 'getCMSEditLink'), 102 | new MethodCallRename('SilverStripe\CMS\Model\CurrentRecordIdentifier', 'currentPageID', 'currentRecordID'), 103 | new MethodCallRename('SilverStripe\CMS\Model\CurrentRecordIdentifier', 'isCurrentPage', 'isCurrentRecord'), 104 | new MethodCallRename('SilverStripe\Assets\Storage\DBFile', 'validate', 'validateFilename'), 105 | new MethodCallRename('SilverStripe\CMS\Controllers\ContentController', 'Menu', 'getMenu'), 106 | new MethodCallRename('SilverStripe\Model\ModelData', 'cachedCall', 'obj'), 107 | new MethodCallRename('SilverStripe\SiteConfig\SiteConfigLeftAndMain', 'save_siteconfig', 'save'), 108 | new MethodCallRename('SilverStripe\Admin\LeftAndMain', 'currentPageID', 'currentRecordID'), 109 | new MethodCallRename('SilverStripe\Admin\LeftAndMain', 'setCurrentPageID', 'setCurrentRecordID'), 110 | new MethodCallRename('SilverStripe\Admin\LeftAndMain', 'currentPage', 'currentRecord'), 111 | new MethodCallRename('SilverStripe\Admin\LeftAndMain', 'isCurrentPage', 'isCurrentRecord'), 112 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'PageList', 'RecordList'), 113 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'LinkPages', 'LinkRecords'), 114 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'LinkPagesWithSearch', 'LinkRecordsWithSearch'), 115 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'LinkPageEdit', 'LinkRecordEdit'), 116 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'LinkPageSettings', 'LinkRecordSettings'), 117 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'LinkPageHistory', 'LinkRecordHistory'), 118 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'LinkPageAdd', 'LinkRecordAdd'), 119 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'SiteTreeAsUL', 'TreeAsUL'), 120 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'getSiteTreeFor', 'getTreeFor'), 121 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'CanOrganiseSitetree', 'canOrganiseTree'), 122 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'getPageTypes', 'getRecordTypes'), 123 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'PageTypes', 'RecordTypes'), 124 | new MethodCallRename('SilverStripe\CMS\Controllers\CMSMain', 'SiteTreeHints', 'TreeHints'), 125 | new MethodCallRename('SilverStripe\CMS\Controllers\LeftAndMainRecordIconsExtension', 'generatePageIconsCss', 'generateRecordIconsCss'), 126 | new MethodCallRename('SilverStripe\Forms\Form', 'validationResult', 'validate'), 127 | new MethodCallRename('SilverStripe\Forms\TextareaField', 'ValueEntities', 'getFormattedValueEntities'), 128 | new MethodCallRename('SilverStripe\Model\List\ListDecorator', 'TotalItems', 'getTotalItems'), 129 | new MethodCallRename('SilverStripe\Model\List\PaginatedList', 'TotalItems', 'getTotalItems'), 130 | ]); 131 | $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ 132 | new RenameClassAndConstFetch('SilverStripe\Admin\LeftAndMain', 'SCHEMA_HEADER', 'SilverStripe\Forms\Schema\FormSchema', 'SCHEMA_HEADER'), 133 | ]); 134 | }; 135 | --------------------------------------------------------------------------------