├── tests ├── test_apps │ ├── original │ │ ├── FileRenameCommand-testLocales │ │ │ ├── src │ │ │ │ ├── Template │ │ │ │ │ └── empty │ │ │ │ └── Locale │ │ │ │ │ └── default.pot │ │ │ └── plugins │ │ │ │ ├── TestPlugin │ │ │ │ └── src │ │ │ │ │ ├── Template │ │ │ │ │ └── empty │ │ │ │ │ └── Locale │ │ │ │ │ └── default.pot │ │ │ │ └── WithoutLocalesPlugin │ │ │ │ └── src │ │ │ │ └── Template │ │ │ │ └── empty │ │ ├── FileRenameCommand-testTemplates │ │ │ ├── src │ │ │ │ ├── View │ │ │ │ │ ├── Cell │ │ │ │ │ │ └── empty │ │ │ │ │ ├── Helper │ │ │ │ │ │ └── empty │ │ │ │ │ ├── AppView.php │ │ │ │ │ └── AjaxView.php │ │ │ │ ├── Locale │ │ │ │ │ └── default.pot │ │ │ │ └── Template │ │ │ │ │ ├── Error │ │ │ │ │ ├── error400.ctp │ │ │ │ │ └── error500.ctp │ │ │ │ │ ├── Layout │ │ │ │ │ └── default.ctp │ │ │ │ │ ├── Pages │ │ │ │ │ └── home.ctp │ │ │ │ │ ├── Email │ │ │ │ │ ├── html │ │ │ │ │ │ └── default.ctp │ │ │ │ │ └── text │ │ │ │ │ │ └── default.ctp │ │ │ │ │ ├── Cell │ │ │ │ │ └── TestCell │ │ │ │ │ │ └── display.ctp │ │ │ │ │ └── Element │ │ │ │ │ └── Flash │ │ │ │ │ └── default.ctp │ │ │ └── plugins │ │ │ │ ├── TestPlugin │ │ │ │ └── src │ │ │ │ │ ├── Locale │ │ │ │ │ └── default.pot │ │ │ │ │ └── Template │ │ │ │ │ ├── Pages │ │ │ │ │ └── home.ctp │ │ │ │ │ ├── Error │ │ │ │ │ ├── error400.ctp │ │ │ │ │ └── error500.ctp │ │ │ │ │ ├── Layout │ │ │ │ │ └── default.ctp │ │ │ │ │ ├── Email │ │ │ │ │ ├── html │ │ │ │ │ │ └── default.ctp │ │ │ │ │ └── text │ │ │ │ │ │ └── default.ctp │ │ │ │ │ ├── Cell │ │ │ │ │ └── TestPluginCell │ │ │ │ │ │ └── bar.ctp │ │ │ │ │ └── Element │ │ │ │ │ └── Flash │ │ │ │ │ └── default.ctp │ │ │ │ └── WithoutTemplatesPlugin │ │ │ │ └── src │ │ │ │ ├── empty │ │ │ │ └── Locale │ │ │ │ └── default.pot │ │ ├── RectorCommand-testApply50 │ │ │ └── src │ │ │ │ ├── SomeView.php │ │ │ │ ├── SomeMailer.php │ │ │ │ ├── SomeWidget.php │ │ │ │ ├── DateTimeRename.php │ │ │ │ ├── SomeCell.php │ │ │ │ ├── Model │ │ │ │ └── Entity │ │ │ │ │ └── Category.php │ │ │ │ ├── SomeComponent.php │ │ │ │ ├── CommandExecuteReturn.php │ │ │ │ ├── SomeTest.php │ │ │ │ ├── FixtureProperties.php │ │ │ │ ├── QueryUpgrade.php │ │ │ │ ├── HelperProperties.php │ │ │ │ └── Plugin.php │ │ ├── RectorCommand-testApplyMigrations45 │ │ │ └── src │ │ │ │ └── Migrations45.php │ │ ├── RectorCommand-testApplyAppDir │ │ │ └── Command │ │ │ │ └── HelloCommand.php │ │ ├── RectorCommand-testApply52 │ │ │ └── src │ │ │ │ └── SomeTest.php │ │ ├── RectorCommand-testApplyChronos3DateTime │ │ │ └── src │ │ │ │ └── Chronos3.php │ │ ├── RectorCommand-testApply53 │ │ │ └── src │ │ │ │ └── SomeTest.php │ │ ├── RectorCommand-testApplyChronos3Date │ │ │ └── src │ │ │ │ └── Chronos3.php │ │ ├── RectorCommand-testApply45 │ │ │ └── src │ │ │ │ └── View │ │ │ │ └── AppView.php │ │ └── RectorCommand-testApply51 │ │ │ └── src │ │ │ └── SomeTest.php │ └── upgraded │ │ ├── FileRenameCommand-testLocales │ │ ├── src │ │ │ └── Template │ │ │ │ └── empty │ │ ├── resources │ │ │ └── locales │ │ │ │ └── default.pot │ │ └── plugins │ │ │ ├── TestPlugin │ │ │ ├── src │ │ │ │ └── Template │ │ │ │ │ └── empty │ │ │ └── resources │ │ │ │ └── locales │ │ │ │ └── default.pot │ │ │ └── WithoutLocalesPlugin │ │ │ └── src │ │ │ └── Template │ │ │ └── empty │ │ ├── FileRenameCommand-testTemplates │ │ ├── src │ │ │ ├── View │ │ │ │ ├── Cell │ │ │ │ │ └── empty │ │ │ │ ├── Helper │ │ │ │ │ └── empty │ │ │ │ ├── AppView.php │ │ │ │ └── AjaxView.php │ │ │ └── Locale │ │ │ │ └── default.pot │ │ ├── templates │ │ │ ├── Pages │ │ │ │ └── home.php │ │ │ ├── Error │ │ │ │ ├── error400.php │ │ │ │ └── error500.php │ │ │ ├── layout │ │ │ │ └── default.php │ │ │ ├── cell │ │ │ │ └── TestCell │ │ │ │ │ └── display.php │ │ │ ├── element │ │ │ │ └── flash │ │ │ │ │ └── default.php │ │ │ └── email │ │ │ │ ├── html │ │ │ │ └── default.php │ │ │ │ └── text │ │ │ │ └── default.php │ │ └── plugins │ │ │ ├── TestPlugin │ │ │ ├── src │ │ │ │ └── Locale │ │ │ │ │ └── default.pot │ │ │ └── templates │ │ │ │ ├── Pages │ │ │ │ └── home.php │ │ │ │ ├── Error │ │ │ │ ├── error400.php │ │ │ │ └── error500.php │ │ │ │ ├── email │ │ │ │ ├── html │ │ │ │ │ └── default.php │ │ │ │ └── text │ │ │ │ │ └── default.php │ │ │ │ ├── layout │ │ │ │ └── default.php │ │ │ │ ├── cell │ │ │ │ └── TestPluginCell │ │ │ │ │ └── bar.php │ │ │ │ └── element │ │ │ │ └── flash │ │ │ │ └── default.php │ │ │ └── WithoutTemplatesPlugin │ │ │ └── src │ │ │ ├── empty │ │ │ └── Locale │ │ │ └── default.pot │ │ ├── RectorCommand-testApply50 │ │ └── src │ │ │ ├── SomeView.php │ │ │ ├── SomeMailer.php │ │ │ ├── SomeWidget.php │ │ │ ├── DateTimeRename.php │ │ │ ├── SomeCell.php │ │ │ ├── Model │ │ │ └── Entity │ │ │ │ └── Category.php │ │ │ ├── SomeTest.php │ │ │ ├── SomeComponent.php │ │ │ ├── CommandExecuteReturn.php │ │ │ ├── FixtureProperties.php │ │ │ ├── QueryUpgrade.php │ │ │ ├── HelperProperties.php │ │ │ └── Plugin.php │ │ ├── RectorCommand-testApplyMigrations45 │ │ └── src │ │ │ └── Migrations45.php │ │ ├── RectorCommand-testApply52 │ │ └── src │ │ │ └── SomeTest.php │ │ ├── RectorCommand-testApplyChronos3DateTime │ │ └── src │ │ │ └── Chronos3.php │ │ ├── RectorCommand-testApply53 │ │ └── src │ │ │ └── SomeTest.php │ │ ├── RectorCommand-testApply45 │ │ └── src │ │ │ └── View │ │ │ └── AppView.php │ │ ├── RectorCommand-testApplyChronos3Date │ │ └── src │ │ │ └── Chronos3.php │ │ └── RectorCommand-testApply51 │ │ └── src │ │ └── SomeTest.php ├── TestCase │ ├── Rector │ │ ├── Namespace_ │ │ │ └── AppUsesStaticCallToUseStatementRector │ │ │ │ ├── Source │ │ │ │ ├── Xml.php │ │ │ │ └── App.php │ │ │ │ ├── config │ │ │ │ └── configured_rule.php │ │ │ │ ├── Fixture │ │ │ │ ├── skip_different_static_call.php.inc │ │ │ │ ├── without_namespace.php.inc │ │ │ │ ├── cakephp_controller.php.inc │ │ │ │ ├── without_namespace_with_strict_types.php.inc │ │ │ │ ├── cakephp_controller_with_strict_types.php.inc │ │ │ │ ├── fixture.php.inc │ │ │ │ ├── cakephp_import_namespaces_up.php.inc │ │ │ │ ├── inside_if.php.inc │ │ │ │ └── cakephp_fixture.php.inc │ │ │ │ └── AppUsesStaticCallToUseStatementRectorTest.php │ │ ├── MethodCall │ │ │ ├── ModalToGetSetRector │ │ │ │ ├── Source │ │ │ │ │ ├── Entity.php │ │ │ │ │ └── SomeModelType.php │ │ │ │ ├── Fixture │ │ │ │ │ ├── fixture4.php.inc │ │ │ │ │ ├── fixture3.php.inc │ │ │ │ │ ├── fixture2.php.inc │ │ │ │ │ └── fixture.php.inc │ │ │ │ ├── ModalToGetSetRectorTest.php │ │ │ │ └── config │ │ │ │ │ └── configured_rule.php │ │ │ ├── AddMethodCallArgsRector │ │ │ │ ├── Source │ │ │ │ │ └── SomeModelType.php │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── AddMethodCallArgsRectorTest.php │ │ │ │ └── Fixture │ │ │ │ │ └── fixture.php.inc │ │ │ ├── RemoveMethodCallArgsRector │ │ │ │ ├── Source │ │ │ │ │ └── SomeModelType.php │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── Fixture │ │ │ │ │ └── fixture.php.inc │ │ │ │ └── RemoveMethodCallArgsRectorTest.php │ │ │ ├── OptionsArrayToNamedParametersRector │ │ │ │ ├── Source │ │ │ │ │ └── ConfigurableClass.php │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── OptionsArrayToNamedParametersRectorTest.php │ │ │ │ └── Fixture │ │ │ │ │ └── options_to_named_parameters.php.inc │ │ │ ├── RenameMethodCallBasedOnParameterRector │ │ │ │ ├── Source │ │ │ │ │ └── SomeModelType.php │ │ │ │ ├── Fixture │ │ │ │ │ ├── skip_fixture2.php.inc │ │ │ │ │ └── fixture.php.inc │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ └── RenameMethodCallBasedOnParameterRectorTest.php │ │ │ ├── EntityPatchRector │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── EntityPatchRectorTest.php │ │ │ │ └── Fixture │ │ │ │ │ ├── skip_non_entity.php.inc │ │ │ │ │ └── fixture.php.inc │ │ │ ├── NewExprToFuncRector │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── NewExprToFuncRectorTest.php │ │ │ │ └── Fixture │ │ │ │ │ ├── aggregate_functions.php.inc │ │ │ │ │ ├── sql_functions.php.inc │ │ │ │ │ └── skip_non_func_methods.php.inc │ │ │ ├── ChangeEntityTraitSetArrayToPatch │ │ │ │ ├── Source │ │ │ │ │ └── OtherClassWithSetMethod.php │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── ChangeEntityTraitSetArrayToPatchTest.php │ │ │ │ └── Fixture │ │ │ │ │ └── fixture.php.inc │ │ │ ├── QueryParamAccessRector │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── QueryParamAccessRectorTest.php │ │ │ │ └── Fixture │ │ │ │ │ ├── fixture.php.inc │ │ │ │ │ └── skip_other_params.php.inc │ │ │ ├── PaginatorCounterFormatRector │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── PaginatorCounterFormatRectorTest.php │ │ │ │ └── Fixture │ │ │ │ │ └── fixture.php.inc │ │ │ ├── NewEntityToNewEmptyEntityRector │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── NewEntityToNewEmptyEntityRectorTest.php │ │ │ │ └── Fixture │ │ │ │ │ └── fixture.php.inc │ │ │ ├── ArrayToFluentCallRector │ │ │ │ ├── Source │ │ │ │ │ ├── FactoryClass.php │ │ │ │ │ └── ConfigurableClass.php │ │ │ │ ├── ArrayToFluentCallRectorTest.php │ │ │ │ ├── Fixture │ │ │ │ │ ├── fluent_factory.php.inc │ │ │ │ │ └── array_to_fluent_call.php.inc │ │ │ │ └── config │ │ │ │ │ └── configured_rule.php │ │ │ └── RemoveIntermediaryMethodRector │ │ │ │ ├── config │ │ │ │ └── configured_rule.php │ │ │ │ ├── RemoveIntermediaryMethodRectorTest.php │ │ │ │ └── Fixture │ │ │ │ └── fixture.php.inc │ │ ├── ClassMethod │ │ │ ├── FormBuildValidatorRector │ │ │ │ ├── config │ │ │ │ │ └── configured_rule.php │ │ │ │ ├── FormBuildValidatorRectorTest.php │ │ │ │ └── Fixture │ │ │ │ │ └── fixture.php.inc │ │ │ └── FormExecuteToProcessRector │ │ │ │ ├── config │ │ │ │ └── configured_rule.php │ │ │ │ ├── Fixture │ │ │ │ ├── skip_when_process_exists.php.inc │ │ │ │ └── fixture.php.inc │ │ │ │ └── FormExecuteToProcessRectorTest.php │ │ └── Property │ │ │ └── ChangeSnakedFixtureNameToPascal │ │ │ ├── config │ │ │ └── configured_rule.php │ │ │ ├── ChangeSnakedFixtureNameToPascalTest.php │ │ │ └── Fixture │ │ │ └── fixture.php.inc │ ├── Command │ │ └── FileRenameCommandTest.php │ └── TestCase.php └── bootstrap.php ├── .github ├── codecov.yml ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── .gitattributes ├── config ├── rector │ ├── chronos3.php │ ├── phpunit80.php │ ├── cakephp40.php │ ├── cakephp41.php │ ├── cakephp42.php │ ├── cakephp43.php │ ├── cakephp44.php │ ├── cakephp45.php │ ├── cakephp50.php │ ├── cakephp51.php │ ├── cakephp52.php │ ├── cakephp53.php │ ├── migrations45.php │ ├── migrations50.php │ └── sets │ │ ├── migrations45.php │ │ ├── cakephp38.php │ │ ├── cakephp51.php │ │ ├── cakephp52.php │ │ ├── cakephp42.php │ │ ├── cakephp45.php │ │ ├── cakephp44.php │ │ ├── cakephp30.php │ │ ├── cakephp41.php │ │ ├── cakephp53.php │ │ ├── cakephp43.php │ │ └── cakephp36.php ├── requirements.php ├── bootstrap.php └── paths.php ├── .editorconfig ├── bin ├── cake.php ├── cake.bat └── cake ├── src ├── Rector │ ├── ValueObject │ │ ├── SetSerializeToView.php │ │ ├── RemoveMethodCall.php │ │ ├── ArrayToFluentCall.php │ │ ├── RemoveIntermediaryMethod.php │ │ ├── FactoryMethod.php │ │ ├── ArrayItemsAndFluentClass.php │ │ ├── AddMethodCallArgs.php │ │ ├── RenameMethodCallBasedOnParameter.php │ │ ├── OptionsArrayToNamedParameters.php │ │ └── ModalToGetSet.php │ ├── NodeAnalyzer │ │ └── FluentChainMethodCallNodeAnalyzer.php │ ├── Set │ │ ├── CakePHPLevelSetList.php │ │ └── CakePHPSetList.php │ └── Rector │ │ ├── MethodCall │ │ ├── EntityIsEmptyRector.php │ │ ├── TableRegistryLocatorRector.php │ │ ├── NewEntityToNewEmptyEntityRector.php │ │ ├── EntityPatchRector.php │ │ ├── ChangeEntityTraitSetArrayToPatchRector.php │ │ ├── SetSerializeToViewBuilderRector.php │ │ ├── StaticConnectionHelperRector.php │ │ ├── RemoveMethodCallRector.php │ │ ├── QueryParamAccessRector.php │ │ └── PaginatorCounterFormatRector.php │ │ └── ClassMethod │ │ └── FormExecuteToProcessRector.php └── Application.php ├── phpunit.xml.dist ├── Makefile ├── phpcs.xml ├── LICENSE.md └── composer.json /tests/test_apps/original/FileRenameCommand-testLocales/src/Template/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testLocales/src/Template/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testLocales/src/Locale/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/View/Cell/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/View/Helper/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/src/View/Cell/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/src/View/Helper/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/Locale/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/src/Locale/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/templates/Pages/home.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/Template/Error/error400.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/Template/Error/error500.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/Template/Layout/default.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/Template/Pages/home.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testLocales/resources/locales/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/templates/Error/error400.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/templates/Error/error500.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/templates/layout/default.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testLocales/plugins/TestPlugin/src/Template/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/Template/Email/html/default.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/Template/Email/text/default.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testLocales/plugins/TestPlugin/src/Template/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/templates/cell/TestCell/display.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/templates/element/flash/default.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/templates/email/html/default.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/templates/email/text/default.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testLocales/plugins/TestPlugin/src/Locale/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Locale/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/WithoutTemplatesPlugin/src/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/Template/Cell/TestCell/display.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/Template/Element/Flash/default.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Locale/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/WithoutTemplatesPlugin/src/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testLocales/plugins/WithoutLocalesPlugin/src/Template/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Template/Pages/home.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testLocales/plugins/TestPlugin/resources/locales/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testLocales/plugins/WithoutLocalesPlugin/src/Template/empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/TestPlugin/templates/Pages/home.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Template/Error/error400.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Template/Error/error500.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Template/Layout/default.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/TestPlugin/templates/Error/error400.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/TestPlugin/templates/Error/error500.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/TestPlugin/templates/email/html/default.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/TestPlugin/templates/email/text/default.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/TestPlugin/templates/layout/default.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Template/Email/html/default.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Template/Email/text/default.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/WithoutTemplatesPlugin/src/Locale/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/TestPlugin/templates/cell/TestPluginCell/bar.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/TestPlugin/templates/element/flash/default.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/plugins/WithoutTemplatesPlugin/src/Locale/default.pot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Template/Cell/TestPluginCell/bar.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/plugins/TestPlugin/src/Template/Element/Flash/default.ctp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | 4 | coverage: 5 | range: "90...100" 6 | 7 | comment: false 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /tmp/ 2 | /vendor/ 3 | /logs/ 4 | /composer.lock 5 | /plugins/DebugKit 6 | /phpunit.phar 7 | .phpunit* 8 | /.idea/ 9 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply50/src/SomeView.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CHRONOS_3]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/phpunit80.php: -------------------------------------------------------------------------------- 1 | sets([PHPUnitSetList::PHPUNIT_80]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp40.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_40]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp41.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_41]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp42.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_42]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp43.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_43]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp44.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_44]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp45.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_45]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp50.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_50]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp51.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_51]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp52.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_52]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/cakephp53.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::CAKEPHP_53]); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply50/src/DateTimeRename.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::MIGRATIONS_45]); 9 | }; 10 | -------------------------------------------------------------------------------- /config/rector/migrations50.php: -------------------------------------------------------------------------------- 1 | sets([CakePHPSetList::MIGRATIONS_50]); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RenameMethodCallBasedOnParameterRector/Source/SomeModelType.php: -------------------------------------------------------------------------------- 1 | set('_serialize', 'result'); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply50/src/SomeCell.php: -------------------------------------------------------------------------------- 1 | viewBuilder()->setOption('serialize', 'result'); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/EntityPatchRector/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | rule(EntityPatchRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply50/src/Model/Entity/Category.php: -------------------------------------------------------------------------------- 1 | rule(NewExprToFuncRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ChangeEntityTraitSetArrayToPatch/Source/OtherClassWithSetMethod.php: -------------------------------------------------------------------------------- 1 | rule(QueryParamAccessRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApplyMigrations45/src/Migrations45.php: -------------------------------------------------------------------------------- 1 | rule(FormBuildValidatorRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply50/src/Model/Entity/Category.php: -------------------------------------------------------------------------------- 1 | rule(FormExecuteToProcessRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApplyMigrations45/src/Migrations45.php: -------------------------------------------------------------------------------- 1 | rule(PaginatorCounterFormatRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/NewEntityToNewEmptyEntityRector/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | rule(NewEntityToNewEmptyEntityRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply50/src/SomeComponent.php: -------------------------------------------------------------------------------- 1 | rule(ChangeSnakedFixtureNameToPascalRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply50/src/SomeTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ChangeEntityTraitSetArrayToPatch/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | rule(ChangeEntityTraitSetArrayToPatchRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | rule(AppUsesStaticCallToUseStatementRector::class); 9 | }; 10 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Source/App.php: -------------------------------------------------------------------------------- 1 | get('MyTable'); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply50/src/CommandExecuteReturn.php: -------------------------------------------------------------------------------- 1 | run($argv)); 13 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApplyAppDir/Command/HelloCommand.php: -------------------------------------------------------------------------------- 1 | styles('green', ['background' => 'green']); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply50/src/SomeTest.php: -------------------------------------------------------------------------------- 1 | useCommandRunner(); 16 | $this->useHttpServer(); 17 | $this->get('/'); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply50/src/FixtureProperties.php: -------------------------------------------------------------------------------- 1 | setName($options['name']); 13 | 14 | return $configurableClass; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ArrayToFluentCallRector/Source/ConfigurableClass.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameClassRector::class, [ 12 | 'Migrations\AbstractMigration' => 'Migrations\BaseMigration', 13 | 'Migrations\AbstractSeed' => 'Migrations\BaseSeed', 14 | ]); 15 | }; 16 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/SetSerializeToView.php: -------------------------------------------------------------------------------- 1 | class; 18 | } 19 | 20 | public function getObjectType(): ObjectType 21 | { 22 | return new ObjectType($this->class); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Fixture/without_namespace.php.inc: -------------------------------------------------------------------------------- 1 | 14 | ----- 15 | 28 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | tests/TestCase/ 9 | 10 | 11 | 12 | 13 | 14 | src/ 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Fixture/cakephp_controller.php.inc: -------------------------------------------------------------------------------- 1 | 12 | ----- 13 | 24 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp38.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration( 12 | RenameMethodRector::class, 13 | [new MethodCallRename('Cake\ORM\Entity', 'visibleProperties', 'getVisible')] 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RemoveIntermediaryMethodRector/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration( 10 | RemoveIntermediaryMethodRector::class, 11 | [new RemoveIntermediaryMethod('getTableLocator', 'get', 'fetchTable')] 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RenameMethodCallBasedOnParameterRector/Fixture/skip_fixture2.php.inc: -------------------------------------------------------------------------------- 1 | getParam($value); 12 | $config = $object->getParam('other'); 13 | $object->withParam('other', 'value'); 14 | } 15 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/ClassMethod/FormExecuteToProcessRector/Fixture/skip_when_process_exists.php.inc: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RemoveMethodCallRector::class, [ 11 | new RemoveMethodCall(SomeModelType::class, 'getAttribute'), 12 | ]); 13 | }; 14 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/AddMethodCallArgsRector/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(AddMethodCallArgsRector::class, [ 11 | new AddMethodCallArgs(SomeModelType::class, 'getAttribute', '2ndArg', 1, true), 12 | ]); 13 | }; 14 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply52/src/SomeTest.php: -------------------------------------------------------------------------------- 1 | [1, 2]], []); 14 | $option = $args->getMultipleOption('a'); 15 | 16 | $entity = new Entity(); 17 | // This should be changed to patch 18 | $entity->set(['paging' => 'test']); 19 | // This should not be changed 20 | $entity->set('paging', 'test'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply52/src/SomeTest.php: -------------------------------------------------------------------------------- 1 | [1, 2]], []); 14 | $option = $args->getArrayOption('a'); 15 | 16 | $entity = new Entity(); 17 | // This should be changed to patch 18 | $entity->patch(['paging' => 'test']); 19 | // This should not be changed 20 | $entity->set('paging', 'test'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Fixture/without_namespace_with_strict_types.php.inc: -------------------------------------------------------------------------------- 1 | 16 | ----- 17 | 32 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Fixture/cakephp_controller_with_strict_types.php.inc: -------------------------------------------------------------------------------- 1 | 14 | ----- 15 | 28 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp51.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameStringRector::class, [ 12 | // Rename the cache configuration used by translations. 13 | '_cake_core_' => '_cake_translations_', 14 | ]); 15 | 16 | $rectorConfig->rule(StaticConnectionHelperRector::class); 17 | }; 18 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/RemoveMethodCall.php: -------------------------------------------------------------------------------- 1 | class; 19 | } 20 | 21 | public function getMethodName(): string 22 | { 23 | return $this->methodName; 24 | } 25 | 26 | public function getObjectType(): ObjectType 27 | { 28 | return new ObjectType($this->class); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/ArrayToFluentCall.php: -------------------------------------------------------------------------------- 1 | $class 10 | */ 11 | public function __construct( 12 | private string $class, 13 | private array $arrayKeysToFluentCalls, 14 | ) { 15 | } 16 | 17 | public function getClass(): string 18 | { 19 | return $this->class; 20 | } 21 | 22 | /** 23 | * @return array 24 | */ 25 | public function getArrayKeysToFluentCalls(): array 26 | { 27 | return $this->arrayKeysToFluentCalls; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameMethodRector::class, [ 12 | new MethodCallRename('Cake\Console\Arguments', 'getMultipleOption', 'getArrayOption'), 13 | ]); 14 | $rectorConfig->rule(ChangeEntityTraitSetArrayToPatchRector::class); 15 | }; 16 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/RemoveIntermediaryMethod.php: -------------------------------------------------------------------------------- 1 | firstMethod; 18 | } 19 | 20 | public function getSecondMethod(): string 21 | { 22 | return $this->secondMethod; 23 | } 24 | 25 | public function getFinalMethod(): string 26 | { 27 | return $this->finalMethod; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ModalToGetSetRector/Fixture/fixture4.php.inc: -------------------------------------------------------------------------------- 1 | makeEntity(); 12 | } 13 | 14 | ?> 15 | ----- 16 | createEntity(); 27 | } 28 | 29 | ?> 30 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | 16 | ----- 17 | 32 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply50/src/QueryUpgrade.php: -------------------------------------------------------------------------------- 1 | find('all', ['conditions' => ['Articles.slug' => 'test']]); 9 | $query->find('list', ['fields' => ['id', 'title']]) 10 | ->order('id') 11 | ->orderAsc('id') 12 | ->orderDesc('id') 13 | ->group('id'); 14 | 15 | $articles->query() 16 | ->order('id') 17 | ->orderAsc('id') 18 | ->orderDesc('id') 19 | ->group('id'); 20 | 21 | $article = $articles->get(1, ['key' => 'cache-key', 'contain' => ['Users']]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply50/src/QueryUpgrade.php: -------------------------------------------------------------------------------- 1 | find('all', conditions: ['Articles.slug' => 'test']); 9 | $query->find('list', fields: ['id', 'title']) 10 | ->orderBy('id') 11 | ->orderByAsc('id') 12 | ->orderByDesc('id') 13 | ->groupBy('id'); 14 | 15 | $articles->query() 16 | ->orderBy('id') 17 | ->orderByAsc('id') 18 | ->orderByDesc('id') 19 | ->groupBy('id'); 20 | 21 | $article = $articles->get(1, cacheKey: 'cache-key', contain: ['Users']); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/ClassMethod/FormExecuteToProcessRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | 17 | ----- 18 | 34 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/EntityPatchRector/EntityPatchRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ModalToGetSetRector/ModalToGetSetRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/NewExprToFuncRector/NewExprToFuncRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RenameMethodCallBasedOnParameterRector/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameMethodCallBasedOnParameterRector::class, [ 11 | new RenameMethodCallBasedOnParameter(SomeModelType::class, 'getParam', 'paging', 'getAttribute'), 12 | new RenameMethodCallBasedOnParameter(SomeModelType::class, 'withParam', 'paging', 'withAttribute'), 13 | ]); 14 | }; 15 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ModalToGetSetRector/Fixture/fixture3.php.inc: -------------------------------------------------------------------------------- 1 | method(); 12 | $config = $object->method('key'); 13 | } 14 | 15 | ?> 16 | ----- 17 | getMethod(); 28 | $config = $object->setMethod('key'); 29 | } 30 | 31 | ?> 32 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/OptionsArrayToNamedParametersRector/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(OptionsArrayToNamedParametersRector::class, [ 12 | new OptionsArrayToNamedParameters(ConfigurableClass::class, ['find']), 13 | new OptionsArrayToNamedParameters(ConfigurableClass::class, [ 14 | 'get', 'rename' => ['key' => 'cacheKey'], 15 | ]), 16 | ]); 17 | }; 18 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/QueryParamAccessRector/QueryParamAccessRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/AddMethodCallArgsRector/AddMethodCallArgsRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RemoveMethodCallArgsRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | getAttribute('paging'); 11 | $object->setAttribute('paging', []); 12 | } 13 | 14 | ?> 15 | ----- 16 | setAttribute('paging', []); 26 | } 27 | 28 | ?> 29 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp42.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameClassRector::class, [ 12 | 'Cake\Core\Exception\Exception' => 'Cake\Core\Exception\CakeException', 13 | 'Cake\Database\Exception' => 'Cake\Database\Exception\DatabaseException', 14 | ]); 15 | 16 | $rectorConfig->ruleWithConfiguration( 17 | RenameMethodRector::class, 18 | [new MethodCallRename('Cake\ORM\Behavior', 'getTable', 'table')] 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/ClassMethod/FormBuildValidatorRector/FormBuildValidatorRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ArrayToFluentCallRector/ArrayToFluentCallRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 18 | } 19 | 20 | public static function provideData(): Iterator 21 | { 22 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 23 | } 24 | 25 | public function provideConfigFilePath(): string 26 | { 27 | return __DIR__ . '/config/configured_rule.php'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/FactoryMethod.php: -------------------------------------------------------------------------------- 1 | type); 21 | } 22 | 23 | public function getMethod(): string 24 | { 25 | return $this->method; 26 | } 27 | 28 | public function getPosition(): int 29 | { 30 | return $this->position; 31 | } 32 | 33 | public function getNewClass(): string 34 | { 35 | return $this->newClass; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RemoveMethodCallArgsRector/RemoveMethodCallArgsRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/ArrayItemsAndFluentClass.php: -------------------------------------------------------------------------------- 1 | $arrayItems 10 | * @param array $fluentCalls 11 | */ 12 | public function __construct( 13 | private array $arrayItems, 14 | private array $fluentCalls, 15 | ) { 16 | } 17 | 18 | /** 19 | * @return array<\PhpParser\Node\ArrayItem> 20 | */ 21 | public function getArrayItems(): array 22 | { 23 | return $this->arrayItems; 24 | } 25 | 26 | /** 27 | * @return array 28 | */ 29 | public function getFluentCalls(): array 30 | { 31 | return $this->fluentCalls; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/ClassMethod/FormExecuteToProcessRector/FormExecuteToProcessRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/PaginatorCounterFormatRector/PaginatorCounterFormatRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/NewEntityToNewEmptyEntityRector/NewEntityToNewEmptyEntityRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RemoveIntermediaryMethodRector/RemoveIntermediaryMethodRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Property/ChangeSnakedFixtureNameToPascal/ChangeSnakedFixtureNameToPascalTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ChangeEntityTraitSetArrayToPatch/ChangeEntityTraitSetArrayToPatchTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Property/ChangeSnakedFixtureNameToPascal/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | 18 | ----- 19 | 36 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/AddMethodCallArgsRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | getAttribute('paging'); 11 | $object->getAttribute(); 12 | } 13 | 14 | ?> 15 | ----- 16 | getAttribute('paging', '2ndArg', 1, true); 26 | $object->getAttribute('2ndArg', 1, true); 27 | } 28 | 29 | ?> 30 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/AddMethodCallArgs.php: -------------------------------------------------------------------------------- 1 | values = $values; 18 | } 19 | 20 | public function getClass(): string 21 | { 22 | return $this->class; 23 | } 24 | 25 | public function getMethodName(): string 26 | { 27 | return $this->methodName; 28 | } 29 | 30 | public function getValues(): array 31 | { 32 | return $this->values; 33 | } 34 | 35 | public function getObjectType(): ObjectType 36 | { 37 | return new ObjectType($this->class); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/OptionsArrayToNamedParametersRector/OptionsArrayToNamedParametersRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 18 | } 19 | 20 | public static function provideData(): Iterator 21 | { 22 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 23 | } 24 | 25 | public function provideConfigFilePath(): string 26 | { 27 | return __DIR__ . '/config/configured_rule.php'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/AppUsesStaticCallToUseStatementRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RenameMethodCallBasedOnParameterRector/RenameMethodCallBasedOnParameterRectorTest.php: -------------------------------------------------------------------------------- 1 | doTestFile($filePath); 17 | } 18 | 19 | public static function provideData(): Iterator 20 | { 21 | return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); 22 | } 23 | 24 | public function provideConfigFilePath(): string 25 | { 26 | return __DIR__ . '/config/configured_rule.php'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | src/ 6 | tests/ 7 | 8 | tests/test_apps/ 9 | tests/TestCase/Rector/ 10 | 11 | 12 | 0 13 | 14 | 15 | 0 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Fixture/cakephp_import_namespaces_up.php.inc: -------------------------------------------------------------------------------- 1 | 17 | ----- 18 | 34 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/RenameMethodCallBasedOnParameter.php: -------------------------------------------------------------------------------- 1 | oldMethod; 21 | } 22 | 23 | public function getParameterName(): string 24 | { 25 | return $this->parameterName; 26 | } 27 | 28 | public function getNewMethod(): string 29 | { 30 | return $this->newMethod; 31 | } 32 | 33 | public function getOldObjectType(): ObjectType 34 | { 35 | return new ObjectType($this->oldClass); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /bin/cake.bat: -------------------------------------------------------------------------------- 1 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 2 | :: 3 | :: Cake is a Windows batch script for invoking CakePHP shell commands 4 | :: 5 | :: CakePHP(tm) : Rapid Development Framework (https://cakephp.org) 6 | :: Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) 7 | :: 8 | :: Licensed under The MIT License 9 | :: Redistributions of files must retain the above copyright notice. 10 | :: 11 | :: @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) 12 | :: @link https://cakephp.org CakePHP(tm) Project 13 | :: @since 2.0.0 14 | :: @license https://opensource.org/licenses/mit-license.php MIT License 15 | :: 16 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 17 | 18 | @echo off 19 | 20 | SET app=%0 21 | SET lib=%~dp0 22 | 23 | php "%lib%cake.php" %* 24 | 25 | echo. 26 | 27 | exit /B %ERRORLEVEL% 28 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ArrayToFluentCallRector/Fixture/fluent_factory.php.inc: -------------------------------------------------------------------------------- 1 | buildClass('foo'); 12 | 13 | $factory->buildClass('foo', []); 14 | 15 | $factory->buildClass('foo', ['baz' => 1]); 16 | } 17 | 18 | ?> 19 | ----- 20 | buildClass('foo'); 31 | 32 | $factory->buildClass('foo'); 33 | 34 | $factory->buildClass('foo', ['baz' => 1]); 35 | } 36 | 37 | ?> 38 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Fixture/inside_if.php.inc: -------------------------------------------------------------------------------- 1 | 19 | ----- 20 | 38 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApplyChronos3DateTime/src/Chronos3.php: -------------------------------------------------------------------------------- 1 | addYear(); 9 | $dateTime->subYear(); 10 | $dateTime->addYearWithOverflow(); 11 | $dateTime->subYearWithOverflow(); 12 | $dateTime->addMonth(); 13 | $dateTime->subMonth(); 14 | $dateTime->addMonthWithOverflow(); 15 | $dateTime->subMonthWithOverflow(); 16 | $dateTime->addDay(); 17 | $dateTime->subDay(); 18 | $dateTime->addWeekday(); 19 | $dateTime->subWeekday(); 20 | $dateTime->addWeek(); 21 | $dateTime->subWeek(); 22 | 23 | $dateTime->addHour(); 24 | $dateTime->subHour(); 25 | $dateTime->addMinute(); 26 | $dateTime->subMinute(); 27 | $dateTime->addSecond(); 28 | $dateTime->subSecond(); 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RenameMethodCallBasedOnParameterRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | getParam('paging'); 12 | $object->withParam('paging', 'value'); 13 | } 14 | 15 | ?> 16 | ----- 17 | getAttribute('paging'); 28 | $object->withAttribute('paging', 'value'); 29 | } 30 | 31 | ?> 32 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ModalToGetSetRector/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(ModalToGetSetRector::class, [ 11 | 12 | new ModalToGetSet(SomeModelType::class, 'config', null, null, 2, 'array'), 13 | new ModalToGetSet( 14 | SomeModelType::class, 15 | 'customMethod', 16 | 'customMethodGetName', 17 | 'customMethodSetName', 18 | 2, 19 | 'array' 20 | ), 21 | new ModalToGetSet(SomeModelType::class, 'makeEntity', 'createEntity', 'generateEntity'), 22 | new ModalToGetSet(SomeModelType::class, 'method'), 23 | 24 | ]); 25 | }; 26 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply53/src/SomeTest.php: -------------------------------------------------------------------------------- 1 | isEmpty('test'); 18 | $entity->set('test', 'value'); // This should stay as is 19 | $entity->set('test', 'value', ['asOriginal' => 'true']); // This should stay as is 20 | $entity->set(['test' => 'value']); // This should be changed to patch 21 | $entity->set(['test' => 'value'], ['asOriginal' => 'true']); // This should be changed to patch 22 | 23 | $table = $this->fetchTable('Articles'); 24 | $expr = $table->find()->newExpr(); 25 | } 26 | 27 | public function findSomething(Query $query, array $options): Query { 28 | return $query; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApplyChronos3DateTime/src/Chronos3.php: -------------------------------------------------------------------------------- 1 | addYears(1); 9 | $dateTime->subYears(1); 10 | $dateTime->addYearsWithOverflow(1); 11 | $dateTime->subYearsWithOverflow(1); 12 | $dateTime->addMonths(1); 13 | $dateTime->subMonths(1); 14 | $dateTime->addMonthsWithOverflow(1); 15 | $dateTime->subMonthsWithOverflow(1); 16 | $dateTime->addDays(1); 17 | $dateTime->subDays(1); 18 | $dateTime->addWeekdays(1); 19 | $dateTime->subWeekdays(1); 20 | $dateTime->addWeeks(1); 21 | $dateTime->subWeeks(1); 22 | 23 | $dateTime->addHours(1); 24 | $dateTime->subHours(1); 25 | $dateTime->addMinutes(1); 26 | $dateTime->subMinutes(1); 27 | $dateTime->addSeconds(1); 28 | $dateTime->subSeconds(1); 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply53/src/SomeTest.php: -------------------------------------------------------------------------------- 1 | hasValue('test'); 18 | $entity->set('test', 'value'); // This should stay as is 19 | $entity->set('test', 'value', ['asOriginal' => 'true']); // This should stay as is 20 | $entity->patch(['test' => 'value']); // This should be changed to patch 21 | $entity->patch(['test' => 'value'], ['asOriginal' => 'true']); // This should be changed to patch 22 | 23 | $table = $this->fetchTable('Articles'); 24 | $expr = $table->find()->expr(); 25 | } 26 | 27 | public function findSomething(\Cake\ORM\Query\SelectQuery $query, array $options): \Cake\ORM\Query\SelectQuery { 28 | return $query; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/OptionsArrayToNamedParameters.php: -------------------------------------------------------------------------------- 1 | class; 19 | } 20 | 21 | public function getObjectType(): ObjectType 22 | { 23 | return new ObjectType($this->class); 24 | } 25 | 26 | /** 27 | * @return array 28 | */ 29 | public function getMethod(): string 30 | { 31 | return $this->methods[0] ?? ''; 32 | } 33 | 34 | /** 35 | * @return array 36 | */ 37 | public function getRenames(): array 38 | { 39 | if (isset($this->methods['rename'])) { 40 | return $this->methods['rename']; 41 | } 42 | 43 | return []; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply50/src/HelperProperties.php: -------------------------------------------------------------------------------- 1 | set('_serialize', 'result'); 40 | } 41 | } 42 | 43 | class CustomBehavior extends Behavior 44 | { 45 | protected $_defaultConfig = []; 46 | } 47 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ModalToGetSetRector/Fixture/fixture2.php.inc: -------------------------------------------------------------------------------- 1 | customMethod(); 12 | $config = $object->customMethod('key'); 13 | 14 | $object->customMethod('key', 'value'); 15 | $object->customMethod(['key' => 'value']); 16 | } 17 | 18 | ?> 19 | ----- 20 | customMethodGetName(); 31 | $config = $object->customMethodGetName('key'); 32 | 33 | $object->customMethodSetName('key', 'value'); 34 | $object->customMethodSetName(['key' => 'value']); 35 | } 36 | 37 | ?> 38 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/RemoveIntermediaryMethodRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | regularMethod('call'); 10 | $this->getTableLocator()->otherMethod(); 11 | $this->Users = $this->getTableLocator()->get('Users'); 12 | $articles = $this->getTableLocator()->get('Articles', ['table' => 'alt_articles']); 13 | $comments = $this->getTableLocator() 14 | ->get('Comments'); 15 | } 16 | } 17 | 18 | ?> 19 | ----- 20 | regularMethod('call'); 29 | $this->getTableLocator()->otherMethod(); 30 | $this->Users = $this->fetchTable('Users'); 31 | $articles = $this->fetchTable('Articles', ['table' => 'alt_articles']); 32 | $comments = $this->fetchTable('Comments'); 33 | } 34 | } 35 | 36 | ?> 37 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ArrayToFluentCallRector/config/configured_rule.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(ArrayToFluentCallRector::class, [ 14 | ArrayToFluentCallRector::ARRAYS_TO_FLUENT_CALLS => [ 15 | new ArrayToFluentCall(ConfigurableClass::class, [ 16 | 'name' => 'setName', 17 | 'size' => 'setSize', 18 | ]), 19 | ], 20 | ArrayToFluentCallRector::FACTORY_METHODS => [ 21 | new FactoryMethod(FactoryClass::class, 'buildClass', ConfigurableClass::class, 2), 22 | ], 23 | ]); 24 | }; 25 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/NewEntityToNewEmptyEntityRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | newEntity(); 13 | 14 | // This should NOT be changed (has arguments) 15 | $entity2 = $this->newEntity(['title' => 'Test']); 16 | 17 | return $entity; 18 | } 19 | } 20 | 21 | ?> 22 | ----- 23 | newEmptyEntity(); 35 | 36 | // This should NOT be changed (has arguments) 37 | $entity2 = $this->newEntity(['title' => 'Test']); 38 | 39 | return $entity; 40 | } 41 | } 42 | 43 | ?> 44 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) CakePHP(tm) : Rapid Development Framework (https://cakephp.org) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply50/src/HelperProperties.php: -------------------------------------------------------------------------------- 1 | viewBuilder()->setOption('serialize', 'result'); 40 | } 41 | } 42 | 43 | class CustomBehavior extends Behavior 44 | { 45 | protected array $_defaultConfig = []; 46 | } 47 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp45.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameClassRector::class, [ 12 | 'Cake\Datasource\Paging\Paginator' => 'Cake\Datasource\Paging\NumericPaginator', 13 | 'Cake\TestSuite\ContainerStubTrait' => 'Cake\Core\TestSuite\ContainerStubTrait', 14 | 'Cake\TestSuite\HttpClientTrait' => 'Cake\Http\TestSuite\HttpClientTrait', 15 | 'Cake\Cache\InvalidArgumentException' => 'Cake\Cache\Exception\InvalidArgumentException', 16 | ]); 17 | 18 | $rectorConfig->ruleWithConfiguration( 19 | RenameMethodRector::class, 20 | [ 21 | new MethodCallRename('Cake\View\View', 'loadHelper', 'addHelper'), 22 | new MethodCallRename('Cake\Validation\Validator', 'isArray', 'array'), 23 | ] 24 | ); 25 | 26 | }; 27 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Fixture/cakephp_fixture.php.inc: -------------------------------------------------------------------------------- 1 | 18 | ----- 19 | 36 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ModalToGetSetRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | config(); 14 | $config = $object->config('key'); 15 | $object->config('key', 'value'); 16 | $object->config(['key' => 'value']); 17 | $object->config('key'); 18 | } 19 | } 20 | 21 | ?> 22 | ----- 23 | getConfig(); 36 | $config = $object->getConfig('key'); 37 | $object->setConfig('key', 'value'); 38 | $object->setConfig(['key' => 'value']); 39 | $object->getConfig('key'); 40 | } 41 | } 42 | 43 | ?> 44 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/View/AppView.php: -------------------------------------------------------------------------------- 1 | loadHelper('Html');` 34 | * 35 | * @return void 36 | */ 37 | public function initialize() 38 | { 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/FileRenameCommand-testTemplates/src/View/AppView.php: -------------------------------------------------------------------------------- 1 | loadHelper('Html');` 34 | * 35 | * @return void 36 | */ 37 | public function initialize() 38 | { 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApplyChronos3Date/src/Chronos3.php: -------------------------------------------------------------------------------- 1 | addYear(); 9 | $date->subYear(); 10 | $date->addYearWithOverflow(); 11 | $date->subYearWithOverflow(); 12 | $date->addMonth(); 13 | $date->subMonth(); 14 | $date->addMonthWithOverflow(); 15 | $date->subMonthWithOverflow(); 16 | $date->addDay(); 17 | $date->subDay(); 18 | $date->addWeekday(); 19 | $date->subWeekday(); 20 | $date->addWeek(); 21 | $date->subWeek(); 22 | 23 | $date = new \Cake\Chronos\MutableDate(); 24 | $date->addYear(); 25 | $date->subYear(); 26 | $date->addYearWithOverflow(); 27 | $date->subYearWithOverflow(); 28 | $date->addMonth(); 29 | $date->subMonth(); 30 | $date->addMonthWithOverflow(); 31 | $date->subMonthWithOverflow(); 32 | $date->addDay(); 33 | $date->subDay(); 34 | $date->addWeekday(); 35 | $date->subWeekday(); 36 | $date->addWeek(); 37 | $date->subWeek(); 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply45/src/View/AppView.php: -------------------------------------------------------------------------------- 1 | loadHelper('Html');` 34 | * 35 | * @return void 36 | */ 37 | public function initialize() 38 | { 39 | $this->loadHelper('Html', ['className' => 'MyHtml']); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply45/src/View/AppView.php: -------------------------------------------------------------------------------- 1 | loadHelper('Html');` 34 | * 35 | * @return void 36 | */ 37 | public function initialize() 38 | { 39 | $this->addHelper('Html', ['className' => 'MyHtml']); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApplyChronos3Date/src/Chronos3.php: -------------------------------------------------------------------------------- 1 | addYears(1); 9 | $date->subYears(1); 10 | $date->addYearsWithOverflow(1); 11 | $date->subYearsWithOverflow(1); 12 | $date->addMonths(1); 13 | $date->subMonths(1); 14 | $date->addMonthsWithOverflow(1); 15 | $date->subMonthsWithOverflow(1); 16 | $date->addDays(1); 17 | $date->subDays(1); 18 | $date->addWeekdays(1); 19 | $date->subWeekdays(1); 20 | $date->addWeeks(1); 21 | $date->subWeeks(1); 22 | 23 | $date = new \Cake\Chronos\ChronosDate(); 24 | $date->addYears(1); 25 | $date->subYears(1); 26 | $date->addYearsWithOverflow(1); 27 | $date->subYearsWithOverflow(1); 28 | $date->addMonths(1); 29 | $date->subMonths(1); 30 | $date->addMonthsWithOverflow(1); 31 | $date->subMonthsWithOverflow(1); 32 | $date->addDays(1); 33 | $date->subDays(1); 34 | $date->addWeekdays(1); 35 | $date->subWeekdays(1); 36 | $date->addWeeks(1); 37 | $date->subWeeks(1); 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ArrayToFluentCallRector/Fixture/array_to_fluent_call.php.inc: -------------------------------------------------------------------------------- 1 | buildClass('foo', [ 12 | 'name' => 'bar', 13 | 'size' => 2, 14 | ]); 15 | 16 | $factory->buildClass('foo', ['name' => 'bar']) 17 | ->setSize(3) 18 | ->doSomething(); 19 | 20 | $factory->buildClass('foo', [ 21 | 'name' => 'bar', 22 | 'baz' => 4, 23 | ]); 24 | } 25 | 26 | ?> 27 | ----- 28 | buildClass('foo')->setName('bar')->setSize(2); 39 | 40 | $factory->buildClass('foo')->setName('bar') 41 | ->setSize(3) 42 | ->doSomething(); 43 | 44 | $factory->buildClass('foo', [ 45 | 'baz' => 4, 46 | ])->setName('bar'); 47 | } 48 | 49 | ?> 50 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply51/src/SomeTest.php: -------------------------------------------------------------------------------- 1 | [ 19 | 'className' => 'FileEngine', 20 | 'prefix' => 'myapp_cake_core_', 21 | 'path' => 'persistent', 22 | 'serialize' => true, 23 | 'duration' => '+1 years', 24 | ], 25 | ]; 26 | } 27 | 28 | public function testConnectionHelper() 29 | { 30 | $connectionHelper = new ConnectionHelper(); 31 | $connection = ConnectionManager::get('test'); 32 | $connectionHelper->runWithoutConstraints($connection, function ($connection) { 33 | $connection->execute('SELECT * FROM table'); 34 | }); 35 | $connectionHelper->dropTables('test', ['table']); 36 | $connectionHelper->enableQueryLogging(['test']); 37 | $connectionHelper->truncateTables('test', ['table']); 38 | $connectionHelper->addTestAliases(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/EntityPatchRector/Fixture/skip_non_entity.php.inc: -------------------------------------------------------------------------------- 1 | set(['key' => 'value']); 21 | 22 | // Should NOT transform: unknown object type 23 | $someObject->set(['data' => 'test']); 24 | 25 | return $object; 26 | } 27 | } 28 | 29 | ?> 30 | ----- 31 | set(['key' => 'value']); 51 | 52 | // Should NOT transform: unknown object type 53 | $someObject->set(['data' => 'test']); 54 | 55 | return $object; 56 | } 57 | } 58 | 59 | ?> 60 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cakephp/upgrade", 3 | "type": "rector-extension", 4 | "description": "Command line tool for updating CakePHP applications and plugins.", 5 | "homepage": "https://cakephp.org", 6 | "license": "MIT", 7 | "require": { 8 | "php": "^8.1", 9 | "cakephp/console": "^5.0", 10 | "nette/utils": "^4.0", 11 | "rector/rector": "~2.2.9", 12 | "symfony/string": "^6.0 || ^7.0" 13 | }, 14 | "autoload": { 15 | "psr-4": { 16 | "Cake\\Upgrade\\": "src/" 17 | } 18 | }, 19 | "autoload-dev": { 20 | "psr-4": { 21 | "Cake\\Upgrade\\Test\\TestCase\\": "tests/TestCase/" 22 | } 23 | }, 24 | "prefer-stable": true, 25 | "minimum-stability": "dev", 26 | "scripts": { 27 | "setup": "cp composer.json composer.backup && make install-dev && mv composer.backup composer.json", 28 | "cs-check": "phpcs --colors --parallel=16 -p -s", 29 | "cs-fix": "phpcbf --colors --parallel=16 -p", 30 | "test": "phpunit" 31 | }, 32 | "config": { 33 | "sort-packages": true, 34 | "allow-plugins": { 35 | "dealerdirect/phpcodesniffer-composer-installer": true, 36 | "rector/extension-installer": true 37 | } 38 | }, 39 | "support": { 40 | "source": "https://github.com/cakephp/upgrade" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp44.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameClassRector::class, [ 13 | 'Cake\TestSuite\ConsoleIntegrationTestTrait' => 'Cake\Console\TestSuite\ConsoleIntegrationTestTrait', 14 | 'Cake\TestSuite\Stub\ConsoleInput' => 'Cake\Console\TestSuite\StubConsoleInput', 15 | 'Cake\TestSuite\Stub\ConsoleOutput' => 'Cake\Console\TestSuite\StubConsoleOutput', 16 | 'Cake\TestSuite\Stub\MissingConsoleInputException' => 'Cake\Console\TestSuite\MissingConsoleInputException', 17 | 'Cake\TestSuite\HttpClientTrait' => 'Cake\Http\TestSuite\HttpClientTrait', 18 | ]); 19 | 20 | // Apply newExpr()->count() -> func()->count('*') transformation before general newExpr rename 21 | $rectorConfig->rule(NewExprToFuncRector::class); 22 | 23 | $rectorConfig->ruleWithConfiguration( 24 | RenameMethodRector::class, 25 | [new MethodCallRename('Cake\Database\Query', 'newExpr', 'expr')], 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/ChangeEntityTraitSetArrayToPatch/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | set(['paging' => 'test']); 13 | // This should not be changed 14 | $object->set('paging', 'test'); 15 | 16 | $otherObject = new OtherClassWithSetMethod(); 17 | // This should not be changed as well 18 | $otherObject->set(['paging' => 'test']); 19 | } 20 | 21 | ?> 22 | ----- 23 | patch(['paging' => 'test']); 35 | // This should not be changed 36 | $object->set('paging', 'test'); 37 | 38 | $otherObject = new OtherClassWithSetMethod(); 39 | // This should not be changed as well 40 | $otherObject->set(['paging' => 'test']); 41 | } 42 | 43 | ?> 44 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/PaginatorCounterFormatRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | counter(['format' => __('Page {{page}} of {{pages}}')]); 11 | 12 | // This should NOT be converted (already using direct format) 13 | echo $paginator->counter(__('Showing {{current}} of {{count}}')); 14 | 15 | // This should NOT be converted (has more than one array item) 16 | echo $paginator->counter(['format' => __('Page {{page}}'), 'model' => 'Articles']); 17 | } 18 | 19 | ?> 20 | ----- 21 | counter(__('Page {{page}} of {{pages}}')); 31 | 32 | // This should NOT be converted (already using direct format) 33 | echo $paginator->counter(__('Showing {{current}} of {{count}}')); 34 | 35 | // This should NOT be converted (has more than one array item) 36 | echo $paginator->counter(['format' => __('Page {{page}}'), 'model' => 'Articles']); 37 | } 38 | 39 | ?> 40 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/QueryParamAccessRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | getParam('?'); 15 | 16 | // Should also work with method chaining 17 | $params = $this->getRequest()->getParam('?'); 18 | 19 | return $queryParams; 20 | } 21 | 22 | protected function getRequest(): ServerRequest 23 | { 24 | return new ServerRequest(); 25 | } 26 | } 27 | 28 | ?> 29 | ----- 30 | getQueryParams(); 44 | 45 | // Should also work with method chaining 46 | $params = $this->getRequest()->getQueryParams(); 47 | 48 | return $queryParams; 49 | } 50 | 51 | protected function getRequest(): ServerRequest 52 | { 53 | return new ServerRequest(); 54 | } 55 | } 56 | 57 | ?> 58 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply51/src/SomeTest.php: -------------------------------------------------------------------------------- 1 | [ 19 | 'className' => 'FileEngine', 20 | 'prefix' => 'myapp_cake_core_', 21 | 'path' => 'persistent', 22 | 'serialize' => true, 23 | 'duration' => '+1 years', 24 | ], 25 | ]; 26 | } 27 | 28 | public function testConnectionHelper() 29 | { 30 | $connectionHelper = new ConnectionHelper(); 31 | $connection = ConnectionManager::get('test'); 32 | \Cake\TestSuite\ConnectionHelper::runWithoutConstraints($connection, function ($connection) { 33 | $connection->execute('SELECT * FROM table'); 34 | }); 35 | \Cake\TestSuite\ConnectionHelper::dropTables('test', ['table']); 36 | \Cake\TestSuite\ConnectionHelper::enableQueryLogging(['test']); 37 | \Cake\TestSuite\ConnectionHelper::truncateTables('test', ['table']); 38 | \Cake\TestSuite\ConnectionHelper::addTestAliases(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/QueryParamAccessRector/Fixture/skip_other_params.php.inc: -------------------------------------------------------------------------------- 1 | getParam('id'); 15 | $action = $request->getParam('action'); 16 | $paging = $request->getParam('paging'); 17 | 18 | // Should NOT transform: non-Request object 19 | $someObject->getParam('?'); 20 | 21 | return compact('id', 'action', 'paging'); 22 | } 23 | } 24 | 25 | ?> 26 | ----- 27 | getParam('id'); 41 | $action = $request->getParam('action'); 42 | $paging = $request->getParam('paging'); 43 | 44 | // Should NOT transform: non-Request object 45 | $someObject->getParam('?'); 46 | 47 | return compact('id', 'action', 'paging'); 48 | } 49 | } 50 | 51 | ?> 52 | -------------------------------------------------------------------------------- /config/requirements.php: -------------------------------------------------------------------------------- 1 | newExpr()->count(); 14 | $countField = $query->newExpr()->count('id'); 15 | $sum = $query->newExpr()->sum('total'); 16 | $avg = $query->newExpr()->avg('score'); 17 | $min = $query->newExpr()->min('price'); 18 | $max = $query->newExpr()->max('price'); 19 | 20 | return compact('count', 'sum', 'avg', 'min', 'max'); 21 | } 22 | } 23 | 24 | ?> 25 | ----- 26 | func()->count('*'); 39 | $countField = $query->func()->count('id'); 40 | $sum = $query->func()->sum('total'); 41 | $avg = $query->func()->avg('score'); 42 | $min = $query->func()->min('price'); 43 | $max = $query->func()->max('price'); 44 | 45 | return compact('count', 'sum', 'avg', 'min', 'max'); 46 | } 47 | } 48 | 49 | ?> 50 | -------------------------------------------------------------------------------- /tests/TestCase/Command/FileRenameCommandTest.php: -------------------------------------------------------------------------------- 1 | setupTestApp(__FUNCTION__); 30 | Configure::write('App.paths.plugins', TEST_APP . 'plugins'); 31 | 32 | $this->exec('upgrade file_rename templates ' . TEST_APP); 33 | $this->assertTestAppUpgraded(); 34 | } 35 | 36 | public function testLocales(): void 37 | { 38 | $this->setupTestApp(__FUNCTION__); 39 | Configure::write('App.paths.plugins', TEST_APP . 'plugins'); 40 | 41 | $this->exec('upgrade file_rename locales ' . TEST_APP); 42 | $this->assertTestAppUpgraded(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/NewExprToFuncRector/Fixture/sql_functions.php.inc: -------------------------------------------------------------------------------- 1 | newExpr()->now(); 13 | $diff = $query->newExpr()->dateDiff('created', 'modified'); 14 | $extract = $query->newExpr()->extract('year', 'created'); 15 | 16 | // Other SQL functions 17 | $concat = $query->newExpr()->concat(['first_name', 'last_name']); 18 | $coalesce = $query->newExpr()->coalesce(['email', 'backup_email']); 19 | $rand = $query->newExpr()->rand(); 20 | 21 | return $query; 22 | } 23 | } 24 | 25 | ?> 26 | ----- 27 | func()->now(); 39 | $diff = $query->func()->dateDiff('created', 'modified'); 40 | $extract = $query->func()->extract('year', 'created'); 41 | 42 | // Other SQL functions 43 | $concat = $query->func()->concat(['first_name', 'last_name']); 44 | $coalesce = $query->func()->coalesce(['email', 'backup_email']); 45 | $rand = $query->func()->rand(); 46 | 47 | return $query; 48 | } 49 | } 50 | 51 | ?> 52 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/EntityPatchRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | set with array literal 18 | $entity->set(['name' => 'Test', 'email' => 'test@example.com']); 19 | 20 | // Should NOT transform: set with variable 21 | $data = ['name' => 'Test']; 22 | $entity->set($data); 23 | 24 | // Should NOT transform: set with non-array argument 25 | $entity->set('name', 'Test'); 26 | 27 | return $entity; 28 | } 29 | } 30 | 31 | ?> 32 | ----- 33 | set with array literal 50 | $entity->patch(['name' => 'Test', 'email' => 'test@example.com']); 51 | 52 | // Should NOT transform: set with variable 53 | $data = ['name' => 'Test']; 54 | $entity->set($data); 55 | 56 | // Should NOT transform: set with non-array argument 57 | $entity->set('name', 'Test'); 58 | 59 | return $entity; 60 | } 61 | } 62 | 63 | ?> 64 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/ClassMethod/FormBuildValidatorRector/Fixture/fixture.php.inc: -------------------------------------------------------------------------------- 1 | add('name', 'length', [ 15 | 'rule' => ['minLength', 10], 16 | 'message' => 'Name is required', 17 | ]) 18 | ->add('email', 'format', [ 19 | 'rule' => 'email', 20 | 'message' => 'A valid email address is required', 21 | ]); 22 | 23 | return $validator; 24 | } 25 | } 26 | 27 | ?> 28 | ----- 29 | add('name', 'length', [ 43 | 'rule' => ['minLength', 10], 44 | 'message' => 'Name is required', 45 | ]) 46 | ->add('email', 'format', [ 47 | 'rule' => 'email', 48 | 'message' => 'A valid email address is required', 49 | ]); 50 | 51 | return $validator; 52 | } 53 | } 54 | 55 | ?> 56 | -------------------------------------------------------------------------------- /src/Rector/ValueObject/ModalToGetSet.php: -------------------------------------------------------------------------------- 1 | getMethod = $getMethod ?? 'get' . ucfirst($unprefixedMethod); 29 | $this->setMethod = $setMethod ?? 'set' . ucfirst($unprefixedMethod); 30 | } 31 | 32 | public function getObjectType(): ObjectType 33 | { 34 | return new ObjectType($this->type); 35 | } 36 | 37 | public function getUnprefixedMethod(): string 38 | { 39 | return $this->unprefixedMethod; 40 | } 41 | 42 | public function getGetMethod(): string 43 | { 44 | return $this->getMethod; 45 | } 46 | 47 | public function getSetMethod(): string 48 | { 49 | return $this->setMethod; 50 | } 51 | 52 | public function getMinimalSetterArgumentCount(): int 53 | { 54 | return $this->minimalSetterArgumentCount; 55 | } 56 | 57 | public function getFirstArgumentType(): ?string 58 | { 59 | return $this->firstArgumentType; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp30.php: -------------------------------------------------------------------------------- 1 | rule(AppUsesStaticCallToUseStatementRector::class); 11 | 12 | $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ 13 | # see https://github.com/cakephp/upgrade/blob/756410c8b7d5aff9daec3fa1fe750a3858d422ac/src/Shell/Task/RenameClassesTask.php#L37 14 | 'Cake\Network\Http\HttpSocket' => 'Cake\Network\Http\Client', 15 | 'Cake\Model\ConnectionManager' => 'Cake\Database\ConnectionManager', 16 | 'Cake\TestSuite\CakeTestCase' => 'Cake\TestSuite\TestCase', 17 | 'Cake\TestSuite\Fixture\CakeTestFixture' => 'Cake\TestSuite\Fixture\TestFixture', 18 | 'Cake\Utility\String' => 'Cake\Utility\Text', 19 | 'CakePlugin' => 'Plugin', 20 | 'CakeException' => 'Exception', 21 | # see https://book.cakephp.org/3/en/appendices/3-0-migration-guide.html#configure 22 | 'Cake\Configure\PhpReader' => 'Cake\Core\Configure\EnginePhpConfig', 23 | 'Cake\Configure\IniReader' => 'Cake\Core\Configure\EngineIniConfig', 24 | 'Cake\Configure\ConfigReaderInterface' => 'Cake\Core\Configure\ConfigEngineInterface', 25 | # https://book.cakephp.org/3/en/appendices/3-0-migration-guide.html#request 26 | 'CakeRequest' => 'Cake\Network\Request', 27 | ]); 28 | }; 29 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp41.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameClassRector::class, [ 13 | 'Cake\Routing\Exception\RedirectException' => 'Cake\Http\Exception\RedirectException', 14 | 'Cake\Database\Expression\Comparison' => 'Cake\Database\Expression\ComparisonExpression', 15 | ]); 16 | 17 | $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ 18 | new MethodCallRename('Cake\Database\Schema\TableSchema', 'getPrimary', 'getPrimaryKey'), 19 | new MethodCallRename('Cake\Database\Type\DateTimeType', 'setTimezone', 'setDatabaseTimezone'), 20 | new MethodCallRename('Cake\Database\Expression\QueryExpression', 'or_', 'or'), 21 | new MethodCallRename('Cake\Database\Expression\QueryExpression', 'and_', 'and'), 22 | new MethodCallRename('Cake\View\Form\ContextInterface', 'primaryKey', 'getPrimaryKey'), 23 | new MethodCallRename( 24 | 'Cake\Http\Middleware\CsrfProtectionMiddleware', 25 | 'whitelistCallback', 26 | 'skipCheckCallback' 27 | ), 28 | ]); 29 | 30 | $rectorConfig->ruleWithConfiguration(ModalToGetSetRector::class, [new ModalToGetSet('Cake\Form\Form', 'schema')]); 31 | }; 32 | -------------------------------------------------------------------------------- /tests/test_apps/original/FileRenameCommand-testTemplates/src/View/AjaxView.php: -------------------------------------------------------------------------------- 1 | response = $this->response->withType('ajax'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/test_apps/original/RectorCommand-testApply50/src/Plugin.php: -------------------------------------------------------------------------------- 1 | response = $this->response->withType('ajax'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Rector/NodeAnalyzer/FluentChainMethodCallNodeAnalyzer.php: -------------------------------------------------------------------------------- 1 | methodCall()->chainedMethodCall()" 14 | * 15 | * Taken from https://github.com/rectorphp/rector/blob/d8da002b107c9b64d464bb48101290d4d078df4b/packages/Defluent/NodeAnalyzer/FluentChainMethodCallNodeAnalyzer.php 16 | * https://github.com/rectorphp/rector/blob/main/LICENSE 17 | */ 18 | final class FluentChainMethodCallNodeAnalyzer 19 | { 20 | /** 21 | * @api doctrine 22 | */ 23 | public function resolveRootMethodCall(MethodCall $methodCall): ?MethodCall 24 | { 25 | $callerNode = $methodCall->var; 26 | while ($callerNode instanceof MethodCall && $callerNode->var instanceof MethodCall) { 27 | $callerNode = $callerNode->var; 28 | } 29 | if ($callerNode instanceof MethodCall) { 30 | return $callerNode; 31 | } 32 | 33 | return null; 34 | } 35 | 36 | /** 37 | * @return \PhpParser\Node\Expr|\PhpParser\Node\Name 38 | */ 39 | public function resolveRootExpr(MethodCall $methodCall): Expr|Name 40 | { 41 | $callerNode = $methodCall->var; 42 | while ($callerNode instanceof MethodCall || $callerNode instanceof StaticCall) { 43 | $callerNode = $callerNode instanceof StaticCall ? $callerNode->class : $callerNode->var; 44 | } 45 | 46 | return $callerNode; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/NewExprToFuncRector/Fixture/skip_non_func_methods.php.inc: -------------------------------------------------------------------------------- 1 | newExpr()->eq('status', 1); 13 | $expr2 = $query->newExpr()->gt('price', 100); 14 | $expr3 = $query->newExpr()->and(['status' => 1, 'active' => true]); 15 | 16 | // Should NOT transform: standalone newExpr() call 17 | $expr4 = $query->newExpr(); 18 | 19 | // Should NOT transform: non-Query object 20 | $someObject->newExpr()->count(); 21 | 22 | return $query; 23 | } 24 | } 25 | 26 | ?> 27 | ----- 28 | newExpr()->eq('status', 1); 40 | $expr2 = $query->newExpr()->gt('price', 100); 41 | $expr3 = $query->newExpr()->and(['status' => 1, 'active' => true]); 42 | 43 | // Should NOT transform: standalone newExpr() call 44 | $expr4 = $query->newExpr(); 45 | 46 | // Should NOT transform: non-Query object 47 | $someObject->newExpr()->count(); 48 | 49 | return $query; 50 | } 51 | } 52 | 53 | ?> 54 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp53.php: -------------------------------------------------------------------------------- 1 | count() -> func()->count('*') transformation before general newExpr rename 17 | $rectorConfig->rule(NewExprToFuncRector::class); 18 | 19 | $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ 20 | new MethodCallRename('Cake\Database\Query', 'newExpr', 'expr'), 21 | ]); 22 | $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ 23 | 'Cake\ORM\Query' => 'Cake\ORM\Query\SelectQuery', 24 | 'Cake\TestSuite\Fixture\TransactionFixtureStrategy' => 'Cake\TestSuite\Fixture\TransactionStrategy', 25 | 'Cake\TestSuite\Fixture\TruncateFixtureStrategy' => 'Cake\TestSuite\Fixture\TruncateStrategy', 26 | ]); 27 | $rectorConfig->rule(EntityIsEmptyRector::class); 28 | $rectorConfig->rule(EntityPatchRector::class); 29 | $rectorConfig->rule(FormExecuteToProcessRector::class); 30 | $rectorConfig->rule(QueryParamAccessRector::class); 31 | }; 32 | -------------------------------------------------------------------------------- /tests/test_apps/upgraded/RectorCommand-testApply50/src/Plugin.php: -------------------------------------------------------------------------------- 1 | isEmpty() with !$entity->hasValue() for \Cake\ORM\Entity descendants', 22 | [ 23 | new CodeSample( 24 | '$entity->isEmpty();', 25 | '!$entity->hasValue();', 26 | ), 27 | ], 28 | ); 29 | } 30 | 31 | public function getNodeTypes(): array 32 | { 33 | return [MethodCall::class]; 34 | } 35 | 36 | public function refactor(Node $node): ?Node 37 | { 38 | if (!$node instanceof MethodCall) { 39 | return null; 40 | } 41 | 42 | if (!$this->isName($node->name, 'isEmpty')) { 43 | return null; 44 | } 45 | 46 | $objectType = $this->getType($node->var); 47 | if (!$objectType instanceof ObjectType) { 48 | return null; 49 | } 50 | 51 | if (!$objectType->isInstanceOf(Entity::class)->yes()) { 52 | return null; 53 | } 54 | 55 | $newMethodCall = new MethodCall( 56 | $node->var, 57 | new Identifier('hasValue'), 58 | $node->args, 59 | ); 60 | 61 | // Replace with !$entity->hasValue($args) 62 | return new BooleanNot($newMethodCall); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Application.php: -------------------------------------------------------------------------------- 1 | add('upgrade', UpgradeCommand::class); 52 | $commands->add('upgrade file_rename', FileRenameCommand::class); 53 | $commands->add('upgrade rector', RectorCommand::class); 54 | 55 | return $commands; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Rector/Rector/MethodCall/TableRegistryLocatorRector.php: -------------------------------------------------------------------------------- 1 | get()`', [ 17 | new ConfiguredCodeSample( 18 | <<<'CODE_SAMPLE' 19 | TableRegistry::get('something'); 20 | CODE_SAMPLE 21 | , 22 | <<<'CODE_SAMPLE' 23 | TableRegistry::getTableLocator()->get('something'); 24 | CODE_SAMPLE, 25 | ), 26 | ]); 27 | } 28 | 29 | public function getNodeTypes(): array 30 | { 31 | return [StaticCall::class]; 32 | } 33 | 34 | public function refactor(Node $node): ?Node 35 | { 36 | if (! $node instanceof StaticCall) { 37 | return null; 38 | } 39 | 40 | // Ensure it's a static call we're looking for: TableRegistry::get(...) 41 | if (! $this->isStaticCallMatch($node, 'Cake\ORM\TableRegistry', 'get')) { 42 | return null; 43 | } 44 | 45 | // Create new static call TableRegistry::getTableLocator()->get(...) 46 | return $this->nodeFactory->createMethodCall( 47 | $this->nodeFactory->createStaticCall('Cake\ORM\TableRegistry', 'getTableLocator'), 48 | 'get', 49 | $node->args, 50 | ); 51 | } 52 | 53 | private function isStaticCallMatch(StaticCall $staticCall, string $className, string $methodName): bool 54 | { 55 | // Check if the static call is `TableRegistry::get` 56 | return $this->isName($staticCall->class, $className) && $this->isName($staticCall->name, $methodName); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Rector/Rector/MethodCall/NewEntityToNewEmptyEntityRector.php: -------------------------------------------------------------------------------- 1 | newEntity() to Table->newEmptyEntity() when called with no arguments. 16 | * 17 | * @see https://github.com/cakephp/upgrade/issues/143 18 | */ 19 | final class NewEntityToNewEmptyEntityRector extends AbstractRector 20 | { 21 | public function getRuleDefinition(): RuleDefinition 22 | { 23 | return new RuleDefinition( 24 | 'Rename Table->newEntity() to Table->newEmptyEntity() when called with no arguments', 25 | [ 26 | new CodeSample( 27 | <<<'CODE_SAMPLE' 28 | $entity = $this->Articles->newEntity(); 29 | CODE_SAMPLE 30 | , 31 | <<<'CODE_SAMPLE' 32 | $entity = $this->Articles->newEmptyEntity(); 33 | CODE_SAMPLE, 34 | ), 35 | ], 36 | ); 37 | } 38 | 39 | /** 40 | * @return array> 41 | */ 42 | public function getNodeTypes(): array 43 | { 44 | return [MethodCall::class]; 45 | } 46 | 47 | /** 48 | * @param \PhpParser\Node\Expr\MethodCall $node 49 | */ 50 | public function refactor(Node $node): ?Node 51 | { 52 | if (!$this->isName($node->name, 'newEntity')) { 53 | return null; 54 | } 55 | 56 | if (!$this->isObjectType($node->var, new ObjectType('Cake\ORM\Table'))) { 57 | return null; 58 | } 59 | 60 | // Only rename if there are no arguments 61 | if (count($node->args) > 0) { 62 | return null; 63 | } 64 | 65 | $node->name = new Identifier('newEmptyEntity'); 66 | 67 | return $node; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp43.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration( 17 | RenameMethodRector::class, 18 | [new MethodCallRename('Cake\Controller\Component', 'shutdown', 'afterFilter')] 19 | ); 20 | 21 | $rectorConfig->ruleWithConfiguration(PropertyFetchToMethodCallRector::class, [ 22 | new PropertyFetchToMethodCall('Cake\Network\Socket', 'connected', 'isConnected'), 23 | new PropertyFetchToMethodCall('Cake\Network\Socket', 'encrypted', 'isEncrypted'), 24 | new PropertyFetchToMethodCall('Cake\Network\Socket', 'lastError', 'lastError'), 25 | ]); 26 | 27 | $rectorConfig->ruleWithConfiguration( 28 | RemoveIntermediaryMethodRector::class, 29 | [new RemoveIntermediaryMethod('getTableLocator', 'get', 'fetchTable')] 30 | ); 31 | 32 | // These rector rules were removed in rector 0.17 - see https://github.com/rectorphp/rector-src/pull/3777 33 | //$rectorConfig->ruleWithConfiguration(MethodCallToAnotherMethodCallWithArgumentsRector::class, [ 34 | // new MethodCallToAnotherMethodCallWithArguments( 35 | // 'Cake\Database\DriverInterface', 36 | // 'supportsQuoting', 37 | // 'supports', 38 | // ['quote'], 39 | // ), 40 | // new MethodCallToAnotherMethodCallWithArguments( 41 | // 'Cake\Database\DriverInterface', 42 | // 'supportsSavepoints', 43 | // 'supports', 44 | // ['savepoint'] 45 | // ), 46 | //]); 47 | }; 48 | -------------------------------------------------------------------------------- /src/Rector/Rector/MethodCall/EntityPatchRector.php: -------------------------------------------------------------------------------- 1 | set([...]) to $entity->patch([...]) only if first argument is an array literal', 22 | [ 23 | new CodeSample( 24 | <<<'CODE_SAMPLE' 25 | $entity->set(['test' => 'value']); 26 | CODE_SAMPLE 27 | , 28 | <<<'CODE_SAMPLE' 29 | $entity->patch(['test' => 'value']); 30 | CODE_SAMPLE, 31 | ), 32 | ], 33 | ); 34 | } 35 | 36 | public function getNodeTypes(): array 37 | { 38 | return [MethodCall::class]; 39 | } 40 | 41 | public function refactor(Node $node): ?Node 42 | { 43 | if (!$node instanceof MethodCall) { 44 | return null; 45 | } 46 | 47 | // must be $something->set(...) 48 | if (!$node->name instanceof Identifier || $node->name->toString() !== 'set') { 49 | return null; 50 | } 51 | 52 | // must have at least 1 argument 53 | if ($node->args === [] || !isset($node->args[0])) { 54 | return null; 55 | } 56 | 57 | $firstArg = $node->args[0]->value; 58 | 59 | // only change if first argument is an array literal 60 | if (!$firstArg instanceof Array_) { 61 | return null; 62 | } 63 | 64 | $callerType = $this->getType($node->var); 65 | if (!$callerType instanceof ObjectType) { 66 | return null; 67 | } 68 | 69 | if (!$callerType->isInstanceOf(Entity::class)->yes()) { 70 | return null; 71 | } 72 | 73 | // change the method name 74 | $node->name = new Identifier('patch'); 75 | 76 | return $node; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tests/TestCase/Rector/MethodCall/OptionsArrayToNamedParametersRector/Fixture/options_to_named_parameters.php.inc: -------------------------------------------------------------------------------- 1 | find(); 13 | $instance->find('all'); 14 | $instance->find('list', ['fields' => ['name']]); 15 | $instance->find('all', [ 16 | 'conditions' => ['Articles.id' => $value], 17 | 'order' => ['Articles.id' => 'asc'], 18 | ]); 19 | 20 | // Preserve named parameters should they exist. 21 | $instance->find('all', 22 | conditions: ['Articles.id' => $value], 23 | order: ['Articles.id' => 'asc'], 24 | ); 25 | $instance->get(1, contain: ['Articles' => ['Categories']]); 26 | 27 | // Array values are not spread 28 | $options = ['conditions' => ['Articles.id' => $value]]; 29 | $instance->find('all', $options); 30 | 31 | // Can modify get as well. 32 | $instance->get(1); 33 | $instance->get(1, ['key' => 'cache-this']); 34 | } 35 | 36 | ?> 37 | ----- 38 | find(); 50 | $instance->find('all'); 51 | $instance->find('list', fields: ['name']); 52 | $instance->find('all', 53 | conditions: ['Articles.id' => $value], 54 | order: ['Articles.id' => 'asc']); 55 | 56 | // Preserve named parameters should they exist. 57 | $instance->find('all', 58 | conditions: ['Articles.id' => $value], 59 | order: ['Articles.id' => 'asc'], 60 | ); 61 | $instance->get(1, contain: ['Articles' => ['Categories']]); 62 | 63 | // Array values are not spread 64 | $options = ['conditions' => ['Articles.id' => $value]]; 65 | $instance->find('all', $options); 66 | 67 | // Can modify get as well. 68 | $instance->get(1); 69 | $instance->get(1, cacheKey: 'cache-this'); 70 | } 71 | 72 | ?> 73 | -------------------------------------------------------------------------------- /config/bootstrap.php: -------------------------------------------------------------------------------- 1 | getMessage() . "\n"); 43 | } 44 | 45 | /* 46 | * Load an environment local configuration file. 47 | * You can use a file like app_local.php to provide local overrides to your 48 | * shared configuration. 49 | */ 50 | //Configure::load('app_local', 'default'); 51 | 52 | /* 53 | * Set the default server timezone. Using UTC makes time calculations / conversions easier. 54 | * Check https://php.net/manual/en/timezones.php for list of valid timezone strings. 55 | */ 56 | date_default_timezone_set(Configure::read('App.defaultTimezone')); 57 | 58 | /* 59 | * Configure the mbstring extension to use the correct encoding. 60 | */ 61 | mb_internal_encoding(Configure::read('App.encoding')); 62 | 63 | /* 64 | * Set the default locale. This controls how dates, number and currency is 65 | * formatted and sets the default language to use for translations. 66 | */ 67 | ini_set('intl.default_locale', Configure::read('App.defaultLocale')); 68 | 69 | Log::setConfig(Configure::consume('Log')); 70 | -------------------------------------------------------------------------------- /bin/cake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | ################################################################################ 3 | # 4 | # Cake is a shell script for invoking CakePHP shell commands 5 | # 6 | # CakePHP(tm) : Rapid Development Framework (https://cakephp.org) 7 | # Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) 8 | # 9 | # Licensed under The MIT License 10 | # For full copyright and license information, please see the LICENSE.txt 11 | # Redistributions of files must retain the above copyright notice. 12 | # 13 | # @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) 14 | # @link https://cakephp.org CakePHP(tm) Project 15 | # @since 1.2.0 16 | # @license https://opensource.org/licenses/mit-license.php MIT License 17 | # 18 | ################################################################################ 19 | 20 | # Canonicalize by following every symlink of the given name recursively 21 | canonicalize() { 22 | NAME="$1" 23 | if [ -f "$NAME" ] 24 | then 25 | DIR=$(dirname -- "$NAME") 26 | NAME=$(cd -P "$DIR" > /dev/null && pwd -P)/$(basename -- "$NAME") 27 | fi 28 | while [ -h "$NAME" ]; do 29 | DIR=$(dirname -- "$NAME") 30 | SYM=$(readlink "$NAME") 31 | NAME=$(cd "$DIR" > /dev/null && cd $(dirname -- "$SYM") > /dev/null && pwd)/$(basename -- "$SYM") 32 | done 33 | echo "$NAME" 34 | } 35 | 36 | # Find a CLI version of PHP 37 | findCliPhp() { 38 | for TESTEXEC in php php-cli /usr/local/bin/php 39 | do 40 | SAPI=`echo "" | $TESTEXEC 2>/dev/null` 41 | if [ "$SAPI" = "cli" ] 42 | then 43 | echo $TESTEXEC 44 | return 45 | fi 46 | done 47 | echo "Failed to find a CLI version of PHP; falling back to system standard php executable" >&2 48 | echo "php"; 49 | } 50 | 51 | # If current path is a symlink, resolve to real path 52 | realname="$0" 53 | if [ -L "$realname" ] 54 | then 55 | realname=$(readlink -f "$0") 56 | fi 57 | 58 | CONSOLE=$(dirname -- "$(canonicalize "$realname")") 59 | APP=$(dirname "$CONSOLE") 60 | 61 | # If your CLI PHP is somewhere that this doesn't find, you can define a PHP environment 62 | # variable with the correct path in it. 63 | if [ -z "$PHP" ] 64 | then 65 | PHP=$(findCliPhp) 66 | fi 67 | 68 | if [ $(basename $realname) != 'cake' ] 69 | then 70 | exec $PHP "$CONSOLE"/cake.php $(basename $realname) "$@" 71 | else 72 | exec $PHP "$CONSOLE"/cake.php "$@" 73 | fi 74 | 75 | exit 76 | -------------------------------------------------------------------------------- /src/Rector/Rector/MethodCall/ChangeEntityTraitSetArrayToPatchRector.php: -------------------------------------------------------------------------------- 1 | set(array) with $this->patch(array) when the first param is an array', 21 | [ 22 | new ConfiguredCodeSample( 23 | <<<'CODE_SAMPLE' 24 | $this->set(['key' => 'value']); 25 | CODE_SAMPLE 26 | , 27 | <<<'CODE_SAMPLE' 28 | $this->patch(['key' => 'value']); 29 | CODE_SAMPLE, 30 | ), 31 | ], 32 | ); 33 | } 34 | 35 | public function getNodeTypes(): array 36 | { 37 | return [MethodCall::class]; 38 | } 39 | 40 | public function refactor(Node $node): ?Node 41 | { 42 | if (! $node instanceof MethodCall) { 43 | return null; 44 | } 45 | 46 | // Check the method name is "set" 47 | if (! $this->isName($node->name, 'set')) { 48 | return null; 49 | } 50 | 51 | // Check that the first argument exists and is an array 52 | if (! isset($node->args[0])) { 53 | return null; 54 | } 55 | 56 | $firstArg = $node->args[0]->value; 57 | if (! $firstArg instanceof Array_) { 58 | return null; 59 | } 60 | 61 | // Make sure the method is called on an object that uses EntityTrait 62 | $callerType = $this->getType($node->var); 63 | if (! $callerType instanceof ObjectType) { 64 | return null; 65 | } 66 | 67 | $classReflection = $callerType->getClassReflection(); 68 | if ($classReflection === null) { 69 | return null; 70 | } 71 | if (! $classReflection->hasTraitUse('Cake\Datasource\EntityTrait')) { 72 | return null; 73 | } 74 | 75 | // Rename the method to "patch" 76 | $node->name = new Identifier('patch'); 77 | 78 | return $node; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Rector/Rector/MethodCall/SetSerializeToViewBuilderRector.php: -------------------------------------------------------------------------------- 1 | set(\'_serialize\', \'result\')` to ' . 19 | '`$this->viewBuilder()->setOption(\'serialize\', \'result\')`.', 20 | [ 21 | new ConfiguredCodeSample( 22 | <<<'CODE_SAMPLE' 23 | $this->set('_serialize', 'result'); 24 | CODE_SAMPLE 25 | , 26 | <<<'CODE_SAMPLE' 27 | $this->viewBuilder()->setOption('serialize', 'result'); 28 | CODE_SAMPLE, 29 | ), 30 | ], 31 | ); 32 | } 33 | 34 | public function getNodeTypes(): array 35 | { 36 | return [MethodCall::class]; 37 | } 38 | 39 | public function refactor(Node $node): ?Node 40 | { 41 | if (! $node instanceof MethodCall) { 42 | return null; 43 | } 44 | 45 | // Ensure it's the method call we're looking for: $this->set('_serialize', ...) 46 | if (! $this->isMethodCallMatch($node, 'set', '_serialize')) { 47 | return null; 48 | } 49 | 50 | // Create the new method call 51 | return $this->nodeFactory->createMethodCall( 52 | $this->nodeFactory->createMethodCall($node->var, 'viewBuilder'), 53 | 'setOption', 54 | ['serialize', $node->args[1]->value], 55 | ); 56 | } 57 | 58 | private function isMethodCallMatch(MethodCall $methodCall, string $methodName, string $firstArgumentValue): bool 59 | { 60 | // Check if the method is 'set' 61 | if (! $this->isName($methodCall->name, $methodName)) { 62 | return false; 63 | } 64 | 65 | // Check if the first argument is '_serialize'w 66 | return isset($methodCall->args[0]) && $methodCall->args[0]->value->value === $firstArgumentValue; 67 | } 68 | 69 | public function configure(array $configuration): void 70 | { 71 | // No configuration options 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Rector/Rector/MethodCall/StaticConnectionHelperRector.php: -------------------------------------------------------------------------------- 1 | runWithoutConstraints($connection, function ($connection) { 28 | $connection->execute('SELECT * FROM table'); 29 | }); 30 | CODE_SAMPLE 31 | , 32 | <<<'CODE_SAMPLE' 33 | ConnectionHelper::runWithoutConstraints($connection, function ($connection) { 34 | $connection->execute('SELECT * FROM table'); 35 | }); 36 | CODE_SAMPLE, 37 | ), 38 | ]); 39 | } 40 | 41 | public function getNodeTypes(): array 42 | { 43 | return [MethodCall::class, Assign::class]; 44 | } 45 | 46 | public function refactor(Node $node): ?Node 47 | { 48 | if ($node instanceof Assign) { 49 | if ($node->expr instanceof New_ && $this->isName($node->expr->class, 'ConnectionHelper')) { 50 | // Remove the instantiation statement 51 | $parent = $node->getAttribute(AttributeKey::PARENT_NODE); 52 | if ($parent instanceof Expression) { 53 | $this->removeNode($parent); 54 | } 55 | } 56 | 57 | return null; 58 | } 59 | 60 | // Ensure the node is a method call on the ConnectionHelper instance 61 | if (! $this->isObjectType($node->var, new ObjectType(ConnectionHelper::class))) { 62 | return null; 63 | } 64 | 65 | // Replace with a static method call 66 | return new StaticCall( 67 | new Node\Name\FullyQualified(ConnectionHelper::class), 68 | $node->name, 69 | $node->args, 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /config/paths.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | private array $callsWithRemoveMethodCallArgs = []; 29 | 30 | public function getRuleDefinition(): RuleDefinition 31 | { 32 | return new RuleDefinition('Remove method call', [ 33 | new ConfiguredCodeSample( 34 | <<<'CODE_SAMPLE' 35 | $obj = new SomeClass(); 36 | $obj->methodCall1(); 37 | $obj->methodCall2(); 38 | CODE_SAMPLE, 39 | <<<'CODE_SAMPLE' 40 | $obj = new SomeClass(); 41 | $obj->methodCall2(); 42 | CODE_SAMPLE, 43 | ['SomeClass', 'methodCall1'], 44 | ), 45 | ]); 46 | } 47 | 48 | /** 49 | * @return array> 50 | */ 51 | public function getNodeTypes(): array 52 | { 53 | return [Expression::class]; 54 | } 55 | 56 | /** 57 | * @param \PhpParser\Node\Stmt\Expression $node 58 | */ 59 | public function refactor(Node $node): ?int 60 | { 61 | if (! $node->expr instanceof MethodCall) { 62 | return null; 63 | } 64 | 65 | foreach ($this->callsWithRemoveMethodCallArgs as $removedFunction) { 66 | if (! $this->isObjectType($node->expr->var, $removedFunction->getObjectType())) { 67 | continue; 68 | } 69 | 70 | if (! $this->isName($node->expr->name, $removedFunction->getMethodName())) { 71 | continue; 72 | } 73 | 74 | return NodeVisitor::REMOVE_NODE; 75 | } 76 | 77 | return null; 78 | } 79 | 80 | /** 81 | * @param array $configuration 82 | */ 83 | public function configure(array $configuration): void 84 | { 85 | $this->callsWithRemoveMethodCallArgs = $configuration[self::REMOVE_METHOD_CALL_ARGS] ?? $configuration; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Rector/Rector/MethodCall/QueryParamAccessRector.php: -------------------------------------------------------------------------------- 1 | getParam('?') to $request->getQueryParams() 17 | * 18 | * In CakePHP 6.0, the getParam('?') shortcut for accessing query parameters 19 | * is removed. Instead, use getQueryParams() directly. 20 | * 21 | * @see https://book.cakephp.org/6/en/appendices/6-0-migration-guide.html 22 | */ 23 | final class QueryParamAccessRector extends AbstractRector 24 | { 25 | public function __construct( 26 | private ValueResolver $valueResolver, 27 | ) { 28 | } 29 | 30 | public function getRuleDefinition(): RuleDefinition 31 | { 32 | return new RuleDefinition( 33 | 'Change $request->getParam(\'?\') to $request->getQueryParams()', 34 | [ 35 | new CodeSample( 36 | <<<'CODE_SAMPLE' 37 | $queryParams = $request->getParam('?'); 38 | CODE_SAMPLE 39 | , 40 | <<<'CODE_SAMPLE' 41 | $queryParams = $request->getQueryParams(); 42 | CODE_SAMPLE, 43 | ), 44 | ], 45 | ); 46 | } 47 | 48 | public function getNodeTypes(): array 49 | { 50 | return [MethodCall::class]; 51 | } 52 | 53 | public function refactor(Node $node): ?Node 54 | { 55 | if (!$node instanceof MethodCall) { 56 | return null; 57 | } 58 | 59 | // Must be ->getParam() call 60 | if (!$node->name instanceof Identifier || $node->name->toString() !== 'getParam') { 61 | return null; 62 | } 63 | 64 | // Must have at least one argument 65 | if (count($node->args) < 1) { 66 | return null; 67 | } 68 | 69 | // First argument must be the string '?' 70 | $firstArg = $node->args[0]->value; 71 | if (!$this->valueResolver->isValue($firstArg, '?')) { 72 | return null; 73 | } 74 | 75 | // Check if this is called on a Request object 76 | $callerType = $this->getType($node->var); 77 | if (!$callerType instanceof ObjectType) { 78 | return null; 79 | } 80 | 81 | if ( 82 | !$callerType->isInstanceOf('Cake\Http\ServerRequest')->yes() && 83 | !$callerType->isInstanceOf('Psr\Http\Message\ServerRequestInterface')->yes() 84 | ) { 85 | return null; 86 | } 87 | 88 | // Transform to getQueryParams() with no arguments 89 | $node->name = new Identifier('getQueryParams'); 90 | $node->args = []; 91 | 92 | return $node; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/Rector/Rector/MethodCall/PaginatorCounterFormatRector.php: -------------------------------------------------------------------------------- 1 | counter(['format' => ...]) to Paginator->counter(...). 18 | * 19 | * @see https://github.com/cakephp/upgrade/issues/143 20 | */ 21 | final class PaginatorCounterFormatRector extends AbstractRector 22 | { 23 | public function getRuleDefinition(): RuleDefinition 24 | { 25 | return new RuleDefinition( 26 | 'Convert Paginator->counter([\'format\' => ...]) to Paginator->counter(...)', 27 | [ 28 | new CodeSample( 29 | <<<'CODE_SAMPLE' 30 | $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}')]); 31 | CODE_SAMPLE 32 | , 33 | <<<'CODE_SAMPLE' 34 | $this->Paginator->counter(__('Page {{page}} of {{pages}}')); 35 | CODE_SAMPLE, 36 | ), 37 | ], 38 | ); 39 | } 40 | 41 | /** 42 | * @return array> 43 | */ 44 | public function getNodeTypes(): array 45 | { 46 | return [MethodCall::class]; 47 | } 48 | 49 | /** 50 | * @param \PhpParser\Node\Expr\MethodCall $node 51 | */ 52 | public function refactor(Node $node): ?Node 53 | { 54 | if (!$this->isName($node->name, 'counter')) { 55 | return null; 56 | } 57 | 58 | if (!$this->isObjectType($node->var, new ObjectType('Cake\View\Helper\PaginatorHelper'))) { 59 | return null; 60 | } 61 | 62 | // Must have exactly one argument 63 | if (count($node->args) !== 1) { 64 | return null; 65 | } 66 | 67 | $firstArgNode = $node->args[0]; 68 | if (!$firstArgNode instanceof Arg) { 69 | return null; 70 | } 71 | 72 | $firstArg = $firstArgNode->value; 73 | 74 | // Check if the argument is an array 75 | if (!$firstArg instanceof Array_) { 76 | return null; 77 | } 78 | 79 | // Check if the array has exactly one item with key 'format' 80 | if (count($firstArg->items) !== 1) { 81 | return null; 82 | } 83 | 84 | $arrayItem = $firstArg->items[0]; 85 | 86 | if (!$arrayItem->key instanceof String_) { 87 | return null; 88 | } 89 | 90 | if ($arrayItem->key->value !== 'format') { 91 | return null; 92 | } 93 | 94 | // Replace the array argument with just the format value 95 | $node->args = [new Arg($arrayItem->value)]; 96 | 97 | return $node; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/Rector/Set/CakePHPSetList.php: -------------------------------------------------------------------------------- 1 | > $GITHUB_OUTPUT 39 | 40 | - name: Get date part for cache key 41 | id: key-date 42 | run: echo "date=$(date +'%Y-%m')" >> $GITHUB_OUTPUT 43 | 44 | - name: Cache composer dependencies 45 | uses: actions/cache@v5 46 | with: 47 | path: ${{ steps.composer-cache.outputs.dir }} 48 | key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }} 49 | 50 | - name: Composer Install 51 | run: | 52 | if ${{ matrix.prefer-lowest == 'prefer-lowest' }}; then 53 | make install-dev-lowest 54 | elif ${{ matrix.php-version == '8.1' }}; then 55 | make install-dev-ignore-reqs 56 | else 57 | make install-dev 58 | fi 59 | 60 | - name: Setup problem matchers for PHPUnit 61 | if: matrix.php-version == '8.1' 62 | run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" 63 | 64 | - name: Run PHPUnit 65 | run: vendor/bin/phpunit --display-incomplete --display-skipped 66 | 67 | cs-stan: 68 | name: Coding Standard & Static Analysis 69 | runs-on: ubuntu-22.04 70 | 71 | steps: 72 | - uses: actions/checkout@v6 73 | 74 | - name: Setup PHP 75 | uses: shivammathur/setup-php@v2 76 | with: 77 | php-version: '8.1' 78 | extensions: mbstring, intl 79 | tools: cs2pr 80 | coverage: none 81 | 82 | - name: Get composer cache directory 83 | id: composer-cache 84 | run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT 85 | 86 | - name: Get date part for cache key 87 | id: key-date 88 | run: echo "date=$(date +'%Y-%m')" >> $GITHUB_OUTPUT 89 | 90 | - name: Cache composer dependencies 91 | uses: actions/cache@v5 92 | with: 93 | path: ${{ steps.composer-cache.outputs.dir }} 94 | key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }} 95 | 96 | - name: Composer install 97 | run: make install-dev 98 | 99 | - name: Run PHP CodeSniffer 100 | run: vendor/bin/phpcs --report=checkstyle | cs2pr 101 | -------------------------------------------------------------------------------- /src/Rector/Rector/ClassMethod/FormExecuteToProcessRector.php: -------------------------------------------------------------------------------- 1 | > 61 | */ 62 | public function getNodeTypes(): array 63 | { 64 | return [Class_::class]; 65 | } 66 | 67 | /** 68 | * @param \PhpParser\Node\Stmt\Class_ $node 69 | */ 70 | public function refactor(Node $node): ?Node 71 | { 72 | if (!$this->isObjectType($node, new ObjectType('Cake\Form\Form'))) { 73 | return null; 74 | } 75 | 76 | // Check if process() already exists 77 | $hasProcess = false; 78 | foreach ($node->stmts as $stmt) { 79 | if ($stmt instanceof ClassMethod && $this->isName($stmt->name, 'process')) { 80 | $hasProcess = true; 81 | break; 82 | } 83 | } 84 | 85 | // If process() exists, don't rename _execute() 86 | if ($hasProcess) { 87 | return null; 88 | } 89 | 90 | // Find and rename _execute() method 91 | $hasChanges = false; 92 | foreach ($node->stmts as $stmt) { 93 | if (!$stmt instanceof ClassMethod) { 94 | continue; 95 | } 96 | 97 | if (!$this->isName($stmt->name, '_execute')) { 98 | continue; 99 | } 100 | 101 | // Rename the method to process() 102 | $stmt->name = new Identifier('process'); 103 | 104 | $hasChanges = true; 105 | break; 106 | } 107 | 108 | return $hasChanges ? $node : null; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /config/rector/sets/cakephp36.php: -------------------------------------------------------------------------------- 1 | ruleWithConfiguration(RenameMethodRector::class, [ 14 | new MethodCallRename('Cake\ORM\Table', 'association', 'getAssociation'), 15 | new MethodCallRename('Cake\Validation\ValidationSet', 'isPresenceRequired', 'requirePresence'), 16 | new MethodCallRename('Cake\Validation\ValidationSet', 'isEmptyAllowed', 'allowEmpty'), 17 | ]); 18 | 19 | $rectorConfig->ruleWithConfiguration(PropertyFetchToMethodCallRector::class, [ 20 | new PropertyFetchToMethodCall('Cake\Controller\Controller', 'name', 'getName', 'setName'), 21 | new PropertyFetchToMethodCall('Cake\Controller\Controller', 'plugin', 'getPlugin', 'setPlugin'), 22 | new PropertyFetchToMethodCall('Cake\Form\Form', 'validator', 'getValidator', 'setValidator'), 23 | ]); 24 | 25 | $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ 26 | 'Cake\Cache\Engine\ApcEngine' => 'Cake\Cache\Engine\ApcuEngine', 27 | 'Cake\Network\Exception\BadRequestException' => 'Cake\Http\Exception\BadRequestException', 28 | 'Cake\Network\Exception\ConflictException' => 'Cake\Http\Exception\ConflictException', 29 | 'Cake\Network\Exception\ForbiddenException' => 'Cake\Http\Exception\ForbiddenException', 30 | 'Cake\Network\Exception\GoneException' => 'Cake\Http\Exception\GoneException', 31 | 'Cake\Network\Exception\HttpException' => 'Cake\Http\Exception\HttpException', 32 | 'Cake\Network\Exception\InternalErrorException' => 'Cake\Http\Exception\InternalErrorException', 33 | 'Cake\Network\Exception\InvalidCsrfTokenException' => 'Cake\Http\Exception\InvalidCsrfTokenException', 34 | 'Cake\Network\Exception\MethodNotAllowedException' => 'Cake\Http\Exception\MethodNotAllowedException', 35 | 'Cake\Network\Exception\NotAcceptableException' => 'Cake\Http\Exception\NotAcceptableException', 36 | 'Cake\Network\Exception\NotFoundException' => 'Cake\Http\Exception\NotFoundException', 37 | 'Cake\Network\Exception\NotImplementedException' => 'Cake\Http\Exception\NotImplementedException', 38 | 'Cake\Network\Exception\ServiceUnavailableException' => 'Cake\Http\Exception\ServiceUnavailableException', 39 | 'Cake\Network\Exception\UnauthorizedException' => 'Cake\Http\Exception\UnauthorizedException', 40 | 'Cake\Network\Exception\UnavailableForLegalReasonsException' 41 | => 'Cake\Http\Exception\UnavailableForLegalReasonsException', 42 | 'Cake\Network\Session' => 'Cake\Http\Session', 43 | 'Cake\Network\Session\DatabaseSession' => 'Cake\Http\Session\DatabaseSession', 44 | 'Cake\Network\Session\CacheSession' => 'Cake\Http\Session\CacheSession', 45 | 'Cake\Network\CorsBuilder' => 'Cake\Http\CorsBuilder', 46 | 'Cake\View\Widget\WidgetRegistry' => 'Cake\View\Widget\WidgetLocator', 47 | ]); 48 | }; 49 | -------------------------------------------------------------------------------- /tests/TestCase/TestCase.php: -------------------------------------------------------------------------------- 1 | testAppDir = $className . '-' . $testName; 41 | $testAppPath = ORIGINAL_APPS . $this->testAppDir; 42 | 43 | if (file_exists($testAppPath)) { 44 | $fs = new Filesystem(); 45 | $fs->deleteDir(TEST_APP); 46 | $fs->copyDir($testAppPath, TEST_APP); 47 | } 48 | } 49 | 50 | protected function assertTestAppUpgraded(): void 51 | { 52 | $appFs = $this->getFsInfo(TEST_APP); 53 | $upgradedFs = $this->getFsInfo(UPGRADED_APPS . $this->testAppDir); 54 | $this->assertEquals($upgradedFs['tree'], $appFs['tree'], 'Upgraded test_app does not match `upgraded_apps`'); 55 | 56 | foreach ($upgradedFs['files'] as $relativePath) { 57 | $this->assertFileEquals(UPGRADED_APPS . $this->testAppDir . DS . $relativePath, TEST_APP . $relativePath, $relativePath); 58 | } 59 | } 60 | 61 | protected function getFsInfo(string $path): array 62 | { 63 | if ($path[-1] !== DS) { 64 | $path .= DS; 65 | } 66 | 67 | $iterator = new RecursiveIteratorIterator( 68 | new RecursiveDirectoryIterator( 69 | $path, 70 | RecursiveDirectoryIterator::KEY_AS_PATHNAME | 71 | RecursiveDirectoryIterator::CURRENT_AS_FILEINFO | 72 | RecursiveDirectoryIterator::SKIP_DOTS, 73 | ), 74 | RecursiveIteratorIterator::SELF_FIRST, 75 | ); 76 | 77 | $tree = []; 78 | $files = []; 79 | foreach ($iterator as $filePath => $fileInfo) { 80 | $relativePath = substr($filePath, strlen($path)); 81 | if ($fileInfo->isDir()) { 82 | $tree[$relativePath] = []; 83 | } elseif ($fileInfo->isFile() && $fileInfo->getFileName() !== 'empty') { 84 | $tree[$relativePath] = $fileInfo->getFileName(); 85 | $files[] = $relativePath; 86 | } 87 | } 88 | 89 | return ['tree' => Hash::expand($tree, DS), 'files' => $files]; 90 | } 91 | } 92 | --------------------------------------------------------------------------------