<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://sugarclub.sugarai.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon</link><description /><dc:language>en-US</dc:language><generator>Telligent Community 12</generator><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon</link><pubDate>Wed, 10 Sep 2025 18:20:03 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Current Revision posted to Dev Tutorials by Rafael Fernandes on 9/10/2025 6:20:03 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the fully qualified paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        &amp;#39;/path/to/sugar/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        &amp;#39;/path/to/sugar/custom/clients/&amp;#39;,
        &amp;#39;/path/to/sugar/custom/modules/ActivityStream/&amp;#39;,
        &amp;#39;/path/to/sugar/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        &amp;#39;/path/to/sugar/custom/modules/pmse_Project/&amp;#39;,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&amp;nbsp;Rector will generate a sample code with &lt;code&gt;__DIR__,&lt;/code&gt;&amp;nbsp;that, however, translates to &amp;quot;current folder&amp;quot; which can be different than your Sugar install. As a rule of thumb, always use fully qualified names &lt;em&gt;&lt;strong&gt;without&lt;/strong&gt;&lt;/em&gt; the &lt;code&gt;__DIR__&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Modify the &lt;code&gt;rector.php&lt;/code&gt; config file to upgrade the code to the newest supported PHP version (in our case, 8.3):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Specify PHP 8.3 as your phpVersion:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_83);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to have only the incompatible rules between PHP 7.4 to PHP 8.3, you can use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;safeCount&lt;/code&gt; rule to your config if you are in a supported Sugar version&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;?php
...
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
...
return static function (RectorConfig $rectorConfig): void {
...
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
...&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example (incompatibilities only)&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run&amp;nbsp;&lt;span&gt;incompatible rules between PHP 7.4 to PHP 8.3&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php
declare(strict_types=1);

use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php74\Rector\Double\RealToFloatTypeCastRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Config\RectorConfig;
use Rector\ValueObject\PhpVersion;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_83);

    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class,
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/20</link><pubDate>Wed, 10 Sep 2025 18:16:46 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 20 posted to Dev Tutorials by Rafael Fernandes on 9/10/2025 6:16:46 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the fully qualified paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        &amp;#39;/path/to/sugar/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        &amp;#39;/path/to/sugar/custom/clients/&amp;#39;,
        &amp;#39;/path/to/sugar/custom/modules/ActivityStream/&amp;#39;,
        &amp;#39;/path/to/sugar/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        &amp;#39;/path/to/sugar/custom/modules/pmse_Project/&amp;#39;,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&amp;nbsp;Rector will generate a sample code with &lt;code&gt;__DIR__,&lt;/code&gt;&amp;nbsp;that, however, translates to &amp;quot;current folder&amp;quot; which can be different than your Sugar install. As a rule of thumb, always use fully qualified names &lt;em&gt;&lt;strong&gt;without&lt;/strong&gt;&lt;/em&gt; the &lt;code&gt;__DIR__&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Modify the &lt;code&gt;rector.php&lt;/code&gt; config file to upgrade the code to the newest supported PHP version (in our case, 8.3):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Specify PHP 8.3 as your phpVersion:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_83);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to have only the incompatible rules between PHP 7.4 to PHP 8.3, you can use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;safeCount&lt;/code&gt; rule to your config if you are in a supported Sugar version&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;?php
...
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
...
return static function (RectorConfig $rectorConfig): void {
...
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
...&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example (incompatibilities only)&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run&amp;nbsp;&lt;span&gt;incompatible rules between PHP 7.4 to PHP 8.3&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php
declare(strict_types=1);

use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php74\Rector\Double\RealToFloatTypeCastRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Config\RectorConfig;
use Rector\ValueObject\PhpVersion;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_83);

    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class,
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/19</link><pubDate>Mon, 17 Mar 2025 13:05:08 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 19 posted to Dev Tutorials by Rafael Fernandes on 3/17/2025 1:05:08 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;Modify the &lt;code&gt;rector.php&lt;/code&gt; config file to upgrade the code to the newest supported PHP version (in our case, 8.3):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Specify PHP 8.3 as your phpVersion:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_83);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to have only the incompatible rules between PHP 7.4 to PHP 8.3, you can use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;safeCount&lt;/code&gt; rule to your config if you are in a supported Sugar version&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;?php
...
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
...
return static function (RectorConfig $rectorConfig): void {
...
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
...&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example (incompatibilities only)&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run&amp;nbsp;&lt;span&gt;incompatible rules between PHP 7.4 to PHP 8.3&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php
declare(strict_types=1);

use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php74\Rector\Double\RealToFloatTypeCastRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Config\RectorConfig;
use Rector\ValueObject\PhpVersion;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);
    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/18</link><pubDate>Mon, 17 Mar 2025 13:00:06 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 18 posted to Dev Tutorials by Rafael Fernandes on 3/17/2025 1:00:06 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;Modify the &lt;code&gt;rector.php&lt;/code&gt; config file to upgrade the code to the newest supported PHP version (in our case, 8.3):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Specify PHP 8.3 as your phpVersion:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_83);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to have only the incompatible rules between PHP 7.4 to PHP 8.3, you can use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;safeCount&lt;/code&gt; rule to your config if you are in a supported Sugar version&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;?php
...
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
...
return static function (RectorConfig $rectorConfig): void {
...
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
...&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a &lt;code&gt;rector.php&lt;/code&gt; similar to this to run all Rector rules against your code:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_83);

    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class,
    ]);

    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example (incompatibilities only)&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run&amp;nbsp;&lt;span&gt;incompatible rules between PHP 7.4 to PHP 8.3&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php
declare(strict_types=1);

use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php74\Rector\Double\RealToFloatTypeCastRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Config\RectorConfig;
use Rector\ValueObject\PhpVersion;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);
    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/17</link><pubDate>Thu, 26 Oct 2023 17:45:20 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 17 posted to Dev Tutorials by Rafael Fernandes on 10/26/2023 5:45:20 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Specify PHP 8.2 as your phpVersion:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar (it will skip those but will run all the other rules available in your rector version).&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to have only the incompatible rules between PHP 7.4 to PHP 8.2, you can use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        Php8ResourceReturnToObjectRector::class,
        Php81ResourceReturnToObjectRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;safeCount&lt;/code&gt; rule to your config if you are in a supported Sugar version&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;?php
...
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
...
return static function (RectorConfig $rectorConfig): void {
...
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
...&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run all Rector rules against your code:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example (incompatibilities only)&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run&amp;nbsp;&lt;span&gt;incompatible rules between PHP 7.4 to PHP 8.2&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php
declare(strict_types=1);

use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php74\Rector\Double\RealToFloatTypeCastRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Config\RectorConfig;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);
    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/16</link><pubDate>Tue, 10 Oct 2023 16:52:19 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 16 posted to Dev Tutorials by Rafael Fernandes on 10/10/2023 4:52:19 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Specify PHP 8.2 as your phpVersion:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar (it will skip those but will run all the other rules available in your rector version).&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to have only the incompatible rules between PHP 7.4 to PHP 8.2, you can use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        Php8ResourceReturnToObjectRector::class,
        Php81ResourceReturnToObjectRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;safeCount&lt;/code&gt; rule to your config if you are in a supported Sugar version&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;?php
...
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
...
return static function (RectorConfig $rectorConfig): void {
...
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
...&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run all Rector rules against your code:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example (incompatibilities only)&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run&amp;nbsp;&lt;span&gt;incompatible rules between PHP 7.4 to PHP 8.2&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php
declare(strict_types=1);

use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php74\Rector\Double\RealToFloatTypeCastRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Php80\Rector\FuncCall\Php8ResourceReturnToObjectRector;
use Rector\Config\RectorConfig;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Php81\Rector\FuncCall\Php81ResourceReturnToObjectRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);
    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        Php8ResourceReturnToObjectRector::class,
        Php81ResourceReturnToObjectRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
        StaticCallOnNonStaticToInstanceCallRector::class
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/15</link><pubDate>Thu, 07 Sep 2023 15:31:14 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 15 posted to Dev Tutorials by Rafael Fernandes on 9/7/2023 3:31:14 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Specify PHP 8.2 as your phpVersion:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar (it will skip those but will run all the other rules available in your rector version).&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to have only the incompatible rules between PHP 7.4 to PHP 8.2, you can use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        Php8ResourceReturnToObjectRector::class,
        Php81ResourceReturnToObjectRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;safeCount&lt;/code&gt; rule to your config if you are in a supported Sugar version&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;?php
...
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
...
return static function (RectorConfig $rectorConfig): void {
...
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
...&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run all Rector rules against your code:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example (incompatibilities only)&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this to run&amp;nbsp;&lt;span&gt;incompatible rules between PHP 7.4 to PHP 8.2&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php
declare(strict_types=1);

use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php74\Rector\Double\RealToFloatTypeCastRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Php80\Rector\FuncCall\Php8ResourceReturnToObjectRector;
use Rector\Config\RectorConfig;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Php81\Rector\FuncCall\Php81ResourceReturnToObjectRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);
    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        Php8ResourceReturnToObjectRector::class,
        Php81ResourceReturnToObjectRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/14</link><pubDate>Thu, 07 Sep 2023 15:25:14 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 14 posted to Dev Tutorials by Rafael Fernandes on 9/7/2023 3:25:14 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Specify PHP 8.2 as your phpVersion:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar (it will skip those but will run all the other rules available in your rector version).&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to have only the incompatible rules between PHP 7.4 to PHP 8.2, you can use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        Php8ResourceReturnToObjectRector::class,
        Php81ResourceReturnToObjectRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;safeCount&lt;/code&gt; rule to your config if you are in a supported Sugar version&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;?php
...
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
...
return static function (RectorConfig $rectorConfig): void {
...
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
...&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example (incompatibilities only)&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php
declare(strict_types=1);

use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php74\Rector\Double\RealToFloatTypeCastRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Php80\Rector\FuncCall\Php8ResourceReturnToObjectRector;
use Rector\Config\RectorConfig;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Php81\Rector\FuncCall\Php81ResourceReturnToObjectRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);
    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        Php8ResourceReturnToObjectRector::class,
        Php81ResourceReturnToObjectRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
    ]);
    $rectorConfig-&amp;gt;ruleWithConfiguration(RenameFunctionRector::class, [
        &amp;#39;count&amp;#39; =&amp;gt; &amp;#39;safeCount&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/13</link><pubDate>Thu, 07 Sep 2023 15:20:10 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 13 posted to Dev Tutorials by Rafael Fernandes on 9/7/2023 3:20:10 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Specify PHP 8.2 as your phpVersion:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar (it will skip those but will run all the other rules available in your rector version).&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to have only the incompatible rules between PHP 7.4 to PHP 8.2, you can use the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        Php8ResourceReturnToObjectRector::class,
        Php81ResourceReturnToObjectRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
    ]);&lt;/pre&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example (incompatibilities only)&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php
declare(strict_types=1);

use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php74\Rector\Double\RealToFloatTypeCastRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Php80\Rector\FuncCall\Php8ResourceReturnToObjectRector;
use Rector\Config\RectorConfig;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Php81\Rector\FuncCall\Php81ResourceReturnToObjectRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;cacheClass(MemoryCacheStorage::class);
    $rectorConfig-&amp;gt;disableParallel();
    $rectorConfig-&amp;gt;phpVersion(PhpVersion::PHP_82);
    $rectorConfig-&amp;gt;rules([
        AddParamBasedOnParentClassMethodRector::class,
        SetStateToStaticRector::class,
        Php8ResourceReturnToObjectRector::class,
        Php81ResourceReturnToObjectRector::class,
        ArrayKeyExistsOnPropertyRector::class,
        ExportToReflectionFunctionRector::class,
        FilterVarToAddSlashesRector::class,
        MbStrrposEncodingArgumentPositionRector::class,
        MoneyFormatToNumberFormatRector::class,
        RealToFloatTypeCastRector::class,
        RestoreDefaultNullToNullableTypePropertyRector::class,
        StringifyStrNeedlesRector::class,
        GetClassOnNullRector::class,
        ListEachRector::class,
        ReplaceEachAssignmentWithKeyCurrentRector::class,
        ParseStrWithResultArgumentRector::class,
        StringifyDefineRector::class,
        WhileEachToForeachRector::class,
        ConsistentImplodeRector::class,
        CurlyToSquareBracketArrayStringRector::class,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/12</link><pubDate>Tue, 11 Jul 2023 19:43:46 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 12 posted to Dev Tutorials by Rafael Fernandes on 7/11/2023 7:43:46 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Remove/Comment:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Add the following rules:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;sets([
    LevelSetList::UP_TO_PHP_82,
    SetList::PHP_82,
]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/11</link><pubDate>Wed, 19 Apr 2023 19:43:28 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 11 posted to Dev Tutorials by Rafael Fernandes on 4/19/2023 7:43:28 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Replace&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;With&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add the following rules:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;sets([
    LevelSetList::UP_TO_PHP_82,
    SetList::PHP_82,
]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1gudgk28f0"&gt;You can move on to the&amp;nbsp;Execution&lt;span&gt;&amp;nbsp;&lt;/span&gt;Phase:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/836/executing-rector"&gt;Execute Rector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/10</link><pubDate>Wed, 19 Apr 2023 14:29:58 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 10 posted to Dev Tutorials by Rafael Fernandes on 4/19/2023 2:29:58 PM&lt;br /&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package (MLP), a.k.a Addon, compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Replace&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;With&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add the following rules:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;sets([
    LevelSetList::UP_TO_PHP_82,
    SetList::PHP_82,
]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1guavo72a0"&gt;&lt;/h2&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/9</link><pubDate>Wed, 19 Apr 2023 13:09:58 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 9 posted to Dev Tutorials by Rafael Fernandes on 4/19/2023 1:09:58 PM&lt;br /&gt;
&lt;h2 id="mcetoc_1gtthv2b41"&gt;Prepare Rector for Module Loadable Package (MLP)&lt;/h2&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Replace&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;With&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add the following rules:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;sets([
    LevelSetList::UP_TO_PHP_82,
    SetList::PHP_82,
]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1guavo72a0"&gt;&lt;/h2&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Prepare Rector for MLP/Addon</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/8</link><pubDate>Wed, 19 Apr 2023 13:09:33 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 8 posted to Dev Tutorials by Rafael Fernandes on 4/19/2023 1:09:33 PM&lt;br /&gt;
&lt;h2 id="mcetoc_1gtthv2b41"&gt;Module Loadable Package (MLP) Refactor&lt;/h2&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Replace&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;With&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add the following rules:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;sets([
    LevelSetList::UP_TO_PHP_82,
    SetList::PHP_82,
]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1guavo72a0"&gt;&lt;/h2&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Module Loadable Package (MLP) Refactor</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/7</link><pubDate>Tue, 18 Apr 2023 20:20:28 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 7 posted to Dev Tutorials by Rafael Fernandes on 4/18/2023 8:20:28 PM&lt;br /&gt;
&lt;h2 id="mcetoc_1gtthv2b41"&gt;Module Loadable Package (MLP) Refactor&lt;/h2&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Replace&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;With&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add the following rules:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;sets([
    LevelSetList::UP_TO_PHP_82,
    SetList::PHP_82,
]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1guavo72a0"&gt;&lt;/h2&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Module Loadable Package (MLP) Refactor</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/6</link><pubDate>Tue, 18 Apr 2023 20:11:53 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 6 posted to Dev Tutorials by Rafael Fernandes on 4/18/2023 8:11:53 PM&lt;br /&gt;
&lt;h2 id="mcetoc_1gtthv2b41"&gt;Module Loadable Package (MLP) Refactor&lt;/h2&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Replace&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;With&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add the following rules:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;sets([
    LevelSetList::UP_TO_PHP_82,
    SetList::PHP_82,
]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1guavo72a0"&gt;Dry-run Rector&lt;/h2&gt;
&lt;p&gt;Now that you have your Rector properly configured with your MLP data.&lt;/p&gt;
&lt;p&gt;Dry-run gives you the opportunity to see what Rector has found and will execute/change before it actually does it on your behalf.&lt;/p&gt;
&lt;p&gt;it&amp;#39;s time to dry-run rector by executing the following command.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;cd /path/to/sugar &amp;amp;&amp;amp; rector-0.15.20/bin/rector process --clear-cache --dry-run &amp;gt; php82.diff
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Module Loadable Package (MLP) Refactor</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/5</link><pubDate>Tue, 18 Apr 2023 19:38:58 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 5 posted to Dev Tutorials by Rafael Fernandes on 4/18/2023 7:38:58 PM&lt;br /&gt;
&lt;h2 id="mcetoc_1gtthv2b41"&gt;Module Loadable Package (MLP) Refactor&lt;/h2&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;* Please, notice the &amp;#39;/&amp;#39; after &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; constant usage. It is required as &lt;code class="code css-z5oxh7"&gt;__DIR__&lt;/code&gt; does not have a trailing slash.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Modify the rector.php config file to upgrade the code to the newest supported PHP version (in our case, 8.2):&lt;/p&gt;
&lt;p&gt;Replace&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;// register a single rule
$rectorConfig-&amp;gt;rule(InlineConstructorDefaultToPropertyRector::class);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;With&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Add the following rules:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;$rectorConfig-&amp;gt;sets([
    LevelSetList::UP_TO_PHP_82,
    SetList::PHP_82,
]);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The following rules should be skipped to prevent known issues with Sugar.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Full config file example&lt;/h3&gt;
&lt;p&gt;By following those steps, you should have a rector.php similar to this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="php"&gt;&amp;lt;?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);

    $rectorConfig-&amp;gt;phpstanConfig(__DIR__ . &amp;#39;/stan.neon&amp;#39;);

    $rectorConfig-&amp;gt;sets([
        LevelSetList::UP_TO_PHP_82,
        SetList::PHP_82,
    ]);

    $rectorConfig-&amp;gt;skip([
        \Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector::class,
        \Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class,
        \Rector\Php80\Rector\FunctionLike\UnionTypesRector::class,
        \Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector::class,
        \Rector\Php80\Rector\FunctionLike\MixedTypeRector::class,
        \Rector\Php81\Rector\Property\ReadOnlyPropertyRector::class,
        \Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector::class,
        \Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector::class,
        \Rector\Php80\Rector\NotIdentical\StrContainsRector::class,
        \Rector\Php80\Rector\Identical\StrEndsWithRector::class,
        \Rector\Php80\Rector\Identical\StrStartsWithRector::class,
        \Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector::class,
        \Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector::class,
        \Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector::class,
        \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class,
        \Rector\Php81\Rector\Array_\FirstClassCallableRector::class,
        \Rector\Php80\Rector\FuncCall\TokenGetAllToObjectRector::class,
        \Rector\Php81\Rector\ClassMethod\NewInInitializerRector::class,
        \Rector\Php80\Rector\Class_\StringableForToStringRector::class,
        \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class,
        \Rector\Php54\Rector\Array_\LongArrayToShortArrayRector::class,
        \Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector::class,
        \Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
        \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class,
        \Rector\Php80\Rector\FuncCall\ClassOnObjectRector::class,
        \Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector::class,
        \Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector::class,
        \Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector::class,
        \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class,
        __DIR__ . &amp;#39;/include/SugarObjects/templates/file/views/view.edit.php&amp;#39;,
    ]);
};&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Module Loadable Package (MLP) Refactor</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/4</link><pubDate>Tue, 18 Apr 2023 19:18:04 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 4 posted to Dev Tutorials by Rafael Fernandes on 4/18/2023 7:18:04 PM&lt;br /&gt;
&lt;h2 id="mcetoc_1gtthv2b41"&gt;Module Loadable Package (MLP) Refactor&lt;/h2&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;    $rectorConfig-&amp;gt;paths([
        __DIR__ . &amp;#39;/custom/Extension/application/Ext/Include/BuildingBlock_HelloWorldDashlet.php&amp;#39;,
        __DIR__ . &amp;#39;/custom/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/ActivityStream/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/Forecasts/Ext/clients/&amp;#39;,
        __DIR__ . &amp;#39;/custom/modules/pmse_Project/&amp;#39;,
    ]);
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Module Loadable Package (MLP) Refactor</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/3</link><pubDate>Tue, 18 Apr 2023 18:59:38 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 3 posted to Dev Tutorials by Rafael Fernandes on 4/18/2023 6:59:38 PM&lt;br /&gt;
&lt;h2 id="mcetoc_1gtthv2b41"&gt;Module Loadable Package (MLP) Refactor&lt;/h2&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3 id="mcetoc_1guah5gi50"&gt;Prepare your Rector config&lt;/h3&gt;
&lt;p&gt;Copy the paths, and paste them into the rector.php config file that was generated in the previous step, replacing the default paths in &lt;code class="code css-z5oxh7"&gt;$rectorConfig-&amp;gt;paths([&lt;/code&gt; array like this (you can ignore some of the files, like &lt;code class="code css-z5oxh7"&gt;*ext.php&lt;/code&gt; and &lt;code class="code css-z5oxh7"&gt;*orderMapping.php&lt;/code&gt;):&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Module Loadable Package (MLP) Refactor</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/2</link><pubDate>Tue, 18 Apr 2023 15:51:31 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 2 posted to Dev Tutorials by Rafael Fernandes on 4/18/2023 3:51:31 PM&lt;br /&gt;
&lt;h2 id="mcetoc_1gtthv2b41"&gt;Module Loadable Package (MLP) Refactor&lt;/h2&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxxxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Module Loadable Package (MLP) Refactor</title><link>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon/revision/1</link><pubDate>Tue, 18 Apr 2023 15:34:20 GMT</pubDate><guid isPermaLink="false">5c521d64-519d-47a6-9065-134618b211bf:6ad24d35-d4d0-410f-8bd4-16ba03823af4</guid><dc:creator>Rafael Fernandes</dc:creator><comments>https://sugarclub.sugarai.com/dev-club/w/dev-tutorials/834/prepare-rector-for-mlp-addon#comments</comments><description>Revision 1 posted to Dev Tutorials by Rafael Fernandes on 4/18/2023 3:34:20 PM&lt;br /&gt;
&lt;h2 id="mcetoc_1gtthv2b41"&gt;Module Loadable Package (MLP) Refactor&lt;/h2&gt;
&lt;p&gt;If you are looking to make your Module Loadable Package compatible with different versions of PHP, this guide is for you.&lt;/p&gt;
&lt;p&gt;You will&amp;nbsp;install&amp;nbsp;an MLP zip file into Sugar&amp;#39;s instance where Rector is and git has been initialized, by doing that, Sugar will add the MLP in the filesystem and git will let us know what has changed.&lt;/p&gt;
&lt;h3 id="mcetoc_1guaf95jk0"&gt;Prerequisites:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/dev-club/w/dev-tutorials/828/rector-basic-setup"&gt;Basic Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A module loadable package (zip file)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1guafg2ff1"&gt;Upload and Install your MLP&lt;/h3&gt;
&lt;p&gt;Upload and install your MLP as you normally would through Sugar&amp;#39;s UI or API. Sugar will copy your files per manifest definition and perform the database operations as well (which are irrelevant for Rector).&lt;/p&gt;
&lt;p&gt;After it has been installed, execute &lt;code&gt;git status&lt;/code&gt; commands to see which files were updated/added by Sugar:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="batchfile"&gt;sh-3.2$ git status
On branch main
Changes not staged for commit:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to update what will be committed)
  (use &amp;quot;git restore &amp;lt;file&amp;gt;...&amp;quot; to discard changes in working directory)
        modified:   config_override.php
        modified:   custom/application/Ext/Include/modules.ext.php

Untracked files:
  (use &amp;quot;git add &amp;lt;file&amp;gt;...&amp;quot; to include in what will be committed)
        custom/Extension/application/Ext/Include/xxxxxxx.php
        custom/Extension/application/Ext/Include/orderMapping.php
        custom/modules/ActivityStream/
        custom/modules/Forecasts/Ext/clients/
        custom/modules/pmse_Project/

no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item></channel></rss>